diff -bruN freeswan-1.9.orig/CREDITS freeswan-1.9/CREDITS
--- freeswan-1.9.orig/CREDITS	Mon Feb 26 18:56:08 2001
+++ freeswan-1.9/CREDITS	Wed May 16 10:57:20 2001
@@ -60,6 +60,8 @@
 <http://www.xs4all.nl/~freeswan/> for other contributors to this project
 and related ones.
 
+This product includes software developed by the OpenSSL Project for use 
+in the OpenSSL Toolkit (http://www.openssl.org/).
 
 
 This file is RCSID $Id: CREDITS,v 1.20.2.1 2001/02/26 23:56:08 henry Exp $
diff -bruN freeswan-1.9.orig/INSTALL.pkix freeswan-1.9/INSTALL.pkix
--- freeswan-1.9.orig/INSTALL.pkix	Wed Dec 31 19:00:00 1969
+++ freeswan-1.9/INSTALL.pkix	Wed May 16 10:57:20 2001
@@ -0,0 +1,47 @@
+Documentation on how to use the PKIX extension for IPSec can be found under
+'doc/pkix'. Within that directory, you will also find working examples I 
+have preserved to test the various connection modes I have successfully
+connection with FreeSWAN. There are also some scripts you might (will?)
+find useful.
+
+Requirements:
+OpenLDAP 1.2 or better
+OpenSSL 0.9.5a with Shared Libraries compiled.
+
+
+  If you have to compile OpenSSL 0.9.5a yourself, here's how you should 
+compile it. Don't forget to add '/usr/local/ssl/lib' (or whatever your SSL 
+path is going to be) to '/etc/ld.so.conf'. This following script will let 
+you create '.so' shared library files. Of course, Run it as Root.:
+-------------------------------------------------------
+./config
+make
+if [ ! -d shlib_dir ]; 
+then 
+  mkdir shlib_dir 
+else 
+  rm -f shlib_dir/*
+fi
+cd shlib_dir
+ar -x ../libcrypto.a && gcc -shared ./*.o -Wl,-soname \
+  -Wl,libcrypto.so -o ./libcrypto.so.0.9.5a && rm *.o
+ar -x ../libssl.a && gcc -shared ./*.o -Wl,-soname \
+  -Wl,libssl.so -o ./libssl.so.0.9.5a && rm *.o
+cp libssl.so.0.9.5a /usr/local/ssl/lib
+cp libcrypto.so.0.9.5a /usr/local/ssl/lib
+cd ..
+make install
+ldconfig
+-------------------------------------------------------
+
+NOTE: I don't think freeswan-pkix will compile against OpenSSL 0.9.6. There
+has been many major changes in the OpenSSL project.
+
+Don't forget to edit the root Makefile for OPENSSLROOT and LDAPROOT if their
+include paths are non-standard (ie: not under /usr/include/).
+
+
+Otherwise, just follow FreeSWAN's own INSTALL file normally.
+
+-- Luc Lanthier
+luc.lanthier@rebel.com
diff -bruN freeswan-1.9.orig/LICENSE freeswan-1.9/LICENSE
--- freeswan-1.9.orig/LICENSE	Wed Dec 31 19:00:00 1969
+++ freeswan-1.9/LICENSE	Wed May 16 10:57:20 2001
@@ -0,0 +1,29 @@
+Legal statements
+----------------
+
+X.509 FreeS/WAN patch:
+Copyright (C) 1999, Neil Dunbar 
+Copyright (C) 2000, Luc Lanthier <luc.lanthier@rebel.com>
+        Rebel.com, Ottawa, Canada
+
+X.509 FreeS/WAN-PGPNet patch:
+Copyright (C) 2000, Andreas Hess, Patrick Lichtsteiner, Roger Wegmann &
+                    Andreas Steffen <andreas.steffen@zhwin.ch>,
+        Zurich University of Applied Sciences in Winterthur, Switzerland
+
+PGPnet-RSA portions of patch:
+Copyright (C) 2000, Kai Martius <kai@secunet.de>
+
+fswcert utility:
+Copyright (C) 2000, Andreas Gruenbacher <a.gruenbacher@computer.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.
diff -bruN freeswan-1.9.orig/Makefile freeswan-1.9/Makefile
--- freeswan-1.9.orig/Makefile	Fri Feb 23 11:31:38 2001
+++ freeswan-1.9/Makefile	Wed May 16 10:57:20 2001
@@ -13,21 +13,41 @@
 #
 # RCSID $Id: Makefile,v 1.123.2.2 2001/02/23 16:31:38 henry Exp $
 
-# install pathnames; DESTDIR can be used to supply a prefix to them all
-# PUBDIR is where the "ipsec" command goes; beware, many things define PATH
-# settings which are assumed to include it (or at least, to include *some*
-# copy of the "ipsec" command).
-PUBDIR=$(DESTDIR)/usr/local/sbin
-# PRIVDIR is where commands get put, REALPRIVDIR is where they think they
-# will be run from in the end (currently only used by utils/ipsec)
+
+# change this to 0 if you don't want OPENSSL support turned on
+# it will turn off all pkix support also
+# check the paths for the OPENSSLROOT and LDAPROOT
+export USEOPENSSL=1
+ifeq "$(USEOPENSSL)" "1"
+export OPENSSLROOT=/usr/local/ssl
+export OPENSSLINCLS=-I$(OPENSSLROOT)/include
+export OPENSSLLIBS=-L$(OPENSSLROOT)/lib -lcrypto
+
+export LDAPROOT=/usr/local
+export LDAPINCS=-I$(LDAPROOT)/include
+endif
+
+# PREFIX controls where everything gets installed to.  This is intended
+# only for use by RPM, which installs everything into a temporary root
+# prior to creating the package.
+export PREFIX ?= /
+
+# public and private command directories
+# Beware, many things define PATH settings which are assumed to include
+# PUBDIR (or at least, to include *some* copy of the "ipsec" command).
+PUBDIR=$(PREFIX)/usr/local/sbin
+
+# PRIVDIR is where things get put, FINALPRIVDIR is where they think they
+# will be put (currently only used by utils/ipsec)
+PRIVDIR=/usr/local/lib/ipsec
+FINALPRIVDIR=/usr/local/lib/ipsec
 REALPRIVDIR=/usr/local/lib/ipsec
-PRIVDIR=$(DESTDIR)$(REALPRIVDIR)
 # where manpages go
-MANTREE=$(DESTDIR)/usr/local/man
+MANTREE=/usr/local/man
 # all relevant manpage subdirectories
 MANPLACES=man3 man5 man8
 # where configuration files go
-CONFDIR=$(DESTDIR)/etc
+CONFDIR=$(PREFIX)/etc
 # RCDIR is where boot/shutdown scripts go (first RCDIRS that exists gets it);
 # REALRCDIR is where they think they will ultimately be (for utils/Makefile)
 RCDIRS=/etc/rc.d/init.d /etc/rc.d /etc/init.d /sbin/init.d
@@ -38,7 +58,7 @@
 RCDIR=$(DESTDIR)$(REALRCDIR)
 
 # kernel location, and location of kernel patches in the distribution
-KERNELSRC=/usr/src/linux
+KERNELSRC?=/usr/src/linux
 DIRIN22=$(KERNELSRC)/net/netlink
 FILIN24=$(KERNELSRC)/net/khttpd/main.c
 KERNELREL=$(shell { test -f $(FILIN24) && echo 2.3; } || { test -d $(DIRIN22) && echo 2.2; } )
@@ -48,6 +68,8 @@
 # note, some of the patches know the last part of this path
 KERNELKLIPS=$(KERNELSRC)/net/ipsec
 
+
+
 # kernel make name:  zImage for 2.0.xx, bzImage for 2.2.xx and later, and
 # different foolishness on the Alpha (what ever happened to standards?)
 B=$(shell test -d $(DIRIN22) && echo b)
@@ -89,7 +111,24 @@
 	ln -s `pwd`/libdes/asm/*.pl $(KERNELKLIPS)/libdes/asm
 	ln -s `pwd`/libdes/asm/perlasm $(KERNELKLIPS)/libdes/asm
 	ln -s `pwd`/zlib/Makefile $(KERNELKLIPS)/zlib
-	ln -s `pwd`/zlib/*.[chS] $(KERNELKLIPS)/zlib
+
+kcopy:
+	rm -rf $(KERNELKLIPS)
+	mkdir -p $(KERNELKLIPS)/libdes/asm
+	mkdir -p $(KERNELKLIPS)/libfreeswan
+	mkdir -p $(KERNELKLIPS)/zlib
+	cp -R --verbose `pwd`/klips/net/ipsec/Makefile $(KERNELKLIPS)
+	cp -R --verbose `pwd`/klips/net/ipsec/Config.in $(KERNELKLIPS)
+	cp -R --verbose `pwd`/klips/net/ipsec/defconfig $(KERNELKLIPS)
+	cp -R --verbose `pwd`/klips/net/ipsec/*.[ch] $(KERNELKLIPS)
+	cp -R --verbose `pwd`/lib/Makefile.kernel $(KERNELKLIPS)/libfreeswan/Makefile
+	cp -R --verbose `pwd`/lib/*.[ch] $(KERNELKLIPS)/libfreeswan
+	cp -R --verbose `pwd`/libdes/Makefile $(KERNELKLIPS)/libdes
+	cp -R --verbose `pwd`/libdes/*.[ch] $(KERNELKLIPS)/libdes
+	cp -R --verbose `pwd`/libdes/asm/*.pl $(KERNELKLIPS)/libdes/asm
+	cp -R --verbose `pwd`/libdes/asm/perlasm $(KERNELKLIPS)/libdes/asm
+	cp -R --verbose `pwd`/zlib/Makefile $(KERNELKLIPS)/zlib
+	cp -R --verbose `pwd`/zlib/*.[chS] $(KERNELKLIPS)/zlib
 
 PATCHER=utils/patcher
 patches:
@@ -210,8 +249,8 @@
 	cd utils ; $(MAKE) $(SETTINGS)
 
 install:
-	mkdir -p $(PRIVDIR) $(PUBDIR)
-	for m in $(MANPLACES) ; do mkdir -p $(MANTREE)/$$m ; done
+	mkdir -p $(PREFIX)/$(PRIVDIR) $(PREFIX)/$(PUBDIR)
+	for m in $(MANPLACES) ; do mkdir -p $(PREFIX)/$(MANTREE)/$$m ; done
 	cd lib ; $(MAKE) install $(SETTINGS)
 	cd klips/utils ; $(MAKE) install $(SETTINGS)
 	cd pluto ; $(MAKE) install $(SETTINGS)
@@ -329,3 +368,9 @@
 	ctags `find lib pluto klips/utils klips/net/ipsec -name '*.[ch]'`
 
 dummy:
+
+patchclean:
+	find $(KERNELSRC) -name '*.preipsec' -exec rm {} \;
+	find $(KERNELSRC) -name '*.wipsec' -exec rm {} \;
+	find $(KERNELSRC) -name '*.ipsecmd5' -exec rm {} \;
+
diff -bruN freeswan-1.9.orig/doc/DES.readme_first freeswan-1.9/doc/DES.readme_first
--- freeswan-1.9.orig/doc/DES.readme_first	Wed Dec 31 19:00:00 1969
+++ freeswan-1.9/doc/DES.readme_first	Mon Jun  4 11:34:31 2001
@@ -0,0 +1,16 @@
+DES has been readded via the pkix patch. This just means that it is
+supported, but not necessarily used as the primary cypher.
+
+You can __force__ to use only DES or 3DES with the following whack command:
+
+DES only:
+  -- force_encrypt_cypher des
+3DES only:
+  -- force_encrypt_cypher 3des
+
+You can also pass this parameter along to pluto via /etc/ipsec.conf
+
+DES only:
+	force_encrypt_cypher=des
+3DES only:
+	force_encrypt_cypher=3des
diff -bruN freeswan-1.9.orig/doc/HowTo.html freeswan-1.9/doc/HowTo.html
--- freeswan-1.9.orig/doc/HowTo.html	Tue Mar 27 23:16:54 2001
+++ freeswan-1.9/doc/HowTo.html	Mon Jun  4 01:15:59 2001
@@ -75,7 +75,7 @@
 <LI><A HREF="#2_4_3">Make sure Lilo knows about the new kernel</A></LI>
 </UL>
 <LI><A HREF="#testinstall">Testing to see if install succeeded</A></LI>
-<LI><A HREF="#2_6">Links to other sections</A></LI>
+<LI><A HREF="#2_6">Where to go from here</A></LI>
 </UL>
 <B><A HREF="#setup">Configuration</A></B>
 <UL>
@@ -148,6 +148,7 @@
 <LI><A HREF="#filters">Filtering rules for IPSEC packets</A></LI>
 <UL>
 <LI><A HREF="#through">IPSEC through the gateway</A></LI>
+<LI><A HREF="#ipsec_only">Preventing non-IPSEC traffic</A></LI>
 <LI><A HREF="#unknowngate">Filtering packets from unknown gateways</A></LI>
 </UL>
 <LI><A HREF="#otherfilter">Other packet filters</A></LI>
@@ -188,6 +189,9 @@
 <LI><A HREF="#statusinfo">Status information</A></LI>
 </UL>
 <LI><A HREF="#pluto.problems">Pluto problem hints</A></LI>
+<UL>
+<LI><A HREF="#gdb.pluto">Using GDB on Pluto</A></LI>
+</UL>
 <LI><A HREF="#ifconfig">ifconfig reports for KLIPS debugging</A></LI>
 <LI><A HREF="#testgates">Testing between security gateways</A></LI>
 <LI><A HREF="#c.guide">Claudia's guide</A></LI>
@@ -233,8 +237,7 @@
 <LI><A HREF="#kernel">Other 2.0.x Intel Kernels</A></LI>
 <LI><A HREF="#2.2">2.2 and 2.4 Kernels</A></LI>
 </UL>
-<LI><A HREF="#otherdist">Intel Linux distributions other than Redhat 
-5.x and 6.x</A></LI>
+<LI><A HREF="#otherdist">Intel Linux distributions other than Redhat</A></LI>
 <UL>
 <LI><A HREF="#rh7">Redhat 7.0</A></LI>
 <LI><A HREF="#suse">SuSE Linux</A></LI>
@@ -264,7 +267,7 @@
 <LI><A HREF="#patch.interop">Patches to extend interoperability</A></LI>
 <LI><A HREF="#interop.problem">Interoperability problems</A></LI>
 <UL>
-<LI><A HREF="#noDES">Systems that want to use DES</A></LI>
+<LI><A HREF="#noDES">Systems that want to use single DES</A></LI>
 </UL>
 <LI><A HREF="#otherpub">Interop HowTo documents</A></LI>
 <LI><A HREF="#mail.interop">Interoperation with specific products</A></LI>
@@ -278,6 +281,8 @@
 <LI><A HREF="#Raptor">Raptor Firewall</A></LI>
 <LI><A HREF="#gauntlet">Gauntlet firewall GVPN</A></LI>
 <LI><A HREF="#checkpoint">Checkpoint Firewall-1</A></LI>
+<LI><A HREF="#redcreek">Redcreek Ravlin</A></LI>
+<LI><A HREF="#sentinel">SSH Sentinel</A></LI>
 <LI><A HREF="#Fsecure">F-Secure VPN for Windows</A></LI>
 <LI><A HREF="#watchguard">Watchguard</A></LI>
 <LI><A HREF="#Xedia">Xedia Access Point/QVPN</A></LI>
@@ -495,6 +500,8 @@
 <LI><A HREF="#old_to_new">Can different FreeS/WAN versions talk to each 
 other?</A></LI>
 <LI><A HREF="#versions">Does FreeS/WAN run on my version of Linux?</A></LI>
+<LI><A HREF="#versions">Does FreeS/WAN run on the latest kernel version?</A>
+</LI>
 <LI><A HREF="#versions">Can I modify FreeS/WAN to ...?</A></LI>
 <LI><A HREF="#versions">Can I contribute to the project?</A></LI>
 <LI><A HREF="#versions">Is there detailed design documentation?</A></LI>
@@ -502,6 +509,7 @@
 <LI><A HREF="#versions">Compilation problems</A></LI>
 <UL>
 <LI><A HREF="#versions">gmp.h: No such file or directory</A></LI>
+<LI><A HREF="#versions">... virtual memory exhausted</A></LI>
 </UL>
 <LI><A HREF="#versions">Life's little mysteries</A></LI>
 <UL>
@@ -513,6 +521,8 @@
 <LI><A HREF="#versions">The firewall ate my packets!</A></LI>
 <LI><A HREF="#versions">Dropped connections</A></LI>
 <LI><A HREF="#versions">TCPdump on the gateway shows strange things</A></LI>
+<LI><A HREF="#versions">Traceroute does not show anything between the 
+gateways</A></LI>
 </UL>
 <LI><A HREF="#versions">Testing in stages</A></LI>
 <UL>
@@ -530,15 +540,22 @@
 <LI><A HREF="#versions">Interpreting error messages</A></LI>
 <UL>
 <LI><A HREF="#versions">SIOCADDRT:Network is unreachable</A></LI>
+<LI><A HREF="#versions">ipsec_setup: Fatal error, kernel appears to 
+lack KLIPS</A></LI>
 <LI><A HREF="#versions">Connection names in Pluto error messages</A></LI>
 <LI><A HREF="#versions">Pluto: ... can't orient connection</A></LI>
 <LI><A HREF="#versions">Pluto: ... no connection is known</A></LI>
+<LI><A HREF="#versions">Pluto: ... no suitable connection ...</A></LI>
+<LI><A HREF="#versions">Pluto: ... no connection has been authorized</A></LI>
 <LI><A HREF="#versions">Pluto: ... OAKLEY_DES_CBC is not supported.</A></LI>
 <LI><A HREF="#versions"> Pluto: ... no acceptable transform</A></LI>
 <LI><A HREF="#versions">ECONNREFUSED error message</A></LI>
 <LI><A HREF="#versions">ipsec_setup: Cannot adjust kernel flags</A></LI>
 <LI><A HREF="#versions">... trouble writing to /dev/ipsec ... SA 
 already in use</A></LI>
+<LI><A HREF="#versions">... ignoring ... payload</A></LI>
+<LI><A HREF="#versions">ipsec_setup: ... interfaces ... and ... share 
+address ...</A></LI>
 </UL>
 <LI><A HREF="#versions">Can I ...</A></LI>
 <UL>
@@ -551,13 +568,18 @@
 net?</A></LI>
 <LI><A HREF="#versions">Can I use Quality of Service routing with 
 FreeS/WAN?</A></LI>
+<LI><A HREF="#versions">Can I recognise dead tunnels and shut them down?</A>
+</LI>
+<LI><A HREF="#versions">Can I build tunnels over a demand-dialed link?</A>
+</LI>
 <LI><A HREF="#PKIcert">Does FreeS/WAN support X.509 or other PKI 
 certificates?</A></LI>
 <LI><A HREF="#PKIcert">Does FreeS/WAN support Radius or other user 
 authentication?</A></LI>
-<LI><A HREF="#noDES">Does FreeS/WAN support single DES encryption?</A></LI>
+<LI><A HREF="#noDES.faq">Does FreeS/WAN support single DES encryption?</A>
+</LI>
 </UL>
-<LI><A HREF="#DESonly">Why don't you restrict the mailing list to 
+<LI><A HREF="#noDES.faq">Why don't you restrict the mailing lists to 
 reduce spam?</A></LI>
 </UL>
 <HR>
@@ -602,7 +624,7 @@
 <UL>
 <LI><A href="#KLIPS">KLIPS</A> (kernel IPSEC) implements AH, ESP, and 
 packet handling within the  kernel</LI>
-<LI><A href="#pluto">Pluto</A> (an IKE daemon) implements IKE, 
+<LI><A href="#Pluto">Pluto</A> (an IKE daemon) implements IKE, 
 negotiating connections with other  systems</LI>
 <LI>various scripts provide an adminstrator's interface to the 
  machinery</LI>
@@ -633,7 +655,7 @@
 flexible and can be used to secure nearly any type of Internet traffic. 
 Two applications, however, are extremely widespread:</P>
 <UL>
-<LI>a <A href="#VPN">Virtual Private Network</A>, or VPN, allows 
+<LI>a <A href="#vpn">Virtual Private Network</A>, or VPN, allows 
 multiple  sites to communicate securely over an insecure Internet by 
 encrypting all  communication between the sites.</LI>
 <LI>&quot;Road Warriors&quot; connect to the office from home, or perhaps from a 
@@ -708,7 +730,8 @@
 <LI>If Network Address Translation (NAT) is applied between the two 
 IPSEC  Gateways, this breaks IPSEC. IPSEC authenticates packets on an 
 end-to-end  basis, to ensure they are not altered en route. NAT 
-rewrites packets as  they go by.</LI>
+rewrites packets as  they go by. See our <A href="#NAT">firewalls</A>
+ document for details.</LI>
 </UL>
 <P> In most situations, however, FreeS/WAN supports road warrior 
 connections just fine.</P>
@@ -721,7 +744,7 @@
 .  We hope this will go some distance toward creating a secure 
 Internet, an environment where message privacy is the default. See our <A
 href="politics.html">history and politics of cryptography</A> section 
-for discussion</P>
+for discussion.</P>
 <P> Both systems pick up the authentication information they need from 
 the <A href="glossary.html#DNS.gloss">DNS</A> (domain name service), 
 the service they already use to look up IP addresses. Of course the 
@@ -731,8 +754,9 @@
 encrypt, and encrypt whatever they can. Whether they also accept 
 unencrypted communication is a policy decision the administrator can 
 make.</P>
-<P> A draft document giving most of the <A href="opportunism.txt">
-details</A> of how we plan to implement this is available.</P>
+<P> A draft document giving most of the details of how we plan to 
+implement this has been posted to the mailing list. See <A href="#applied">
+links</A> below.</P>
 <P> Only one current product we know of implements a form of 
 opportunistic encryption. <A href="#ssmail">Secure sendmail</A> will 
 automatically encrypt server-to-server mail transfers whenever possible.</P>
@@ -873,8 +897,12 @@
 <LI><A href="ftp://ftp.net.lut.ac.uk/freeswan">the UK</A></LI>
 <LI><A href="http://storm.alert.sk/comp/mirrors/freeswan/">Slovak 
  Republic</A></LI>
+<LI><A href="http://the.wiretapped.net/security/vpn-tunnelling/freeswan/">
+Australia</A></LI>
 <LI><A href="http://freeswan.technolust.cx/">technolust</A></LI>
 <LI>Ivan Moore's <A href="http://snowcrash.tdyc.com/freeswan/">site</A></LI>
+<LI>the <A href="http://www.cryptoarchive.net/">Crypto Archive</A> on 
+the <A href="http://www.securityportal.com/"> Security Portal</A> site </LI>
 </UL>
 <H4><A name="munitions">The &quot;munitions&quot; archive of Linux crypto software</A>
 </H4>
@@ -888,12 +916,17 @@
 </UL>
 <P> Any of those will have a list of other &quot;munitions&quot; mirrors. </P>
 <H3><A name="archives">Archives of the project mailing list</A></H3>
+ Until quite recently, there was only one FreeS/WAN mailing list, and 
+archives of it were: 
 <UL>
 <LI><A href="http://www.sandelman.ottawa.on.ca/linux-ipsec">Canada</A></LI>
 <LI><A href="http://www.nexial.com">Holland</A></LI>
 </UL>
-<P> The two archives use completely different search engines. You might 
-want to try both.</P>
+ The two archives use completely different search engines. You might 
+want to try both.
+<P> More recently we have expanded to five lists, each with its own 
+archive. See <A href="mail.html">details</A> elsewhere in the 
+documentation. </P>
 <P><A href="mail.html">More information</A> on this and other mailing 
 lists.</P>
 <H2><A name="products">Products containing FreeS/WAN</A></H2>
@@ -915,8 +948,8 @@
 <LI><A href="http://www.trustix.net/">Trustix Secure Linux</A> (Norway) </LI>
 </UL>
 <P> For distributions which do not include FreeS/WAN and are not Redhat 
-6.x (which we develop and test on), there is additional information in 
-our <A href="#otherdist">compatibility</A> section.</P>
+(which we develop and test on), there is additional information in our <A
+href="#otherdist">compatibility</A> section.</P>
 <P> We would appreciate hearing of other distributions using FreeS/WAN.</P>
 <H3><A name="fw_dist">Firewall distributions</A></H3>
  FreeS/WAN is also included in, or available for, more specialised 
@@ -956,6 +989,9 @@
 <LI><A href="http://www.merilus.com">Merilus</A> use FreeS/WAN in their 
 Gateway Guardian firewall  product and in their <A href="http://www.merilus.com/firecard/index.shtml">
 Firecard</A> product, a Linux firewall on a PCI card. </LI>
+<LI><A href="http://www.kyzo.com/">Kyzo</A> have a &quot;pizza box&quot; product 
+line with various types of  server, all running from flash. One of them 
+is an IPSEC/PPTP VPN server. </LI>
 </UL>
 <P>We would appreciate hearing of other products using FreeS/WAN.</P>
 <H2><A name="docs">Documentation</A></H2>
@@ -1064,7 +1100,7 @@
 <UL>
 <LI>kernel programmer Richard Guy Briggs on <A href="http://www.sandelman.ottawa.on.ca/linux-ipsec/html/2001/02/msg00435.html">
  redesign of KLIPS</A></LI>
-<LI>technical lead Henry Spencer on <A href="http://www.sandelman.ottawa.on.ca/linux-ipsec/html/2001/02/msg00381.html">
+<LI>technical lead Henry Spencer on <A href="http://www.sandelman.ottawa.on.ca/linux-ipsec/html/2001/05/msg00084.html">
  opportunistic encryption</A></LI>
 </UL>
  Both documents are works in progress and may be revised. Check the 
@@ -1155,16 +1191,23 @@
 <P> If you have not done this before, you will need to read the <A href="http://metalab.unc.edu/LDP/HOWTO/Kernel-HOWTO.html">
 Kernel HowTo</A>.</P>
 <H3><A name="choosek">Choosing a kernel</A></H3>
-<H4><A name="2.2">2.2.x for most users</A></H4>
-<P> Most users should run the most stable available series of Linux 
-production <A href="#kernel">kernels</A>. At time of writing (February 
-2001), we recommend the 2.2 series for most users. The latest version 
-is 2.2.18.</P>
+<H4><A name="2.2">2.2.19 for many users</A></H4>
+<P> Many users can continue to run kernels from the 2.2 series of Linux 
+production <A href="#kernel">kernels</A>. </P>
+<P> At time of writing (June 2001), the latest version is 2.2.19. If 
+you are going to use a 2.2 kernel, we <STRONG>strongly recommend</STRONG>
+ upgrading to 2.2.19 since: </P>
+<UL>
+<LI>It has a number of small security fixes not found in earlier 
+kernels. </LI>
+<LI>There have been changes in some kernel file formats that make it 
+difficult to compile a current FreeS/WAN with earlier kernels. See the <A
+href="mail.html">mailing list archives</A> for details if needed. </LI>
+</UL>
 <H4><A name="2.4">2.4.x is possible</A></H4>
- The new 2.4 series of kernels were first released in January 2001 and 
-are currently (mid-February) at 2.4.2. FreeS/WAN does work on these 
-kernels, but for production use we suggest waiting a while yet. 
-<P> On the other hand, 2.4 has new firewalling code called <A href="http://netfilter.kernelnotes.org/unreliable-guides/index.html">
+ The new 2.4 series of kernels began in January 2001 and are currently 
+(early June) at 2.4.5. FreeS/WAN is known to work on 2.4.5. 
+<P> 2.4 has new firewalling code called <A href="http://netfilter.kernelnotes.org/unreliable-guides/index.html">
 netfilter</A>. This may provide good reasons to move to 2.4, especially 
 on for gateway machines. </P>
 <H4><A name="2.0">2.0.x should still work</A></H4>
@@ -1182,10 +1225,10 @@
 for use by kernel developers. By convention, production kernels have an 
 even second digit in the version number (2.0, 2.2, 2.4) and development 
 kernels have an odd digit there (2.1, 2.3, 2.5). 
-<P> At time of writing (February 2001, shortly after the release of 
-2.4), no more 2.3 kernels are being produced and the 2.5 series has not 
-been started yet, so just now development kernels are not an issue. No 
-doubt a 2.5 series will be started in the next few months. </P>
+<P> At time of writing, no more 2.3 kernels are being produced and the 
+2.5 series has not been started yet, so just now development kernels 
+are not an issue. No doubt a 2.5 series will be started in the next few 
+months. </P>
 <P><STRONG> Development kernels are not intended for production use</STRONG>
 . They change often and include new code which has not yet been 
 thoroughly tested. <STRONG>This regularly breaks things, including 
@@ -1472,7 +1515,7 @@
 </UL>
 <P> Of course any status information at this point should be 
 uninteresting since you have not yet configured connections.</P>
-<H2><A NAME="2_6">Links to other sections</A></H2>
+<H2><A NAME="2_6">Where to go from here</A></H2>
 <P>See the following section for information on <A href="config.html">
 configuring connections</A>.</P>
 <P>Alternately, you might want to look at background material on the <A href="ipsec.html">
@@ -1965,14 +2008,6 @@
 been removed in FreeS/WAN 1.9. However, if the other end of the tunnel 
 is an older version, the restriction will still apply there, so some 
 caution is still required. </P>
-<P>The <VAR>conn %default</VAR> section shipped in our example file 
-includes  parameters for manual keying. These are <STRONG>completely 
- insecure</STRONG>, intended only for testing. We recommend you leave 
-these  in place during testing since it is sometimes useful to be able 
-to test with  manual keying. Once testing is done, however, delete the 
-test keys or ensure  that they are commented out with # characters. 
-Production use of manual  keying is not recommended, but is possible 
-and is described in a <A href="#prodman"> later section</A>.</P>
 <H3><A name="edit.conn">Editing a connection description</A></H3>
 <P>Edit our example connection to match what you want to do.  Rename it 
  appropriately for the connection you would like to build: 
@@ -2038,9 +2073,9 @@
 The  file syntax allows names to be used, but this creates an 
 additional risk. If  someone can subvert the DNS service, then they can 
 redirect packets whose  addresses are looked up via that service.</P>
-<P>Many of the variables in this file come in pairs such as 
-&quot;leftsubnet: and  &quot;rightsubnet&quot;, one for each end of the connection. 
-The variables on the left  side are:</P>
+<P> Many of the variables in this file come in pairs such as 
+&quot;leftsubnet: and &quot;rightsubnet&quot;, one for each end of the connection. The 
+variables on the left side are:</P>
 <DL>
 <DT>left</DT>
 <DD>The gateway's external interface, the one it uses to talk to the 
@@ -2068,14 +2103,16 @@
 <DD>Addresses for the machines which left is protecting. 
 <UL>
 <LI>Often something like 101.202.203.0/24 to indicate that a subnet 
- resides behind left.</LI>
+ resides behind left. Often this subnet will be directly connected  to 
+left, but this not necessary. The only requirement is that left  must 
+be able to route to it.</LI>
 <LI>If you omit the leftsubnet line, then left is both the security 
  gateway and the only client on that end.</LI>
 </UL>
  For some applications, you may want to create two connections, one to 
  protect traffic from the subnet behind left and another to protect 
  traffic from the left gateway itself. This takes two connection 
- descriptions.</DD>
+ descriptions. See <A href="#multitunnel">below</A>.</DD>
 <DT>leftfirewall</DT>
 <DD>Set to &quot;yes&quot; if there is a firewall in play that suppresses 
  forwarding, for example if a subnet behind left uses non-routable 
@@ -2332,19 +2369,166 @@
 Practical Configurations</A> document also has an example  of using RSA 
 authentication for road warriors.</P>
 <H3><A name="oppex">Opportunistic encryption</A></H3>
-<P> This section is currently just a placeholder for the opportunistic 
-encryption documentation I'll write when the design has solidified 
-somewhat.</P>
-<H4><A name="dnskey">Putting public keys in DNS</A></H4>
-<P>Release 1.4 had the first experimental code to support fetching 
-public  key information from the other system's DNS entries. Even in 
-1.6, this is  still experimental code. You cannot trust it for 
-production use until</P>
-<UL>
-<LI>both our code is much better tested (you can help with that!)</LI>
-<LI>and <A href="#SDNS">secure DNS</A> is widely deployed</LI>
-</UL>
-<P>The relevant lines in the config file would look like this:</P>
+ We use the term <A href="glossary.html">opportunistic encryption</A>
+ for encryption which does not rely on any pre-arranged connection, 
+hence does not require that the administrators of the two gateways 
+involved communicate with each other (for example, to exchange keys) 
+before their systems can create a secure connection. 
+<P> The idea is that each gateway check the destinations of outgoing 
+packets, see if an encrypted connection is possible and, if so, take 
+the opportuntity to encrypt. The opportunity will exist whenever the 
+admins on both ends have set their systems up for opportunistic 
+encryption. </P>
+<P> This makes encryption the default behaviour, and could greatly 
+increase the overall security of the Internet if it were widely enough 
+adopted. See our documents: </P>
+<DL>
+<DT><A href="politics.html">history and politics</A></DT>
+<DD>for the reasons we want to do this </DD>
+<DT><A href="#traffic.resist">IPSEC protocols</A></DT>
+<DD>for discussion of the general principle of encrypting as much as 
+possible </DD>
+</DL>
+<P> The gateways must be able to authenticate each other for IPSEC to 
+be secure. For opportunistic encryption, we rely on the domain name 
+system, <A href="glossary.html">DNS</A>, to provide the RSA keys needed 
+for this authentication.  Note, that currently this is not entirely 
+secure because <STRONG>the DNS mechanism it relies on is not fully 
+secure</STRONG>. Eventually, as <A href="#SDNS">secure DNS</A> becomes 
+widely deployed, this will change. </P>
+<H4><A name="opp.status">Status</A></H4>
+ The team have been working on this for some time, and testing 
+internally. As of late May, 2001 this code is ready for wider testing. <STRONG>
+We encourage everyone to try it.</STRONG>
+<P> The main documentation items so far are: </P>
+<UL>
+<LI>an <A href="opportunism.howto">Opportunism HowTo</A> by Pluto 
+programmer Hugh Redelmeier </LI>
+<LI>a design document by Hugh and technical lead Henry Spencer. A <A href="#applied">
+link</A> to this is in our introduction. </LI>
+</UL>
+ I am playing catch up; HTML documentation so far is neither complete 
+nor particularly clear. What I have so far is below. 
+<P> Note that both software and documentation for this are changing 
+quickly. You may want the latest snapshot for opportunism experiments. </P>
+<P><STRONG> We do not yet recommend this code for production use</STRONG>
+. You should still protect your critical data with explicitly 
+configured IPSEC tunnels, rather than relying on opportunistic for 
+everything at this stage. </P>
+<H4><A name="dns.background">Some DNS background</A></H4>
+<P> Opportunism requires that the gateway systems be able to fetch 
+public keys, and other IPSEC-related information, from each other's DNS 
+(domain name service) records. </P>
+<P> DNS is a distributed database that maps names to IP addresses and 
+vice versa. A system named gateway.example.com with IP address 
+10.20.30.40 should have at least two DNS records: </P>
+<DL>
+<DT>gateway.example.com. IN A 10.20.30.40 </DT>
+<DD>used to look up the name and get an IP address </DD>
+<DT>40.30.20.10.in-addr.arpa. IN PTR gateway.example.com. </DT>
+<DD>used for reverse lookups, looking up the name associated with an 
+address. Notice that the digits here are in reverse order; the actual 
+address is 10.20.30.40 but we use 40.30.20.10 here. </DD>
+</DL>
+ Some syntactic details are: 
+<UL>
+<LI>the IN indicates that these records are for <STRONG>In</STRONG>
+ternet addresses </LI>
+<LI>The final periods in '.com.' and '.arpa.' are required. They 
+indicate the root of the domain name system. </LI>
+</UL>
+ For much more detail, see the <A href="http://www.linuxdoc.org/LDP/nag2/index.html">
+Linux Network Administrator's Guide</A> or a DNS <A href="#DNS.book">
+reference book</A>. 
+<P> The capitalised strings after IN indicate the type of record. 
+Possible types include: </P>
+<UL>
+<LI><STRONG>A</STRONG>ddress </LI>
+<LI><STRONG>P</STRONG>oin<STRONG>T</STRONG>e<STRONG>R</STRONG></LI>
+<LI><STRONG>C</STRONG>anonical <STRONG>NAME</STRONG>, records to 
+support aliasing,  multiple names for one address </LI>
+<LI><STRONG>MX</STRONG>, used in mail handling </LI>
+<LI><STRONG>SIG</STRONG>nature, used in <A href="#SDNS">secure DNS</A></LI>
+<LI><STRONG>KEY</STRONG>, used in <A href="#SDNS">secure DNS</A></LI>
+<LI><STRONG>T</STRONG>e<STRONG>XT</STRONG>, a multi-purpose record type </LI>
+</UL>
+ To set up for opportunistic encryption, you add some KEY and TXT 
+records to your DNS data. 
+<H4><A name="dnskey">Putting IPSEC information in DNS</A></H4>
+ There are two types of DNS record to be added: 
+<UL>
+<LI>each gateway must have a KEY record which other gateways can query 
+to fetch its RSA authentication key </LI>
+<LI>any client whose communications are to be protected by a gateway 
+must have a TXT record pointing to that machine as an authorised IPSEC 
+gateway </LI>
+</UL>
+<A href="manpage.d/ipsec_rsasigkey.8.html"> ipsec_rsasigkey(8)</A>
+ provides the key in DNS record format as a comment. You need to cut 
+and paste the comment from <A href="manpage.d/ipsec.secrets.5.html">
+ipsec.secrets(5)</A> (or wherever you have the private key) into the 
+appropriate place in the DNS records. 
+<P> There are two ways to handle this, depending on whether or not you 
+control the reverse lookup (in-addr.arpa.) sections of the DNS files 
+for your gateway. You must have control of the reverse DNS information 
+for clients or this cannot work at all. </P>
+<H5>If you control the gateway's reverse map</H5>
+ If you control the gateway's reverse map, you just add a KEY record 
+there. Here is an example, with many characters of the key itself left 
+out: 
+<PRE>
+40.30.20.10.in-addr.arpa. IN KEY 0x4200 4 1 AQNJjkKlIk9...nYyUkKK8
+</PRE>
+ This allows lookups on the IP address of the gateway to retrieve the 
+key. 
+<P> A client that wishes to be protected by Opportunistic Encryption 
+must include a special TXT record in its reverse-map. If you control 
+the gateway's reverse map, example client records would look like this: </P>
+<PRE>
+42.42.42.10.in-addr.arpa. IN PTR deepthought.example.com.
+42.42.42.10.in-addr.arpa. IN TXT &quot;X-IPsec-Server(10)=10.20.30.40 AQNJjkKlIk9...nYyUkKK8&quot;
+</PRE>
+ which can also be written as just: 
+<PRE>
+42.42.42.10.in-addr.arpa. IN PTR deepthought.example.com.
+                          IN TXT &quot;X-IPsec-Server(10)=10.20.30.40 AQNJjkKlIk9...nYyUkKK8&quot;
+</PRE>
+ This provides the IP address of the security gateway and the public 
+key which the gateway will use to authenticate itself. This is the 
+preferred variant. Using it, the remote system does one lookup and gets 
+everything it needs for IKE negotiations. 
+<H5>If you <EM>don't</EM> control the gateway's reverse map</H5>
+ The approach must be slightly different if you do not have control 
+over the contents of the reverse map for your gateway. Perhaps your ISP 
+controls that, and provides no way for you to put data into their maps. 
+Without that, you cannot set your gateway up to respond to incoming 
+opportunistic requests (short of changing ISPs, which you might 
+consider). 
+<P> However, suppose a friend over at example.org will let you put 
+things in their maps. That will allow you to set your gateway up to 
+handle opportunistic connections for which it is the initiator. </P>
+<P> You still need to be able to put data in the reverse map for your 
+clients. However, that data is slightly different: </P>
+<PRE>
+42.42.42.10.in-addr.arpa. IN PTR deepthought.example.com.
+                          IN TXT &quot;X-IPsec-Server(10)=something.example.org&quot;
+</PRE>
+ Over at example.org, your friend inserts these lines in the DNS data 
+files: 
+<PRE>
+something.example.org. IN A 10.20.30.40
+                       IN KEY 0x4200 4 1 AQNJjkKlIk9...nYyUkKK8
+</PRE>
+ Your gateway must identify itself in IKE as something.example.org, not 
+as gateway.example.com. You set that up via <VAR>leftid=</VAR> or <VAR>
+rightid=</VAR> entries in <A href="manpage.d/ipsec.conf.5.html">
+ipsec.conf(5)</A>. 
+<P> With this arrangement, the remote gateway does two lookups. First 
+it does a reverse lookup on the client IP address and finds the gateway 
+name  &quot;something.example.org&quot;. Then it looks up that name to get the IP 
+address and key for the gateway. </P>
+<H4><A name="opp.config">ipsec.conf entries for opportunism</A></H4>
+ The relevant lines in the config file would look like this:
 <PRE>
         leftid=@gateway.example.com
         leftrsasigkey=%dns
@@ -2603,13 +2787,13 @@
 <H3><A name="tcpdump">Testing with tcpdump</A></H3>
 <P> To verify that all is working, run tcpdump(8) on a machine which 
 can listen to the traffic between the gateways.</P>
-<P> This really has to be done from a third machine, not from one of 
-the gateways. On the gateways you'll see packets at intermediate stages 
-of processing and the result will be confusing. Also, both tcpdump(8) 
-and nmap(8) use the libpcap library. Some versions of that library 
-(e.g. the ones that shipped with Redhat 5) do not recognise ipsec? 
-devices and will generate &quot;bad physical medium&quot; error messages if you 
-try to use it with them.</P>
+<P> This is most easily done from a third machine, rather than from one 
+of the gateways. On the gateways you may see packets at intermediate 
+stages of processing and the result may be confusing. </P>
+<P> If the results make no sense at all, or you see &quot;bad physical 
+medium&quot; error messages, you probably have an outdated version of 
+tcpdump(8) that does not handle IPSEC at all. See our <A href="#tcpdump">
+FAQ</A>.</P>
 <P> The packets should, except for some of the header information, be 
 utterly unintelligible. The output of good encryption looks exactly 
 like random noise.</P>
@@ -3085,12 +3269,12 @@
  what type of software is sending the messages. If the settings are 
  &quot;daemon.error&quot; as in our example, then syslogd treats the messages as 
  error messages from a daemon. </DD>
-<P>Note that <A href="#pluto">Pluto</A> does not currently pay 
+<P>Note that <A href="#Pluto">Pluto</A> does not currently pay 
  attention to this variable. The variable controls setup messages  only.</P>
 <DT>klipsdebug=</DT>
 <DD>Debug settings for <A href="#KLIPS">KLIPS</A>.</DD>
 <DT>plutodebug=</DT>
-<DD>Debug settings for <A href="#pluto">Pluto</A>.</DD>
+<DD>Debug settings for <A href="#Pluto">Pluto</A>.</DD>
 <DT>... for both the above DEBUG settings</DT>
 <DD>Normally, leave empty as shown above for no debugging output.
 <BR> Use &quot;all&quot; for maximum information.
@@ -3108,7 +3292,7 @@
  boot time. Useful for testing, but not for long term use. Connections 
  which are automatically started should also be automatically  re-keyed.</DD>
 <DT>pluto=yes</DT>
-<DD>Whether to start <A href="#pluto">Pluto</A> when ipsec startup is 
+<DD>Whether to start <A href="#Pluto">Pluto</A> when ipsec startup is 
  done.
 <BR> This parameter is optional and defaults to &quot;yes&quot; if not present. </DD>
 <P>&quot;yes&quot; is strongly recommended for production use so that the keying 
@@ -3227,6 +3411,47 @@
 functionality. You cannot use them as gateways with a subnet behind 
 them. To get that functionality, you must upgrade to Windows 2000 
 server or the commercially available PGP products. </P>
+<H4><A name="advroute">One tunnel plus advanced routing</A></H4>
+ It is also possible to use the new routing features in 2.2 and later 
+kernels to avoid most needs for multple tunnels. Here is one mailing 
+list message on the topic: 
+<PRE>
+Subject: Re: linux-ipsec: IPSec packets not entering tunnel?
+   Date: Mon, 20 Nov 2000
+   From: Justin Guyett &lt;jfg@sonicity.com&gt;
+
+On Mon, 20 Nov 2000, Claudia Schmeing wrote:
+
+&gt; Right                                                         Left
+&gt;                      &quot;home&quot;                &quot;office&quot;
+&gt; 10.92.10.0/24 ---- 24.93.85.110 ========= 216.175.164.91 ---- 10.91.10.24/24
+&gt;
+&gt; I've created all four tunnels, and can ping to test each of them,
+&gt; *except* homegate-officenet.
+
+I keep wondering why people create all four tunnels.  Why not route
+traffic generated from home to 10.91.10.24/24 out ipsec0 with iproute2?
+And 99% of the time you don't need to access &quot;office&quot; directly, which
+means you can eliminate all but the subnet&lt;-&gt;subnet connection.
+</PRE>
+ and FreeS/WAN technical lead Henry Spencer's comment: 
+<PRE>
+&gt; I keep wondering why people create all four tunnels.  Why not route
+&gt; traffic generated from home to 10.91.10.24/24 out ipsec0 with iproute2?
+
+This is feasible, given some iproute2 attention to source addresses, but
+it isn't something we've documented yet... (partly because we're still
+making some attempt to support 2.0.xx kernels, which can't do this, but
+mostly because we haven't caught up with it yet).
+
+&gt; And 99% of the time you don't need to access &quot;office&quot; directly, which
+&gt; means you can eliminate all but the subnet&lt;-&gt;subnet connection.
+
+Correct in principle, but people will keep trying to ping to or from the
+gateways during testing, and sometimes they want to run services on the
+gateway machines too.
+
+</PRE>
 <H3><A name="biggate">Many tunnels from a single gateway</A></H3>
 <P> FreeS/WAN allows a single gateway machine to build tunnels to many 
 others. There may, however, be some problems for large numbers as 
@@ -3534,31 +3759,46 @@
 <PRE>        ipsec setup restart</PRE>
 <P>Again, this breaks any existing connections.</P>
 <H3><A name="unencrypted">Unencrypted tunnels</A></H3>
-<P> Sometimes you will want to create a tunnel without encryption. The 
-IPSEC protocols provide two ways to do this, either using <A href="#AH">
-AH</A> without <A href="#ESP">ESP</A> or using ESP with null 
-encryption. With Linux FreeS/WAN, these are currently supported for 
-manually keyed connections, but not with automatic keying, so we'll 
-look at other solutions here.</P>
+<P> Sometimes you might want to create a tunnel without encryption. 
+Often this is a bad idea, even if you have some data which need not be 
+private. See this <A href="#traffic.resist">discussion</A>. </P>
+<P> The IPSEC protocols provide two ways to do build such tunnels, </P>
+<UL>
+<LI>using <A href="#AH">AH</A> without <A href="#ESP">ESP</A></LI>
+<LI>using ESP with null encryption. </LI>
+</UL>
+ Linux FreeS/WAN allows AH-only for manually keyed connections, but not 
+with automatic keying, and does not support null encryption, so we'll 
+look at other solutions here.
 <P> One situation in which this comes up is when otherwise some data 
 would be  encrypted twice. Alice wants a secure tunnel from her machine 
 to Bob's.  Since she's behind one security gateway and he's behind 
 another, part of the  tunnel that they build passes through the tunnel 
 that their site admins have  built between the gateways. All of Alice 
 and Bob's messages are encrypted  twice.</P>
-<P>There are several ways to handle this.</P>
+<P> There are several ways to handle this.</P>
 <UL>
 <LI>Just accept the overhead of double encryption. The site admins 
-might  choose this if policy says encrypt everything, if they don't 
-entirely  trust Alice and Bob, or if they don't feel the saved cycles 
-are worth  the time they'd need to build a non-encrypted tunnel for 
-Alice and Bob's  packets.</LI>
+might  choose this if any of the following apply: 
+<UL>
+<LI>policy says encrypt everything (usually, it should) </LI>
+<LI>they don't entirely trust Alice and Bob (usually, if they don't 
+have to, they  shouldn't) </LI>
+<LI>if they don't feel the saved cycles are worth the time they'd need 
+to  build a non-encrypted tunnel for Alice and Bob's packets (often, 
+they aren't) </LI>
+</UL>
+</LI>
 <LI>Use a plain IP-in-IP tunnel. These are not well documented. A good 
  starting point is in the Linux kernel source tree, in 
  /usr/src/linux/drivers/net/README.tunnel.</LI>
-<LI>Use a manually-keyed AH-only tunnel. This is recommended over ESP 
-with  null encryption.</LI>
+<LI>Use a manually-keyed AH-only tunnel.</LI>
 </UL>
+<P> Note that if Alice and Bob want end-to-end security, they must 
+build a tunnel end-to-end between their machines or use some other 
+end-to-end tool such as PGP or SSL that suits their data. The only 
+question is whether the admins build some special unencrypted tunnel 
+for those already-encrypted packets. </P>
 <HR>
 <H1><A name="manpages">FreeS/WAN manual pages</A></H1>
 <P> The various components of Linux FreeS/WAN are of course documented 
@@ -3802,16 +4042,20 @@
 must allow UDP  500 and at least one of AH or ESP on the interface that 
 communicates with  the other gateway. </P>
 <H3><A name="through">IPSEC <EM>through</EM></A> the gateway</H3>
-<P>The preceeding paragraph deals with packets <EM>addressed to or sent 
-from  your gateway</EM>. It is a separate policy decision whether to 
-permit such  packets to pass <EM>through</EM> the gateway so that 
+<P> The preceeding paragraph deals with packets <EM>addressed to or 
+sent from  your gateway</EM>. It is a separate policy decision whether 
+to permit such  packets to pass <EM>through</EM> the gateway so that 
 client machines can  build end-to-end IPSEC tunnels of their own. This 
 may not be practical if  you are using <A href="#NAT">NAT (IP 
 masquerade)</A> on your gateway, and  may conflict with some corporate 
 security policies. Other than that, it is  likely a good idea.</P>
+<H3><A name="ipsec_only">Preventing non-IPSEC traffic</A></H3>
+ You can of course also filter <EM>everything but</EM> UDP port 500 and 
+ESP or AH to restrict traffic to IPSEC only, either for anyone 
+communicating with your host or just for specific partners. 
 <H3><A name="unknowngate">Filtering packets from unknown gateways</A></H3>
-<P>It is possible to use firewall rules to restrict UDP 500, ESP and AH 
- packets so that these packets are accepted only from known gateways. 
+<P> It is possible to use firewall rules to restrict UDP 500, ESP and 
+AH packets so that these packets are accepted only from known gateways. 
 This is  not strictly necessary since FreeS/WAN will discard packets 
 from unknown  gateways. You might, however, want to do it for any of a 
 number of reasons.  For example:</P>
@@ -3857,7 +4101,7 @@
 which can affect the  operation of FreeS/WAN or of diagnostic tools 
 commonly used with it. These  are discussed below.</P>
 <H3><A name="ICMP">ICMP filtering</A></H3>
-<P><A href="#icmp">ICMP</A> is the <STRONG>I</STRONG>nternet <STRONG>C</STRONG>
+<P><A href="#ICMP">ICMP</A> is the <STRONG>I</STRONG>nternet <STRONG>C</STRONG>
 ontrol <STRONG>M</STRONG>essage <STRONG>P</STRONG>rotocol. It is used 
 for messages between IP implementations themselves, whereas IP used is 
 used between the clients of those implementations. ICMP is, 
@@ -3969,9 +4213,15 @@
  Here you have a choice of techniques depending on whether you want to 
 make your client subnet visible to clients on the other end: 
 <UL>
-<LI>If you want to make them visible, then give the client subnet 
-addresses as the <VAR>leftsubnet=</VAR> parameter in the connection 
-description and 
+<LI>If you want the single gateway to behave like the two shown above, 
+with your clients hidden behind the NAT, then omit the <VAR>leftsubnet=</VAR>
+ parameter. It then defaults to the gateway address. Clients on the 
+other end then talk via the tunnel only to your gateway. The gateway 
+takes packets emerging from the tunnel, applies normal masquerading, 
+and forwards them to clients. </LI>
+<LI>If you want to make your client machines visible, then give the 
+client subnet addresses as the <VAR>leftsubnet=</VAR> parameter in the 
+connection description and 
 <DL>
 <DT>either </DT>
 <DD>set <VAR>leftfirewall=yes</VAR> to use the default <VAR>updown</VAR>
@@ -3987,11 +4237,6 @@
 client subnet addresses, although of course the encapsulating packets 
 use gateway addresses in their headers. Clients behind the right 
 security gateway see a route via that gateway to the left subnet.</P>
-<LI>If you want your clients hidden, then omit the <VAR>leftsubnet=</VAR>
- parameter. It then defaults to the gateway address. Clients on the 
-other end then talk via the tunnel only to your gateway. The gateway 
-takes packets emerging from the tunnel, applies normal masquerading, 
-and forwards them to clients. </LI>
 </UL>
 <H3><A name="nat_bad">NAT between gateways is problematic</A></H3>
 <P> We recommend not trying to build IPSEC connections which pass 
@@ -4220,7 +4465,7 @@
 # or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 # for more details.
 #
-# RCSID $Id: firewall.html,v 1.10.2.3 2001/03/15 00:12:35 henry Exp $
+# RCSID $Id: firewall.html,v 1.16 2001/05/02 20:56:27 sandy Exp $
 
 # check interface version
 case &quot;$PLUTO_VERSION&quot; in
@@ -4311,7 +4556,7 @@
 only to known receivers) </LI>
 </UL>
 </LI>
-<LI>let <A href="#pluto">Pluto</A> deal with IKE </LI>
+<LI>let <A href="#Pluto">Pluto</A> deal with IKE </LI>
 <LI>let <A href="#KLIPS">KLIPS</A> deal with ESP </LI>
 <LI>if necessary, filter incoming packets emerging from KLIPS. </LI>
 </UL>
@@ -4331,7 +4576,7 @@
 message</A>. </P>
 <P> Those scripts were based on David Ranch's scripts for his &quot;Trinity 
 OS&quot; for setting up a secure Linux. Check his <A href="http://www.ecst.csuchico.edu/~dranch/LINUX/index-linux.html">
-home page</A> for the latest version and for information on his <A href="#Ranch">
+home page</A> for the latest version and for information on his <A href="#ranch">
 book</A> on securing Linux. If you are going to base your firewalling 
 on Ranch's scripts, we recommend using his latest version, and sending 
 him any IPSEC modifications you make for incorporation into later 
@@ -4373,9 +4618,9 @@
 <H2><A name="info">Information available on your system</A></H2>
 <H3><A name="pages">man pages provided</A></H3>
 <DL>
-<DT>ipsec.conf(5)</DT>
+<DT><A href="manpage.d/ipsec.conf.5.html">ipsec.conf(5)</A></DT>
 <DD>Manual page for IPSEC configuration file.</DD>
-<DT>ipsec(8)</DT>
+<DT><A href="manpage.d/ipsec.8.html">ipsec(8)</A></DT>
 <DD>Primary man page for ipsec utilities.</DD>
 </DL>
 <P>Other man pages are on</P>
@@ -4399,7 +4644,7 @@
 <DD>Copious debugging info.</DD>
 </DL>
 <H2><A name="pluto.problems">Pluto problem hints</A></H2>
-<P>From a message posted to the mailing list Jan 14 2000 by Pluto 
+<P> From a message posted to the mailing list Jan 14 2000 by Pluto 
 developer  Hugh Redelmeier:</P>
 <PRE>
 Until ipsec auto and whack/pluto get fixed:
@@ -4423,6 +4668,33 @@
  Various error messages from Pluto are discussed in the <A href="#error">
 FAQ</A> and the <A href="manpage.d/ipsec_pluto.8.html">ipsec_pluto(8)</A>
  man page. 
+<H3><A name="gdb.pluto">Using GDB on Pluto</A></H3>
+ You may need to use the GNU degugger, gdb(1), on Pluto. This should be 
+necessary only in unusal cases, for example if you encounter a problem 
+which the Pluto developer cannot readily reproduce or if you are 
+modifying Pluto. 
+<P> Here are the Pluto developer's suggestions for doing this: </P>
+<PRE>
+Can you get a core dump and use gdb to find out what Pluto was doing
+when it died?
+
+To get a core dump, you will have to set dumpdir to point to a
+suitable directory (see ipsec.conf(5)).
+
+To get gdb to tell you interesting stuff:
+        $ script
+        $ cd dump-directory-you-chose
+        $ gdb /usr/local/lib/ipsec/pluto core
+        (gdb) where
+        (gdb) quit
+        $ exit
+
+The resulting output will have been captured by the script command in
+a file called &quot;typescript&quot;.  Send it to the list.
+
+Do not delete the core file.  I may need to ask you to print out some
+more relevant stuff.
+</PRE>
 <H2><A name="ifconfig">ifconfig reports for KLIPS debugging</A></H2>
 <P>From a mail message from our KLIPS developer:</P>
 <PRE>
@@ -5041,7 +5313,7 @@
 <PRE>        man 8 ipsec_tncfg</PRE>
 </DL>
 <H2><A name="pluto">Pluto key and connection management daemon</A></H2>
-<P><A href="#pluto"> Pluto</A> is our key management and negotiation 
+<P><A href="#Pluto"> Pluto</A> is our key management and negotiation 
 daemon. It lives in the pluto directory, along with its low-level user 
 utility, whack. </P>
 <P> There are no subdirectories. Documentation is a man page, <A href="manpage.d/ipsec_pluto.8.html">
@@ -5101,11 +5373,11 @@
 patchers and commenters there, especially the ones quoted below but 
  also various contributors we haven't quoted.</P>
 <H2><A name="spec">Implemented parts of the IPSEC Specification</A></H2>
-<P>In general, do not expect Linux FreeS/WAN to do everything yet. This 
-is a  work-in-progress and some parts of the IPSEC specification are 
-not yet  implemented.</P>
+<P> In general, do not expect Linux FreeS/WAN to do everything yet. 
+This is a work-in-progress and some parts of the IPSEC specification 
+are not yet implemented.</P>
 <H3><A name="in">In Linux FreeS/WAN</A></H3>
-<P>Things we do, as of version 1.9:</P>
+<P> Things we do, as of version 1.9:</P>
 <UL>
 <LI>key management methods 
 <DL>
@@ -5113,7 +5385,7 @@
 <DD>using keys stored in /etc/ipsec.conf</DD>
 <DT>automatically keyed</DT>
 <DD>Automatically negotiating session keys as required. All 
- connections are automatically re-keyed periodically. The <A href="#pluto">
+ connections are automatically re-keyed periodically. The <A href="#Pluto">
  Pluto</A> daemon implements this  using the <A href="#IKE">IKE</A>
  protocol.</DD>
 </DL>
@@ -5144,10 +5416,6 @@
 </LI>
 <LI>encryption transforms 
 <DL>
-<DT>null encryption (to use ESP as an authentication-only service) </DT>
-<DD>We implement this since the RFCs require it. Since it is  obviously 
-insecure, we disable it by default. It can be enabled  with a kernel 
-configuration option.</DD>
 <DT><A href="#DES">DES</A></DT>
 <DD>DES is in the source code since it is needed to implement  3DES, 
 but single DES is not made available to users because <A href="#desnotsecure">
@@ -5179,7 +5447,9 @@
 </LI>
 </UL>
 <P> All combinations of implemented transforms are supported. Note that 
-some  form of authentication is recommended whenever encryption is used.</P>
+some form of packet-level <STRONG>authentication is required whenever 
+encryption is used</STRONG>. Without it, the encryption will not be 
+secure.</P>
 <H3><A name="dropped">Deliberately ommitted</A></H3>
  We do not implement everything in the RFCs because some of those 
 things are insecure. See our discussions of avoiding <A href="#weak">
@@ -5187,16 +5457,17 @@
 <P>
 <P> Things we deliberately omit which are required in the RFCs are:</P>
 <UL>
+<LI>null encryption (to use ESP as an authentication-only service) </LI>
 <LI>single DES </LI>
 <LI>DH group 1, a 768-bit modp group </LI>
 </UL>
-<P> Since these are the only encryption algorithm and DH group the RFCs 
-require, it is possible in theory to have a standards-conforming 
+<P> Since these are the only encryption algorithms and DH group the 
+RFCs require, it is possible in theory to have a standards-conforming 
 implementation which will not interpoperate with FreeS/WAN. Such an 
 implementation would be inherently insecure, so we do not consider this 
 a problem. Anyway, most implementations sensibly include more secure 
-options as well, so dropping single DES and Group 1 does not greatly 
-hinder interoperation in practice.</P>
+options as well, so dropping null encryption, single DES and Group 1 
+does not greatly hinder interoperation in practice.</P>
 <P> We also do not implement some optional features allowed by the 
 RFCs: </P>
 <UL>
@@ -5212,7 +5483,7 @@
 default. Typically, these are easily solved with a configuration change 
 that overrides that default.</P>
 <H3><A name="not">Not (yet) in Linux FreeS/WAN</A></H3>
-<P>Things we don't yet do, as of version 1.9:</P>
+<P> Things we don't yet do, as of version 1.91:</P>
 <UL>
 <LI>key management methods 
 <UL>
@@ -5238,6 +5509,9 @@
 <P>We expect eventually to do it using DNS. The newer versions of <A href="#BIND">
 BIND</A> provide much of what we need but they are not  yet widespread 
 and our code to communicate with them is not  ready.</P>
+<P><STRONG> Update:</STRONG> As of 1.91, we have beta-testable code for 
+opportunistic encryption. See our <A href="#oppex">configuration 
+document</A>. </P>
 </UL>
 </LI>
 </UL>
@@ -5257,6 +5531,19 @@
 <LI>authentication transforms </LI>
 <P>No optional additional authentication transforms are currently 
  implemented and we do not forsee a need to add any soon.</P>
+<LI>Policy checking on decrypted packets </LI>
+<P> To fully comply with the RFCs, it is not enough just to accept only 
+packets  which survive any firewall rules in place to limit what IPSEC 
+packets get in,  and then pass KLIPS authentication. That is what 
+FreeS/WAN currently does. </P>
+<P> We should also apply additional tests, for example ensuring that 
+all packets  emerging from a particular tunnel have sourcen and 
+destination addresses that  fall within the subnets defined for that 
+tunnel, and that packets with those  addresses that did not emerge from 
+the appropriate tunnel are disallowed. </P>
+<P> This will be done as part of the KLIPS rewrite currently in 
+progress. See  these <A href="#applied">links</A> and the <A href="mail.html">
+ design mailing list</A> for discussion. </P>
 <H2><A name="pfkey">Our PF-Key implementation</A></H2>
 <P>We use PF-key Version Two for communication between the KLIPS kernel 
 code  and the Pluto Daemon. PF-Key v2 is defined by <A href="http://www.normos.org/ietf/rfc/rfc2367.txt">
@@ -5270,34 +5557,37 @@
 not  yet doing much upward communication from kernel to user space. 
 This will  change, but is not at the top of our priority list.</P>
 <H3><A name="pfk.port">PF-Key portability</A></H3>
-<P>PF-Key came out of Berkeley Unix work and is used in the various BSD 
-IPSEC  implementations. We assume also in This means there is some hope 
-of  porting our Pluto(8) to one of the BSD distributions or running 
-their  photurisd(8) on Linux if you prefer <A href="#photuris">Photuris</A>
- key  management over IKE.</P>
-<P>It is, however, more complex than that. The three PF-Key 
-implementations  we have looked at -- ours, OpenBSD and KAME -- all 
-have extensions beyond  the RFC, and the extensions are different. 
-There have been discussions aimed  at sorting out the differences, 
-perhaps for a version three PF-Key spec. All  players are in favour of 
-this, but everyone involved is busy and it is not  clear whether or 
-when these discussions might bear fruit.</P>
+<P> PF-Key came out of Berkeley Unix work and is used in the various 
+BSD IPSEC implementations, and in Solaris. This means there is some 
+hope of porting our Pluto(8) to one of the BSD distributions, or of 
+running their photurisd(8) on Linux if you prefer <A href="#photuris">
+Photuris</A> key management over IKE.</P>
+<P> It is, however, more complex than that. The PK-Key RFC deliberately 
+deals only with keying, not policy management. The three PF-Key 
+implementations we have looked at -- ours, OpenBSD and KAME -- all have 
+extensions to deal with security policy, and the extensions are 
+different. There have been discussions aimed at sorting out the 
+differences, perhaps for a version three PF-Key spec. All players are 
+in favour of this, but everyone involved is busy and it is not clear 
+whether or when these discussions might bear fruit.</P>
 <H2><A name="otherk">Kernels other than 2.0.38 and 2.2.18</A></H2>
-<P>We develop and test on:</P>
+<P> We develop and test on:</P>
 <UL>
-<LI>Redhat 5.2 with a 2.0.38 kernel.</LI>
-<LI>Redhat 6.1 with a 2.2.18 kernel.</LI>
+<LI>Redhat 6.1 with a 2.2.19 kernel.</LI>
+<LI>Redhat 7.1 with a 2.4.4 kernel.</LI>
 </UL>
 <P> This is what we recommend. </P>
 <H3><A name="kernel">Other 2.0.x Intel Kernels</A></H3>
 <P> Consider upgrading to the 2.2 kernel series. If you want to stay 
-with the 2.0 series, then we strongly recommend 2.0.38. It has some 
-security patches not present in earlier 2.0 kernels.</P>
+with the 2.0 series, then we strongly recommend 2.0.39. Some useful 
+security patches were added in 2.0.38.</P>
 <P> Various versions of the code have run at various times on most 
-2.0.xx kernels, but the current version is tested only on 2.0.38 and is 
-unlikely to compile on older kernels. Some of our patches for older 
-kernels are shipped in 2.0.37 and later, so they are no longer provided 
-in FreeS/WAN.</P>
+2.0.xx kernels, but the current version is only lightly tested on 
+2.0.39, and not at all on older kernels. </P>
+<P> Some of our patches for older kernels are shipped in 2.0.37 and 
+later, so they are no longer provided in FreeS/WAN. This means recent 
+versions of FreeS/WAN will probably not compile om anything earlier 
+than 2.0.37.</P>
 <H3><A name="2.2">2.2 and 2.4 Kernels</A></H3>
 <DL>
 <DT>FreeS/WAN 1.0</DT>
@@ -5308,12 +5598,11 @@
 <DT>FreeS/WAN 1.9</DT>
 <DD>runs on 2.0, 2.2 or 2.4 kernels</DD>
 </DL>
-<P> We suggest the latest 2.2 kernel (2.2.18 at time of writing) for 
-production use. </P>
-<H2><A name="otherdist">Intel Linux distributions other than Redhat 5.x 
-and 6.x</A></H2>
-<P> We develop and test on Redhat 5.2 for 2.0 kernels, and on Redhat 
-6.1 for 2.2, so minor changes may be required for other distributions.</P>
+<P> We suggest the latest 2.2 kernel or 2.4 (2.2.19 or 2.4.5 at time of 
+writing) for production use. </P>
+<H2><A name="otherdist">Intel Linux distributions other than Redhat</A></H2>
+<P> We develop and test on Redhat 6.1 for 2.2 kernels, and on Redhat 
+7.1 for 2.4, so minor changes may be required for other distributions.</P>
 <H3><A name="rh7">Redhat 7.0</A></H3>
 <P> There are some problems with FreeS/WAN on Redhat 7.0, but they are 
 soluble. </P>
@@ -5353,8 +5642,8 @@
  Check the <A href="mail.html">mailing list</A> archive for more recent 
 news.
 <H3><A name="suse">SuSE Linux</A></H3>
-<P>SuSE 6.3 and later versions, at least in Europe, ship with FreeS/WAN 
- included.</P>
+<P> SuSE 6.3 and later versions, at least in Europe, ship with 
+FreeS/WAN included.</P>
 <P>Here are some notes for an earlier SuSE version.</P>
 <H4>SuSE Linux 5.3</H4>
 <PRE>Date: Mon, 30 Nov 1998
@@ -5697,9 +5986,8 @@
 made, but at time of writing (February 2001), the job is not complete. 
 For more recent information, check the <A href="mail.html">mailing list</A>
 .</P>
-<P> In short, Linux currently has both IPv6 support and IPSEC support, 
-but <STRONG>the two do not work together yet</STRONG>. We, and others, 
-are working on integrating them, but it is a substantial job. </P>
+<P> The first release of Linux IPv6 with FreeS/WAN support is now <A href="http://www.ipv6.iabg.de/downloadframe/index.html">
+ available</A>. </P>
 <H3><A name="v6.back">IPv6 background</A></H3>
 <P> IPv6 has been specified by an IETF <A href="http://www.ietf.org/html.charters/ipngwg-charter.html">
 working group</A>. The group's page lists over 30 RFCs to date, and 
@@ -5788,40 +6076,50 @@
 those formats. See this list of <A href="#patch"> patches and add-ons</A>
 . </P>
 <H2><A name="interop.problem">Interoperability problems</A></H2>
-<P>The IPSEC RFCs are complex and include a number of optional 
+<P> The IPSEC RFCs are complex and include a number of optional 
 features.  There is considerable opportunity for even two correct, 
 standard-conforming,  implementations to disagree on details in a way 
 that blocks interoperation.  Of course, misinterpretations of the 
 standards and implementation or  configuration errors on either end can 
 also foul things up.</P>
 <P>That said, FreeS/WAN interoperates successfully with many other 
- implementations. There is a <A href="interop.html">list</A> in another 
- section.</P>
+ implementations. There is a <A href="#mail.interop">list</A> below.</P>
 <P> Known areas where problems may appear are:</P>
 <UL>
+<LI><STRONG>FreeS/WAN does not implement single DES</STRONG> because <A href="#desnotsecure">
+DES is insecure</A>. Suggestions on what to do if  the device you want 
+to talk to has only DES are <A href="#noDES">below</A>.</LI>
+<LI><STRONG>FreeS/WAN does not implement Diffie-Hellman group 1</STRONG>
+ because it  it is not entirely clear that this is secure.</LI>
 <LI>The RFCs define two modes for IKE negotiations -- main mode and 
  aggressive mode. Aggressive mode is slightly faster, but reveals more 
  information to an eavesdropper. Specifically, it lets an eavesdropper 
  know what identities are in use. <STRONG>FreeS/WAN does not implement 
  aggressive mode</STRONG>, so any negotiation another implementation 
- tries that way will fail. In principle this should not be a problem 
- since main mode support is required in all implementations and 
-aggressive  mode is optional. </LI>
-<P> In practice, it is sometimes a problem. Some implementations 
-default to  aggressive mode unless you configure them for main mode.</P>
-<LI><STRONG>FreeS/WAN does not implement single DES</STRONG> because <A href="#desnotsecure">
-DES is insecure</A>. Suggestions on what to do if  the device you want 
-to talk to has only DES are in our <A href="#noDES">FAQ</A> document.</LI>
-<LI><STRONG>FreeS/WAN does not implement Diffie-Hellman group 1</STRONG>
- because it  it is not entirely clear that this is secure. </LI>
-<LI>For automatic keying, <STRONG>the FreeS/WAN default is to provide <A href="#PFS">
- perfect forward secrecy</A></STRONG>. We see no reason not  to; this 
-is more secure and costs little. Some other implementations,  however, 
-turn PFS off by default. </LI>
+ tries that way will fail. </LI>
+<P> In principle this should not be a problem  since main mode support 
+is required in all implementations and aggressive  mode is optional. 
+ In practice, it is sometimes a problem.  Some implementations default 
+to  aggressive mode unless you configure them for main mode.</P>
+<LI> For automatic keying, <STRONG>the FreeS/WAN default is to provide <A
+href="#PFS"> perfect forward secrecy</A></STRONG>. We see no reason not 
+ to; this is more secure and costs little. Some other implementations, 
+ however, turn PFS off by default. </LI>
 <P> You can turn PFS off in FreeS/WAN with the <VAR>pfs=no</VAR>
  setting in <A href="manpage.d/ipsec.conf.5.html"> ipsec.conf(5)</A>, 
 but if possible  we suggest you enable it on the other end instead. 
 That is more secure.</P>
+<LI> The IKE protocol allows several types of optional message. Two 
+things happen  which are allowed by the RFCs: 
+<UL>
+<LI>Some implementations send various optional messages. </LI>
+<LI>FreeS/WAN ignores them. </LI>
+</UL>
+ However, problems may arise if the other end relies on some expected 
+effect  of these messages. There are two FAQ questions dealing with 
+this, one on the <A href="#ignore"> log message</A> FreeS/WAN gives 
+when ignoring  optional payloads and one on the <A href="#deadtunnel">
+delete SA</A> payload. </LI>
 </UL>
 <P> The general rule is that to interoperate with FreeS/WAN, the other 
 implementation should be configured for:</P>
@@ -5831,34 +6129,39 @@
 <LI>Diffie-Hellman Group 2 or 5 </LI>
 </UL>
 <P> This is possible for most implementations.</P>
-<H3><A name="noDES">Systems that want to use DES</A></H3>
-<P> Linux FreeS/WAN does not support DES transforms. Neither Pluto's 
-IKE connections nor KLIPS' IPSEC connections can use DES. Since <A href="#desnotsecure">
-DES is insecure</A> we do not, and will not at any future time, provide 
-it.</P>
+<H3><A name="noDES">Systems that want to use single DES</A></H3>
+<P> Linux FreeS/WAN does not support single DES transforms. Neither 
+Pluto's IKE connections nor KLIPS' IPSEC connections can use DES. Since <A
+href="#desnotsecure">DES is insecure</A> we do not, and will not at any 
+future time, provide it.</P>
 <P> DES is, unfortunately, a mandatory part of the <A href="#IPSEC">
 IPSEC</A> standard. Despite that, we will not implement DES. We believe 
 it is more important to provide security than to comply with a standard 
-which has been subverted into allowing weak algorithms. See our <A href="politics.html">
-history and politics</A> section for discussion.</P>
-<P>Some implementations may offer DES as the default. In such cases we 
+which has been <A href="#weak">subverted</A> into allowing weak 
+algorithms. See our <A href="politics.html">history and politics</A>
+ section for discussion.</P>
+<P> Some implementations may offer DES as the default. In such cases we 
 urge  you to change them to <A href="#3DES">Triple DES</A>. If this is 
 not  possible, for example because <A href="#exlaw">export laws</A>
  prevent your  vendor from offerring you adequate crytography, we urge 
-you to complain  vigorously to</P>
+you to complain vigorously to one or more of:</P>
 <UL>
-<LI>your government</LI>
+<LI>your government, especially any department concerned with 
+protecting citizens'  privacy or your nation's communication 
+infrastructure</LI>
 <LI>the vendor</LI>
-<LI>the embassy of the nation whose laws are problematic for you.</LI>
+<LI>the embassy of the nation whose laws are problematic for you</LI>
 </UL>
-<P> In the meanwhile, use FreeS/WAN to get strong crypto until the laws 
-are fixed.</P>
+<P> Consider using FreeS/WAN instead. PCs are cheap and we deliver 3DES 
+now. </P>
 <P> FreeS/WAN does have <A href="#DES">DES</A> code in it as a sort of 
 historical accident, since we need it to implement our default 
 (currently, our only) block cipher, <A href="#3DES">Triple DES</A>. 
 However, since <A href="#desnotsecure">DES is insecure</A>, we do not 
-provide any interface to that code and, as a matter of policy, will 
-provide no help to anyone who may wish to use it.</P>
+provide any interface to that code.</P>
+<P> As a matter of project policy, we will not help anyone subvert 
+FreeS/WAN to provide <A href="#desnotsecure">insecure DES encryption</A>
+. </P>
 <H2><A name="otherpub">Interop HowTo documents</A></H2>
 <P> The FreeS/WAN team does not have the resources to test with 
 anything like the full range of <A href="#implement">other IPSEC 
@@ -6023,7 +6326,7 @@
 I've attached some ipsec barf output - pluto still complains a few times,
 but it gets there :-)
 </PRE>
-<P>A later message from Ian:</P>
+<P> A later message from Ian:</P>
 <PRE>
 This configuration is provided as-is and with no assistance or guarantee
 that it works whatsover. In particular your attention is drawn to the versions
@@ -6101,6 +6404,19 @@
 |     7500 Series
 </PRE>
 <H3><A name="bay">Nortel (Bay Networks) Contivity switch</A></H3>
+ There is one known issue in FreeS/WAN-to-Contivity interoperation. 
+Recent versions of FreeS/WAN no longer support DH group 1 for key 
+exchange. Older versions of Contivity software support nothing else. 
+Group 2 was added in more recent releases. So: 
+<UL>
+<LI>older FreeS/WANs, such as 1.5, will work with any Contivity 
+software. Key exchange will be done using DH Group 1. This may not be 
+secure. </LI>
+<LI>current FreeS/WANs will work only with recent Contivity releases 
+supporting DH Group 2. Contivity 3.5 is one such release. </LI>
+</UL>
+ We recommend using the latest Contivity release. 
+<P> Some messages from the mailing list: </P>
 <PRE>
 Subject: Contivity Extranet Switch
    Date: Fri, 11 Jun 1999
@@ -6507,6 +6823,13 @@
 HowTo</A> for connecting FreeS/WAN and this product can be downloaded 
 from the  vendor's site or browsed at a VPN mailing list <A href="http://kubarb.phsx.ukans.edu/~tbird/vpn.html">
 site</A>.</P>
+<H3><A name="redcreek">Redcreek Ravlin</A></H3>
+ We have reports of successful interoperation at an interop <A href="http://www.opus1.com/vpn/atl99display.html">
+conference</A>, but there is also a mailing list <A href="http://www.sandelman.ottawa.on.ca/linux-ipsec/html/2000/11/msg00510.html">
+ thread</A> discussing difficulties some users have encountered. 
+<H3><A name="sentinel">SSH Sentinel</A></H3>
+ The vendor's <A href="http://www.ipsec.com/products/sentinel/documents.html">
+ web site</A> has configuration examples for use with FreeS/WAN. 
 <H3><A name="Fsecure">F-Secure VPN for Windows</A></H3>
 <PRE>   Subject: linux-ipsec: Identification through other than IP number
    Date: Tue, 13 Apr 1999
@@ -7140,8 +7463,9 @@
 of both domains or consider setting up WINS service(s).
 </PRE>
  We suspect that in some cases it may be more complex than that. See 
-the discussion of Linux services and Windows 2000 <A href="#lin2k">below</A>
-. 
+the discussion of <A href="#lin2k">Linux services and Windows 2000</A>
+ below and the <A href="#otherpub">Interop HowTo</A> documents listed 
+above. 
 <H3><A name="win2k">Windows 2000</A></H3>
 <P> Windows 2000 ships with an IPSEC implementation built in. There may 
 be  restrictions. We have had mailing list reports that only the server 
@@ -7211,16 +7535,9 @@
 http://www.sandelman.ottawa.on.ca/linux-ipsec/html/2001/02/msg00195.html
 </PRE>
 <H4><A name="interop.win2k">FreeS/WAN-to-Win2000 interop</A></H4>
-<P>As for IPSEC interoperation between Windows 2000 and FreeS/WAN, 
-there are some web sites:</P>
-<UL>
-<LI>The Norwegian company <A href="http://security.nta.no/freeswan-w2k.html">
-Telenor</A></LI>
-<LI><A href="http://jixen.tripod.com/#Win2000-Fwan">Jean-Francois 
- Nadeau</A></LI>
-<LI><A href="http://el06-24-29-255-187.ce.mediaone.net/carl/linux/ipsec/swan-w2k/swanw2k-b.html">
-Carl's guide</A></LI>
-</UL>
+<P> As for IPSEC interoperation between Windows 2000 and FreeS/WAN, 
+there are several web sites listed under <A href="#otherpub">Interop 
+HowTo</A> documents above.</P>
 <P>Here is a discussion from the mailing list:</P>
 <PRE>From: &quot;Jean-Francois Nadeau&quot; &lt;jna@microflex.ca&gt;
 Subject: Win2000 IPsec  interop. in tunnel mode
@@ -7358,19 +7675,18 @@
 general-purpose digital computers. </LI>
 <LI>Ultra made codebreaking a large-scale enterprise, producing 
 intelligence on an industrial scale. This was not a &quot;black chamber&quot;, 
-not some hidden room in some obscure government building with a small 
-crew of code-breakers. The whole operation -- from intercept operators 
-all over the world grabbing copies of enemy communications, through 
-large-scale code-breaking and analysis of the decrypted material (with 
-an enormous set of files for cross-referencing), to delivery of 
-intelligence to field commanders -- was huge, and very carefully 
-managed. </LI>
+not a hidden room in some obscure government building with a small crew 
+of code-breakers. The whole operation -- from wholesale interception of 
+enemy communications by stations around the world, through large-scale 
+code-breaking and analysis of the decrypted material (with an enormous 
+set of files for cross-referencing), to delivery of intelligence to 
+field commanders -- was huge, and very carefully managed. </LI>
 </UL>
 <P> So by the end of the war, Allied code-breakers were expert at 
 large-scale mechanised code-breaking. The payoffs were enormous. </P>
 <H4><A name="postwar">Postwar and Cold War</A></H4>
  The wartime innovations were enthusiastically adopted by post-war and 
-Cold War signals intelligence agencies. Presumably most nations now 
+Cold War signals intelligence agencies. Presumably many nations now 
 have some agency capable of sophisticated attacks on communications 
 security, and quite a few engage in such activity on a large scale. 
 <P> America's <A href="#NSA">NSA</A>, for example, is said to be both 
@@ -7391,7 +7707,7 @@
 electronic mail, or tapping into the huge volumes of data on new media 
 such as fiber optics or satellite links. None of these targets existed 
 in 1950. All of them can be attacked today, and almost certainly are 
-being attacked on a large scale. </P>
+being attacked. </P>
 <P> The Ultra story was not made public until the 1970s. Much of the 
 recent history of codes and code-breaking has not been made public, and 
 some of it may never be. Two important books are: </P>
@@ -7423,20 +7739,26 @@
 networking becoming ubiquitous, cryptography is now important to almost 
 everyone. Among the developments since the 1970s: </P>
 <UL>
-<LI>the US gov't established the <A href="#DES">DES</A> standard, a <A href="#block">
-block cipher</A> for cryptographic protection of unclassfied documents </LI>
-<LI><A href="#public">public key</A> cryptography invented by Diffie 
-and Hellman </LI>
-<LI>academic conferences such as <A href="http://www-cse.ucsd.edu/users/mihir/crypto2k.html">
-Crypto</A>, <A href="http://www.esat.kuleuven.ac.be/cosic/eurocrypt2000/">
-Eurocrypt</A>, ... </LI>
-<LI>companies offerring cryptographic products: <A href="#RSAco">RSA</A>
-, <A href="#PGPI">PGP</A>, the many vendors with <A href="#PKI">PKI</A>
- products, ... </LI>
-<LI>crypto in other products: operating systems, word processors, ... </LI>
-<LI>network protocols based on crypto: <A href="#SSH"> SSH</A>, <A href="#SSL">
-SSL</A>, <A href="#IPSEC"> IPSEC</A>, ... </LI>
-<LI>widespread use of cryptography to secure bank cards, terminals, ... </LI>
+<LI>The US gov't established the Data Encryption Standard, <A href="#DES">
+DES</A> standard, a <A href="#block">block cipher</A> for cryptographic 
+protection of unclassfied documents. It has also been widely used in 
+industry. </LI>
+<LI><A href="#public">Public key</A> cryptography was invented by 
+Diffie and Hellman. </LI>
+<LI>Academic conferences such as <A href="http://www-cse.ucsd.edu/users/mihir/crypto2k.html">
+Crypto</A> and <A href="http://www.esat.kuleuven.ac.be/cosic/eurocrypt2000/">
+Eurocrypt</A> began. </LI>
+<LI>Several companies began offerring cryptographic products: <A href="#RSAco">
+RSA</A>, <A href="#PGPI">PGP</A>, the many vendors with <A href="#PKI">
+PKI</A> products, ... </LI>
+<LI>Cryptography appeared in other products: operating systems, word 
+processors, ... </LI>
+<LI>Network protocols based on crypto were developed: <A href="#SSH">
+ SSH</A>, <A href="#SSL">SSL</A>, <A href="#IPSEC"> IPSEC</A>, ... </LI>
+<LI>Crytography came into widespread use to secure bank cards, 
+terminals, ... </LI>
+<LI>The US government replaced <A href="#DES">DES</A> with the much 
+stronger Advanced Encryption Standard, <A href="#AES">AES</A></LI>
 </UL>
 <P> This has led to a complex ongoing battle between various mainly 
 government groups wanting to control the spread of crypto and various 
@@ -7497,14 +7819,20 @@
 communication systems, but that it is an activity of the  investigative 
 authorities and intelligence services of many countries with 
  governments of different political signature. </BLOCKQUOTE> Even if 
-they have nothing on the scale of Echelon, most or all intelligence 
-agencies and  police forces certainly have some interception 
-capability. </LI>
+they have nothing on the scale of Echelon, most intelligence agencies 
+and  police forces certainly have some interception capability. </LI>
+<LI><A href="#NSA">NSA</A> tapping of submarine communication cables, 
+described  in <A href="http://www.zdnet.com/zdnn/stories/news/0,4586,2764372,00.html">
+this article</A></LI>
 <LI>A proposal for international co-operation on <A href="http://www.heise.de/tp/english/special/enfo/4306/1.html">
  Internet surveillance</A>.</LI>
 <LI>Alleged <A href="http://cryptome.org/nsa-sabotage.htm">sabotage</A>
  of security  products by the <A href="#NSA">NSA</A> (the US signals 
 intelligence agency).</LI>
+<LI>The German armed forces and some government departments will stop 
+using American software for fear of NSA  &quot;back doors&quot;, according to 
+this <A href="http://www.theregister.co.uk/content/4/17679.html">news 
+story</A>. </LI>
 <LI>The British Regulation of Investigatory Powers bill. See  this <A href="http://www.fipr.org/rip/index.html">
 web page.</A> and  perhaps this <A href="http://ars.userfriendly.org/cartoons/?id=20000806&amp;mode=classic">
 cartoon</A>.</LI>
@@ -7538,6 +7866,8 @@
 <UL>
 <LI>industrial espionage, as for example in this <A href="http://www.zdnet.com/zdnn/stories/news/0,4586,2626931,00.html">
 news story</A></LI>
+<LI>attacks by organised criminals, as in this <A href="http://www.sans.org/newlook/alerts/NTE-bank.htm">
+ large-scale attack</A></LI>
 <LI>collection of personal data by various companies. 
 <UL>
 <LI>for example, consider the various corporate winners of Privacy 
@@ -7894,11 +8224,13 @@
 held by some third party and turned over to law enforcement or security 
 agencies under some conditions.</P>
 <PRE>
-Mary had cryptography
-Her keys were in escrow
-And everything that Mary said
-The feds were sure to know
+  Mary had cryptography
+  Her keys were in escrow
+  And everything that Mary said
+  The feds were sure to know
 </PRE>
+ (If anyone knows the origin of that ditty, let <A href="mailto:sandy@storm.ca">
+let me know</A> so I can credit the author.) 
 <P> There is an excellent paper available on <A href="http://www.cdt.org/crypto/risks98/">
 Risks of Escrowed Encryption</A>, from a group of cryptographic 
 luminaries which included our project leader.</P>
@@ -7916,14 +8248,18 @@
 <P> FreeS/WAN does not support escrowed encryption, and never will.</P>
 <H3><A name="shortkeys">Limited key lengths</A></H3>
 <P> Various governments, and some vendors, have also made persistent 
-attempts to convince people that weak systems are sufficient for some 
-data, that strong cryptography should be reserved for cases where the 
-extra overheads are justified. This is nonsense.</P>
+attempts to convince people that: </P>
+<UL>
+<LI>weak systems are sufficient for some data </LI>
+<LI>strong cryptography should be reserved for cases where the extra 
+overheads are justified </LI>
+</UL>
+<STRONG> This is nonsense</STRONG>.
 <P> Weak systems touted include:</P>
 <UL>
 <LI>the ludicrously weak (deliberately crippled) 40-bit ciphers that 
 until  recently were all various <A href="#exlaw">export laws</A>
- allowed.</LI>
+ allowed</LI>
 <LI>56-bit single DES, discussed <A href="#desnotsecure">below</A></LI>
 <LI>64-bit symmetric ciphers and 512-bit RSA, the maximums for 
 unrestricted  export under various current laws</LI>
@@ -7954,10 +8290,12 @@
 usually <A href="#hybrid">hybrid</A> systems in which the bulk of the 
 work is done  by a symmetric cipher. The effect of increasing the cost 
 of the public  key operations is typically negligible because the 
-public key operations  use only a tiny fraction of total resources. For 
-example, if public key  operations use use 1% of the time in a hybrid 
-system and you triple the  cost of public key operations, the overall 
-effect is a 2% rise in system  cost.</LI>
+public key operations  use only a tiny fraction of total resources. </LI>
+<P> For example, suppose public key  operations use use 1% of the time 
+in a hybrid system and you triple the  cost of public key operations. 
+The cost of symmetric cipher operations  is unchanged at 99% of the 
+original total cost, so the overall effect is a  jump from 99 + 1 = 100 
+to 99 + 3 = 102, a 2% rise in system cost.</P>
 </UL>
 <P> In short, <STRONG>there has never been any technical reason to use 
 inadequate ciphers</STRONG>. The only reason there has ever been for 
@@ -8634,7 +8972,7 @@
 Multicast is not yet supported, though there are  Internet Draft 
 documents for that.</P>
 <P>IPSEC creates <STRONG>secure tunnels through untrusted networks</STRONG>
-.  Sites connected by these tunnels form VPNs, <A href="#VPN">Virtual 
+.  Sites connected by these tunnels form VPNs, <A href="#vpn">Virtual 
 Private  Networks</A>.</P>
 <P>IPSEC gateways can be installed wherever they are required.</P>
 <UL>
@@ -8682,7 +9020,7 @@
  on various protocols become difficult if authentication at  packet 
 level is in use on the potential victims' communication channel.</P>
 <H3><A name="authonly">Using authentication without encryption</A></H3>
-<P>Where appropriate, IPSEC can provide authentication without 
+<P> Where appropriate, IPSEC can provide authentication without 
 encryption.  One might do this, for example:</P>
 <UL>
 <LI>where the data is public but one wants to be sure of getting the 
@@ -8695,6 +9033,12 @@
 protocols  harder.</LI>
 </UL>
 <P> Authentication has lower overheads than encryption. </P>
+<P> The protocols provide four ways to build such connections, using 
+either an AH-only connection or ESP using null encryption, and in 
+either manually or automatically keyed mode. FreeS/WAN supports only 
+one of these, manually keyed AH-only connections, and <STRONG>we do not 
+recommend using that</STRONG>. Our reasons are discussed under <A href="#traffic.resist">
+Resisting traffic analysis</A> a few sections further along. </P>
 <H3><A name="encnoauth">Encryption without authentication is dangerous</A>
 </H3>
 <P>Originally, the IPSEC encryption protocol <A href="#ESP">ESP</A>
@@ -8712,7 +9056,7 @@
 <LI>ESP for encryption and authentication</LI>
 <LI>AH for authentication alone</LI>
 </UL>
-<P>Other variants are allowed by the standard, but not much used:</P>
+<P> Other variants are allowed by the standard, but not much used:</P>
 <DL>
 <DT>ESP encryption without authentication</DT>
 <DD><STRONG>Bellovin has demonstrated fatal flaws in this. Do not  use.</STRONG>
@@ -8732,14 +9076,14 @@
  might use ESP as well.</DD>
 <DT>ESP authentication without encryption</DT>
 <DD>The standard allows this, calling it &quot;null encryption&quot;. FreeS/WAN 
- does not normally support it, but it can be enabled with a kernel 
- configuration option. We recommend that you use AH instead if 
+ does not support it. We recommend that you use AH instead if 
  authentication is all you require. AH authenticates parts of the IP 
- header, which ESP-null does not do. Also, if you do not enable 
- ESP-null on your FreeS/WAN machine, then you run no risk of a 
- configuration error using this when it should be encrypting.</DD>
+ header, which ESP-null does not do.</DD>
 </DL>
-<P>There are fairly frequent suggestions that AH be dropped entirely 
+ Some of these variants cannot be used with FreeS/WAN because we do not 
+support ESP-null and do not support automatic keying of AH-only 
+connections. 
+<P> There are fairly frequent suggestions that AH be dropped entirely 
 from  the IPSEC specifications since ESP and null encryption can handle 
 that  situation. It is not clear whether this will occur. My guess is 
 that it is  unlikely.</P>
@@ -8770,13 +9114,12 @@
 useful intelligence from encrypted traffic without breaking the 
 encryption. For example, an eavesdropper might deduce something 
 interesting merely by knowing that your CEO was exchanging email with a 
-particular venture capital firm. Or that all the CEO's mail this week 
-went to a firm of bankruptcy trustees and a half dozen executive 
-recruiting agencies. </P>
+particular venture capital firm, or that the CEO was talking to a firm 
+of bankruptcy trustees and a half dozen executive recruiting agencies. </P>
 <P> Except in the simplest cases, traffic analysis is hard to do well. 
 It requires both considerable resources and considerable analytic 
 skill. However, intelligence agencies of various nations have been 
-doing it for centuries and most of them are likely quite good at it by 
+doing it for centuries and many of them are likely quite good at it by 
 now. Various commercial organisations, especially those working on 
 &quot;targeted marketing&quot; may also be quite good at analysing certain types 
 of traffic. </P>
@@ -9206,13 +9549,10 @@
 may choose to support  additional algorithms in either category.</P>
 <P>The authentication algorithms are the same ones used in the IPSEC <A href="#AH">
 authentication header</A>.</P>
-<P>We do not implement single DES since <A href="#desnotsecure">DES is 
- insecure</A>. Instead we provide <A href="#3DES">triple DES or 3DES</A>
+<P> We do not implement single DES since <A href="#desnotsecure">DES is 
+insecure</A>. Instead we provide <A href="#3DES">triple DES or 3DES</A>
 .  This is currently the only encryption algorithm supported.</P>
-<P>We do implement null encryption, but it is disabled by default. You 
-can  enable it in the IPSEC part of kernel configuration if required. 
-We would  suggest, however, that if you need only authentication, you 
-should use AH  rather than ESP with null encryption.</P>
+<P> We do not implement null encryption since it is obviously insecure.</P>
 <H2><A name="modes">IPSEC modes</A></H2>
 <P>IPSEC can connect in two modes. Transport mode is a host-to-host 
  connection involving only two machines. In tunnel mode, the IPSEC 
@@ -9273,11 +9613,11 @@
 are  stored with the connection definitions in /etc/ipsec.conf.</P>
 <P><A href="#manual">Manual keying</A> is useful for debugging since it 
  allows you to test the <A href="#KLIPS">KLIPS</A> kernel IPSEC code 
-without  the <A href="#pluto">Pluto</A> daemon doing key negotiation.</P>
+without  the <A href="#Pluto">Pluto</A> daemon doing key negotiation.</P>
 <P>In general, however, automatic keying is preferred because it is 
 more  secure.</P>
 <H4><A name="auto">Automatic keying</A></H4>
-<P>In automatic keying, the <A href="#pluto">Pluto</A> daemon 
+<P>In automatic keying, the <A href="#Pluto">Pluto</A> daemon 
 negotiates  keys using the <A href="#IKE">IKE</A> Internet Key Exchange 
 protocol.  Connections are automatically re-keyed periodically.</P>
 <P>This is considerably more secure than manual keying. In either case 
@@ -9289,7 +9629,7 @@
 two admins make changes. Moreover, they  have to communicate the new 
 keys securely, perhaps with <A href="#PGP">PGP</A> or <A href="#SSH">SSH</A>
 .  This may be possible in some  cases, but as a general solution it is 
-expensive, bothersome and unreliable.  Far better to let <A href="#pluto">
+expensive, bothersome and unreliable.  Far better to let <A href="#Pluto">
 Pluto</A> handle these chores; no doubt  the administrators have enough 
 to do.</P>
 <P>Also, automatic keying is inherently more secure against an attacker 
@@ -9359,7 +9699,7 @@
 Linux FreeS/WAN might be  a good project for a volunteer. The likely 
 starting point would be the  OpenBSD photurisd code.</P>
 <H4><A name="skip">SKIP</A></H4>
-<P><A href="#skip">SKIP</A> is yet another key management protocol, 
+<P><A href="#SKIP">SKIP</A> is yet another key management protocol, 
  developed by Sun. At one point it was fairly widely used, but our 
 current  impression is that it is moribund, displaced by IKE. Sun now 
 (as of Solaris  8.0) ship an IPSEC implementation using IKE. We have no 
@@ -9379,7 +9719,8 @@
 <DD>
 <UL>
 <LI>The general list for discussing use of the software </LI>
-<LI>The place for seeking <STRONG>help with problems</STRONG>. </LI>
+<LI>The place for seeking <STRONG>help with problems</STRONG> (but 
+please check the <A href="faq.html">FAQ</A> first). </LI>
 <LI>Anyone can post. </LI>
 </UL>
 </DD>
@@ -9401,7 +9742,9 @@
 <LI><STRONG>Design discussions</STRONG>, for people working on 
 FreeS/WAN development or others with an interest  in design and 
 security issues. </LI>
-<LI>Only subscribers can post. </LI>
+<LI>It would be a good idea to read the existing design papers (see 
+this <A href="#applied">list</A>) before  posting. </LI>
+<LI>Anyone can post. </LI>
 </UL>
 </DD>
 <DT><A href="mailto:announce-request@lists.freeswan.org?body=subscribe">
@@ -9413,7 +9756,10 @@
 software. </LI>
 <LI>All posts here are also sent to the users list. You need not 
 subscribe to both. </LI>
-<LI>Only authorised people can post. </LI>
+<LI>Only the FreeS/WAN team can post. </LI>
+<LI>If you have something you feel should go on this list, send it to <VAR>
+announce-admin@lists.freeswan.org</VAR>.  Unless it is obvious, please 
+include a short note explaining why we should post it.</LI>
 </UL>
 </DD>
 <DT><A href="mailto:briefs-request@lists.freeswan.org?body=subscribe">
@@ -9424,7 +9770,7 @@
 <LI><STRONG>Weekly summaries</STRONG> of activity on the users list. </LI>
 <LI>All posts here are also sent to the users list. You need not 
 subscribe to both. </LI>
-<LI>Only authorised people can post. </LI>
+<LI>Only the FreeS/WAN team can post. </LI>
 </UL>
 </DD>
 </DL>
@@ -9436,6 +9782,8 @@
 <LI>send mail to <VAR>listname</VAR>-request@lists.freeswan.org with a 
 one-line message body &quot;subscribe&quot; </LI>
 </UL>
+<P> Archives of these lists are available via the <A href="http://www.freeswan.org/mail.html">
+web interface</A>. </P>
 <H4><A name="policy.list">List policies</A></H4>
 <STRONG> US citizens or residents are asked not to post code to the 
 lists, not even one-line bug fixes</STRONG>. The project cannot accept 
@@ -9455,7 +9803,9 @@
 <LI><A href="http://www.sandelman.ottawa.on.ca/linux-ipsec">Canada</A></LI>
 <LI><A href="http://www.nexial.com">Holland</A></LI>
 </UL>
-<P>Note that these use different search engines. Try both.</P>
+<P> Note that these use different search engines. Try both.</P>
+<P> Archives of the new lists are available via the <A href="http://www.freeswan.org/mail.html">
+web interface</A>. </P>
 <H3><A name="additional">Other FreeS/WAN related lists</A></H3>
 <P> There are several other lists related to FreeS/WAN: </P>
 <UL>
@@ -9569,10 +9919,24 @@
 <LI>patches for <A href="http://www.strongsec.com/freeswan/">X.509 
  certificate support</A>, also available from a <A href="http://www.twi.ch/~sna/strongsec/freeswan/">
 mirror site</A></LI>
+<LI>a <A href="http://tzukanov.narod.ru/">series</A> of patches that 
+<UL>
+<LI>provide GOST, a Russian gov't. standard cipher, in MMX assembler </LI>
+<LI>add GOST to OpenSSL </LI>
+<LI>add GOST to the International kernel patch </LI>
+<LI>let FreeS/WAN use International kernel patch ciphers </LI>
+</UL>
+</LI>
+<LI><A href="http://www.ipv6.iabg.de/downloadframe/index.html">IPv6 
+support</A></LI>
 </UL>
 <P> Before using these, check the <A href="mail.html">mailing list</A>
  for news of newer versions and to see whether they have been 
 incorporated into more recent versions of FreeS/WAN.</P>
+<P><STRONG> Note:</STRONG> At one point the way PGP generates RSA keys 
+and the way FreeS/WAN checks them for validity before using them were 
+slightly different, so quite a few PGP-generated keys would be rejected 
+by FreeS/WAN, confusing users no end. This is fixed in 1.9. </P>
 <P> A set of PKIX patches were recently announced on the mailing list:</P>
 <PRE>
 Subject: a different PKIX patch.
@@ -9612,6 +9976,8 @@
 <LI><A href="ftp://ftp.heise.de/pub/ct/listings/9916-180.tgz">patches</A>
  to add <A href="#Blowfish">Blowfish</A>, <A href="#IDEA">IDEA</A> and <A
 href="#CAST128">CAST-128</A> to FreeS/WAN</LI>
+<LI><A href="http://www.cendio.se/~bellman/aggressive-pluto.snap.tar.gz">
+patches</A> for aggressive  mode support </LI>
 </UL>
 <P> These patches are for older versions of FreeS/WAN and will likely 
 not work with the current version.  Older versions of FreeS/WAN may be 
@@ -9665,7 +10031,7 @@
 <UL>
 <LI>other Linux <A href="#linuxIPSEC">IPSEC implementations</A></LI>
 <LI><A href="http://www.tik.ee.ethz.ch/~skip/">ENskip</A>, a free 
- implementation of Sun's <A href="#skip">SKIP</A> protocol</LI>
+ implementation of Sun's <A href="#SKIP">SKIP</A> protocol</LI>
 <LI><A href="http://sunsite.auc.dk/vpnd/">vpnd</A>, a non-IPSEC VPN 
 daemon  for Linux which creates tunnels using <A href="#Blowfish">
 Blowfish</A> encryption</LI>
@@ -9781,7 +10147,7 @@
 <H2><A name="implement">IPSEC Implementations</A></H2>
 <H3><A name="linuxprod">Linux products</A></H3>
 <P> Vendors using FreeS/WAN in turnkey firewall or VPN products are 
-listed in  our <A href="turnkey">introduction</A>.</P>
+listed in  our <A href="#turnkey">introduction</A>.</P>
 <P>Other vendors have Linux IPSEC products which, as far as we know, do 
 not  use FreeS/WAN</P>
 <UL>
@@ -10416,7 +10782,7 @@
  FreeS/WAN</A> would be useful undertaking, and considerable freely 
  available code exists to start from. One complication is that our code 
  is built for a 64-bit block cipher and AES uses a 128-bit block. 
- Volunteers via the <A href="#list">mailing list</A> would be  welcome.</P>
+ Volunteers via the <A href="#list">mailing lists</A> would be  welcome.</P>
 <P>For more information, see the <A href="http://csrc.nist.gov/encryption/aes/aes_home.htm">
  NIST AES home  page</A> or the <A href="http://www.ii.uib.no/~larsr/aes.html">
  Block  Cipher Lounge AES page</A>. For code and benchmarks see <A href="http://www.btinternet.com/~brian.gladman/">
@@ -10811,7 +11177,7 @@
 and a fragment carries information on where it starts  within that 64K 
 and how long it is. The &quot;ping of death&quot; delivers  fragments that say, 
 for example, that they start at 60K and are  20K long. Attempting to 
-re-assemble thse without checking for  overflow can be fatal.</LI>
+re-assemble these without checking for  overflow can be fatal.</LI>
 </UL>
 </DD>
 <P>The two example attacks discussed were both quite effective when 
@@ -11211,9 +11577,8 @@
 come from one IP address, that of its Internet  interface. It then gets 
 all the replies, does some table lookups and  more header rewriting, 
 and delivers the replies to the appropriate  client machines.</P>
-<P>To use masquerade with Linux FreeS/WAN, you must set 
- leftfirewall=yes and/or rightfirewall=yes in the connection 
- description in /etc/ipsec.conf.</P>
+<P> For information on using masquerade with Linux FreeS/WAN, see our <A href="#NAT">
+ firewall document</A> and the <A href="#masq.faq">FAQ</A> and.</P>
 <DT><A name="IPng">IPng</A></DT>
 <DD>&quot;IP the Next Generation&quot;, see <A href="#ipv6.gloss">IPv6</A>.</DD>
 <DT><A name="IPv4">IPv4</A></DT>
@@ -11315,18 +11680,9 @@
  this  list</A>.</P>
 <DT><A name="M">M</A></DT>
 <DT><A name="list">Mailing list</A></DT>
-<DD>The <A href="#FreeSWAN">Linux FreeS/WAN</A> project has an open 
- public email list for bug reports and software development 
- discussions. The list address is <B>linux-ipsec@clinet.fi</B>. To 
- subscribe, send mail to <A href="mailto:majordomo@clinet.fi">
-majordomo@clinet.fi</A> with a  one-line message body &quot;subscribe 
-linux-ipsec&quot;.For more information,  send majordomo the one-line message 
-&quot;help&quot;. </DD>
-<P>NOTE: <STRONG>US citizens or residents are asked not to post code 
- to the list, not even one-line bug fixes.</STRONG> The project cannot 
- accept code which might entangle it in US export restrictions.</P>
-<P>For more detail, see our document on this and other <A href="mail.html">
-mailing lists</A>.</P>
+<DD>The <A href="#FreeSWAN">Linux FreeS/WAN</A> project has several 
+ public email lists for bug reports and software development 
+ discussions. See our document on <A href="mail.html">mailing lists</A>.</DD>
 <DT><A name="middle">Man-in-the-middle attack</A></DT>
 <DD>An <A href="#active">active attack</A> in which the attacker 
  impersonates each of the legitimate players in a protocol to the 
@@ -11544,7 +11900,9 @@
  communications, without a pre-shared secret and without a common <A href="#PKI">
 PKI</A> or previous exchange of public keys. This is one  of the goals 
 of the Linux FreeS/WAN project, discussed in our <A href="#goals">
-introduction</A> section.</DD>
+introduction</A> section. </DD>
+<P> Setting up for opportunistic encryption is described in our <A href="#oppex">
+ configuration</A> document.</P>
 <DT><A name="P">P</A></DT>
 <DT><A name="P1363"><A href="http://grouper.ieee.org/groups/1363">P1363 
  standard</A></A></DT>
@@ -12451,6 +12809,8 @@
 <LI><A href="#old_to_new"> Can different FreeS/WAN versions talk to 
 each other?</A></LI>
 <LI><A href="#versions"> Does FreeS/WAN run on my version of Linux?</A></LI>
+<LI><A href="#k.versions"> Does FreeS/WAN run on the latest kernel 
+version?</A></LI>
 <LI><A href="#modify.faq"> Can I modify FreeS/WAN to ...?</A></LI>
 <LI><A href="#contrib.faq"> Can I contribute to the project?</A></LI>
 <LI><A href="#ddoc.faq">Is there detailed design documentation?</A></LI>
@@ -12458,6 +12818,7 @@
 <LI><A href="#compile.faq">Compilation problems</A></LI>
 <UL>
 <LI><A href="#gmp.h_missing">gmp.h: No such file or directory</A></LI>
+<LI><A href="#noVM">... virtual memory exhausted</A></LI>
 </UL>
 <LI><A href="#setup.faq"> Life's little mysteries</A></LI>
 <UL>
@@ -12469,6 +12830,8 @@
 <LI><A href="#firewall_ate">The firewall ate my packets!</A></LI>
 <LI><A href="#dropconn">Dropped connections</A></LI>
 <LI><A href="#tcpdump"> TCPdump on the gateway shows strange things</A></LI>
+<LI><A href="#no_trace"> Traceroute does not show anything between the 
+gateways</A></LI>
 </UL>
 <LI><A href="#man4debug">Testing in stages</A></LI>
 <UL>
@@ -12487,9 +12850,14 @@
 <LI><A href="#error"> Interpreting error messages</A></LI>
 <UL>
 <LI><A href="#unreachable">SIOCADDRT:Network is unreachable</A></LI>
+<LI><A href="#noKLIPS">ipsec_setup: Fatal error, kernel appears to lack 
+KLIPS</A></LI>
 <LI><A href="#conn_name">Connection names in Pluto error messages</A></LI>
 <LI><A href="#cantorient">Pluto: ... can't orient connection</A></LI>
 <LI><A href="#noconn"> Pluto: ... no connection is known</A></LI>
+<LI><A href="#nosuit"> Pluto: ... no suitable connection ...</A></LI>
+<LI><A href="#noconn.auth"> Pluto: ... no connection has been authorized</A>
+</LI>
 <LI><A href="#noDESsupport"> Pluto: ... OAKLEY_DES_CBC is not supported.</A>
 </LI>
 <LI><A href="#notransform"> Pluto: ... no acceptable transform</A></LI>
@@ -12498,6 +12866,9 @@
 <LI><A href="#kflags"> ipsec_setup: Cannot adjust kernel flags</A></LI>
 <LI><A href="#SAused"> ... trouble writing to /dev/ipsec ... SA already 
 in use</A></LI>
+<LI><A href="#ignore"> ... ignoring ... payload</A></LI>
+<LI><A href="#dup_address">ipsec_setup: ... interfaces ... and ... 
+share address ...</A></LI>
 </UL>
 <LI><A href="#canI">Can I ...</A></LI>
 <UL>
@@ -12510,19 +12881,18 @@
 net?</A></LI>
 <LI><A href="#QoS">Can I use Quality of Service routing with FreeS/WAN?</A>
 </LI>
+<LI><A href="#deadtunnel">Can I recognise dead tunnels and shut them 
+down?</A></LI>
+<LI><A href="#demanddial">Can I build tunnels over a demand-dialed link?</A>
+</LI>
 <LI><A href="#PKIcert"> Does FreeS/WAN support X.509 or other PKI 
 certificates?</A></LI>
 <LI><A href="#Radius"> Does FreeS/WAN support Radius or other user 
 authentication?</A></LI>
-<LI><A href="#noDES"> Does FreeS/WAN support single DES encryption?</A></LI>
-<UL>
-<LI><A href="#DESstandard"> But isn't DES support part of the IPSEC 
-standard?</A></LI>
-<LI><A href="#DESonly"> I have to talk to .... which offers only DES. 
-How do I do this?</A></LI>
-</UL>
+<LI><A href="#noDES.faq"> Does FreeS/WAN support single DES encryption?</A>
+</LI>
 </UL>
-<LI><A href="#spam">Why don't you restrict the mailing list to reduce 
+<LI><A href="#spam">Why don't you restrict the mailing lists to reduce 
 spam?</A></LI>
 </UL>
 <HR>
@@ -12617,11 +12987,56 @@
 compatibility</A> document. </P>
 <P> FreeS/WAN has been tested on multiprocessor Intel Linux and worked 
 there. Note, however, that we do not test this often and have never 
-tested on multiprocessor machines of other architectures. </P>
+tested on multiprocessor machines of other architectures. <A name="k.versions">
+</P>
+<H3>Does FreeS/WAN run on the latest kernel version?</H3>
+ Quite often, no. 
+<P> Released versions of FreeS/WAN generally run on whatever production 
+kernels were current at the time of the release. For example, FreeS/WAN 
+1.91 runs on kernel 2.2.19 or 2.4.5. Often they will run on slightly 
+earlier or later kernels as well, but we test on the current production 
+kernels, so those are strongly recommended. </P>
+<P> The kernel is under active development and it is not uncommon for 
+changes to appear that cause problems for FreeS/WAN. For example, 2.4.6 
+or 2.4.7 may have changes that break FreeS/WAN 1.91. Or not; you can't 
+tell in advance. When such changes appear, we put a fix in the 
+FreeS/WAN snapshots, and distribute it with our next release. </P>
+<P> However, this is not a top priority for us, and it may take 
+anything from a few days to several weeks for such a problem to find 
+its way to the top of our kernel programmer's todo list. In the 
+meanwhile, you have two choices: either stick with a slightly older 
+kernel, or fix the problem yourself and send us a patch. </P>
+<P> We don't even try to keep up with kernel changes outside the main 
+2.2 and 2.4 branches, such as the 2.4.x-ac patched versions from Alan 
+Cox or (when they appear) the 2.5 series of development kernels. We'd 
+rather work on developing the FreeS/WAN code than on chasing these 
+moving targets. </P>
 <H3><A name="modify.faq">Can I modify FreeS/WAN to ...?</A></H3>
  You are free to modify FreeS/WAN in any way. See the discussion of <A href="#licensing">
 licensing</A> in our introduction document. 
 <H3><A name="contrib.faq">Can I contribute to the project?</A></H3>
+ In general, we welcome contributions from the community. Various 
+contributed patches, either to fix bugs or to add features, have been 
+incorporated into our distribution. Other patches, not yet included in 
+the distribution, are listed in our <A href="#patch">web links</A>
+ section. 
+<P> Users have also contributed heavily to documentation, both by 
+creating their own <A href="#howto">HowTos</A> and by posting things on 
+the <A href="mail.html">mailing lists</A> which I have quoted in these 
+HTML docs. </P>
+<P> There are, however, some caveats. </P>
+<P> FreeS/WAN is being implemented in Canada, by Canadians, largely to 
+ensure that is it is entirely free of export restrictions. See this <A href="#status">
+discussion</A>. We <STRONG>cannot accept code contributions from US 
+residents or citizens</STRONG>, not even one-line bugs fixes. The 
+reasons for this were recently discussed extensively on the mailing 
+list, in a thread starting <A href="http://www.sandelman.ottawa.on.ca/linux-ipsec/html/2001/01/msg00111.html">
+here</A>. </P>
+<P> Not all contributions are of interest to us. The project has a set 
+of fairly ambitious and quite specific goals, described in our <A href="#goals">
+introduction</A>. Contributions that lead toward these goals are likely 
+to be welcomed enthusiastically. Other contributions may be seen as 
+lower priority, or even as a distraction. </P>
 <H3><A name="ddoc.faq">Is there detailed design documentation?</A></H3>
  There are: 
 <UL>
@@ -12652,6 +13067,20 @@
 is <NOBR><VAR>apt-get install gmp2</VAR></NOBR>. </P>
 <P> For more information and the latest version, see the <A href="http://www.swox.com/gmp/">
 GMP home page</A>. </P>
+<H3><A name="noVM">... virtual memory exhausted</A></H3>
+ We have had several reports of this message appearing, all on SPARC 
+Linux. Here is a mailing message on a solution: 
+<PRE>
+&gt; ipsec_sha1.c: In function `SHA1Transform':
+&gt; ipsec_sha1.c:95: virtual memory exhausted
+
+I'm seeing exactly the same problem on an Ultra with 256MB ram and 500
+MB swap.  Except I am compiling version 1.5 and its Red Hat 6.2.
+
+I can get around this by using -O instead of -O2 for the optimization
+level.  So it is probably a bug in the optimizer on the sparc complier. 
+I'll try and chase this down on the sparc lists.
+</PRE>
 <H2><A name="setup.faq">Life's little mysteries</A></H2>
  FreeS/WAN is a fairly complex product. (Neither the networks it runs 
 on nor the protocols it uses are simple, so it could hardly be 
@@ -12851,8 +13280,9 @@
  using a different specification; the route is altered  as necessary) 
 without having a ``window'' in which packets  might go elsewhere based 
 on a more general route.  Such  a  route can be removed using the 
---unroute operation (and is  implicitly removed by --delete).  See also 
-this mailing list <A href="http://www.sandelman.ottawa.on.ca/linux-ipsec/html/2000/11/msg00523.html">
+--unroute operation (and is  implicitly removed by --delete). </BLOCKQUOTE>
+</P>
+<P> See also this mailing list <A href="http://www.sandelman.ottawa.on.ca/linux-ipsec/html/2000/11/msg00523.html">
 message</A>. </P>
 <H3><A name="firewall_ate">The firewall ate my packets!</A></H3>
  If firewalls filter out:
@@ -12871,7 +13301,7 @@
 any number of reasons, ranging from hardware failures to various 
 software problems such as the path MTU problems discussed <A href="#pmtu.broken">
 elsewhere in the FAQ</A>. Fortunately, various diagnostic tools exist 
-that help you sort many of the possible problems.</P>
+that help you sort out many of the possible problems.</P>
 <P> There is one situation, however, where FreeS/WAN (using default 
 settings) may destroy a connection for no readily apparent reason. This 
 occurs when things are <STRONG>misconfigured</STRONG> so that <STRONG>
@@ -12880,7 +13310,7 @@
 <P> In this situation, the first tunnel comes up fine and works until 
 the second is established. At that point, because of the way we track 
 connections internally, the first tunnel ceases to exist as far as this 
-gateway is concerned. Of course the far end does not know that and a 
+gateway is concerned. Of course the far end does not know that, and a 
 storm of error messages appears on both systems as it tries to use the 
 tunnel.</P>
 <P> If the far end gives up, goes back to square one and negotiates a 
@@ -12962,6 +13392,77 @@
 <P> Note that nothing on either subnet needs to change. This lets you 
 test most of your IPSEC setup before connecting to the insecure 
 Internet. </P>
+<H3><A name="no_trace">Traceroute does not show anything between the 
+gateways</A></H3>
+ As far as traceroute can see, the two gateways are one hop apart; the 
+data packet goes directly from one to the other through the tunnel. Of 
+course the outer packets that implement the tunnel pass through 
+whatever lies between the gateways, but  those packets are built and 
+dismantled by the gateways. Traceroute does not see them and cannot 
+report anything about their path. 
+<P> Here is a mailing list message with more detail. </P>
+<PRE>
+Date: Mon, 14 May 2001
+To: linux-ipsec@freeswan.org
+From: &quot;John S. Denker&quot; &lt;jsd@research.att.com&lt;
+Subject: Re: traceroute: one virtual hop
+
+At 02:20 PM 5/14/01 -0400, Claudia Schmeing wrote:
+&gt;
+&gt;&gt; &gt; A bonus question: traceroute in subnet to subnet enviroment looks like:
+&gt;&gt; &gt; 
+&gt;&gt; &gt; traceroute to andris.dmz (172.20.24.10), 30 hops max, 38 byte packets
+&gt;&gt; &gt; 1  drama (172.20.1.1)  0.716 ms  0.942 ms  0.434 ms
+&gt;&gt; &gt; 2  * * *
+&gt;&gt; &gt; 3  andris.dmz (172.20.24.10)  73.576 ms  78.858 ms  79.434 ms
+&gt;&gt; &gt; 
+&gt;&gt; &gt; Why aren't there the other hosts which take part in the delivery during 
+&gt;    * * * ?
+&gt;
+&gt;If there is an ipsec tunnel between GateA and Gate B, this tunnel forms a 
+&gt;'virtual wire'.  When it is tunneled, the original packet becomes an inner 
+&gt;packet, and new ESP and/or AH headers are added to create an outer packet 
+&gt;around it. You can see an example of how this is done for AH at 
+&gt;doc/ipsec.html#AH . For ESP it is similar.
+&gt;
+&gt;Think about the packet's path from the inner packet's perspective.
+&gt;It leaves the subnet, goes into the tunnel, and re-emerges in the second
+&gt;subnet. This perspective is also the only one available to the
+&gt;'traceroute' command when the IPSec tunnel is up.
+
+Claudia got this exactly right.  Let me just expand on a couple of points:
+
+*) GateB is exactly one (virtual) hop away from GateA.  This is how it
+would be if there were a physically private wire from A to B.  The
+virtually private connection should work the same, and it does.
+
+*) While the information is in transit from GateA to GateB, the hop count
+of the outer header (the &quot;envelope&quot;) is being decremented.  The hop count
+of the inner header (the &quot;contents&quot; of the envelope) is not decremented and
+should not be decremented.  The hop count of the outer header is not
+derived from and should not be derived from the hop count of the inner header.
+
+Indeed, even if the packets did time out in transit along the tunnel, there
+would be no way for traceroute to find out what happened.  Just as
+information cannot leak _out_ of the tunnel to the outside, information
+cannot leak _into_ the tunnel from outside, and this includes ICMP messages
+from routers along the path.
+
+There are some cases where one might wish for information about what is
+happening at the IP layer (below the tunnel layer) -- but the protocol
+makes no provision for this.  This raises all sorts of conceptual issues.
+AFAIK nobody has ever cared enough to really figure out what _should_
+happen, let alone implement it and standardize it.
+
+*) I consider the &quot;* * *&quot; to be a slight bug.  One might wish for it to be
+replaced by &quot;GateB GateB GateB&quot;.  It has to do with treating host-to-subnet
+traffic different from subnet-to-subnet traffic (and other gory details).
+I fervently hope KLIPS2 will make this problem go away.
+
+*) If you want to ask questions about the link from GateA to GateB at the
+IP level (below the tunnel level), you have to ssh to GateA and launch a
+traceroute from there.
+</PRE>
 <H2><A name="man4debug">Testing in stages</A></H2>
 <P> It is often useful in debugging to test things one at a time:</P>
 <UL>
@@ -13010,13 +13511,18 @@
 UDP port 500 packets used in key negotiation. 
 <P> Other possibilities:</P>
 <UL>
-<LI>mis-configuration of auto connection in the /etc/ipsec.conf file</LI>
+<LI>mis-configuration of auto connection in the /etc/ipsec.conf file. </LI>
+<P>One common  configuration error is forgetting that you need <VAR>
+auto=add</VAR> to load the  connection description on the receiving end 
+so it recognises the connection  when the other end asks for it.</P>
 <LI>error in shared secret in /etc/ipsec.secrets</LI>
 <LI>one gateway lacks a route to the other so Pluto's UDP packets are 
  lost</LI>
 <LI>bugs in Pluto</LI>
 <LI>incompatibilities between Pluto's <A href="#IKE">IKE</A>
- implementation and the IKE at the other end of the tunnel.</LI>
+ implementation and the IKE at the other end of the tunnel. </LI>
+<P>Some possibile problems  are discussed in out <A href="#interop.problem">
+interoperation</A> document.</P>
 </UL>
 <H3><A name="nocomp">IPSEC works, but connections using compression fail</A>
 </H3>
@@ -13110,6 +13616,37 @@
  Since the above message was written, we have modified the updown 
 script to provide a better diagnostic for this problem. Check <VAR>
 /var/log/messages</VAR>. 
+<H3><A name="noKLIPS">ipsec_setup: Fatal error, kernel appears to lack 
+KLIPS</A></H3>
+ This message indicates an installation failure. The kernel you are 
+running does not contain the KLIPS (kernel IPSEC) code.
+<P>
+<P> Here is one of Claudia's messages on the topic: </P>
+<PRE>
+&gt; I tried to install freeswan 1.8 on my mandrake 7.2 test box. ...
+
+&gt; It does show version and some output for whack.
+
+Yes, because the Pluto (daemon) part of ipsec is installed correctly, but
+as we see below the kernel portion is not.
+
+&gt; However, I get the following from /var/log/messages:
+&gt; 
+&gt; Mar 11 22:11:55 pavillion ipsec_setup: Starting FreeS/WAN IPSEC 1.8...
+&gt; Mar 11 22:12:02 pavillion ipsec_setup: modprobe: Can't locate module ipsec
+&gt; Mar 11 22:12:02 pavillion ipsec_setup: Fatal error, kernel appears to lack
+&gt; KLIPS.
+
+This is your problem. You have not successfully installed a kernel with
+IPSec machinery in it. 
+
+Did you build Linux FreeS/WAN as a module? If so, you need to ensure that 
+your new module has been installed in the directory where your kernel 
+loader normally finds your modules. If not, you need to ensure
+that the new IPSec-enabled kernel is being loaded correctly.
+
+See also doc/install.html, and INSTALL in the distro.
+</PRE>
 <H3><A name="conn_name">Connection names in Pluto error messages</A></H3>
 <P> From Pluto programmer Hugh Redelmeier:</P>
 <PRE>
@@ -13152,11 +13689,11 @@
 connection and Pluto does not have a connection description that 
 matches what the remote system has requested. The most common cause is 
 a configuration error on one end or the other. 
-<P> The match involves the <VAR>left</VAR>, <VAR>right</VAR>, <VAR>
-leftsubnet</VAR> and <VAR>rightsubnet</VAR> parameters and must be 
-exact. For example, if your left subnet is a.b.c.0/24 then neither a 
-single machine in that net nor a smaller subnet such as a.b.c.64/26 
-will be considered a match. </P>
+<P> Parameters involved in this match are <VAR>left</VAR>, <VAR>right</VAR>
+, <VAR>leftsubnet</VAR> and <VAR>rightsubnet</VAR>. </P>
+<P><STRONG> The match must be exact</STRONG>. For example, if your left 
+subnet is a.b.c.0/24 then neither a single machine in that net nor a 
+smaller subnet such as a.b.c.64/26 will be considered a match. </P>
 <P> The message can also occur when an appropriate description exists 
 but Pluto has not loaded it. Use an <VAR>auto=add</VAR> statement in 
 the connection description, or an <VAR>ipsec auto --add &lt;conn_name&gt;</VAR>
@@ -13185,13 +13722,91 @@
 The leftsubnet= (client) in your conn is 216.112.83.64/26.  It must
 exactly match what pluto is looking for, and it does not.
 </PRE>
+<H3><A name="nosuit">Pluto: ... no suitable connection ...</A></H3>
+ This is similar to the <A href="#noconn">no connection known</A>
+ error, but occurs at a different point in Pluto processing. 
+<P> Here is one of Claudia's messages explaining the problem: </P>
+<PRE>
+You write,
+
+&gt; What could be the reason of the following error? 
+&gt; &quot;no suitable connection for peer '@xforce'&quot;
+
+When a connection is initiated by the peer, Pluto must choose which entry in 
+the conf file best matches the incoming connection. A preliminary choice is 
+made on the basis of source and destination IPs, since that information is 
+available at that time. 
+
+A payload containing an ID arrives later in the negotiation. Based on this
+id and the *id= parameters, Pluto refines its conn selection. ...
+
+The message &quot;no suitable connection&quot; indicates that in this refining step,
+Pluto does not find a connection that matches that ID.
+
+Please see &quot;Selecting a connection when responding&quot; in man ipsec_pluto for
+more details.
+</PRE>
+<P> See also <A href="#conn_name">Connection names in Pluto error 
+messages</A>. </P>
+<H3><A name="noconn.auth">Pluto: ... no connection has been authorized</A>
+</H3>
+ Here is one of Claudia's messages discussing this problem: 
+<PRE>
+You write,
+
+&gt;  May 22 10:46:31 debian Pluto[25834]: packet from x.y.z.p:10014: 
+&gt;  initial Main Mode message from x.y.z.p:10014 
+                            but no connection has been authorized
+
+This error occurs early in the connection negotiation process,
+at the first step of IKE negotiation (Main Mode), which is itself the 
+first of two negotiation phases involved in creating an IPSec connection.
+
+Here, Linux FreeS/WAN receives a packet from a potential peer, which 
+requests that they begin discussing a connection.
+
+The &quot;no connection has been authorized&quot; means that there is no connection 
+description in Linux FreeS/WAN's internal database that can be used to 
+link your ipsec interface with that peer.
+
+
+
+&quot;But of course I configured that connection!&quot; 
+
+It may be that the appropriate connection description exists in ipsec.conf 
+but has not been added to the database with ipsec auto --add myconn or the 
+auto=add method. Or, the connection description may be misconfigured.
+
+The only parameters that are relevant in this decision are left= and right= .
+Local and remote ports are also taken into account -- we see that the port 
+is printed in the message above -- but there is no way to control these
+in ipsec.conf.
+
+
+Failure at &quot;no connection has been authorized&quot; is similar to the
+&quot;no connection is known for...&quot; error in the FAQ, and the &quot;no suitable
+connection&quot; error described in the snapshot's FAQ. In all three cases,
+Linux FreeS/WAN is trying to match parameters received in the
+negotiation with the connection description in the local config file.
+
+As it receives more information, its matches take more parameters into 
+account, and become more precise:  first the pair of potential peers,
+then the peer IDs, then the endpoints (including any subnets).
+
+The &quot;no suitable connection for peer *&quot; occurs toward the end of IKE 
+(Main Mode) negotiation, when the IDs are matched.
+
+&quot;no connection is known for a/b===c...d&quot; is seen at the beginning of IPSec 
+(Quick Mode, phase 2) negotiation, when the connections are matched using
+left, right, and any information about the subnets.
+</PRE>
 <H3><A name="noDESsupport">Pluto: ... OAKLEY_DES_CBC is not supported.</A>
 </H3>
  This message occurs when the other system attempts to negotiate a 
 connection using single DES, which we do not support because it is <A href="#desnotsecure">
 insecure</A>. 
-<P> Another FAQ section describes <A href="#noDES">how to deal with</A>
- systems that attempt to use single DES. </P>
+<P> Our interoperation document has suggestions for <A href="#noDES">
+ how to deal with</A> systems that attempt to use single DES. </P>
 <H3><A name="notransform"> Pluto: ... no acceptable transform</A></H3>
  This message means that the other gateway has made a proposal for 
 connection parameters, but nothing they proposed is acceptable to 
@@ -13204,7 +13819,7 @@
 FreeS/WAN does not support that. (see <A href="#noDES">below</A> for 
 DES problems) </LI>
 </UL>
- A more detailed explanation, from Pluto programmer Hugh Redelmaier:
+ A more detailed explanation, from Pluto programmer Hugh Redelmeier:
 <PRE>
 Background:
 
@@ -13375,6 +13990,54 @@
 </PRE>
  This problem is also discussed in this FAQ under the heading <A href="#spi_error">
 One manual connection works, but second one fails</A>. 
+<H3><A name="ignore">... ignoring ... payload</A></H3>
+ This message is harmless. The IKE protocol provides for a number of 
+optional messages types: 
+<UL>
+<LI>delete SA </LI>
+<LI>initial contact </LI>
+<LI>vendor ID </LI>
+<LI> ... </LI>
+</UL>
+ An implementation is never required to send these, but they are 
+allowed to.  The receiver is not required to do anything with them. 
+FreeS/WAN ignores them, but notifies you via the logs. 
+<P> For the &quot;ignoring delete SA Payload&quot; message, see also the 
+discussion below of cleaning up <A href="#deadtunnel">dead tunnels</A>. </P>
+<H3><A name="dup_address">ipsec_setup: ... interfaces ... and ... share 
+address ...</A></H3>
+ This is a fatal error. FreeS/WAN cannot cope with two or more 
+interfaces using the same IP address. You must re-configure to avoid 
+this. 
+<P> A mailing list message on the topic from Pluto developer Hugh 
+Redelmeier: </P>
+<PRE>
+| I'm trying to get freeswan working between two machine where one has a ppp
+| interface.
+| I've already suceeded with  two machines with ethernet ports but  the ppp
+| interface is causing me problems.
+|  basically when I run ipsec start  i get
+| ipsec_setup: Starting FreeS/WAN IPSEC 1.7...
+| ipsec_setup: 003 IP interfaces ppp1 and ppp0 share address 192.168.0.10!
+| ipsec_setup: 003 IP interfaces ppp1 and ppp2 share address 192.168.0.10!
+| ipsec_setup: 003 IP interfaces ppp0 and ppp2 share address 192.168.0.10!
+| ipsec_setup: 003 no public interfaces found
+|
+| followed by lots of cannot work out interface for connection messages
+|
+| now I can specify the interface in ipsec.conf to be ppp0 , but this does
+| not affect the above behaviour. A quick look in server.c indicates that the
+| interfaces value  is not used but some sort of raw detect happens.
+|
+| I guess I could prevent the formation of the extra ppp interfaces or
+| allocate them different ip but I'd  rather not. if at all possible. Any
+| suggestions please.
+
+Pluto won't touch an interface that shares an IP address with another.
+This will eventually change, but it probably won't happen soon.
+
+For now, you will have to give the ppp1 and ppp2 different addresses.
+</PRE>
 <H2><A name="canI">Can I ...</A></H2>
 <H3><A name="reload">Can I reload connection info without restarting?</A>
 </H3>
@@ -13403,6 +14066,8 @@
 There may be more bits to look for, depending on what you are trying
 to do.
 </PRE>
+<P> Another useful command here is <NOBR><VAR>ipsec auto --replace 
+&lt;conn_name&gt;</VAR></NOBR> which re-reads data for a named connection. </P>
 <H3><A name="masq.faq">Can I use several masqueraded subnets?</A></H3>
  Yes. This is done all the time. See the discussion in our <A href="#route_or_not">
 setup</A> document. The only restriction is that the subnets on the two 
@@ -13482,24 +14147,27 @@
 a tunnel that pokes through both masquerades and delivers packets from <VAR>
 leftsubnet</VAR> to <VAR>rightsubnet</VAR> and vice versa. For this to 
 work, the two subnets <EM>must</EM> be distinct. </P>
-<P> There are only two solutions to this problem. </P>
+<P> There are several solutions to this problem. </P>
 <UL>
-<LI>Usually, you re-number the subnets. Perhaps the Vancouver office 
-becomes 192.168.101.0/24, Calgary 192.168.102.0/24 and so on. FreeS/WAN 
-can happily handle this. With, for example <VAR>
+<LI>Usually, you <STRONG>re-number the subnets</STRONG>. Perhaps the 
+Vancouver office becomes 192.168.101.0/24, Calgary 192.168.102.0/24 and 
+so on. FreeS/WAN can happily handle this. With, for example <VAR>
 leftsubnet=192.168.101.0/24</VAR> and <VAR>rightsubnet=192.168.102.0/24</VAR>
  in a connection description, any machine in Calgary can talk to any 
 machine in Vancouver. If you want to be more restrictive and use 
 something like <VAR>leftsubnet=192.168.101.128/25</VAR> and <VAR>
 rightsubnet=192.168.102.240/28</VAR> so only certain machines on each 
 end have access to the tunnel, that's fine too. </LI>
-<LI>Alternately, you can just give up routing directly to machines on 
-the subnets. Omit the <VAR>leftsubnet</VAR> and <VAR>rightsubnet</VAR>
- parameters from your connection descriptions. Your IPSEC tunnels will 
-then run between the public interfaces of the two firewalls. Packets 
-will be masqueraded both before they are put into tunnels and after 
-they emerge. Your Vancouver client machines will see only one Calgary 
-machine, the firewall. </LI>
+<LI>You could also <STRONG>split the subnet</STRONG> into smaller ones, 
+for example using <VAR>192.168.1.0/25</VAR> in Vancouver and <VAR>
+rightsubnet=192.168.0.128/25</VAR> in Calgary. </LI>
+<LI>Alternately, you can just <STRONG>give up routing</STRONG> directly 
+to machines on the subnets. Omit the <VAR>leftsubnet</VAR> and <VAR>
+rightsubnet</VAR> parameters from your connection descriptions. Your 
+IPSEC tunnels will then run between the public interfaces of the two 
+firewalls. Packets will be masqueraded both before they are put into 
+tunnels and after they emerge. Your Vancouver client machines will see 
+only one Calgary machine, the firewall. </LI>
 </UL>
 <H3><A name="road.masq">Can I assign a road warrior an address on my 
 net?</A></H3>
@@ -13539,8 +14207,145 @@
 DiffServ does not interact well with tunneling in general.  Ways of
 improving this are being studied.
 </PRE>
- See <A href="manpage.d/ipsec.conf.5.html">ipsec.conf(5)</A> for more 
-on the <VAR>hidetos=</VAR> parameter. <A name="PKIcert">
+<P> Copying the TOS information from the encapsulated packet to the 
+outer header reveals the TOS information to an eavesdropper. It is not 
+clear whether or how an attacker could use this information, but since 
+we do not have to give it to him, our default is not to. </P>
+<P> See <A href="manpage.d/ipsec.conf.5.html">ipsec.conf(5)</A> for 
+more on the <VAR>hidetos=</VAR> parameter. </P>
+<H3><A name="deadtunnel">Can I recognise dead tunnels and shut them 
+down?</A></H3>
+ There is no general mechanism to do this is in the IPSEC protocols. 
+<P> From time to time, there is discussion on the IETF Working Group <A href="#ietf">
+mailing list</A> of adding a &quot;keep-alive&quot; mechanism (which some say 
+should be called &quot;make-dead&quot;), but it is a fairly complex problem and 
+no consensus has been reached on whether or how it should be done. </P>
+<P> The protocol does have optional <A href="#ignore">delete-SA</A>
+ messages which one side can send when it closes a connection in hopes 
+this will cause the other side to do the same. FreeS/WAN does not 
+currently support these. In any case, they would not solve the problem 
+since: </P>
+<UL>
+<LI>a gateway that crashes or hangs would not send the messages </LI>
+<LI>the sender is not required to send them </LI>
+<LI>they are not authenticated, so any receiver that trusts them leaves 
+itself open to a <A href="#DOS">denial of service</A> attack </LI>
+<LI>the receiver is not required to do anything about them </LI>
+<LI>the receiver cannot acknowledge them; the protocol provides no 
+mechanism for that </LI>
+<LI>since they are not acknowledged, the sender cannot rely on them </LI>
+</UL>
+<P> However, connections do have limited lifetimes and you can control 
+how many attempts your gateway makes to rekey before giving up. For 
+example, you can set: </P>
+<PRE>
+conn default
+	keyingtries=3
+	keylife=30m
+</PRE>
+ With these settings old connections will be cleaned up. Within 30 
+minutes of the other end dying, rekeying will be attempted. If it 
+succeeds, the new connection replaces the old one. If it fails, no new 
+connection is created. Either way, the old connection is taken down 
+when its lifetime expires. 
+<P> Here is a mailing list message on the topic from FreeS/WAN tech 
+support person Claudia Schmeing: </P>
+<PRE>
+You ask how to determine whether a tunnel is redundant:
+
+&gt; Can anybody explain the best way to determine this. Esp when a RW has
+&gt; disconnected? I thought 'ipsec auto --status' might be one way.
+
+If a tunnel goes down from one end, Linux FreeS/WAN on the
+other end has no way of knowing this until it attempts to rekey.
+Once it tries to rekey and fails, it will 'know' that the tunnel is 
+down.
+
+Because it doesn't have a way of knowing the state until this point, 
+it will also not be able to tell you the state via ipsec auto --status.
+
+&gt; However, comparing output from a working tunnel with that of one that
+&gt; was closed 
+&gt; did not show clearly show tunnel status.
+
+If your tunnel is down but not 'unrouted' (see man ipsec_auto), you
+should not be able to ping the opposite side of the tunnel. You can
+use this as an indicator of tunnel status.
+
+On a related note, you may be interested to know that as of 1.7, 
+redundant tunnels caused by RW disconnections are likely to be 
+less of a pain. From doc/CHANGES:
+
+    There is a new configuration parameter, uniqueids, to control a new Pluto
+    option:  when a new connection is negotiated with the same ID as an old
+    one, the old one is deleted immediately.  This should help eliminate
+    dangling Road Warrior connections when the same Road Warrior reconnects. 
+    It thus requires that IDs not be shared by hosts (a previously legal but
+    probably useless capability).  NOTE WELL:  the sample ipsec.conf now has
+    uniqueids=yes in its config-setup section.
+
+
+Cheers,
+
+Claudia
+</PRE>
+<H3><A name="demanddial">Can I build tunnels over a demand-dialed link?</A>
+</H3>
+ This is possible, but not easy. FreeS/WAN technical lead Henry Spencer 
+wrote: 
+<PRE>
+&gt; 5. If the ISDN link goes down in between and is reestablished, the SAs
+&gt; are still up but the eroute are deleted and the IPSEC interface shows
+&gt; garbage (with ifconfig)
+&gt; 6. Only restarting IPSEC will bring the VPN back online.
+
+This one is awkward to solve.  If the real interface that the IPsec
+interface is mounted on goes down, it takes most of the IPsec machinery
+down with it, and a restart is the only good way to recover. 
+
+The only really clean fix, right now, is to split the machines in two: 
+
+1. A minimal machine serves as the network router, and only it is aware
+that the link goes up and down. 
+
+2. The IPsec is done on a separate gateway machine, which thinks it has
+a permanent network connection, via the router.
+
+This is clumsy but it does work.  Trying to do both functions within a
+single machine is tricky.  There is a software package (diald) which will
+give the illusion of a permanent connection for demand-dialed modem
+connections; I don't know whether it's usable for ISDN, or whether it can
+be made to cooperate properly with FreeS/WAN. 
+
+Doing a restart each time the interface comes up *does* work, although it
+is a bit painful.  I did that with PPP when I was running on a modem link;
+it wasn't hard to arrange the PPP scripts to bring IPsec up and down at
+the right times.  (I'd meant to investigate diald but never found time.)
+
+In principle you don't need to do a complete restart on reconnect, but you
+do have to rebuild some things, and we have no nice clean way of doing
+only the necessary parts.
+</PRE>
+ In the same thread, one user commented: 
+<PRE>
+Subject: Re: linux-ipsec: IPSEC and Dial Up Connections
+   Date: Wed, 22 Nov 2000
+   From: Andy Bradford &lt;andyb@calderasystems.com&gt;
+
+On Wed, 22 Nov 2000 19:47:11 +0100, Philip Reetz wrote:
+
+&gt; Are there any ideas what might be the cause of the problem and any way
+&gt; to work around it.
+&gt; Any help is highly appreciated.
+
+On my laptop, when using ppp there is a ip-up script in /etc/ppp that 
+will be executed each time that the ppp interface is brought up.  
+Likewise there is an ip-down script that is called when it is taken 
+down.  You might consider custimzing those to stop and start FreeS/Wan 
+with each connection.  I believe that ISDN uses the same files, though 
+I could be wrong---there should be something similar though.
+</PRE>
+<A name="PKIcert">
 <H3>Does FreeS/WAN support X.509 or other PKI certificates?</H3>
  FreeS/WAN, as distributed, does not currently support use of <A href="#X509">
 X.509</A> or other <A href="#PKI">PKI</A> certificates for 
@@ -13576,40 +14381,34 @@
 authentication. </LI>
 </UL>
  If either of those is trustworthy, it is not clear that you need user 
-authentication in IPSEC. <A name="noDES">
+authentication in IPSEC. <A name="noDES.faq">
 <H3>Does FreeS/WAN support single DES encryption?</H3>
  No, single DES is not used either at the <A href="#IKE">IKE</A> level 
 for negotiating connections or at the <A href="#IPSEC">IPSEC</A> level 
 for actually building them. 
-<P> Single DES is <A href="#desnotsecure">insecure</A>. <A name="DESstandard">
-</P>
-<H4>But isn't DES support part of the IPSEC standard?</H4>
- Yes, but <A href="#desnotsecure">DES is insecure</A>. As we see it, it 
-is more important to deliver real security than to comply with a 
+<P> Single DES is <A href="#desnotsecure">insecure</A>. As we see it, 
+it is more important to deliver real security than to comply with a 
 standard which has been subverted into allowing use of inadequate 
-methods. See this <A href="#weak">discussion</A>. <A name="DESonly">
-<H4>I have to talk to .... which offers only DES. How do I do this?</H4>
- Ask the device vendor for the <A href="#3DES">triple DES</A> upgrade. 
-These exist for many IPSEC devices. If no cipher stronger than DES is 
-available, we recommend you not use that IPSEC implementation. 
-<P> If a 3DES implementation exists but your vendor cannot sell it to 
-you because of export laws, consider complaining to one or more of: </P>
-<UL>
-<LI>the vendor </LI>
-<LI>your own government, especially any branch concerned with citizen's 
-privacy and/or protection of communication infrastructure </LI>
-<LI>the local embassy of the nation which restricts export to you </LI>
-</UL>
-<P> Consider using FreeS/WAN instead. PCs are cheap and we deliver 3DES 
-now. </P>
-<P> As a matter of project policy, we will not help anyone subvert 
-FreeS/WAN to provide <A href="#desnotsecure">insecure DES encryption</A>
-. </P>
-<H2><A name="spam">Why don't you restrict the mailing list to reduce 
+methods. See this <A href="#weak">discussion</A>. </P>
+<P> If you want to interoperate with an IPSEC implementation which 
+offers only DES, see our <A href="#noDES">interoperation</A> document. </P>
+<H2><A name="spam">Why don't you restrict the mailing lists to reduce 
 spam?</A></H2>
-<P> As a matter of policy, the list needs to be open to 
-non-subscribers. Project management feel strongly that maintaining this 
-openness is more important than blocking spam. </P>
+<P> As a matter of policy, some of our <A href="mail.html">mailing lists</A>
+ need to be open to non-subscribers. Project management feel strongly 
+that maintaining this openness is more important than blocking spam. </P>
+<UL>
+<LI>Users should be able to get help or report bugs without 
+subscribing. </LI>
+<LI>Even a user who is subscribed may not have access to his or her 
+subscribed account when he or she needs help, miles from home base in 
+the middle of setting up a client's gateway. </LI>
+<LI>There is arguably a legal requirement for this policy. A US 
+resident or citizen could be charged under munitions export laws for 
+providing technical assistance to a foreign cryptographic project. Such 
+a charge would be more easily defended if the discussion takes place in 
+public, on an open list. </LI>
+</UL>
 <P> This has been discussed several times at some length on the list. 
 See the <A href="#archive">list archives</A>. Bringing the topic up 
 again is unlikely to be useful. Please don't. Or at the very least, 
@@ -13621,10 +14420,19 @@
 The decision is final, and is not open to discussion.  This needs to be 
 communicated better to people, and steps are being taken to do that. </BLOCKQUOTE>
  Adding this FAQ section is one of the steps he refers to. </P>
-<P> You have various options other than just putting up with the spam 
-or unsubscribing: </P>
+<P> You have various options other than just putting up with the spam, 
+filtering it yourself, or unsubscribing: </P>
 <UL>
-<LI>read the list via one of its <A href="#archive">archives</A></LI>
+<LI>read the main list via one of its <A href="#archive">archives</A></LI>
+<LI>subscribe only to one or both of our lists with restricted posting 
+rules: 
+<UL>
+<LI><A href="mailto:briefs@lists.freeswan.org?body=subscribe">briefs</A>
+, weekly list summaries </LI>
+<LI><A href="mailto:announce@lists.freeswan.org?body=subscribe">announce</A>
+, project-related announcements </LI>
+</UL>
+</LI>
 <LI>subscribe to one or more of the <A href="#additional">other 
 FreeS/WAN-related lists</A>. </LI>
 </UL>
@@ -13647,7 +14455,8 @@
 filtering. </P>
 <P> For information on tracking down spammers, see these <A href="http://www.rahul.net/falk/#howtos">
 HowTos</A>, or the <A href="http://www.sputum.com/index2.html">Sputum</A>
- site. </P>
+ site. Sputum have a Linux anti-spam screensaver available for 
+download. </P>
 <P> Here is a more detailed message from Henry: </P>
 <PRE>
 On Mon, 15 Jan 2001, Jay Vaughan wrote:
@@ -13739,5 +14548,5 @@
         John Gilmore
         founder sponsor, FreeS/WAN project
 </PRE>
-</A></A></A></A></BODY>
+</A></A></A></BODY>
 </HTML>
diff -bruN freeswan-1.9.orig/doc/compat.html freeswan-1.9/doc/compat.html
--- freeswan-1.9.orig/doc/compat.html	Tue Mar 27 23:16:51 2001
+++ freeswan-1.9/doc/compat.html	Mon Jun  4 01:15:56 2001
@@ -15,11 +15,11 @@
 patchers and commenters there, especially the ones quoted below but 
  also various contributors we haven't quoted.</P>
 <H2><A name="spec">Implemented parts of the IPSEC Specification</A></H2>
-<P>In general, do not expect Linux FreeS/WAN to do everything yet. This 
-is a  work-in-progress and some parts of the IPSEC specification are 
-not yet  implemented.</P>
+<P> In general, do not expect Linux FreeS/WAN to do everything yet. 
+This is a work-in-progress and some parts of the IPSEC specification 
+are not yet implemented.</P>
 <H3><A name="in">In Linux FreeS/WAN</A></H3>
-<P>Things we do, as of version 1.9:</P>
+<P> Things we do, as of version 1.9:</P>
 <UL>
 <LI>key management methods 
 <DL>
@@ -59,10 +59,6 @@
 </LI>
 <LI>encryption transforms 
 <DL>
-<DT>null encryption (to use ESP as an authentication-only service) </DT>
-<DD>We implement this since the RFCs require it. Since it is  obviously 
-insecure, we disable it by default. It can be enabled  with a kernel 
-configuration option.</DD>
 <DT><A href="glossary.html#DES">DES</A></DT>
 <DD>DES is in the source code since it is needed to implement  3DES, 
 but single DES is not made available to users because <A href="politics.html#desnotsecure">
@@ -94,7 +90,9 @@
 </LI>
 </UL>
 <P> All combinations of implemented transforms are supported. Note that 
-some  form of authentication is recommended whenever encryption is used.</P>
+some form of packet-level <STRONG>authentication is required whenever 
+encryption is used</STRONG>. Without it, the encryption will not be 
+secure.</P>
 <H3><A name="dropped">Deliberately ommitted</A></H3>
  We do not implement everything in the RFCs because some of those 
 things are insecure. See our discussions of avoiding <A href="politics.html#weak">
@@ -102,16 +100,17 @@
 <P>
 <P> Things we deliberately omit which are required in the RFCs are:</P>
 <UL>
+<LI>null encryption (to use ESP as an authentication-only service) </LI>
 <LI>single DES </LI>
 <LI>DH group 1, a 768-bit modp group </LI>
 </UL>
-<P> Since these are the only encryption algorithm and DH group the RFCs 
-require, it is possible in theory to have a standards-conforming 
+<P> Since these are the only encryption algorithms and DH group the 
+RFCs require, it is possible in theory to have a standards-conforming 
 implementation which will not interpoperate with FreeS/WAN. Such an 
 implementation would be inherently insecure, so we do not consider this 
 a problem. Anyway, most implementations sensibly include more secure 
-options as well, so dropping single DES and Group 1 does not greatly 
-hinder interoperation in practice.</P>
+options as well, so dropping null encryption, single DES and Group 1 
+does not greatly hinder interoperation in practice.</P>
 <P> We also do not implement some optional features allowed by the 
 RFCs: </P>
 <UL>
@@ -127,7 +126,7 @@
 default. Typically, these are easily solved with a configuration change 
 that overrides that default.</P>
 <H3><A name="not">Not (yet) in Linux FreeS/WAN</A></H3>
-<P>Things we don't yet do, as of version 1.9:</P>
+<P> Things we don't yet do, as of version 1.91:</P>
 <UL>
 <LI>key management methods 
 <UL>
@@ -155,6 +154,9 @@
 <P>We expect eventually to do it using DNS. The newer versions of <A href="glossary.html#BIND">
 BIND</A> provide much of what we need but they are not  yet widespread 
 and our code to communicate with them is not  ready.</P>
+<P><STRONG> Update:</STRONG> As of 1.91, we have beta-testable code for 
+opportunistic encryption. See our <A href="config.html#oppex">
+configuration document</A>. </P>
 </UL>
 </LI>
 </UL>
@@ -175,6 +177,19 @@
 <LI>authentication transforms </LI>
 <P>No optional additional authentication transforms are currently 
  implemented and we do not forsee a need to add any soon.</P>
+<LI>Policy checking on decrypted packets </LI>
+<P> To fully comply with the RFCs, it is not enough just to accept only 
+packets  which survive any firewall rules in place to limit what IPSEC 
+packets get in,  and then pass KLIPS authentication. That is what 
+FreeS/WAN currently does. </P>
+<P> We should also apply additional tests, for example ensuring that 
+all packets  emerging from a particular tunnel have sourcen and 
+destination addresses that  fall within the subnets defined for that 
+tunnel, and that packets with those  addresses that did not emerge from 
+the appropriate tunnel are disallowed. </P>
+<P> This will be done as part of the KLIPS rewrite currently in 
+progress. See  these <A href="intro.html#applied">links</A> and the <A href="mail.html">
+ design mailing list</A> for discussion. </P>
 <H2><A name="pfkey">Our PF-Key implementation</A></H2>
 <P>We use PF-key Version Two for communication between the KLIPS kernel 
 code  and the Pluto Daemon. PF-Key v2 is defined by <A href="http://www.normos.org/ietf/rfc/rfc2367.txt">
@@ -188,34 +203,37 @@
 not  yet doing much upward communication from kernel to user space. 
 This will  change, but is not at the top of our priority list.</P>
 <H3><A name="pfk.port">PF-Key portability</A></H3>
-<P>PF-Key came out of Berkeley Unix work and is used in the various BSD 
-IPSEC  implementations. We assume also in This means there is some hope 
-of  porting our Pluto(8) to one of the BSD distributions or running 
-their  photurisd(8) on Linux if you prefer <A href="glossary.html#photuris">
+<P> PF-Key came out of Berkeley Unix work and is used in the various 
+BSD IPSEC implementations, and in Solaris. This means there is some 
+hope of porting our Pluto(8) to one of the BSD distributions, or of 
+running their photurisd(8) on Linux if you prefer <A href="glossary.html#photuris">
 Photuris</A> key  management over IKE.</P>
-<P>It is, however, more complex than that. The three PF-Key 
-implementations  we have looked at -- ours, OpenBSD and KAME -- all 
-have extensions beyond  the RFC, and the extensions are different. 
-There have been discussions aimed  at sorting out the differences, 
-perhaps for a version three PF-Key spec. All  players are in favour of 
-this, but everyone involved is busy and it is not  clear whether or 
-when these discussions might bear fruit.</P>
+<P> It is, however, more complex than that. The PK-Key RFC deliberately 
+deals only with keying, not policy management. The three PF-Key 
+implementations we have looked at -- ours, OpenBSD and KAME -- all have 
+extensions to deal with security policy, and the extensions are 
+different. There have been discussions aimed at sorting out the 
+differences, perhaps for a version three PF-Key spec. All players are 
+in favour of this, but everyone involved is busy and it is not clear 
+whether or when these discussions might bear fruit.</P>
 <H2><A name="otherk">Kernels other than 2.0.38 and 2.2.18</A></H2>
-<P>We develop and test on:</P>
+<P> We develop and test on:</P>
 <UL>
-<LI>Redhat 5.2 with a 2.0.38 kernel.</LI>
-<LI>Redhat 6.1 with a 2.2.18 kernel.</LI>
+<LI>Redhat 6.1 with a 2.2.19 kernel.</LI>
+<LI>Redhat 7.1 with a 2.4.4 kernel.</LI>
 </UL>
 <P> This is what we recommend. </P>
 <H3><A name="kernel">Other 2.0.x Intel Kernels</A></H3>
 <P> Consider upgrading to the 2.2 kernel series. If you want to stay 
-with the 2.0 series, then we strongly recommend 2.0.38. It has some 
-security patches not present in earlier 2.0 kernels.</P>
+with the 2.0 series, then we strongly recommend 2.0.39. Some useful 
+security patches were added in 2.0.38.</P>
 <P> Various versions of the code have run at various times on most 
-2.0.xx kernels, but the current version is tested only on 2.0.38 and is 
-unlikely to compile on older kernels. Some of our patches for older 
-kernels are shipped in 2.0.37 and later, so they are no longer provided 
-in FreeS/WAN.</P>
+2.0.xx kernels, but the current version is only lightly tested on 
+2.0.39, and not at all on older kernels. </P>
+<P> Some of our patches for older kernels are shipped in 2.0.37 and 
+later, so they are no longer provided in FreeS/WAN. This means recent 
+versions of FreeS/WAN will probably not compile om anything earlier 
+than 2.0.37.</P>
 <H3><A name="2.2">2.2 and 2.4 Kernels</A></H3>
 <DL>
 <DT>FreeS/WAN 1.0</DT>
@@ -226,12 +244,11 @@
 <DT>FreeS/WAN 1.9</DT>
 <DD>runs on 2.0, 2.2 or 2.4 kernels</DD>
 </DL>
-<P> We suggest the latest 2.2 kernel (2.2.18 at time of writing) for 
-production use. </P>
-<H2><A name="otherdist">Intel Linux distributions other than Redhat 5.x 
-and 6.x</A></H2>
-<P> We develop and test on Redhat 5.2 for 2.0 kernels, and on Redhat 
-6.1 for 2.2, so minor changes may be required for other distributions.</P>
+<P> We suggest the latest 2.2 kernel or 2.4 (2.2.19 or 2.4.5 at time of 
+writing) for production use. </P>
+<H2><A name="otherdist">Intel Linux distributions other than Redhat</A></H2>
+<P> We develop and test on Redhat 6.1 for 2.2 kernels, and on Redhat 
+7.1 for 2.4, so minor changes may be required for other distributions.</P>
 <H3><A name="rh7">Redhat 7.0</A></H3>
 <P> There are some problems with FreeS/WAN on Redhat 7.0, but they are 
 soluble. </P>
@@ -271,8 +288,8 @@
  Check the <A href="mail.html">mailing list</A> archive for more recent 
 news.
 <H3><A name="suse">SuSE Linux</A></H3>
-<P>SuSE 6.3 and later versions, at least in Europe, ship with FreeS/WAN 
- included.</P>
+<P> SuSE 6.3 and later versions, at least in Europe, ship with 
+FreeS/WAN included.</P>
 <P>Here are some notes for an earlier SuSE version.</P>
 <H4>SuSE Linux 5.3</H4>
 <PRE>Date: Mon, 30 Nov 1998
@@ -615,9 +632,8 @@
 made, but at time of writing (February 2001), the job is not complete. 
 For more recent information, check the <A href="mail.html">mailing list</A>
 .</P>
-<P> In short, Linux currently has both IPv6 support and IPSEC support, 
-but <STRONG>the two do not work together yet</STRONG>. We, and others, 
-are working on integrating them, but it is a substantial job. </P>
+<P> The first release of Linux IPv6 with FreeS/WAN support is now <A href="http://www.ipv6.iabg.de/downloadframe/index.html">
+ available</A>. </P>
 <H3><A name="v6.back">IPv6 background</A></H3>
 <P> IPv6 has been specified by an IETF <A href="http://www.ietf.org/html.charters/ipngwg-charter.html">
 working group</A>. The group's page lists over 30 RFCs to date, and 
diff -bruN freeswan-1.9.orig/doc/config.html freeswan-1.9/doc/config.html
--- freeswan-1.9.orig/doc/config.html	Tue Mar 27 23:16:51 2001
+++ freeswan-1.9/doc/config.html	Mon Jun  4 01:15:55 2001
@@ -497,14 +497,6 @@
 been removed in FreeS/WAN 1.9. However, if the other end of the tunnel 
 is an older version, the restriction will still apply there, so some 
 caution is still required. </P>
-<P>The <VAR>conn %default</VAR> section shipped in our example file 
-includes  parameters for manual keying. These are <STRONG>completely 
- insecure</STRONG>, intended only for testing. We recommend you leave 
-these  in place during testing since it is sometimes useful to be able 
-to test with  manual keying. Once testing is done, however, delete the 
-test keys or ensure  that they are commented out with # characters. 
-Production use of manual  keying is not recommended, but is possible 
-and is described in a <A href="#prodman"> later section</A>.</P>
 <H3><A name="edit.conn">Editing a connection description</A></H3>
 <P>Edit our example connection to match what you want to do.  Rename it 
  appropriately for the connection you would like to build: 
@@ -570,9 +562,9 @@
 The  file syntax allows names to be used, but this creates an 
 additional risk. If  someone can subvert the DNS service, then they can 
 redirect packets whose  addresses are looked up via that service.</P>
-<P>Many of the variables in this file come in pairs such as 
-&quot;leftsubnet: and  &quot;rightsubnet&quot;, one for each end of the connection. 
-The variables on the left  side are:</P>
+<P> Many of the variables in this file come in pairs such as 
+&quot;leftsubnet: and &quot;rightsubnet&quot;, one for each end of the connection. The 
+variables on the left side are:</P>
 <DL>
 <DT>left</DT>
 <DD>The gateway's external interface, the one it uses to talk to the 
@@ -600,14 +592,16 @@
 <DD>Addresses for the machines which left is protecting. 
 <UL>
 <LI>Often something like 101.202.203.0/24 to indicate that a subnet 
- resides behind left.</LI>
+ resides behind left. Often this subnet will be directly connected  to 
+left, but this not necessary. The only requirement is that left  must 
+be able to route to it.</LI>
 <LI>If you omit the leftsubnet line, then left is both the security 
  gateway and the only client on that end.</LI>
 </UL>
  For some applications, you may want to create two connections, one to 
  protect traffic from the subnet behind left and another to protect 
  traffic from the left gateway itself. This takes two connection 
- descriptions.</DD>
+ descriptions. See <A href="#multitunnel">below</A>.</DD>
 <DT>leftfirewall</DT>
 <DD>Set to &quot;yes&quot; if there is a firewall in play that suppresses 
  forwarding, for example if a subnet behind left uses non-routable 
@@ -864,19 +858,168 @@
 Practical Configurations</A> document also has an example  of using RSA 
 authentication for road warriors.</P>
 <H3><A name="oppex">Opportunistic encryption</A></H3>
-<P> This section is currently just a placeholder for the opportunistic 
-encryption documentation I'll write when the design has solidified 
-somewhat.</P>
-<H4><A name="dnskey">Putting public keys in DNS</A></H4>
-<P>Release 1.4 had the first experimental code to support fetching 
-public  key information from the other system's DNS entries. Even in 
-1.6, this is  still experimental code. You cannot trust it for 
-production use until</P>
+ We use the term <A href="glossary.html">opportunistic encryption</A>
+ for encryption which does not rely on any pre-arranged connection, 
+hence does not require that the administrators of the two gateways 
+involved communicate with each other (for example, to exchange keys) 
+before their systems can create a secure connection. 
+<P> The idea is that each gateway check the destinations of outgoing 
+packets, see if an encrypted connection is possible and, if so, take 
+the opportuntity to encrypt. The opportunity will exist whenever the 
+admins on both ends have set their systems up for opportunistic 
+encryption. </P>
+<P> This makes encryption the default behaviour, and could greatly 
+increase the overall security of the Internet if it were widely enough 
+adopted. See our documents: </P>
+<DL>
+<DT><A href="politics.html">history and politics</A></DT>
+<DD>for the reasons we want to do this </DD>
+<DT><A href="ipsec.html#traffic.resist">IPSEC protocols</A></DT>
+<DD>for discussion of the general principle of encrypting as much as 
+possible </DD>
+</DL>
+<P> The gateways must be able to authenticate each other for IPSEC to 
+be secure. For opportunistic encryption, we rely on the domain name 
+system, <A href="glossary.html">DNS</A>, to provide the RSA keys needed 
+for this authentication.  Note, that currently this is not entirely 
+secure because <STRONG>the DNS mechanism it relies on is not fully 
+secure</STRONG>. Eventually, as <A href="glossary.html#SDNS">secure DNS</A>
+ becomes widely deployed, this will change. </P>
+<H4><A name="opp.status">Status</A></H4>
+ The team have been working on this for some time, and testing 
+internally. As of late May, 2001 this code is ready for wider testing. <STRONG>
+We encourage everyone to try it.</STRONG>
+<P> The main documentation items so far are: </P>
+<UL>
+<LI>an <A href="opportunism.howto">Opportunism HowTo</A> by Pluto 
+programmer Hugh Redelmeier </LI>
+<LI>a design document by Hugh and technical lead Henry Spencer. A <A href="intro.html#applied">
+link</A> to this is in our introduction. </LI>
+</UL>
+ I am playing catch up; HTML documentation so far is neither complete 
+nor particularly clear. What I have so far is below. 
+<P> Note that both software and documentation for this are changing 
+quickly. You may want the latest snapshot for opportunism experiments. </P>
+<P><STRONG> We do not yet recommend this code for production use</STRONG>
+. You should still protect your critical data with explicitly 
+configured IPSEC tunnels, rather than relying on opportunistic for 
+everything at this stage. </P>
+<H4><A name="dns.background">Some DNS background</A></H4>
+<P> Opportunism requires that the gateway systems be able to fetch 
+public keys, and other IPSEC-related information, from each other's DNS 
+(domain name service) records. </P>
+<P> DNS is a distributed database that maps names to IP addresses and 
+vice versa. A system named gateway.example.com with IP address 
+10.20.30.40 should have at least two DNS records: </P>
+<DL>
+<DT>gateway.example.com. IN A 10.20.30.40 </DT>
+<DD>used to look up the name and get an IP address </DD>
+<DT>40.30.20.10.in-addr.arpa. IN PTR gateway.example.com. </DT>
+<DD>used for reverse lookups, looking up the name associated with an 
+address. Notice that the digits here are in reverse order; the actual 
+address is 10.20.30.40 but we use 40.30.20.10 here. </DD>
+</DL>
+ Some syntactic details are: 
 <UL>
-<LI>both our code is much better tested (you can help with that!)</LI>
-<LI>and <A href="glossary.html#SDNS">secure DNS</A> is widely deployed</LI>
-</UL>
-<P>The relevant lines in the config file would look like this:</P>
+<LI>the IN indicates that these records are for <STRONG>In</STRONG>
+ternet addresses </LI>
+<LI>The final periods in '.com.' and '.arpa.' are required. They 
+indicate the root of the domain name system. </LI>
+</UL>
+ For much more detail, see the <A href="http://www.linuxdoc.org/LDP/nag2/index.html">
+Linux Network Administrator's Guide</A> or a DNS <A href="biblio.html#DNS.book">
+reference book</A>. 
+<P> The capitalised strings after IN indicate the type of record. 
+Possible types include: </P>
+<UL>
+<LI><STRONG>A</STRONG>ddress </LI>
+<LI><STRONG>P</STRONG>oin<STRONG>T</STRONG>e<STRONG>R</STRONG></LI>
+<LI><STRONG>C</STRONG>anonical <STRONG>NAME</STRONG>, records to 
+support aliasing,  multiple names for one address </LI>
+<LI><STRONG>MX</STRONG>, used in mail handling </LI>
+<LI><STRONG>SIG</STRONG>nature, used in <A href="glossary.html#SDNS">
+secure DNS</A></LI>
+<LI><STRONG>KEY</STRONG>, used in <A href="glossary.html#SDNS">secure 
+DNS</A></LI>
+<LI><STRONG>T</STRONG>e<STRONG>XT</STRONG>, a multi-purpose record type </LI>
+</UL>
+ To set up for opportunistic encryption, you add some KEY and TXT 
+records to your DNS data. 
+<H4><A name="dnskey">Putting IPSEC information in DNS</A></H4>
+ There are two types of DNS record to be added: 
+<UL>
+<LI>each gateway must have a KEY record which other gateways can query 
+to fetch its RSA authentication key </LI>
+<LI>any client whose communications are to be protected by a gateway 
+must have a TXT record pointing to that machine as an authorised IPSEC 
+gateway </LI>
+</UL>
+<A href="manpage.d/ipsec_rsasigkey.8.html"> ipsec_rsasigkey(8)</A>
+ provides the key in DNS record format as a comment. You need to cut 
+and paste the comment from <A href="manpage.d/ipsec.secrets.5.html">
+ipsec.secrets(5)</A> (or wherever you have the private key) into the 
+appropriate place in the DNS records. 
+<P> There are two ways to handle this, depending on whether or not you 
+control the reverse lookup (in-addr.arpa.) sections of the DNS files 
+for your gateway. You must have control of the reverse DNS information 
+for clients or this cannot work at all. </P>
+<H5>If you control the gateway's reverse map</H5>
+ If you control the gateway's reverse map, you just add a KEY record 
+there. Here is an example, with many characters of the key itself left 
+out: 
+<PRE>
+40.30.20.10.in-addr.arpa. IN KEY 0x4200 4 1 AQNJjkKlIk9...nYyUkKK8
+</PRE>
+ This allows lookups on the IP address of the gateway to retrieve the 
+key. 
+<P> A client that wishes to be protected by Opportunistic Encryption 
+must include a special TXT record in its reverse-map. If you control 
+the gateway's reverse map, example client records would look like this: </P>
+<PRE>
+42.42.42.10.in-addr.arpa. IN PTR deepthought.example.com.
+42.42.42.10.in-addr.arpa. IN TXT &quot;X-IPsec-Server(10)=10.20.30.40 AQNJjkKlIk9...nYyUkKK8&quot;
+</PRE>
+ which can also be written as just: 
+<PRE>
+42.42.42.10.in-addr.arpa. IN PTR deepthought.example.com.
+                          IN TXT &quot;X-IPsec-Server(10)=10.20.30.40 AQNJjkKlIk9...nYyUkKK8&quot;
+</PRE>
+ This provides the IP address of the security gateway and the public 
+key which the gateway will use to authenticate itself. This is the 
+preferred variant. Using it, the remote system does one lookup and gets 
+everything it needs for IKE negotiations. 
+<H5>If you <EM>don't</EM> control the gateway's reverse map</H5>
+ The approach must be slightly different if you do not have control 
+over the contents of the reverse map for your gateway. Perhaps your ISP 
+controls that, and provides no way for you to put data into their maps. 
+Without that, you cannot set your gateway up to respond to incoming 
+opportunistic requests (short of changing ISPs, which you might 
+consider). 
+<P> However, suppose a friend over at example.org will let you put 
+things in their maps. That will allow you to set your gateway up to 
+handle opportunistic connections for which it is the initiator. </P>
+<P> You still need to be able to put data in the reverse map for your 
+clients. However, that data is slightly different: </P>
+<PRE>
+42.42.42.10.in-addr.arpa. IN PTR deepthought.example.com.
+                          IN TXT &quot;X-IPsec-Server(10)=something.example.org&quot;
+</PRE>
+ Over at example.org, your friend inserts these lines in the DNS data 
+files: 
+<PRE>
+something.example.org. IN A 10.20.30.40
+                       IN KEY 0x4200 4 1 AQNJjkKlIk9...nYyUkKK8
+</PRE>
+ Your gateway must identify itself in IKE as something.example.org, not 
+as gateway.example.com. You set that up via <VAR>leftid=</VAR> or <VAR>
+rightid=</VAR> entries in <A href="manpage.d/ipsec.conf.5.html">
+ipsec.conf(5)</A>. 
+<P> With this arrangement, the remote gateway does two lookups. First 
+it does a reverse lookup on the client IP address and finds the gateway 
+name  &quot;something.example.org&quot;. Then it looks up that name to get the IP 
+address and key for the gateway. </P>
+<H4><A name="opp.config">ipsec.conf entries for opportunism</A></H4>
+ The relevant lines in the config file would look like this:
 <PRE>
         leftid=@gateway.example.com
         leftrsasigkey=%dns
@@ -1136,13 +1279,13 @@
 <H3><A name="tcpdump">Testing with tcpdump</A></H3>
 <P> To verify that all is working, run tcpdump(8) on a machine which 
 can listen to the traffic between the gateways.</P>
-<P> This really has to be done from a third machine, not from one of 
-the gateways. On the gateways you'll see packets at intermediate stages 
-of processing and the result will be confusing. Also, both tcpdump(8) 
-and nmap(8) use the libpcap library. Some versions of that library 
-(e.g. the ones that shipped with Redhat 5) do not recognise ipsec? 
-devices and will generate &quot;bad physical medium&quot; error messages if you 
-try to use it with them.</P>
+<P> This is most easily done from a third machine, rather than from one 
+of the gateways. On the gateways you may see packets at intermediate 
+stages of processing and the result may be confusing. </P>
+<P> If the results make no sense at all, or you see &quot;bad physical 
+medium&quot; error messages, you probably have an outdated version of 
+tcpdump(8) that does not handle IPSEC at all. See our <A href="faq.html#tcpdump">
+FAQ</A>.</P>
 <P> The packets should, except for some of the header information, be 
 utterly unintelligible. The output of good encryption looks exactly 
 like random noise.</P>
@@ -1768,6 +1911,47 @@
 functionality. You cannot use them as gateways with a subnet behind 
 them. To get that functionality, you must upgrade to Windows 2000 
 server or the commercially available PGP products. </P>
+<H4><A name="advroute">One tunnel plus advanced routing</A></H4>
+ It is also possible to use the new routing features in 2.2 and later 
+kernels to avoid most needs for multple tunnels. Here is one mailing 
+list message on the topic: 
+<PRE>
+Subject: Re: linux-ipsec: IPSec packets not entering tunnel?
+   Date: Mon, 20 Nov 2000
+   From: Justin Guyett &lt;jfg@sonicity.com&gt;
+
+On Mon, 20 Nov 2000, Claudia Schmeing wrote:
+
+&gt; Right                                                         Left
+&gt;                      &quot;home&quot;                &quot;office&quot;
+&gt; 10.92.10.0/24 ---- 24.93.85.110 ========= 216.175.164.91 ---- 10.91.10.24/24
+&gt;
+&gt; I've created all four tunnels, and can ping to test each of them,
+&gt; *except* homegate-officenet.
+
+I keep wondering why people create all four tunnels.  Why not route
+traffic generated from home to 10.91.10.24/24 out ipsec0 with iproute2?
+And 99% of the time you don't need to access &quot;office&quot; directly, which
+means you can eliminate all but the subnet&lt;-&gt;subnet connection.
+</PRE>
+ and FreeS/WAN technical lead Henry Spencer's comment: 
+<PRE>
+&gt; I keep wondering why people create all four tunnels.  Why not route
+&gt; traffic generated from home to 10.91.10.24/24 out ipsec0 with iproute2?
+
+This is feasible, given some iproute2 attention to source addresses, but
+it isn't something we've documented yet... (partly because we're still
+making some attempt to support 2.0.xx kernels, which can't do this, but
+mostly because we haven't caught up with it yet).
+
+&gt; And 99% of the time you don't need to access &quot;office&quot; directly, which
+&gt; means you can eliminate all but the subnet&lt;-&gt;subnet connection.
+
+Correct in principle, but people will keep trying to ping to or from the
+gateways during testing, and sometimes they want to run services on the
+gateway machines too.
+
+</PRE>
 <H3><A name="biggate">Many tunnels from a single gateway</A></H3>
 <P> FreeS/WAN allows a single gateway machine to build tunnels to many 
 others. There may, however, be some problems for large numbers as 
@@ -1824,7 +2008,7 @@
 operations before receiving a reply from the peer.</P>
 <H3><A name="extruded">Extruded Subnets</A></H3>
 <P>What we call <A href="glossary.html#extruded">extruded subnets</A>
- are a special case  of <A href="glossary.html#VPN">VPNs</A>.</P>
+ are a special case  of <A href="web.html#VPN">VPNs</A>.</P>
 <P>If your buddy has some unused IP addresses, in his subnet far off at 
 the  other side of the Internet, he can loan them to you... provided 
 that the  connection between you and him is fast enough to carry all 
@@ -2075,31 +2259,47 @@
 <PRE>        ipsec setup restart</PRE>
 <P>Again, this breaks any existing connections.</P>
 <H3><A name="unencrypted">Unencrypted tunnels</A></H3>
-<P> Sometimes you will want to create a tunnel without encryption. The 
-IPSEC protocols provide two ways to do this, either using <A href="glossary.html#AH">
-AH</A> without <A href="glossary.html#ESP">ESP</A> or using ESP with 
-null encryption. With Linux FreeS/WAN, these are currently supported 
-for manually keyed connections, but not with automatic keying, so we'll 
-look at other solutions here.</P>
+<P> Sometimes you might want to create a tunnel without encryption. 
+Often this is a bad idea, even if you have some data which need not be 
+private. See this <A href="ipsec.html#traffic.resist">discussion</A>. </P>
+<P> The IPSEC protocols provide two ways to do build such tunnels, </P>
+<UL>
+<LI>using <A href="glossary.html#AH">AH</A> without <A href="glossary.html#ESP">
+ESP</A></LI>
+<LI>using ESP with null encryption. </LI>
+</UL>
+ Linux FreeS/WAN allows AH-only for manually keyed connections, but not 
+with automatic keying, and does not support null encryption, so we'll 
+look at other solutions here.
 <P> One situation in which this comes up is when otherwise some data 
 would be  encrypted twice. Alice wants a secure tunnel from her machine 
 to Bob's.  Since she's behind one security gateway and he's behind 
 another, part of the  tunnel that they build passes through the tunnel 
 that their site admins have  built between the gateways. All of Alice 
 and Bob's messages are encrypted  twice.</P>
-<P>There are several ways to handle this.</P>
+<P> There are several ways to handle this.</P>
 <UL>
 <LI>Just accept the overhead of double encryption. The site admins 
-might  choose this if policy says encrypt everything, if they don't 
-entirely  trust Alice and Bob, or if they don't feel the saved cycles 
-are worth  the time they'd need to build a non-encrypted tunnel for 
-Alice and Bob's  packets.</LI>
+might  choose this if any of the following apply: 
+<UL>
+<LI>policy says encrypt everything (usually, it should) </LI>
+<LI>they don't entirely trust Alice and Bob (usually, if they don't 
+have to, they  shouldn't) </LI>
+<LI>if they don't feel the saved cycles are worth the time they'd need 
+to  build a non-encrypted tunnel for Alice and Bob's packets (often, 
+they aren't) </LI>
+</UL>
+</LI>
 <LI>Use a plain IP-in-IP tunnel. These are not well documented. A good 
  starting point is in the Linux kernel source tree, in 
  /usr/src/linux/drivers/net/README.tunnel.</LI>
-<LI>Use a manually-keyed AH-only tunnel. This is recommended over ESP 
-with  null encryption.</LI>
+<LI>Use a manually-keyed AH-only tunnel.</LI>
 </UL>
+<P> Note that if Alice and Bob want end-to-end security, they must 
+build a tunnel end-to-end between their machines or use some other 
+end-to-end tool such as PGP or SSL that suits their data. The only 
+question is whether the admins build some special unencrypted tunnel 
+for those already-encrypted packets. </P>
 <HR>
 <A HREF="toc.html">Contents</a>
 <A HREF="install.html">Previous</a>
diff -bruN freeswan-1.9.orig/doc/faq.html freeswan-1.9/doc/faq.html
--- freeswan-1.9.orig/doc/faq.html	Tue Mar 27 23:16:52 2001
+++ freeswan-1.9/doc/faq.html	Mon Jun  4 01:15:57 2001
@@ -30,6 +30,8 @@
 <LI><A href="#old_to_new"> Can different FreeS/WAN versions talk to 
 each other?</A></LI>
 <LI><A href="#versions"> Does FreeS/WAN run on my version of Linux?</A></LI>
+<LI><A href="#k.versions"> Does FreeS/WAN run on the latest kernel 
+version?</A></LI>
 <LI><A href="#modify.faq"> Can I modify FreeS/WAN to ...?</A></LI>
 <LI><A href="#contrib.faq"> Can I contribute to the project?</A></LI>
 <LI><A href="#ddoc.faq">Is there detailed design documentation?</A></LI>
@@ -37,6 +39,7 @@
 <LI><A href="#compile.faq">Compilation problems</A></LI>
 <UL>
 <LI><A href="#gmp.h_missing">gmp.h: No such file or directory</A></LI>
+<LI><A href="#noVM">... virtual memory exhausted</A></LI>
 </UL>
 <LI><A href="#setup.faq"> Life's little mysteries</A></LI>
 <UL>
@@ -47,7 +50,10 @@
 <LI><A href="#down_route"> When a tunnel goes down, packets vanish</A></LI>
 <LI><A href="#firewall_ate">The firewall ate my packets!</A></LI>
 <LI><A href="#dropconn">Dropped connections</A></LI>
-<LI><A href="#tcpdump"> TCPdump on the gateway shows strange things</A></LI>
+<LI><A href="config.html#tcpdump"> TCPdump on the gateway shows strange 
+things</A></LI>
+<LI><A href="#no_trace"> Traceroute does not show anything between the 
+gateways</A></LI>
 </UL>
 <LI><A href="#man4debug">Testing in stages</A></LI>
 <UL>
@@ -66,9 +72,14 @@
 <LI><A href="#error"> Interpreting error messages</A></LI>
 <UL>
 <LI><A href="#unreachable">SIOCADDRT:Network is unreachable</A></LI>
+<LI><A href="#noKLIPS">ipsec_setup: Fatal error, kernel appears to lack 
+KLIPS</A></LI>
 <LI><A href="#conn_name">Connection names in Pluto error messages</A></LI>
 <LI><A href="#cantorient">Pluto: ... can't orient connection</A></LI>
 <LI><A href="#noconn"> Pluto: ... no connection is known</A></LI>
+<LI><A href="#nosuit"> Pluto: ... no suitable connection ...</A></LI>
+<LI><A href="#noconn.auth"> Pluto: ... no connection has been authorized</A>
+</LI>
 <LI><A href="#noDESsupport"> Pluto: ... OAKLEY_DES_CBC is not supported.</A>
 </LI>
 <LI><A href="#notransform"> Pluto: ... no acceptable transform</A></LI>
@@ -77,6 +88,9 @@
 <LI><A href="#kflags"> ipsec_setup: Cannot adjust kernel flags</A></LI>
 <LI><A href="#SAused"> ... trouble writing to /dev/ipsec ... SA already 
 in use</A></LI>
+<LI><A href="#ignore"> ... ignoring ... payload</A></LI>
+<LI><A href="#dup_address">ipsec_setup: ... interfaces ... and ... 
+share address ...</A></LI>
 </UL>
 <LI><A href="#canI">Can I ...</A></LI>
 <UL>
@@ -89,19 +103,18 @@
 net?</A></LI>
 <LI><A href="#QoS">Can I use Quality of Service routing with FreeS/WAN?</A>
 </LI>
+<LI><A href="#deadtunnel">Can I recognise dead tunnels and shut them 
+down?</A></LI>
+<LI><A href="#demanddial">Can I build tunnels over a demand-dialed link?</A>
+</LI>
 <LI><A href="#PKIcert"> Does FreeS/WAN support X.509 or other PKI 
 certificates?</A></LI>
 <LI><A href="#Radius"> Does FreeS/WAN support Radius or other user 
 authentication?</A></LI>
-<LI><A href="#noDES"> Does FreeS/WAN support single DES encryption?</A></LI>
-<UL>
-<LI><A href="#DESstandard"> But isn't DES support part of the IPSEC 
-standard?</A></LI>
-<LI><A href="#DESonly"> I have to talk to .... which offers only DES. 
-How do I do this?</A></LI>
-</UL>
+<LI><A href="#noDES.faq"> Does FreeS/WAN support single DES encryption?</A>
+</LI>
 </UL>
-<LI><A href="#spam">Why don't you restrict the mailing list to reduce 
+<LI><A href="#spam">Why don't you restrict the mailing lists to reduce 
 spam?</A></LI>
 </UL>
 <HR>
@@ -197,11 +210,56 @@
 compatibility</A> document. </P>
 <P> FreeS/WAN has been tested on multiprocessor Intel Linux and worked 
 there. Note, however, that we do not test this often and have never 
-tested on multiprocessor machines of other architectures. </P>
+tested on multiprocessor machines of other architectures. <A name="k.versions">
+</P>
+<H3>Does FreeS/WAN run on the latest kernel version?</H3>
+ Quite often, no. 
+<P> Released versions of FreeS/WAN generally run on whatever production 
+kernels were current at the time of the release. For example, FreeS/WAN 
+1.91 runs on kernel 2.2.19 or 2.4.5. Often they will run on slightly 
+earlier or later kernels as well, but we test on the current production 
+kernels, so those are strongly recommended. </P>
+<P> The kernel is under active development and it is not uncommon for 
+changes to appear that cause problems for FreeS/WAN. For example, 2.4.6 
+or 2.4.7 may have changes that break FreeS/WAN 1.91. Or not; you can't 
+tell in advance. When such changes appear, we put a fix in the 
+FreeS/WAN snapshots, and distribute it with our next release. </P>
+<P> However, this is not a top priority for us, and it may take 
+anything from a few days to several weeks for such a problem to find 
+its way to the top of our kernel programmer's todo list. In the 
+meanwhile, you have two choices: either stick with a slightly older 
+kernel, or fix the problem yourself and send us a patch. </P>
+<P> We don't even try to keep up with kernel changes outside the main 
+2.2 and 2.4 branches, such as the 2.4.x-ac patched versions from Alan 
+Cox or (when they appear) the 2.5 series of development kernels. We'd 
+rather work on developing the FreeS/WAN code than on chasing these 
+moving targets. </P>
 <H3><A name="modify.faq">Can I modify FreeS/WAN to ...?</A></H3>
  You are free to modify FreeS/WAN in any way. See the discussion of <A href="intro.html#licensing">
 licensing</A> in our introduction document. 
 <H3><A name="contrib.faq">Can I contribute to the project?</A></H3>
+ In general, we welcome contributions from the community. Various 
+contributed patches, either to fix bugs or to add features, have been 
+incorporated into our distribution. Other patches, not yet included in 
+the distribution, are listed in our <A href="web.html#patch">web links</A>
+ section. 
+<P> Users have also contributed heavily to documentation, both by 
+creating their own <A href="intro.html#howto">HowTos</A> and by posting 
+things on the <A href="mail.html">mailing lists</A> which I have quoted 
+in these HTML docs. </P>
+<P> There are, however, some caveats. </P>
+<P> FreeS/WAN is being implemented in Canada, by Canadians, largely to 
+ensure that is it is entirely free of export restrictions. See this <A href="politics.html#status">
+discussion</A>. We <STRONG>cannot accept code contributions from US 
+residents or citizens</STRONG>, not even one-line bugs fixes. The 
+reasons for this were recently discussed extensively on the mailing 
+list, in a thread starting <A href="http://www.sandelman.ottawa.on.ca/linux-ipsec/html/2001/01/msg00111.html">
+here</A>. </P>
+<P> Not all contributions are of interest to us. The project has a set 
+of fairly ambitious and quite specific goals, described in our <A href="intro.html#goals">
+introduction</A>. Contributions that lead toward these goals are likely 
+to be welcomed enthusiastically. Other contributions may be seen as 
+lower priority, or even as a distraction. </P>
 <H3><A name="ddoc.faq">Is there detailed design documentation?</A></H3>
  There are: 
 <UL>
@@ -233,6 +291,20 @@
 is <NOBR><VAR>apt-get install gmp2</VAR></NOBR>. </P>
 <P> For more information and the latest version, see the <A href="http://www.swox.com/gmp/">
 GMP home page</A>. </P>
+<H3><A name="noVM">... virtual memory exhausted</A></H3>
+ We have had several reports of this message appearing, all on SPARC 
+Linux. Here is a mailing message on a solution: 
+<PRE>
+&gt; ipsec_sha1.c: In function `SHA1Transform':
+&gt; ipsec_sha1.c:95: virtual memory exhausted
+
+I'm seeing exactly the same problem on an Ultra with 256MB ram and 500
+MB swap.  Except I am compiling version 1.5 and its Red Hat 6.2.
+
+I can get around this by using -O instead of -O2 for the optimization
+level.  So it is probably a bug in the optimizer on the sparc complier. 
+I'll try and chase this down on the sparc lists.
+</PRE>
 <H2><A name="setup.faq">Life's little mysteries</A></H2>
  FreeS/WAN is a fairly complex product. (Neither the networks it runs 
 on nor the protocols it uses are simple, so it could hardly be 
@@ -432,8 +504,9 @@
  using a different specification; the route is altered  as necessary) 
 without having a ``window'' in which packets  might go elsewhere based 
 on a more general route.  Such  a  route can be removed using the 
---unroute operation (and is  implicitly removed by --delete).  See also 
-this mailing list <A href="http://www.sandelman.ottawa.on.ca/linux-ipsec/html/2000/11/msg00523.html">
+--unroute operation (and is  implicitly removed by --delete). </BLOCKQUOTE>
+</P>
+<P> See also this mailing list <A href="http://www.sandelman.ottawa.on.ca/linux-ipsec/html/2000/11/msg00523.html">
 message</A>. </P>
 <H3><A name="firewall_ate">The firewall ate my packets!</A></H3>
  If firewalls filter out:
@@ -452,7 +525,7 @@
 any number of reasons, ranging from hardware failures to various 
 software problems such as the path MTU problems discussed <A href="#pmtu.broken">
 elsewhere in the FAQ</A>. Fortunately, various diagnostic tools exist 
-that help you sort many of the possible problems.</P>
+that help you sort out many of the possible problems.</P>
 <P> There is one situation, however, where FreeS/WAN (using default 
 settings) may destroy a connection for no readily apparent reason. This 
 occurs when things are <STRONG>misconfigured</STRONG> so that <STRONG>
@@ -461,7 +534,7 @@
 <P> In this situation, the first tunnel comes up fine and works until 
 the second is established. At that point, because of the way we track 
 connections internally, the first tunnel ceases to exist as far as this 
-gateway is concerned. Of course the far end does not know that and a 
+gateway is concerned. Of course the far end does not know that, and a 
 storm of error messages appears on both systems as it tries to use the 
 tunnel.</P>
 <P> If the far end gives up, goes back to square one and negotiates a 
@@ -543,6 +616,77 @@
 <P> Note that nothing on either subnet needs to change. This lets you 
 test most of your IPSEC setup before connecting to the insecure 
 Internet. </P>
+<H3><A name="no_trace">Traceroute does not show anything between the 
+gateways</A></H3>
+ As far as traceroute can see, the two gateways are one hop apart; the 
+data packet goes directly from one to the other through the tunnel. Of 
+course the outer packets that implement the tunnel pass through 
+whatever lies between the gateways, but  those packets are built and 
+dismantled by the gateways. Traceroute does not see them and cannot 
+report anything about their path. 
+<P> Here is a mailing list message with more detail. </P>
+<PRE>
+Date: Mon, 14 May 2001
+To: linux-ipsec@freeswan.org
+From: &quot;John S. Denker&quot; &lt;jsd@research.att.com&lt;
+Subject: Re: traceroute: one virtual hop
+
+At 02:20 PM 5/14/01 -0400, Claudia Schmeing wrote:
+&gt;
+&gt;&gt; &gt; A bonus question: traceroute in subnet to subnet enviroment looks like:
+&gt;&gt; &gt; 
+&gt;&gt; &gt; traceroute to andris.dmz (172.20.24.10), 30 hops max, 38 byte packets
+&gt;&gt; &gt; 1  drama (172.20.1.1)  0.716 ms  0.942 ms  0.434 ms
+&gt;&gt; &gt; 2  * * *
+&gt;&gt; &gt; 3  andris.dmz (172.20.24.10)  73.576 ms  78.858 ms  79.434 ms
+&gt;&gt; &gt; 
+&gt;&gt; &gt; Why aren't there the other hosts which take part in the delivery during 
+&gt;    * * * ?
+&gt;
+&gt;If there is an ipsec tunnel between GateA and Gate B, this tunnel forms a 
+&gt;'virtual wire'.  When it is tunneled, the original packet becomes an inner 
+&gt;packet, and new ESP and/or AH headers are added to create an outer packet 
+&gt;around it. You can see an example of how this is done for AH at 
+&gt;doc/ipsec.html#AH . For ESP it is similar.
+&gt;
+&gt;Think about the packet's path from the inner packet's perspective.
+&gt;It leaves the subnet, goes into the tunnel, and re-emerges in the second
+&gt;subnet. This perspective is also the only one available to the
+&gt;'traceroute' command when the IPSec tunnel is up.
+
+Claudia got this exactly right.  Let me just expand on a couple of points:
+
+*) GateB is exactly one (virtual) hop away from GateA.  This is how it
+would be if there were a physically private wire from A to B.  The
+virtually private connection should work the same, and it does.
+
+*) While the information is in transit from GateA to GateB, the hop count
+of the outer header (the &quot;envelope&quot;) is being decremented.  The hop count
+of the inner header (the &quot;contents&quot; of the envelope) is not decremented and
+should not be decremented.  The hop count of the outer header is not
+derived from and should not be derived from the hop count of the inner header.
+
+Indeed, even if the packets did time out in transit along the tunnel, there
+would be no way for traceroute to find out what happened.  Just as
+information cannot leak _out_ of the tunnel to the outside, information
+cannot leak _into_ the tunnel from outside, and this includes ICMP messages
+from routers along the path.
+
+There are some cases where one might wish for information about what is
+happening at the IP layer (below the tunnel layer) -- but the protocol
+makes no provision for this.  This raises all sorts of conceptual issues.
+AFAIK nobody has ever cared enough to really figure out what _should_
+happen, let alone implement it and standardize it.
+
+*) I consider the &quot;* * *&quot; to be a slight bug.  One might wish for it to be
+replaced by &quot;GateB GateB GateB&quot;.  It has to do with treating host-to-subnet
+traffic different from subnet-to-subnet traffic (and other gory details).
+I fervently hope KLIPS2 will make this problem go away.
+
+*) If you want to ask questions about the link from GateA to GateB at the
+IP level (below the tunnel level), you have to ssh to GateA and launch a
+traceroute from there.
+</PRE>
 <H2><A name="man4debug">Testing in stages</A></H2>
 <P> It is often useful in debugging to test things one at a time:</P>
 <UL>
@@ -591,13 +735,18 @@
 UDP port 500 packets used in key negotiation. 
 <P> Other possibilities:</P>
 <UL>
-<LI>mis-configuration of auto connection in the /etc/ipsec.conf file</LI>
+<LI>mis-configuration of auto connection in the /etc/ipsec.conf file. </LI>
+<P>One common  configuration error is forgetting that you need <VAR>
+auto=add</VAR> to load the  connection description on the receiving end 
+so it recognises the connection  when the other end asks for it.</P>
 <LI>error in shared secret in /etc/ipsec.secrets</LI>
 <LI>one gateway lacks a route to the other so Pluto's UDP packets are 
  lost</LI>
 <LI>bugs in Pluto</LI>
 <LI>incompatibilities between Pluto's <A href="glossary.html#IKE">IKE</A>
- implementation and the IKE at the other end of the tunnel.</LI>
+ implementation and the IKE at the other end of the tunnel. </LI>
+<P>Some possibile problems  are discussed in out <A href="interop.html#interop.problem">
+interoperation</A> document.</P>
 </UL>
 <H3><A name="nocomp">IPSEC works, but connections using compression fail</A>
 </H3>
@@ -691,6 +840,37 @@
  Since the above message was written, we have modified the updown 
 script to provide a better diagnostic for this problem. Check <VAR>
 /var/log/messages</VAR>. 
+<H3><A name="noKLIPS">ipsec_setup: Fatal error, kernel appears to lack 
+KLIPS</A></H3>
+ This message indicates an installation failure. The kernel you are 
+running does not contain the KLIPS (kernel IPSEC) code.
+<P>
+<P> Here is one of Claudia's messages on the topic: </P>
+<PRE>
+&gt; I tried to install freeswan 1.8 on my mandrake 7.2 test box. ...
+
+&gt; It does show version and some output for whack.
+
+Yes, because the Pluto (daemon) part of ipsec is installed correctly, but
+as we see below the kernel portion is not.
+
+&gt; However, I get the following from /var/log/messages:
+&gt; 
+&gt; Mar 11 22:11:55 pavillion ipsec_setup: Starting FreeS/WAN IPSEC 1.8...
+&gt; Mar 11 22:12:02 pavillion ipsec_setup: modprobe: Can't locate module ipsec
+&gt; Mar 11 22:12:02 pavillion ipsec_setup: Fatal error, kernel appears to lack
+&gt; KLIPS.
+
+This is your problem. You have not successfully installed a kernel with
+IPSec machinery in it. 
+
+Did you build Linux FreeS/WAN as a module? If so, you need to ensure that 
+your new module has been installed in the directory where your kernel 
+loader normally finds your modules. If not, you need to ensure
+that the new IPSec-enabled kernel is being loaded correctly.
+
+See also doc/install.html, and INSTALL in the distro.
+</PRE>
 <H3><A name="conn_name">Connection names in Pluto error messages</A></H3>
 <P> From Pluto programmer Hugh Redelmeier:</P>
 <PRE>
@@ -733,11 +913,11 @@
 connection and Pluto does not have a connection description that 
 matches what the remote system has requested. The most common cause is 
 a configuration error on one end or the other. 
-<P> The match involves the <VAR>left</VAR>, <VAR>right</VAR>, <VAR>
-leftsubnet</VAR> and <VAR>rightsubnet</VAR> parameters and must be 
-exact. For example, if your left subnet is a.b.c.0/24 then neither a 
-single machine in that net nor a smaller subnet such as a.b.c.64/26 
-will be considered a match. </P>
+<P> Parameters involved in this match are <VAR>left</VAR>, <VAR>right</VAR>
+, <VAR>leftsubnet</VAR> and <VAR>rightsubnet</VAR>. </P>
+<P><STRONG> The match must be exact</STRONG>. For example, if your left 
+subnet is a.b.c.0/24 then neither a single machine in that net nor a 
+smaller subnet such as a.b.c.64/26 will be considered a match. </P>
 <P> The message can also occur when an appropriate description exists 
 but Pluto has not loaded it. Use an <VAR>auto=add</VAR> statement in 
 the connection description, or an <VAR>ipsec auto --add &lt;conn_name&gt;</VAR>
@@ -766,13 +946,91 @@
 The leftsubnet= (client) in your conn is 216.112.83.64/26.  It must
 exactly match what pluto is looking for, and it does not.
 </PRE>
+<H3><A name="nosuit">Pluto: ... no suitable connection ...</A></H3>
+ This is similar to the <A href="#noconn">no connection known</A>
+ error, but occurs at a different point in Pluto processing. 
+<P> Here is one of Claudia's messages explaining the problem: </P>
+<PRE>
+You write,
+
+&gt; What could be the reason of the following error? 
+&gt; &quot;no suitable connection for peer '@xforce'&quot;
+
+When a connection is initiated by the peer, Pluto must choose which entry in 
+the conf file best matches the incoming connection. A preliminary choice is 
+made on the basis of source and destination IPs, since that information is 
+available at that time. 
+
+A payload containing an ID arrives later in the negotiation. Based on this
+id and the *id= parameters, Pluto refines its conn selection. ...
+
+The message &quot;no suitable connection&quot; indicates that in this refining step,
+Pluto does not find a connection that matches that ID.
+
+Please see &quot;Selecting a connection when responding&quot; in man ipsec_pluto for
+more details.
+</PRE>
+<P> See also <A href="#conn_name">Connection names in Pluto error 
+messages</A>. </P>
+<H3><A name="noconn.auth">Pluto: ... no connection has been authorized</A>
+</H3>
+ Here is one of Claudia's messages discussing this problem: 
+<PRE>
+You write,
+
+&gt;  May 22 10:46:31 debian Pluto[25834]: packet from x.y.z.p:10014: 
+&gt;  initial Main Mode message from x.y.z.p:10014 
+                            but no connection has been authorized
+
+This error occurs early in the connection negotiation process,
+at the first step of IKE negotiation (Main Mode), which is itself the 
+first of two negotiation phases involved in creating an IPSec connection.
+
+Here, Linux FreeS/WAN receives a packet from a potential peer, which 
+requests that they begin discussing a connection.
+
+The &quot;no connection has been authorized&quot; means that there is no connection 
+description in Linux FreeS/WAN's internal database that can be used to 
+link your ipsec interface with that peer.
+
+
+
+&quot;But of course I configured that connection!&quot; 
+
+It may be that the appropriate connection description exists in ipsec.conf 
+but has not been added to the database with ipsec auto --add myconn or the 
+auto=add method. Or, the connection description may be misconfigured.
+
+The only parameters that are relevant in this decision are left= and right= .
+Local and remote ports are also taken into account -- we see that the port 
+is printed in the message above -- but there is no way to control these
+in ipsec.conf.
+
+
+Failure at &quot;no connection has been authorized&quot; is similar to the
+&quot;no connection is known for...&quot; error in the FAQ, and the &quot;no suitable
+connection&quot; error described in the snapshot's FAQ. In all three cases,
+Linux FreeS/WAN is trying to match parameters received in the
+negotiation with the connection description in the local config file.
+
+As it receives more information, its matches take more parameters into 
+account, and become more precise:  first the pair of potential peers,
+then the peer IDs, then the endpoints (including any subnets).
+
+The &quot;no suitable connection for peer *&quot; occurs toward the end of IKE 
+(Main Mode) negotiation, when the IDs are matched.
+
+&quot;no connection is known for a/b===c...d&quot; is seen at the beginning of IPSec 
+(Quick Mode, phase 2) negotiation, when the connections are matched using
+left, right, and any information about the subnets.
+</PRE>
 <H3><A name="noDESsupport">Pluto: ... OAKLEY_DES_CBC is not supported.</A>
 </H3>
  This message occurs when the other system attempts to negotiate a 
 connection using single DES, which we do not support because it is <A href="politics.html#desnotsecure">
 insecure</A>. 
-<P> Another FAQ section describes <A href="#noDES">how to deal with</A>
- systems that attempt to use single DES. </P>
+<P> Our interoperation document has suggestions for <A href="interop.html#noDES">
+ how to deal with</A> systems that attempt to use single DES. </P>
 <H3><A name="notransform"> Pluto: ... no acceptable transform</A></H3>
  This message means that the other gateway has made a proposal for 
 connection parameters, but nothing they proposed is acceptable to 
@@ -782,10 +1040,10 @@
 <LI>policy incompatibilities, for example we require encrypted 
 connections but they are trying to create one with just authentication </LI>
 <LI>interoperation problems, for example they offer only single DES and 
-FreeS/WAN does not support that. (see <A href="#noDES">below</A> for 
-DES problems) </LI>
+FreeS/WAN does not support that. (see <A href="interop.html#noDES">below</A>
+ for DES problems) </LI>
 </UL>
- A more detailed explanation, from Pluto programmer Hugh Redelmaier:
+ A more detailed explanation, from Pluto programmer Hugh Redelmeier:
 <PRE>
 Background:
 
@@ -956,6 +1214,54 @@
 </PRE>
  This problem is also discussed in this FAQ under the heading <A href="#spi_error">
 One manual connection works, but second one fails</A>. 
+<H3><A name="ignore">... ignoring ... payload</A></H3>
+ This message is harmless. The IKE protocol provides for a number of 
+optional messages types: 
+<UL>
+<LI>delete SA </LI>
+<LI>initial contact </LI>
+<LI>vendor ID </LI>
+<LI> ... </LI>
+</UL>
+ An implementation is never required to send these, but they are 
+allowed to.  The receiver is not required to do anything with them. 
+FreeS/WAN ignores them, but notifies you via the logs. 
+<P> For the &quot;ignoring delete SA Payload&quot; message, see also the 
+discussion below of cleaning up <A href="#deadtunnel">dead tunnels</A>. </P>
+<H3><A name="dup_address">ipsec_setup: ... interfaces ... and ... share 
+address ...</A></H3>
+ This is a fatal error. FreeS/WAN cannot cope with two or more 
+interfaces using the same IP address. You must re-configure to avoid 
+this. 
+<P> A mailing list message on the topic from Pluto developer Hugh 
+Redelmeier: </P>
+<PRE>
+| I'm trying to get freeswan working between two machine where one has a ppp
+| interface.
+| I've already suceeded with  two machines with ethernet ports but  the ppp
+| interface is causing me problems.
+|  basically when I run ipsec start  i get
+| ipsec_setup: Starting FreeS/WAN IPSEC 1.7...
+| ipsec_setup: 003 IP interfaces ppp1 and ppp0 share address 192.168.0.10!
+| ipsec_setup: 003 IP interfaces ppp1 and ppp2 share address 192.168.0.10!
+| ipsec_setup: 003 IP interfaces ppp0 and ppp2 share address 192.168.0.10!
+| ipsec_setup: 003 no public interfaces found
+|
+| followed by lots of cannot work out interface for connection messages
+|
+| now I can specify the interface in ipsec.conf to be ppp0 , but this does
+| not affect the above behaviour. A quick look in server.c indicates that the
+| interfaces value  is not used but some sort of raw detect happens.
+|
+| I guess I could prevent the formation of the extra ppp interfaces or
+| allocate them different ip but I'd  rather not. if at all possible. Any
+| suggestions please.
+
+Pluto won't touch an interface that shares an IP address with another.
+This will eventually change, but it probably won't happen soon.
+
+For now, you will have to give the ppp1 and ppp2 different addresses.
+</PRE>
 <H2><A name="canI">Can I ...</A></H2>
 <H3><A name="reload">Can I reload connection info without restarting?</A>
 </H3>
@@ -984,6 +1290,8 @@
 There may be more bits to look for, depending on what you are trying
 to do.
 </PRE>
+<P> Another useful command here is <NOBR><VAR>ipsec auto --replace 
+&lt;conn_name&gt;</VAR></NOBR> which re-reads data for a named connection. </P>
 <H3><A name="masq.faq">Can I use several masqueraded subnets?</A></H3>
  Yes. This is done all the time. See the discussion in our <A href="config.html#route_or_not">
 setup</A> document. The only restriction is that the subnets on the two 
@@ -1063,24 +1371,27 @@
 a tunnel that pokes through both masquerades and delivers packets from <VAR>
 leftsubnet</VAR> to <VAR>rightsubnet</VAR> and vice versa. For this to 
 work, the two subnets <EM>must</EM> be distinct. </P>
-<P> There are only two solutions to this problem. </P>
+<P> There are several solutions to this problem. </P>
 <UL>
-<LI>Usually, you re-number the subnets. Perhaps the Vancouver office 
-becomes 192.168.101.0/24, Calgary 192.168.102.0/24 and so on. FreeS/WAN 
-can happily handle this. With, for example <VAR>
+<LI>Usually, you <STRONG>re-number the subnets</STRONG>. Perhaps the 
+Vancouver office becomes 192.168.101.0/24, Calgary 192.168.102.0/24 and 
+so on. FreeS/WAN can happily handle this. With, for example <VAR>
 leftsubnet=192.168.101.0/24</VAR> and <VAR>rightsubnet=192.168.102.0/24</VAR>
  in a connection description, any machine in Calgary can talk to any 
 machine in Vancouver. If you want to be more restrictive and use 
 something like <VAR>leftsubnet=192.168.101.128/25</VAR> and <VAR>
 rightsubnet=192.168.102.240/28</VAR> so only certain machines on each 
 end have access to the tunnel, that's fine too. </LI>
-<LI>Alternately, you can just give up routing directly to machines on 
-the subnets. Omit the <VAR>leftsubnet</VAR> and <VAR>rightsubnet</VAR>
- parameters from your connection descriptions. Your IPSEC tunnels will 
-then run between the public interfaces of the two firewalls. Packets 
-will be masqueraded both before they are put into tunnels and after 
-they emerge. Your Vancouver client machines will see only one Calgary 
-machine, the firewall. </LI>
+<LI>You could also <STRONG>split the subnet</STRONG> into smaller ones, 
+for example using <VAR>192.168.1.0/25</VAR> in Vancouver and <VAR>
+rightsubnet=192.168.0.128/25</VAR> in Calgary. </LI>
+<LI>Alternately, you can just <STRONG>give up routing</STRONG> directly 
+to machines on the subnets. Omit the <VAR>leftsubnet</VAR> and <VAR>
+rightsubnet</VAR> parameters from your connection descriptions. Your 
+IPSEC tunnels will then run between the public interfaces of the two 
+firewalls. Packets will be masqueraded both before they are put into 
+tunnels and after they emerge. Your Vancouver client machines will see 
+only one Calgary machine, the firewall. </LI>
 </UL>
 <H3><A name="road.masq">Can I assign a road warrior an address on my 
 net?</A></H3>
@@ -1120,8 +1431,146 @@
 DiffServ does not interact well with tunneling in general.  Ways of
 improving this are being studied.
 </PRE>
- See <A href="manpage.d/ipsec.conf.5.html">ipsec.conf(5)</A> for more 
-on the <VAR>hidetos=</VAR> parameter. <A name="PKIcert">
+<P> Copying the TOS information from the encapsulated packet to the 
+outer header reveals the TOS information to an eavesdropper. It is not 
+clear whether or how an attacker could use this information, but since 
+we do not have to give it to him, our default is not to. </P>
+<P> See <A href="manpage.d/ipsec.conf.5.html">ipsec.conf(5)</A> for 
+more on the <VAR>hidetos=</VAR> parameter. </P>
+<H3><A name="deadtunnel">Can I recognise dead tunnels and shut them 
+down?</A></H3>
+ There is no general mechanism to do this is in the IPSEC protocols. 
+<P> From time to time, there is discussion on the IETF Working Group <A href="mail.htl#ietf">
+mailing list</A> of adding a &quot;keep-alive&quot; mechanism (which some say 
+should be called &quot;make-dead&quot;), but it is a fairly complex problem and 
+no consensus has been reached on whether or how it should be done. </P>
+<P> The protocol does have optional <A href="#ignore">delete-SA</A>
+ messages which one side can send when it closes a connection in hopes 
+this will cause the other side to do the same. FreeS/WAN does not 
+currently support these. In any case, they would not solve the problem 
+since: </P>
+<UL>
+<LI>a gateway that crashes or hangs would not send the messages </LI>
+<LI>the sender is not required to send them </LI>
+<LI>they are not authenticated, so any receiver that trusts them leaves 
+itself open to a <A href="glossary.html#DOS">denial of service</A>
+ attack </LI>
+<LI>the receiver is not required to do anything about them </LI>
+<LI>the receiver cannot acknowledge them; the protocol provides no 
+mechanism for that </LI>
+<LI>since they are not acknowledged, the sender cannot rely on them </LI>
+</UL>
+<P> However, connections do have limited lifetimes and you can control 
+how many attempts your gateway makes to rekey before giving up. For 
+example, you can set: </P>
+<PRE>
+conn default
+	keyingtries=3
+	keylife=30m
+</PRE>
+ With these settings old connections will be cleaned up. Within 30 
+minutes of the other end dying, rekeying will be attempted. If it 
+succeeds, the new connection replaces the old one. If it fails, no new 
+connection is created. Either way, the old connection is taken down 
+when its lifetime expires. 
+<P> Here is a mailing list message on the topic from FreeS/WAN tech 
+support person Claudia Schmeing: </P>
+<PRE>
+You ask how to determine whether a tunnel is redundant:
+
+&gt; Can anybody explain the best way to determine this. Esp when a RW has
+&gt; disconnected? I thought 'ipsec auto --status' might be one way.
+
+If a tunnel goes down from one end, Linux FreeS/WAN on the
+other end has no way of knowing this until it attempts to rekey.
+Once it tries to rekey and fails, it will 'know' that the tunnel is 
+down.
+
+Because it doesn't have a way of knowing the state until this point, 
+it will also not be able to tell you the state via ipsec auto --status.
+
+&gt; However, comparing output from a working tunnel with that of one that
+&gt; was closed 
+&gt; did not show clearly show tunnel status.
+
+If your tunnel is down but not 'unrouted' (see man ipsec_auto), you
+should not be able to ping the opposite side of the tunnel. You can
+use this as an indicator of tunnel status.
+
+On a related note, you may be interested to know that as of 1.7, 
+redundant tunnels caused by RW disconnections are likely to be 
+less of a pain. From doc/CHANGES:
+
+    There is a new configuration parameter, uniqueids, to control a new Pluto
+    option:  when a new connection is negotiated with the same ID as an old
+    one, the old one is deleted immediately.  This should help eliminate
+    dangling Road Warrior connections when the same Road Warrior reconnects. 
+    It thus requires that IDs not be shared by hosts (a previously legal but
+    probably useless capability).  NOTE WELL:  the sample ipsec.conf now has
+    uniqueids=yes in its config-setup section.
+
+
+Cheers,
+
+Claudia
+</PRE>
+<H3><A name="demanddial">Can I build tunnels over a demand-dialed link?</A>
+</H3>
+ This is possible, but not easy. FreeS/WAN technical lead Henry Spencer 
+wrote: 
+<PRE>
+&gt; 5. If the ISDN link goes down in between and is reestablished, the SAs
+&gt; are still up but the eroute are deleted and the IPSEC interface shows
+&gt; garbage (with ifconfig)
+&gt; 6. Only restarting IPSEC will bring the VPN back online.
+
+This one is awkward to solve.  If the real interface that the IPsec
+interface is mounted on goes down, it takes most of the IPsec machinery
+down with it, and a restart is the only good way to recover. 
+
+The only really clean fix, right now, is to split the machines in two: 
+
+1. A minimal machine serves as the network router, and only it is aware
+that the link goes up and down. 
+
+2. The IPsec is done on a separate gateway machine, which thinks it has
+a permanent network connection, via the router.
+
+This is clumsy but it does work.  Trying to do both functions within a
+single machine is tricky.  There is a software package (diald) which will
+give the illusion of a permanent connection for demand-dialed modem
+connections; I don't know whether it's usable for ISDN, or whether it can
+be made to cooperate properly with FreeS/WAN. 
+
+Doing a restart each time the interface comes up *does* work, although it
+is a bit painful.  I did that with PPP when I was running on a modem link;
+it wasn't hard to arrange the PPP scripts to bring IPsec up and down at
+the right times.  (I'd meant to investigate diald but never found time.)
+
+In principle you don't need to do a complete restart on reconnect, but you
+do have to rebuild some things, and we have no nice clean way of doing
+only the necessary parts.
+</PRE>
+ In the same thread, one user commented: 
+<PRE>
+Subject: Re: linux-ipsec: IPSEC and Dial Up Connections
+   Date: Wed, 22 Nov 2000
+   From: Andy Bradford &lt;andyb@calderasystems.com&gt;
+
+On Wed, 22 Nov 2000 19:47:11 +0100, Philip Reetz wrote:
+
+&gt; Are there any ideas what might be the cause of the problem and any way
+&gt; to work around it.
+&gt; Any help is highly appreciated.
+
+On my laptop, when using ppp there is a ip-up script in /etc/ppp that 
+will be executed each time that the ppp interface is brought up.  
+Likewise there is an ip-down script that is called when it is taken 
+down.  You might consider custimzing those to stop and start FreeS/Wan 
+with each connection.  I believe that ISDN uses the same files, though 
+I could be wrong---there should be something similar though.
+</PRE>
+<A name="PKIcert">
 <H3>Does FreeS/WAN support X.509 or other PKI certificates?</H3>
  FreeS/WAN, as distributed, does not currently support use of <A href="glossary.html#x509">
 X.509</A> or other <A href="glossary.html#PKI">PKI</A> certificates for 
@@ -1157,42 +1606,36 @@
 authentication. </LI>
 </UL>
  If either of those is trustworthy, it is not clear that you need user 
-authentication in IPSEC. <A name="noDES">
+authentication in IPSEC. <A name="noDES.faq">
 <H3>Does FreeS/WAN support single DES encryption?</H3>
  No, single DES is not used either at the <A href="glossary.html#IKE">
 IKE</A> level for negotiating connections or at the <A href="glossary.html#IPSEC">
 IPSEC</A> level for actually building them. 
-<P> Single DES is <A href="politics.html#desnotsecure">insecure</A>. <A name="DESstandard">
-</P>
-<H4>But isn't DES support part of the IPSEC standard?</H4>
- Yes, but <A href="politics.html#desnotsecure">DES is insecure</A>. As 
+<P> Single DES is <A href="politics.html#desnotsecure">insecure</A>. As 
 we see it, it is more important to deliver real security than to comply 
 with a standard which has been subverted into allowing use of 
 inadequate methods. See this <A href="politics.html#weak">discussion</A>
-. <A name="DESonly">
-<H4>I have to talk to .... which offers only DES. How do I do this?</H4>
- Ask the device vendor for the <A href="glossary.html#3DES">triple DES</A>
- upgrade. These exist for many IPSEC devices. If no cipher stronger 
-than DES is available, we recommend you not use that IPSEC 
-implementation. 
-<P> If a 3DES implementation exists but your vendor cannot sell it to 
-you because of export laws, consider complaining to one or more of: </P>
-<UL>
-<LI>the vendor </LI>
-<LI>your own government, especially any branch concerned with citizen's 
-privacy and/or protection of communication infrastructure </LI>
-<LI>the local embassy of the nation which restricts export to you </LI>
-</UL>
-<P> Consider using FreeS/WAN instead. PCs are cheap and we deliver 3DES 
-now. </P>
-<P> As a matter of project policy, we will not help anyone subvert 
-FreeS/WAN to provide <A href="politics.html#desnotsecure">insecure DES 
-encryption</A>. </P>
-<H2><A name="spam">Why don't you restrict the mailing list to reduce 
+. </P>
+<P> If you want to interoperate with an IPSEC implementation which 
+offers only DES, see our <A href="interop.html#noDES">interoperation</A>
+ document. </P>
+<H2><A name="spam">Why don't you restrict the mailing lists to reduce 
 spam?</A></H2>
-<P> As a matter of policy, the list needs to be open to 
-non-subscribers. Project management feel strongly that maintaining this 
-openness is more important than blocking spam. </P>
+<P> As a matter of policy, some of our <A href="mail.html">mailing lists</A>
+ need to be open to non-subscribers. Project management feel strongly 
+that maintaining this openness is more important than blocking spam. </P>
+<UL>
+<LI>Users should be able to get help or report bugs without 
+subscribing. </LI>
+<LI>Even a user who is subscribed may not have access to his or her 
+subscribed account when he or she needs help, miles from home base in 
+the middle of setting up a client's gateway. </LI>
+<LI>There is arguably a legal requirement for this policy. A US 
+resident or citizen could be charged under munitions export laws for 
+providing technical assistance to a foreign cryptographic project. Such 
+a charge would be more easily defended if the discussion takes place in 
+public, on an open list. </LI>
+</UL>
 <P> This has been discussed several times at some length on the list. 
 See the <A href="mail.html#archive">list archives</A>. Bringing the 
 topic up again is unlikely to be useful. Please don't. Or at the very 
@@ -1204,10 +1647,19 @@
 The decision is final, and is not open to discussion.  This needs to be 
 communicated better to people, and steps are being taken to do that. </BLOCKQUOTE>
  Adding this FAQ section is one of the steps he refers to. </P>
-<P> You have various options other than just putting up with the spam 
-or unsubscribing: </P>
+<P> You have various options other than just putting up with the spam, 
+filtering it yourself, or unsubscribing: </P>
 <UL>
-<LI>read the list via one of its <A href="mail.html#archive">archives</A>
+<LI>read the main list via one of its <A href="mail.html#archive">
+archives</A></LI>
+<LI>subscribe only to one or both of our lists with restricted posting 
+rules: 
+<UL>
+<LI><A href="mailto:briefs@lists.freeswan.org?body=subscribe">briefs</A>
+, weekly list summaries </LI>
+<LI><A href="mailto:announce@lists.freeswan.org?body=subscribe">announce</A>
+, project-related announcements </LI>
+</UL>
 </LI>
 <LI>subscribe to one or more of the <A href="mail.html#additional">
 other FreeS/WAN-related lists</A>. </LI>
@@ -1231,7 +1683,8 @@
 filtering. </P>
 <P> For information on tracking down spammers, see these <A href="http://www.rahul.net/falk/#howtos">
 HowTos</A>, or the <A href="http://www.sputum.com/index2.html">Sputum</A>
- site. </P>
+ site. Sputum have a Linux anti-spam screensaver available for 
+download. </P>
 <P> Here is a more detailed message from Henry: </P>
 <PRE>
 On Mon, 15 Jan 2001, Jay Vaughan wrote:
@@ -1323,7 +1776,7 @@
         John Gilmore
         founder sponsor, FreeS/WAN project
 </PRE>
-</A></A></A></A><HR>
+</A></A></A><HR>
 <A HREF="toc.html">Contents</a>
 <A HREF="rfc.html">Previous</a>
 </BODY>
diff -bruN freeswan-1.9.orig/doc/firewall.html freeswan-1.9/doc/firewall.html
--- freeswan-1.9.orig/doc/firewall.html	Tue Mar 27 23:16:51 2001
+++ freeswan-1.9/doc/firewall.html	Mon Jun  4 01:15:56 2001
@@ -147,16 +147,20 @@
 must allow UDP  500 and at least one of AH or ESP on the interface that 
 communicates with  the other gateway. </P>
 <H3><A name="through">IPSEC <EM>through</EM></A> the gateway</H3>
-<P>The preceeding paragraph deals with packets <EM>addressed to or sent 
-from  your gateway</EM>. It is a separate policy decision whether to 
-permit such  packets to pass <EM>through</EM> the gateway so that 
+<P> The preceeding paragraph deals with packets <EM>addressed to or 
+sent from  your gateway</EM>. It is a separate policy decision whether 
+to permit such  packets to pass <EM>through</EM> the gateway so that 
 client machines can  build end-to-end IPSEC tunnels of their own. This 
-may not be practical if  you are using <A href="#NAT">NAT (IP 
-masquerade)</A> on your gateway, and  may conflict with some corporate 
-security policies. Other than that, it is  likely a good idea.</P>
+may not be practical if  you are using <A href="glossary.html#NAT">NAT 
+(IP masquerade)</A> on your gateway, and  may conflict with some 
+corporate security policies. Other than that, it is  likely a good idea.</P>
+<H3><A name="ipsec_only">Preventing non-IPSEC traffic</A></H3>
+ You can of course also filter <EM>everything but</EM> UDP port 500 and 
+ESP or AH to restrict traffic to IPSEC only, either for anyone 
+communicating with your host or just for specific partners. 
 <H3><A name="unknowngate">Filtering packets from unknown gateways</A></H3>
-<P>It is possible to use firewall rules to restrict UDP 500, ESP and AH 
- packets so that these packets are accepted only from known gateways. 
+<P> It is possible to use firewall rules to restrict UDP 500, ESP and 
+AH packets so that these packets are accepted only from known gateways. 
 This is  not strictly necessary since FreeS/WAN will discard packets 
 from unknown  gateways. You might, however, want to do it for any of a 
 number of reasons.  For example:</P>
@@ -316,9 +320,15 @@
  Here you have a choice of techniques depending on whether you want to 
 make your client subnet visible to clients on the other end: 
 <UL>
-<LI>If you want to make them visible, then give the client subnet 
-addresses as the <VAR>leftsubnet=</VAR> parameter in the connection 
-description and 
+<LI>If you want the single gateway to behave like the two shown above, 
+with your clients hidden behind the NAT, then omit the <VAR>leftsubnet=</VAR>
+ parameter. It then defaults to the gateway address. Clients on the 
+other end then talk via the tunnel only to your gateway. The gateway 
+takes packets emerging from the tunnel, applies normal masquerading, 
+and forwards them to clients. </LI>
+<LI>If you want to make your client machines visible, then give the 
+client subnet addresses as the <VAR>leftsubnet=</VAR> parameter in the 
+connection description and 
 <DL>
 <DT>either </DT>
 <DD>set <VAR>leftfirewall=yes</VAR> to use the default <VAR>updown</VAR>
@@ -334,11 +344,6 @@
 client subnet addresses, although of course the encapsulating packets 
 use gateway addresses in their headers. Clients behind the right 
 security gateway see a route via that gateway to the left subnet.</P>
-<LI>If you want your clients hidden, then omit the <VAR>leftsubnet=</VAR>
- parameter. It then defaults to the gateway address. Clients on the 
-other end then talk via the tunnel only to your gateway. The gateway 
-takes packets emerging from the tunnel, applies normal masquerading, 
-and forwards them to clients. </LI>
 </UL>
 <H3><A name="nat_bad">NAT between gateways is problematic</A></H3>
 <P> We recommend not trying to build IPSEC connections which pass 
@@ -567,7 +572,7 @@
 # or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 # for more details.
 #
-# RCSID $Id: firewall.html,v 1.10.2.3 2001/03/15 00:12:35 henry Exp $
+# RCSID $Id: firewall.html,v 1.16 2001/05/02 20:56:27 sandy Exp $
 
 # check interface version
 case &quot;$PLUTO_VERSION&quot; in
diff -bruN freeswan-1.9.orig/doc/glossary.html freeswan-1.9/doc/glossary.html
--- freeswan-1.9.orig/doc/glossary.html	Tue Mar 27 23:16:52 2001
+++ freeswan-1.9/doc/glossary.html	Mon Jun  4 01:15:56 2001
@@ -154,7 +154,7 @@
  FreeS/WAN</A> would be useful undertaking, and considerable freely 
  available code exists to start from. One complication is that our code 
  is built for a 64-bit block cipher and AES uses a 128-bit block. 
- Volunteers via the <A href="#list">mailing list</A> would be  welcome.</P>
+ Volunteers via the <A href="#list">mailing lists</A> would be  welcome.</P>
 <P>For more information, see the <A href="http://csrc.nist.gov/encryption/aes/aes_home.htm">
  NIST AES home  page</A> or the <A href="http://www.ii.uib.no/~larsr/aes.html">
  Block  Cipher Lounge AES page</A>. For code and benchmarks see <A href="http://www.btinternet.com/~brian.gladman/">
@@ -193,7 +193,7 @@
 <LI>packet authentication, authenticating packets on an established <A href="#SA">
  SA</A>, either with a separate <A href="ipsec.html#AH">authentication 
 header</A> or with the optional  authentication in the <A href="ipsec.html#ESP">
-ESP</A> protocol. In either  case, packet authentication uses a <A href="#HMAC">
+ESP</A> protocol. In either  case, packet authentication uses a <A href="ipsec.html#HMAC">
 hashed message  athentication code</A> technique.</LI>
 </UL>
 <P>Outside IPSEC, passwords are perhaps the most common authentication 
@@ -309,9 +309,9 @@
 <LI><A href="#AES">AES</A> block ciphers using a 128-bit block  instead 
 of the 64-bit block of most current ciphers</LI>
 <LI><A href="#IPSEC">IPSEC</A> using a 32-bit counter for packets  sent 
-on an <A href="ipsec.html#auto">automatically keyed</A><A href="#SA"> SA</A>
- and requiring that the connection always be  rekeyed before the 
-counter overflows.</LI>
+on an <A href="#auto">automatically keyed</A><A href="#SA"> SA</A> and 
+requiring that the connection always be  rekeyed before the counter 
+overflows.</LI>
 </UL>
 <DT><A name="paradox">Birthday paradox</A></DT>
 <DD>Not really a paradox, just a rather counter-intuitive mathematical 
@@ -408,7 +408,7 @@
 things, cryptography.</DD>
 <DT><A name="C">C</A></DT>
 <DT><A name="CA"><A name="C">CA</A></A></DT>
-<DD><B>C</B>ertification <B>A</B>uthority, an entity in a <A href="ipsec.html#PKI">
+<DD><B>C</B>ertification <B>A</B>uthority, an entity in a <A href="#PKI">
 public key infrastructure</A> that can certify keys by  signing them. 
 Usually CAs form a hierarchy. The top of this hierarchy  is called the <A
 href="#rootCA">root CA</A>. </DD>
@@ -416,7 +416,7 @@
 <DT><A name="CAST128">CAST-128</A></DT>
 <DD>A <A href="#block">block cipher</A> using 64-bit blocks and 128-bit 
  keys, described in RFC 2144 and used in products such as <A href="#Entrust">
-Entrust</A> and recent versions of <A href="biblio.html#PGP">PGP</A>. </DD>
+Entrust</A> and recent versions of <A href="#PGP">PGP</A>. </DD>
 <P>This is not required by the <A href="#IPSEC">IPSEC</A> RFCs and not 
  currently used in <A href="#FreeSWAN">Linux FreeS/WAN</A>.</P>
 <DT>CAST-256</DT>
@@ -550,7 +550,7 @@
 and a fragment carries information on where it starts  within that 64K 
 and how long it is. The &quot;ping of death&quot; delivers  fragments that say, 
 for example, that they start at 60K and are  20K long. Attempting to 
-re-assemble thse without checking for  overflow can be fatal.</LI>
+re-assemble these without checking for  overflow can be fatal.</LI>
 </UL>
 </DD>
 <P>The two example attacks discussed were both quite effective when 
@@ -747,7 +747,7 @@
 <P>The EDE two-key variant can also interoperate with the EDE 
  three-key variant used in <A href="#IPSEC">IPSEC</A>; just set  k1=k3.</P>
 <DT><A name="Entrust"><A href="http://www.entrust.com">Entrust</A></A></DT>
-<DD>A Canadian company offerring enterprise <A href="ipsec.html#PKI">PKI</A>
+<DD>A Canadian company offerring enterprise <A href="#PKI">PKI</A>
  products using <A href="#CAST128">CAST-128</A> symmetric crypto, <A href="#RSA">
 RSA</A> public key and <A href="#X509">X.509</A> directories.</DD>
 <DT><A name="EFF">EFF</A></DT>
@@ -786,7 +786,7 @@
  (as they would for, say, the accounting department) they are then 
  encapsulated and sent back onto the Internet for delivery to the 
  branch office.</P>
-<P>For information on doing this with Linux FreeS/WAN, look in our <A href="#extruded">
+<P>For information on doing this with Linux FreeS/WAN, look in our <A href="config.html#extruded">
 Configuration</A> file.</P>
 <DT>Exhaustive search</DT>
 <DD>See <A href="#brute">brute force attack</A>.</DD>
@@ -830,14 +830,14 @@
 <DT><A name="GTR"><A href="http://www.cl.cam.ac.uk/Research/Security/Trust-Register">
 Global  Trust Register</A></A></DT>
 <DD>An attempt to create something like a <A href="#rootCA">root CA</A>
- for <A href="biblio.html#PGP">PGP</A> by publishing both <A href="#GTR">
+ for <A href="#PGP">PGP</A> by publishing both <A href="biblio.html#GTR">
 as a  book</A> and <A href="http://www.cl.cam.ac.uk/Research/Security/Trust-Register">
  on  the web</A> the fingerprints of a set of verified keys for 
 well-known  users and organisations.</DD>
 <DT>GMP</DT>
 <DD>The <B>G</B>NU <B>M</B>ulti-<B>P</B>recision library code, used in <A
-href="#FreeSWAN"> Linux FreeS/WAN</A> by <A href="roadmap.html#Pluto">
-Pluto</A> for <A href="#public">public key</A> calculations.</DD>
+href="#FreeSWAN"> Linux FreeS/WAN</A> by <A href="#Pluto">Pluto</A> for <A
+href="#public">public key</A> calculations.</DD>
 <DT><A name="GNU">GNU</A></DT>
 <DD><B>G</B>NU's <B>N</B>ot <B>U</B>nix, the <A href="#FSF">Free 
  Software Foundation's</A> project aimed at creating a free system with 
@@ -858,8 +858,8 @@
  page</A>.</DD>
 <DT><A name="GPG"><A href="http://www.gnupg.org">GNU Privacy Guard</A></A>
 </DT>
-<DD>An open source implementation of Open <A href="biblio.html#PGP">PGP</A>
- as  defined in RFC 2440.</DD>
+<DD>An open source implementation of Open <A href="#PGP">PGP</A> as 
+ defined in RFC 2440.</DD>
 <DT>GPL</DT>
 <DD>see <A href="#GPL">GNU General Public License</A>.</DD>
 <DT><A name="H">H</A></DT>
@@ -884,11 +884,11 @@
  because they output only 96 bits of the hash. This makes some attacks 
  on the hash functions harder.</P>
 <DT>HMAC</DT>
-<DD>see <A href="#HMAC">Hashed Message Authentication Code</A></DD>
+<DD>see <A href="ipsec.html#HMAC">Hashed Message Authentication Code</A></DD>
 <DT>HMAC-MD5-96</DT>
-<DD>see <A href="#HMAC">Hashed Message Authentication Code</A></DD>
+<DD>see <A href="ipsec.html#HMAC">Hashed Message Authentication Code</A></DD>
 <DT>HMAC-SHA-96</DT>
-<DD>see <A href="#HMAC">Hashed Message Authentication Code</A></DD>
+<DD>see <A href="ipsec.html#HMAC">Hashed Message Authentication Code</A></DD>
 <DT><A name="hybrid">Hybrid cryptosystem</A></DT>
 <DD>A system using both <A href="#public">public key</A> and <A href="#symmetric">
 symmetric cipher</A> techniques. This works well.  Public key methods 
@@ -909,7 +909,7 @@
  such as <A href="#DES">DES</A> which were <A href="politics.html#desnotsecure">
 too  weak for serious use</A>. IDEA is a <A href="#block">block cipher</A>
  using 64-bit blocks and 128-bit keys, and is used in products such as <A
-href="biblio.html#PGP"> PGP</A>. </DD>
+href="#PGP"> PGP</A>. </DD>
 <P>IDEA is not required by the <A href="#IPSEC">IPSEC</A> RFCs and not 
  currently used in <A href="#FreeSWAN">Linux FreeS/WAN</A>.</P>
 <P>IDEA is patented and, with strictly limited exceptions for personal 
@@ -927,8 +927,7 @@
 <DT><A name="IKE">IKE</A></DT>
 <DD><B>I</B>nternet <B>K</B>ey <B>E</B>xchange, based on the <A href="#DH">
 Diffie-Hellman</A> key exchange protocol. IKE is  implemented in <A href="#FreeSWAN">
-Linux FreeS/WAN</A> by the <A href="roadmap.html#Pluto">Pluto daemon</A>
-.</DD>
+Linux FreeS/WAN</A> by the <A href="#Pluto">Pluto daemon</A>.</DD>
 <DT><A name="IV">Initialisation Vector (IV)</A></DT>
 <DD>Some cipher <A href="#mode">modes</A>, including the <A href="#CBC">
 CBC</A> mode which IPSEC uses, require some extra data at  the 
@@ -951,17 +950,16 @@
 come from one IP address, that of its Internet  interface. It then gets 
 all the replies, does some table lookups and  more header rewriting, 
 and delivers the replies to the appropriate  client machines.</P>
-<P>To use masquerade with Linux FreeS/WAN, you must set 
- leftfirewall=yes and/or rightfirewall=yes in the connection 
- description in /etc/ipsec.conf.</P>
+<P> For information on using masquerade with Linux FreeS/WAN, see our <A href="firewall.html#NAT">
+ firewall document</A> and the <A href="faq.html#masq.faq">FAQ</A> and.</P>
 <DT><A name="IPng">IPng</A></DT>
 <DD>&quot;IP the Next Generation&quot;, see <A href="#ipv6.gloss">IPv6</A>.</DD>
 <DT><A name="IPv4">IPv4</A></DT>
-<DD>The current version of the <A href="#IP">Internet protocol  suite</A>
-.</DD>
+<DD>The current version of the <A href="web.html#IP">Internet protocol 
+ suite</A>.</DD>
 <DT><A name="ipv6.gloss">IPv6 (IPng)</A></DT>
-<DD>Version six of the <A href="#IP">Internet protocol suite</A>, 
- currently being developed. It will replace the current <A href="#IPv4">
+<DD>Version six of the <A href="web.html#IP">Internet protocol suite</A>
+,  currently being developed. It will replace the current <A href="#IPv4">
 version four</A>. IPv6 has <A href="#IPSEC">IPSEC</A> as  a mandatory 
 component. </DD>
 <P>See this <A href="http://playground.sun.com/pub/ipng/html/ipng-main.html">
@@ -1005,7 +1003,7 @@
  development kernels only if they have an urgent need for some feature 
  not yet available in production kernels.</P>
 <DT>Keyed message digest</DT>
-<DD>See <A href="#HMAC">HMAC</A>.</DD>
+<DD>See <A href="ipsec.html#HMAC">HMAC</A>.</DD>
 <DT>Key length</DT>
 <DD>see <A href="#brute">brute force attack</A></DD>
 <DT><A name="KLIPS">KLIPS</A></DT>
@@ -1016,15 +1014,15 @@
 <DT><A name="LDAP">LDAP</A></DT>
 <DD><B>L</B>ightweight <B>D</B>irectory <B>A</B>ccess <B>P</B>rotocol, 
  defined in RFCs 1777 and 1778,  a method of accessing information 
- stored in directories. LDAP is used by several <A href="ipsec.html#PKI">
-PKI</A> implementations, often with X.501 directories and <A href="#X509">
-X.509</A> certificates. It may also be used by <A href="#IPSEC">IPSEC</A>
- to obtain key certifications from those PKIs.  This is not yet 
-implemented in <A href="#FreeSWAN">Linux  FreeS/WAN</A>.</DD>
+ stored in directories. LDAP is used by several <A href="#PKI">PKI</A>
+ implementations, often with X.501 directories and <A href="#X509">X.509</A>
+ certificates. It may also be used by <A href="#IPSEC">IPSEC</A> to 
+obtain key certifications from those PKIs.  This is not yet implemented 
+in <A href="#FreeSWAN">Linux  FreeS/WAN</A>.</DD>
 <DT><A name="LIBDES">LIBDES</A></DT>
 <DD>A publicly available library of <A href="#DES">DES</A> code, 
 written  by Eric Young, which <A href="#FreeSWAN">Linux FreeS/WAN</A>
- uses in  both <A href="ipsec.html#KLIPS">KLIPS</A> and <A href="roadmap.html#Pluto">
+ uses in  both <A href="ipsec.html#KLIPS">KLIPS</A> and <A href="#Pluto">
 Pluto</A>.</DD>
 <DT><A name="Linux">Linux</A></DT>
 <DD>A freely available Unix-like operating system based on a kernel 
@@ -1047,7 +1045,7 @@
 other <A href="#IPSEC">IPSEC</A> implementations.  The name is partly 
 taken, with permission, from the <A href="#SWAN">S/WAN</A> multi-vendor 
 IPSEC compatability effort. Linux  FreeS/WAN has two major components, <A
-href="ipsec.html#KLIPS">KLIPS</A> (KerneL  IPSEC Support) and the <A href="roadmap.html#Pluto">
+href="ipsec.html#KLIPS">KLIPS</A> (KerneL  IPSEC Support) and the <A href="#Pluto">
 Pluto</A> daemon which manages  the whole thing. </DD>
 <P>See our <A href="web.html#overview">IPSEC Overview</A> for more 
 detail. For  the code see our <A href="http://freeswan.org"> primary 
@@ -1055,18 +1053,9 @@
  this  list</A>.</P>
 <DT><A name="M">M</A></DT>
 <DT><A name="list">Mailing list</A></DT>
-<DD>The <A href="#FreeSWAN">Linux FreeS/WAN</A> project has an open 
- public email list for bug reports and software development 
- discussions. The list address is <B>linux-ipsec@clinet.fi</B>. To 
- subscribe, send mail to <A href="mailto:majordomo@clinet.fi">
-majordomo@clinet.fi</A> with a  one-line message body &quot;subscribe 
-linux-ipsec&quot;.For more information,  send majordomo the one-line message 
-&quot;help&quot;. </DD>
-<P>NOTE: <STRONG>US citizens or residents are asked not to post code 
- to the list, not even one-line bug fixes.</STRONG> The project cannot 
- accept code which might entangle it in US export restrictions.</P>
-<P>For more detail, see our document on this and other <A href="mail.html">
-mailing lists</A>.</P>
+<DD>The <A href="#FreeSWAN">Linux FreeS/WAN</A> project has several 
+ public email lists for bug reports and software development 
+ discussions. See our document on <A href="mail.html">mailing lists</A>.</DD>
 <DT><A name="middle">Man-in-the-middle attack</A></DT>
 <DD>An <A href="#active">active attack</A> in which the attacker 
  impersonates each of the legitimate players in a protocol to the 
@@ -1104,7 +1093,7 @@
  completely.</P>
 <DT><A name="manual">Manual keying</A></DT>
 <DD>An IPSEC mode in which the keys are provided by the administrator. 
- In FreeS/WAN, they are stored in /etc/ipsec.conf. The alternative, <A href="ipsec.html#auto">
+ In FreeS/WAN, they are stored in /etc/ipsec.conf. The alternative, <A href="#auto">
 automatic keying</A>, is preferred in most cases.</DD>
 <DT><A name="MD4">MD4</A></DT>
 <DD><A href="#digest">Message Digest Algorithm</A> Four from Ron Rivest 
@@ -1119,7 +1108,7 @@
 <P>MD5 is one of two message digest algorithms available in IPSEC. The 
  other is <A href="#SHA">SHA</A>. SHA produces a longer hash and is 
  therefore more resistant to <A href="#birthday">birthday attacks</A>, 
- but this is not a concern for IPSEC. The <A href="#HMAC">HMAC</A>
+ but this is not a concern for IPSEC. The <A href="ipsec.html#HMAC">HMAC</A>
  method used in IPSEC is secure even if the underlying hash is not 
  particularly strong against this attack.</P>
 <DT><A name="meet">Meet-in-the-middle attack</A></DT>
@@ -1157,8 +1146,8 @@
 collision resistance</A>. The main applications are  in message <A href="#authentication">
 authentication</A> and <A href="#signature">digital signature</A>
  schemes. Widely used  algorithms include <A href="#MD5">MD5</A> and <A href="#SHA">
-SHA</A>.  In IPSEC, message digests are used for <A href="#HMAC">HMAC</A>
- authentication of packets.</DD>
+SHA</A>.  In IPSEC, message digests are used for <A href="ipsec.html#HMAC">
+HMAC</A> authentication of packets.</DD>
 <DT><A name="MTU">MTU</A></DT>
 <DD><STRONG>M</STRONG>aximum <STRONG>T</STRONG>ransmission <STRONG> U</STRONG>
 nit, the largest size of packet that can be sent  over a link. This is 
@@ -1281,10 +1270,12 @@
 time pad  FAQ</A>.</P>
 <DT><A name="carpediem">Opportunistic encryption</A></DT>
 <DD>A situation in which any two IPSEC-aware machines can secure their 
- communications, without a pre-shared secret and without a common <A href="ipsec.html#PKI">
+ communications, without a pre-shared secret and without a common <A href="#PKI">
 PKI</A> or previous exchange of public keys. This is one  of the goals 
 of the Linux FreeS/WAN project, discussed in our <A href="intro.html#goals">
-introduction</A> section.</DD>
+introduction</A> section. </DD>
+<P> Setting up for opportunistic encryption is described in our <A href="config.html#oppex">
+ configuration</A> document.</P>
 <DT><A name="P">P</A></DT>
 <DT><A name="P1363"><A href="http://grouper.ieee.org/groups/1363">P1363 
  standard</A></A></DT>
@@ -1305,7 +1296,7 @@
 ragment) bit in the  packet header</LI>
 <LI>any router which cannot send the packet on (outgoing MTU is too 
  small for it, and DF prevents fragmenting it to match) sends back  an <A
-href="#ICMP">ICMP</A> packet reporting the problem</LI>
+href="firewall.html#ICMP">ICMP</A> packet reporting the problem</LI>
 <LI>originator looks at ICMP message and tries a smaller size</LI>
 <LI>eventually, you settle on a size that can pass all routers</LI>
 <LI>thereafter, originator just sends that size and no-one has to 
@@ -1347,7 +1338,7 @@
  Zimmerman. </DD>
 <P>The 2.xx versions of PGP used the <A href="#RSA">RSA</A> public key 
  algorithm and used <A href="#IDEA">IDEA</A> as the symmetric cipher. 
- These versions are described in RFC 1991 and in <A href="biblio.html#PGP">
+ These versions are described in RFC 1991 and in <A href="#PGP">
 Garfinkel's book</A>. Since version 5, the products from <A href="#pgpi">
  PGP Inc</A>. have used <A href="#DH">Diffie-Hellman</A> public key 
 methods and <A href="#CAST128">CAST-128</A> symmetric encryption. These 
@@ -1360,8 +1351,8 @@
 <P>For more information on PGP, including how to obtain it, see our 
  cryptography <A href="web.html#tools">links</A>.</P>
 <DT><A name="PGPI">PGP Inc.</A></DT>
-<DD>A company founded by Zimmerman, the author of <A href="biblio.html#PGP">
-PGP</A>, now a division of <A href="#NAI">NAI</A>. See the <A href="http://www.pgp.com">
+<DD>A company founded by Zimmerman, the author of <A href="#PGP">PGP</A>
+, now a division of <A href="#NAI">NAI</A>. See the <A href="http://www.pgp.com">
  corporate website</A>. </DD>
 <P>Their PGP 6.5 product includes PGPnet, an IPSEC client for 
  Macintosh or for Windows 95/98/NT.</P>
@@ -1385,8 +1376,7 @@
  infrastructure.</P>
 <DT><A name="PKIX">PKIX</A></DT>
 <DD><B>PKI</B> e<B>X</B>change, an <A href="mail.html#IETF">IETF</A>
- standard  that allows <A href="ipsec.html#PKI">PKI</A>s to talk to 
-each other. </DD>
+ standard  that allows <A href="#PKI">PKI</A>s to talk to each other. </DD>
 <P>This is required, for example, when users of a corporate PKI need 
  to communicate with people at client, supplier or government 
  organisations, any of which may have a different PKI in place. I 
@@ -1425,11 +1415,11 @@
  symmetric ciphers</A>. The resulting <A href="#hybrid">hybrid 
 cryptosystems</A> use public key methods to  manage keys for symmetric 
 ciphers.</P>
-<P>Many organisations are currently creating <A href="ipsec.html#PKI">
-PKIs,  public key infrastructures</A> to make these benefits widely 
+<P>Many organisations are currently creating <A href="#PKI">PKIs, 
+ public key infrastructures</A> to make these benefits widely 
  available.</P>
 <DT>Public Key Infrastructure</DT>
-<DD>see <A href="ipsec.html#PKI">PKI</A></DD>
+<DD>see <A href="#PKI">PKI</A></DD>
 <DT><A name="Q">Q</A></DT>
 <DT><A name="R">R</A></DT>
 <DT><A name="random">Random</A></DT>
@@ -1480,7 +1470,7 @@
 packet  headers. These are the routable addresses; we expect routing to 
 be  possible for them. If we send a packet to one of them, we expect 
 (in  most cases; there are various complications) that it will be 
-delivered  if the address is in use and will cause an <A href="#icmp">
+delivered  if the address is in use and will cause an <A href="firewall.html#icmp">
 ICMP</A> error packet to come back to us if not. </DD>
 <P>There are also several classes of <A href="#non-routable">
 non-routable</A> IP addresses.</P>
@@ -1557,7 +1547,7 @@
 Diffie-Hellman key exchange</A> to bootstrap itself. This  would allow <A
 href="#carpediem">opportunistic encryption</A>. Any  pair of machines 
 which could authenticate each other via DNS could  communicate 
-securely, without either a pre-existing shared secret or a  shared <A href="ipsec.html#PKI">
+securely, without either a pre-existing shared secret or a  shared <A href="#PKI">
 PKI</A>.</P>
 <P><A href="#FreeSWAN">Linux FreeS/WAN</A> will support this in a 
  future release.</P>
@@ -1569,7 +1559,7 @@
 <DD>A number added to a packet or message which indicates its position 
  in a sequence of packets or messages. This provides some security 
  against <A href="#replay">replay attacks</A>. </DD>
-<P>For <A href="ipsec.html#auto">automatic keying</A> mode, the <A href="#IPSEC">
+<P>For <A href="#auto">automatic keying</A> mode, the <A href="#IPSEC">
 IPSEC</A> RFCs require that the sender generate sequence  numbers for 
 each packet, but leave it optional whether the receiver  does anything 
 with them.</P>
@@ -1737,12 +1727,12 @@
 <DT><A name="transport">Transport mode</A></DT>
 <DD>An IPSEC application in which the IPSEC gateway is the destination 
  of the protected packets, a machine acts as its own gateway. Contrast 
- with <A href="#tunnel">tunnel mode</A>.</DD>
+ with <A href="ipsec.html#tunnel">tunnel mode</A>.</DD>
 <DT>Triple DES</DT>
 <DD>see <A href="#3DES">3DES</A></DD>
 <DT><A name="tunnel">Tunnel mode</A></DT>
 <DD>An IPSEC application in which an IPSEC gateway provides protection 
- for packets to and from other systems. Contrast with <A href="#transport">
+ for packets to and from other systems. Contrast with <A href="ipsec.html#transport">
 transport mode</A>.</DD>
 <DT><A name="2key">Two-key Triple DES</A></DT>
 <DD>A variant of <A href="#3DES">triple DES or 3DES</A> in which only 
@@ -1769,7 +1759,7 @@
 book form</A> or <A href="http://metalab.unc.edu/LDP/LDP/nag/node1.html">
 on the web</A> for details.</DD>
 <DT>Virtual Private Network</DT>
-<DD>see <A href="#VPN">VPN</A></DD>
+<DD>see <A href="web.html#VPN">VPN</A></DD>
 <DT><A name="VPN">VPN</A></DT>
 <DD><B>V</B>irtual <B>P</B>rivate <B>N</B>etwork, a network which can 
  safely be used as if it were private, even though some of its 
@@ -1790,18 +1780,18 @@
 restricted  under the current version of the agreement. <A href="politics.html#Wassenaar">
  Discussion</A>.</DD>
 <DT><A name="web">Web of Trust</A></DT>
-<DD><A href="biblio.html#PGP">PGP</A>'s method of certifying keys. Any 
-user can  sign a key; you decide which signatures or combinations of 
-signatures  to accept as certification. This contrasts with the 
-hierarchy of <A href="#CA">CAs (Certification Authorities)</A> used in 
-many <A href="ipsec.html#PKI">PKIs (Public Key Infrastructures)</A>. </DD>
-<P>See <A href="#GTR">Global Trust Register</A> for an interesting 
- addition to the web of trust.</P>
+<DD><A href="#PGP">PGP</A>'s method of certifying keys. Any user can 
+ sign a key; you decide which signatures or combinations of signatures 
+ to accept as certification. This contrasts with the hierarchy of <A href="#CA">
+CAs (Certification Authorities)</A> used in many <A href="#PKI">PKIs 
+(Public Key Infrastructures)</A>. </DD>
+<P>See <A href="biblio.html#GTR">Global Trust Register</A> for an 
+interesting  addition to the web of trust.</P>
 <DT><A name="X">X</A></DT>
 <DT><A name="X509">X.509</A></DT>
 <DD>A standard from the <A href="http://www.itu.int">ITU (International 
  Telecommunication Union)</A>, for hierarchical directories with 
- authentication services, used in many <A href="ipsec.html#PKI">PKI</A>
+ authentication services, used in many <A href="#PKI">PKI</A>
  implementations. </DD>
 <P>Use of X.509 services, via the <A href="#LDAP">LDAP protocol</A>, 
  for certification of keys is allowed but not required by the <A href="#IPSEC">
diff -bruN freeswan-1.9.orig/doc/index.html freeswan-1.9/doc/index.html
--- freeswan-1.9.orig/doc/index.html	Tue Mar 27 23:17:16 2001
+++ freeswan-1.9/doc/index.html	Mon Jun  4 01:16:19 2001
@@ -2,6 +2,17 @@
 <HTML>
 <HEAD>
 <TITLE>FreeS/WAN HTML document index</TITLE>
+<meta name="keywords" content="Linux, IPSEC, VPN, security, encryption, crytography, FreeS/WAN, FreeSWAN">
+
+<!--
+
+Written by Sandy Harris for the Linux FreeS/WAN project
+Freely distributable under the GNU General Public License
+
+More information at www.freeswan.org
+Feedback to users@lists.freeswan.org
+
+-->
 </HEAD>
 <BODY>
 <H1>FreeS/WAN documentation</H1>
diff -bruN freeswan-1.9.orig/doc/install.html freeswan-1.9/doc/install.html
--- freeswan-1.9.orig/doc/install.html	Tue Mar 27 23:16:51 2001
+++ freeswan-1.9/doc/install.html	Mon Jun  4 01:15:55 2001
@@ -61,16 +61,23 @@
 <P> If you have not done this before, you will need to read the <A href="http://metalab.unc.edu/LDP/HOWTO/Kernel-HOWTO.html">
 Kernel HowTo</A>.</P>
 <H3><A name="choosek">Choosing a kernel</A></H3>
-<H4><A name="2.2">2.2.x for most users</A></H4>
-<P> Most users should run the most stable available series of Linux 
-production <A href="glossary.html#kernel">kernels</A>. At time of 
-writing (February 2001), we recommend the 2.2 series for most users. 
-The latest version is 2.2.18.</P>
+<H4><A name="2.2">2.2.19 for many users</A></H4>
+<P> Many users can continue to run kernels from the 2.2 series of Linux 
+production <A href="glossary.html#kernel">kernels</A>. </P>
+<P> At time of writing (June 2001), the latest version is 2.2.19. If 
+you are going to use a 2.2 kernel, we <STRONG>strongly recommend</STRONG>
+ upgrading to 2.2.19 since: </P>
+<UL>
+<LI>It has a number of small security fixes not found in earlier 
+kernels. </LI>
+<LI>There have been changes in some kernel file formats that make it 
+difficult to compile a current FreeS/WAN with earlier kernels. See the <A
+href="mail.html">mailing list archives</A> for details if needed. </LI>
+</UL>
 <H4><A name="2.4">2.4.x is possible</A></H4>
- The new 2.4 series of kernels were first released in January 2001 and 
-are currently (mid-February) at 2.4.2. FreeS/WAN does work on these 
-kernels, but for production use we suggest waiting a while yet. 
-<P> On the other hand, 2.4 has new firewalling code called <A href="http://netfilter.kernelnotes.org/unreliable-guides/index.html">
+ The new 2.4 series of kernels began in January 2001 and are currently 
+(early June) at 2.4.5. FreeS/WAN is known to work on 2.4.5. 
+<P> 2.4 has new firewalling code called <A href="http://netfilter.kernelnotes.org/unreliable-guides/index.html">
 netfilter</A>. This may provide good reasons to move to 2.4, especially 
 on for gateway machines. </P>
 <H4><A name="2.0">2.0.x should still work</A></H4>
@@ -88,10 +95,10 @@
 for use by kernel developers. By convention, production kernels have an 
 even second digit in the version number (2.0, 2.2, 2.4) and development 
 kernels have an odd digit there (2.1, 2.3, 2.5). 
-<P> At time of writing (February 2001, shortly after the release of 
-2.4), no more 2.3 kernels are being produced and the 2.5 series has not 
-been started yet, so just now development kernels are not an issue. No 
-doubt a 2.5 series will be started in the next few months. </P>
+<P> At time of writing, no more 2.3 kernels are being produced and the 
+2.5 series has not been started yet, so just now development kernels 
+are not an issue. No doubt a 2.5 series will be started in the next few 
+months. </P>
 <P><STRONG> Development kernels are not intended for production use</STRONG>
 . They change often and include new code which has not yet been 
 thoroughly tested. <STRONG>This regularly breaks things, including 
@@ -378,7 +385,7 @@
 </UL>
 <P> Of course any status information at this point should be 
 uninteresting since you have not yet configured connections.</P>
-<H2><A NAME="2_6">Links to other sections</A></H2>
+<H2><A NAME="2_6">Where to go from here</A></H2>
 <P>See the following section for information on <A href="config.html">
 configuring connections</A>.</P>
 <P>Alternately, you might want to look at background material on the <A href="ipsec.html">
diff -bruN freeswan-1.9.orig/doc/interop.html freeswan-1.9/doc/interop.html
--- freeswan-1.9.orig/doc/interop.html	Tue Mar 27 23:16:51 2001
+++ freeswan-1.9/doc/interop.html	Mon Jun  4 01:15:56 2001
@@ -52,41 +52,50 @@
 those formats. See this list of <A href="web.html#patch"> patches and 
 add-ons</A>. </P>
 <H2><A name="interop.problem">Interoperability problems</A></H2>
-<P>The IPSEC RFCs are complex and include a number of optional 
+<P> The IPSEC RFCs are complex and include a number of optional 
 features.  There is considerable opportunity for even two correct, 
 standard-conforming,  implementations to disagree on details in a way 
 that blocks interoperation.  Of course, misinterpretations of the 
 standards and implementation or  configuration errors on either end can 
 also foul things up.</P>
 <P>That said, FreeS/WAN interoperates successfully with many other 
- implementations. There is a <A href="interop.html">list</A> in another 
- section.</P>
+ implementations. There is a <A href="#mail.interop">list</A> below.</P>
 <P> Known areas where problems may appear are:</P>
 <UL>
+<LI><STRONG>FreeS/WAN does not implement single DES</STRONG> because <A href="politics.html#desnotsecure">
+DES is insecure</A>. Suggestions on what to do if  the device you want 
+to talk to has only DES are <A href="#noDES">below</A>.</LI>
+<LI><STRONG>FreeS/WAN does not implement Diffie-Hellman group 1</STRONG>
+ because it  it is not entirely clear that this is secure.</LI>
 <LI>The RFCs define two modes for IKE negotiations -- main mode and 
  aggressive mode. Aggressive mode is slightly faster, but reveals more 
  information to an eavesdropper. Specifically, it lets an eavesdropper 
  know what identities are in use. <STRONG>FreeS/WAN does not implement 
  aggressive mode</STRONG>, so any negotiation another implementation 
- tries that way will fail. In principle this should not be a problem 
- since main mode support is required in all implementations and 
-aggressive  mode is optional. </LI>
-<P> In practice, it is sometimes a problem. Some implementations 
-default to  aggressive mode unless you configure them for main mode.</P>
-<LI><STRONG>FreeS/WAN does not implement single DES</STRONG> because <A href="politics.html#desnotsecure">
-DES is insecure</A>. Suggestions on what to do if  the device you want 
-to talk to has only DES are in our <A href="FAQ.html#noDES">FAQ</A>
- document.</LI>
-<LI><STRONG>FreeS/WAN does not implement Diffie-Hellman group 1</STRONG>
- because it  it is not entirely clear that this is secure. </LI>
-<LI>For automatic keying, <STRONG>the FreeS/WAN default is to provide <A href="glossary.html#PFS">
- perfect forward secrecy</A></STRONG>. We see no reason not  to; this 
-is more secure and costs little. Some other implementations,  however, 
-turn PFS off by default. </LI>
+ tries that way will fail. </LI>
+<P> In principle this should not be a problem  since main mode support 
+is required in all implementations and aggressive  mode is optional. 
+ In practice, it is sometimes a problem.  Some implementations default 
+to  aggressive mode unless you configure them for main mode.</P>
+<LI> For automatic keying, <STRONG>the FreeS/WAN default is to provide <A
+href="glossary.html#PFS"> perfect forward secrecy</A></STRONG>. We see 
+no reason not  to; this is more secure and costs little. Some other 
+implementations,  however, turn PFS off by default. </LI>
 <P> You can turn PFS off in FreeS/WAN with the <VAR>pfs=no</VAR>
  setting in <A href="manpage.d/ipsec.conf.5.html"> ipsec.conf(5)</A>, 
 but if possible  we suggest you enable it on the other end instead. 
 That is more secure.</P>
+<LI> The IKE protocol allows several types of optional message. Two 
+things happen  which are allowed by the RFCs: 
+<UL>
+<LI>Some implementations send various optional messages. </LI>
+<LI>FreeS/WAN ignores them. </LI>
+</UL>
+ However, problems may arise if the other end relies on some expected 
+effect  of these messages. There are two FAQ questions dealing with 
+this, one on the <A href="faq.html#ignore"> log message</A> FreeS/WAN 
+gives when ignoring  optional payloads and one on the <A href="faq.html#deadtunnel">
+delete SA</A> payload. </LI>
 </UL>
 <P> The general rule is that to interoperate with FreeS/WAN, the other 
 implementation should be configured for:</P>
@@ -96,34 +105,39 @@
 <LI>Diffie-Hellman Group 2 or 5 </LI>
 </UL>
 <P> This is possible for most implementations.</P>
-<H3><A name="noDES">Systems that want to use DES</A></H3>
-<P> Linux FreeS/WAN does not support DES transforms. Neither Pluto's 
-IKE connections nor KLIPS' IPSEC connections can use DES. Since <A href="politics.html#desnotsecure">
-DES is insecure</A> we do not, and will not at any future time, provide 
-it.</P>
+<H3><A name="noDES">Systems that want to use single DES</A></H3>
+<P> Linux FreeS/WAN does not support single DES transforms. Neither 
+Pluto's IKE connections nor KLIPS' IPSEC connections can use DES. Since <A
+href="politics.html#desnotsecure">DES is insecure</A> we do not, and 
+will not at any future time, provide it.</P>
 <P> DES is, unfortunately, a mandatory part of the <A href="glossary.html#IPSEC">
 IPSEC</A> standard. Despite that, we will not implement DES. We believe 
 it is more important to provide security than to comply with a standard 
-which has been subverted into allowing weak algorithms. See our <A href="politics.html">
-history and politics</A> section for discussion.</P>
-<P>Some implementations may offer DES as the default. In such cases we 
-urge  you to change them to <A href="glossary.html#3DES">Triple DES</A>
-. If this is not  possible, for example because <A href="politics.html#exlaw">
+which has been <A href="politics.html#weak">subverted</A> into allowing 
+weak algorithms. See our <A href="politics.html">history and politics</A>
+ section for discussion.</P>
+<P> Some implementations may offer DES as the default. In such cases we 
+urge you to change them to <A href="glossary.html#3DES">Triple DES</A>. 
+If this is not possible, for example because <A href="politics.html#exlaw">
 export laws</A> prevent your  vendor from offerring you adequate 
-crytography, we urge you to complain  vigorously to</P>
+crytography, we urge you to complain vigorously to one or more of:</P>
 <UL>
-<LI>your government</LI>
+<LI>your government, especially any department concerned with 
+protecting citizens'  privacy or your nation's communication 
+infrastructure</LI>
 <LI>the vendor</LI>
-<LI>the embassy of the nation whose laws are problematic for you.</LI>
+<LI>the embassy of the nation whose laws are problematic for you</LI>
 </UL>
-<P> In the meanwhile, use FreeS/WAN to get strong crypto until the laws 
-are fixed.</P>
+<P> Consider using FreeS/WAN instead. PCs are cheap and we deliver 3DES 
+now. </P>
 <P> FreeS/WAN does have <A href="glossary.html#DES">DES</A> code in it 
 as a sort of historical accident, since we need it to implement our 
 default (currently, our only) block cipher, <A href="glossary.html#3DES">
 Triple DES</A>. However, since <A href="politics.html#desnotsecure">DES 
-is insecure</A>, we do not provide any interface to that code and, as a 
-matter of policy, will provide no help to anyone who may wish to use it.</P>
+is insecure</A>, we do not provide any interface to that code.</P>
+<P> As a matter of project policy, we will not help anyone subvert 
+FreeS/WAN to provide <A href="politics.html#desnotsecure">insecure DES 
+encryption</A>. </P>
 <H2><A name="otherpub">Interop HowTo documents</A></H2>
 <P> The FreeS/WAN team does not have the resources to test with 
 anything like the full range of <A href="web.html#implement">other 
@@ -288,7 +302,7 @@
 I've attached some ipsec barf output - pluto still complains a few times,
 but it gets there :-)
 </PRE>
-<P>A later message from Ian:</P>
+<P> A later message from Ian:</P>
 <PRE>
 This configuration is provided as-is and with no assistance or guarantee
 that it works whatsover. In particular your attention is drawn to the versions
@@ -366,6 +380,19 @@
 |     7500 Series
 </PRE>
 <H3><A name="bay">Nortel (Bay Networks) Contivity switch</A></H3>
+ There is one known issue in FreeS/WAN-to-Contivity interoperation. 
+Recent versions of FreeS/WAN no longer support DH group 1 for key 
+exchange. Older versions of Contivity software support nothing else. 
+Group 2 was added in more recent releases. So: 
+<UL>
+<LI>older FreeS/WANs, such as 1.5, will work with any Contivity 
+software. Key exchange will be done using DH Group 1. This may not be 
+secure. </LI>
+<LI>current FreeS/WANs will work only with recent Contivity releases 
+supporting DH Group 2. Contivity 3.5 is one such release. </LI>
+</UL>
+ We recommend using the latest Contivity release. 
+<P> Some messages from the mailing list: </P>
 <PRE>
 Subject: Contivity Extranet Switch
    Date: Fri, 11 Jun 1999
@@ -772,6 +799,13 @@
 HowTo</A> for connecting FreeS/WAN and this product can be downloaded 
 from the  vendor's site or browsed at a VPN mailing list <A href="http://kubarb.phsx.ukans.edu/~tbird/vpn.html">
 site</A>.</P>
+<H3><A name="redcreek">Redcreek Ravlin</A></H3>
+ We have reports of successful interoperation at an interop <A href="http://www.opus1.com/vpn/atl99display.html">
+conference</A>, but there is also a mailing list <A href="http://www.sandelman.ottawa.on.ca/linux-ipsec/html/2000/11/msg00510.html">
+ thread</A> discussing difficulties some users have encountered. 
+<H3><A name="sentinel">SSH Sentinel</A></H3>
+ The vendor's <A href="http://www.ipsec.com/products/sentinel/documents.html">
+ web site</A> has configuration examples for use with FreeS/WAN. 
 <H3><A name="Fsecure">F-Secure VPN for Windows</A></H3>
 <PRE>   Subject: linux-ipsec: Identification through other than IP number
    Date: Tue, 13 Apr 1999
@@ -1407,8 +1441,9 @@
 of both domains or consider setting up WINS service(s).
 </PRE>
  We suspect that in some cases it may be more complex than that. See 
-the discussion of Linux services and Windows 2000 <A href="#lin2k">below</A>
-. 
+the discussion of <A href="#lin2k">Linux services and Windows 2000</A>
+ below and the <A href="#otherpub">Interop HowTo</A> documents listed 
+above. 
 <H3><A name="win2k">Windows 2000</A></H3>
 <P> Windows 2000 ships with an IPSEC implementation built in. There may 
 be  restrictions. We have had mailing list reports that only the server 
@@ -1478,16 +1513,9 @@
 http://www.sandelman.ottawa.on.ca/linux-ipsec/html/2001/02/msg00195.html
 </PRE>
 <H4><A name="interop.win2k">FreeS/WAN-to-Win2000 interop</A></H4>
-<P>As for IPSEC interoperation between Windows 2000 and FreeS/WAN, 
-there are some web sites:</P>
-<UL>
-<LI>The Norwegian company <A href="http://security.nta.no/freeswan-w2k.html">
-Telenor</A></LI>
-<LI><A href="http://jixen.tripod.com/#Win2000-Fwan">Jean-Francois 
- Nadeau</A></LI>
-<LI><A href="http://el06-24-29-255-187.ce.mediaone.net/carl/linux/ipsec/swan-w2k/swanw2k-b.html">
-Carl's guide</A></LI>
-</UL>
+<P> As for IPSEC interoperation between Windows 2000 and FreeS/WAN, 
+there are several web sites listed under <A href="#otherpub">Interop 
+HowTo</A> documents above.</P>
 <P>Here is a discussion from the mailing list:</P>
 <PRE>From: &quot;Jean-Francois Nadeau&quot; &lt;jna@microflex.ca&gt;
 Subject: Win2000 IPsec  interop. in tunnel mode
diff -bruN freeswan-1.9.orig/doc/intro.html freeswan-1.9/doc/intro.html
--- freeswan-1.9.orig/doc/intro.html	Tue Mar 27 23:16:50 2001
+++ freeswan-1.9/doc/intro.html	Mon Jun  4 01:15:55 2001
@@ -157,7 +157,8 @@
 <LI>If Network Address Translation (NAT) is applied between the two 
 IPSEC  Gateways, this breaks IPSEC. IPSEC authenticates packets on an 
 end-to-end  basis, to ensure they are not altered en route. NAT 
-rewrites packets as  they go by.</LI>
+rewrites packets as  they go by. See our <A href="firewall.html#NAT">
+firewalls</A> document for details.</LI>
 </UL>
 <P> In most situations, however, FreeS/WAN supports road warrior 
 connections just fine.</P>
@@ -170,7 +171,7 @@
 .  We hope this will go some distance toward creating a secure 
 Internet, an environment where message privacy is the default. See our <A
 href="politics.html">history and politics of cryptography</A> section 
-for discussion</P>
+for discussion.</P>
 <P> Both systems pick up the authentication information they need from 
 the <A href="glossary.html#DNS.gloss">DNS</A> (domain name service), 
 the service they already use to look up IP addresses. Of course the 
@@ -180,8 +181,9 @@
 encrypt, and encrypt whatever they can. Whether they also accept 
 unencrypted communication is a policy decision the administrator can 
 make.</P>
-<P> A draft document giving most of the <A href="opportunism.txt">
-details</A> of how we plan to implement this is available.</P>
+<P> A draft document giving most of the details of how we plan to 
+implement this has been posted to the mailing list. See <A href="#applied">
+links</A> below.</P>
 <P> Only one current product we know of implements a form of 
 opportunistic encryption. <A href="web.html#ssmail">Secure sendmail</A>
  will automatically encrypt server-to-server mail transfers whenever 
@@ -323,8 +325,12 @@
 <LI><A href="ftp://ftp.net.lut.ac.uk/freeswan">the UK</A></LI>
 <LI><A href="http://storm.alert.sk/comp/mirrors/freeswan/">Slovak 
  Republic</A></LI>
+<LI><A href="http://the.wiretapped.net/security/vpn-tunnelling/freeswan/">
+Australia</A></LI>
 <LI><A href="http://freeswan.technolust.cx/">technolust</A></LI>
 <LI>Ivan Moore's <A href="http://snowcrash.tdyc.com/freeswan/">site</A></LI>
+<LI>the <A href="http://www.cryptoarchive.net/">Crypto Archive</A> on 
+the <A href="http://www.securityportal.com/"> Security Portal</A> site </LI>
 </UL>
 <H4><A name="munitions">The &quot;munitions&quot; archive of Linux crypto software</A>
 </H4>
@@ -338,12 +344,17 @@
 </UL>
 <P> Any of those will have a list of other &quot;munitions&quot; mirrors. </P>
 <H3><A name="archives">Archives of the project mailing list</A></H3>
+ Until quite recently, there was only one FreeS/WAN mailing list, and 
+archives of it were: 
 <UL>
 <LI><A href="http://www.sandelman.ottawa.on.ca/linux-ipsec">Canada</A></LI>
 <LI><A href="http://www.nexial.com">Holland</A></LI>
 </UL>
-<P> The two archives use completely different search engines. You might 
-want to try both.</P>
+ The two archives use completely different search engines. You might 
+want to try both.
+<P> More recently we have expanded to five lists, each with its own 
+archive. See <A href="mail.html">details</A> elsewhere in the 
+documentation. </P>
 <P><A href="mail.html">More information</A> on this and other mailing 
 lists.</P>
 <H2><A name="products">Products containing FreeS/WAN</A></H2>
@@ -365,8 +376,8 @@
 <LI><A href="http://www.trustix.net/">Trustix Secure Linux</A> (Norway) </LI>
 </UL>
 <P> For distributions which do not include FreeS/WAN and are not Redhat 
-6.x (which we develop and test on), there is additional information in 
-our <A href="compatibility.html#otherdist">compatibility</A> section.</P>
+(which we develop and test on), there is additional information in our <A
+href="compatibility.html#otherdist">compatibility</A> section.</P>
 <P> We would appreciate hearing of other distributions using FreeS/WAN.</P>
 <H3><A name="fw_dist">Firewall distributions</A></H3>
  FreeS/WAN is also included in, or available for, more specialised 
@@ -406,6 +417,9 @@
 <LI><A href="http://www.merilus.com">Merilus</A> use FreeS/WAN in their 
 Gateway Guardian firewall  product and in their <A href="http://www.merilus.com/firecard/index.shtml">
 Firecard</A> product, a Linux firewall on a PCI card. </LI>
+<LI><A href="http://www.kyzo.com/">Kyzo</A> have a &quot;pizza box&quot; product 
+line with various types of  server, all running from flash. One of them 
+is an IPSEC/PPTP VPN server. </LI>
 </UL>
 <P>We would appreciate hearing of other products using FreeS/WAN.</P>
 <H2><A name="docs">Documentation</A></H2>
@@ -514,7 +528,7 @@
 <UL>
 <LI>kernel programmer Richard Guy Briggs on <A href="http://www.sandelman.ottawa.on.ca/linux-ipsec/html/2001/02/msg00435.html">
  redesign of KLIPS</A></LI>
-<LI>technical lead Henry Spencer on <A href="http://www.sandelman.ottawa.on.ca/linux-ipsec/html/2001/02/msg00381.html">
+<LI>technical lead Henry Spencer on <A href="http://www.sandelman.ottawa.on.ca/linux-ipsec/html/2001/05/msg00084.html">
  opportunistic encryption</A></LI>
 </UL>
  Both documents are works in progress and may be revised. Check the 
diff -bruN freeswan-1.9.orig/doc/ipsec.html freeswan-1.9/doc/ipsec.html
--- freeswan-1.9.orig/doc/ipsec.html	Tue Mar 27 23:16:51 2001
+++ freeswan-1.9/doc/ipsec.html	Mon Jun  4 01:15:56 2001
@@ -233,7 +233,7 @@
 authentication at  packet level is in use on the potential victims' 
 communication channel.</P>
 <H3><A name="authonly">Using authentication without encryption</A></H3>
-<P>Where appropriate, IPSEC can provide authentication without 
+<P> Where appropriate, IPSEC can provide authentication without 
 encryption.  One might do this, for example:</P>
 <UL>
 <LI>where the data is public but one wants to be sure of getting the 
@@ -246,6 +246,12 @@
 protocols  harder.</LI>
 </UL>
 <P> Authentication has lower overheads than encryption. </P>
+<P> The protocols provide four ways to build such connections, using 
+either an AH-only connection or ESP using null encryption, and in 
+either manually or automatically keyed mode. FreeS/WAN supports only 
+one of these, manually keyed AH-only connections, and <STRONG>we do not 
+recommend using that</STRONG>. Our reasons are discussed under <A href="#traffic.resist">
+Resisting traffic analysis</A> a few sections further along. </P>
 <H3><A name="encnoauth">Encryption without authentication is dangerous</A>
 </H3>
 <P>Originally, the IPSEC encryption protocol <A href="glossary.html#ESP">
@@ -263,7 +269,7 @@
 <LI>ESP for encryption and authentication</LI>
 <LI>AH for authentication alone</LI>
 </UL>
-<P>Other variants are allowed by the standard, but not much used:</P>
+<P> Other variants are allowed by the standard, but not much used:</P>
 <DL>
 <DT>ESP encryption without authentication</DT>
 <DD><STRONG>Bellovin has demonstrated fatal flaws in this. Do not  use.</STRONG>
@@ -283,14 +289,14 @@
  might use ESP as well.</DD>
 <DT>ESP authentication without encryption</DT>
 <DD>The standard allows this, calling it &quot;null encryption&quot;. FreeS/WAN 
- does not normally support it, but it can be enabled with a kernel 
- configuration option. We recommend that you use AH instead if 
+ does not support it. We recommend that you use AH instead if 
  authentication is all you require. AH authenticates parts of the IP 
- header, which ESP-null does not do. Also, if you do not enable 
- ESP-null on your FreeS/WAN machine, then you run no risk of a 
- configuration error using this when it should be encrypting.</DD>
+ header, which ESP-null does not do.</DD>
 </DL>
-<P>There are fairly frequent suggestions that AH be dropped entirely 
+ Some of these variants cannot be used with FreeS/WAN because we do not 
+support ESP-null and do not support automatic keying of AH-only 
+connections. 
+<P> There are fairly frequent suggestions that AH be dropped entirely 
 from  the IPSEC specifications since ESP and null encryption can handle 
 that  situation. It is not clear whether this will occur. My guess is 
 that it is  unlikely.</P>
@@ -321,13 +327,12 @@
 to derive useful intelligence from encrypted traffic without breaking 
 the encryption. For example, an eavesdropper might deduce something 
 interesting merely by knowing that your CEO was exchanging email with a 
-particular venture capital firm. Or that all the CEO's mail this week 
-went to a firm of bankruptcy trustees and a half dozen executive 
-recruiting agencies. </P>
+particular venture capital firm, or that the CEO was talking to a firm 
+of bankruptcy trustees and a half dozen executive recruiting agencies. </P>
 <P> Except in the simplest cases, traffic analysis is hard to do well. 
 It requires both considerable resources and considerable analytic 
 skill. However, intelligence agencies of various nations have been 
-doing it for centuries and most of them are likely quite good at it by 
+doing it for centuries and many of them are likely quite good at it by 
 now. Various commercial organisations, especially those working on 
 &quot;targeted marketing&quot; may also be quite good at analysing certain types 
 of traffic. </P>
@@ -761,14 +766,11 @@
 category.</P>
 <P>The authentication algorithms are the same ones used in the IPSEC <A href="#AH">
 authentication header</A>.</P>
-<P>We do not implement single DES since <A href="politics.html#desnotsecure">
+<P> We do not implement single DES since <A href="politics.html#desnotsecure">
 DES is  insecure</A>. Instead we provide <A href="glossary.html#3DES">
-triple DES or 3DES</A>.  This is currently the only encryption 
-algorithm supported.</P>
-<P>We do implement null encryption, but it is disabled by default. You 
-can  enable it in the IPSEC part of kernel configuration if required. 
-We would  suggest, however, that if you need only authentication, you 
-should use AH  rather than ESP with null encryption.</P>
+triple DES or 3DES</A>. This is currently the only encryption algorithm 
+supported.</P>
+<P> We do not implement null encryption since it is obviously insecure.</P>
 <H2><A name="modes">IPSEC modes</A></H2>
 <P>IPSEC can connect in two modes. Transport mode is a host-to-host 
  connection involving only two machines. In tunnel mode, the IPSEC 
diff -bruN freeswan-1.9.orig/doc/mail.html freeswan-1.9/doc/mail.html
--- freeswan-1.9.orig/doc/mail.html	Tue Mar 27 23:16:51 2001
+++ freeswan-1.9/doc/mail.html	Mon Jun  4 01:15:56 2001
@@ -23,7 +23,8 @@
 <DD>
 <UL>
 <LI>The general list for discussing use of the software </LI>
-<LI>The place for seeking <STRONG>help with problems</STRONG>. </LI>
+<LI>The place for seeking <STRONG>help with problems</STRONG> (but 
+please check the <A href="faq.html">FAQ</A> first). </LI>
 <LI>Anyone can post. </LI>
 </UL>
 </DD>
@@ -45,7 +46,9 @@
 <LI><STRONG>Design discussions</STRONG>, for people working on 
 FreeS/WAN development or others with an interest  in design and 
 security issues. </LI>
-<LI>Only subscribers can post. </LI>
+<LI>It would be a good idea to read the existing design papers (see 
+this <A href="intro.html#applied">list</A>) before  posting. </LI>
+<LI>Anyone can post. </LI>
 </UL>
 </DD>
 <DT><A href="mailto:announce-request@lists.freeswan.org?body=subscribe">
@@ -57,7 +60,10 @@
 software. </LI>
 <LI>All posts here are also sent to the users list. You need not 
 subscribe to both. </LI>
-<LI>Only authorised people can post. </LI>
+<LI>Only the FreeS/WAN team can post. </LI>
+<LI>If you have something you feel should go on this list, send it to <VAR>
+announce-admin@lists.freeswan.org</VAR>.  Unless it is obvious, please 
+include a short note explaining why we should post it.</LI>
 </UL>
 </DD>
 <DT><A href="mailto:briefs-request@lists.freeswan.org?body=subscribe">
@@ -68,7 +74,7 @@
 <LI><STRONG>Weekly summaries</STRONG> of activity on the users list. </LI>
 <LI>All posts here are also sent to the users list. You need not 
 subscribe to both. </LI>
-<LI>Only authorised people can post. </LI>
+<LI>Only the FreeS/WAN team can post. </LI>
 </UL>
 </DD>
 </DL>
@@ -80,6 +86,8 @@
 <LI>send mail to <VAR>listname</VAR>-request@lists.freeswan.org with a 
 one-line message body &quot;subscribe&quot; </LI>
 </UL>
+<P> Archives of these lists are available via the <A href="http://www.freeswan.org/mail.html">
+web interface</A>. </P>
 <H4><A name="policy.list">List policies</A></H4>
 <STRONG> US citizens or residents are asked not to post code to the 
 lists, not even one-line bug fixes</STRONG>. The project cannot accept 
@@ -99,7 +107,9 @@
 <LI><A href="http://www.sandelman.ottawa.on.ca/linux-ipsec">Canada</A></LI>
 <LI><A href="http://www.nexial.com">Holland</A></LI>
 </UL>
-<P>Note that these use different search engines. Try both.</P>
+<P> Note that these use different search engines. Try both.</P>
+<P> Archives of the new lists are available via the <A href="http://www.freeswan.org/mail.html">
+web interface</A>. </P>
 <H3><A name="additional">Other FreeS/WAN related lists</A></H3>
 <P> There are several other lists related to FreeS/WAN: </P>
 <UL>
diff -bruN freeswan-1.9.orig/doc/manpage.d/ipsec.8.html freeswan-1.9/doc/manpage.d/ipsec.8.html
--- freeswan-1.9.orig/doc/manpage.d/ipsec.8.html	Tue Mar 27 23:17:08 2001
+++ freeswan-1.9/doc/manpage.d/ipsec.8.html	Mon Jun  4 01:16:12 2001
@@ -3,7 +3,7 @@
 <HTML><HEAD><TITLE>Manpage of IPSEC</TITLE>
 </HEAD><BODY>
 <H1>IPSEC</H1>
-Section: Maintenance Commands (8)<BR>Updated: 11 Dec 2000<BR><A HREF="#index">Index</A>
+Section: Maintenance Commands (8)<BR>Updated: 1 June 2001<BR><A HREF="#index">Index</A>
 <A HREF="http://localhost/cgi-bin/man/man2html">Return to Main Contents</A><HR>
 
 
@@ -63,24 +63,30 @@
 <I>command</I>
 
 with a suitable PATH environment variable,
-and also provides an IPSECDIR environment variable containing
-the full pathname of the directory where the IPsec utilities are stored.
+and also provides IPSEC_DIR and IPSEC_VERSION environment variables,
+containing respectively
+the full pathname of the directory where the IPsec utilities are stored
+and the IPsec version number.
 <P>
 
 <B>ipsec --help</B>
 
 lists the available commands.
 Most have their own manual pages, e.g.
-<I><A HREF="ipsec_manual.8.html">ipsec_manual</A></I>(8)
+<I><A HREF="ipsec_auto.8.html">ipsec_auto</A></I>(8)
 
 for
-<I>manual</I>.
+<I>auto</I>.
 
 <P>
 
 <B>ipsec --version</B>
 
 supplies the version number of Linux FreeS/WAN.
+A version number of the form ``U<I>xxx</I>/K<I>yyy</I>''
+indicates that the user-level utilities are version <I>xxx</I>
+but the kernel portion appears to be version <I>yyy</I>
+(this form is used only if the two disagree).
 <P>
 
 <B>ipsec --copyright</B>
@@ -93,22 +99,37 @@
 reports where
 <I>ipsec</I>
 
-thinkgs the IPsec utilities are stored.
+thinks the IPsec utilities are stored.
 <A NAME="lbAE">&nbsp;</A>
 <H2>FILES</H2>
 
-/usr/local/lib/ipsec<TT>&nbsp;&nbsp;&nbsp;</TT>utilities directory (default location)<BR>
+/usr/local/lib/ipsec<TT>&nbsp;&nbsp;&nbsp;</TT>usual utilities directory<BR>
 <A NAME="lbAF">&nbsp;</A>
 <H2>SEE ALSO</H2>
 
 
-<A HREF="ipsec_manual.8.html">ipsec_manual</A>(8), <A HREF="ipsec_auto.8.html">ipsec_auto</A>(8),
-<A HREF="ipsec_klipsdebug.8.html">ipsec_klipsdebug</A>(8), <A HREF="ipsec_barf.8.html">ipsec_barf</A>(8)
+
+<A HREF="ipsec.conf.5.html">ipsec.conf</A>(5), <A HREF="ipsec.secrets.5.html">ipsec.secrets</A>(5),
+<A HREF="ipsec_auto.8.html">ipsec_auto</A>(8),
+<A HREF="ipsec_barf.8.html">ipsec_barf</A>(8),
+<A HREF="ipsec_setup.8.html">ipsec_setup</A>(8),
+<A HREF="ipsec_showdefaults.8.html">ipsec_showdefaults</A>(8),
+<A HREF="ipsec_showhostkey.8.html">ipsec_showhostkey</A>(8)
+
+
+<P>
+
+HTML documentation shipped with the release, starting with
+<I>doc/index.html</I>.
+
+<I>&lt;<A HREF="http://www.freeswan.org/doc.html">http://www.freeswan.org/doc.html</A>&gt;</I>
+
+may also be of use.
 <A NAME="lbAG">&nbsp;</A>
 <H2>HISTORY</H2>
 
-Written for the Linux FreeS/WAN project
-&lt;<A HREF="http://www.xs4all.nl/~freeswan/">http://www.xs4all.nl/~freeswan/</A>&gt;
+Written for Linux FreeS/WAN
+&lt;<A HREF="http://www.freeswan.org">http://www.freeswan.org</A>&gt;
 by Henry Spencer.
 <A NAME="lbAH">&nbsp;</A>
 <H2>BUGS</H2>
@@ -136,6 +157,6 @@
 This document was created by
 <A HREF="http://localhost/cgi-bin/man/man2html">man2html</A>,
 using the manual pages.<BR>
-Time: 04:17:08 GMT, March 28, 2001
+Time: 05:16:11 GMT, June 04, 2001
 </BODY>
 </HTML>
diff -bruN freeswan-1.9.orig/doc/manpage.d/ipsec.conf.5.html freeswan-1.9/doc/manpage.d/ipsec.conf.5.html
--- freeswan-1.9.orig/doc/manpage.d/ipsec.conf.5.html	Tue Mar 27 23:17:08 2001
+++ freeswan-1.9/doc/manpage.d/ipsec.conf.5.html	Mon Jun  4 01:16:12 2001
@@ -3,7 +3,7 @@
 <HTML><HEAD><TITLE>Manpage of IPSEC.CONF</TITLE>
 </HEAD><BODY>
 <H1>IPSEC.CONF</H1>
-Section: File Formats (5)<BR>Updated: 9 March 2001<BR><A HREF="#index">Index</A>
+Section: File Formats (5)<BR>Updated: 29 May 2001<BR><A HREF="#index">Index</A>
 <A HREF="http://localhost/cgi-bin/man/man2html">Return to Main Contents</A><HR>
 
 
@@ -118,9 +118,10 @@
 There can be white space on either side of the
 <B>=</B>.
 
-The parameter names are specific to a section type.
+Parameter names follow the same syntax as section names,
+and are specific to a section type.
 Unless otherwise explicitly specified,
-no parameter may appear more than once in a section.
+no parameter name may appear more than once in a section.
 <P>
 
 An empty
@@ -350,41 +351,6 @@
 <B>no</B>
 
 (the default).
-<DT><B>auto</B>
-
-<DD>
-what operation, if any, should be done automatically at IPsec startup;
-currently-accepted values are
-<B>add</B>
-
-(signifying an
-<I>ipsec_auto</I>
-
-<B>add</B>),
-
-<B>start</B>
-
-(signifying an
-<I>ipsec_auto</I>
-
-<B>start</B>),
-
-and
-<B>ignore</B>
-
-(also the default) (signifying no automatic startup operation).
-This parameter is ignored unless the
-<B>plutoload</B>
-
-or
-<B>plutostart</B>
-
-configuration parameter is set suitably; see the
-<B>config</B>
-
-<B>setup</B>
-
-discussion below.
 <DT><B>left</B>
 
 <DD>
@@ -456,7 +422,10 @@
 next-hop gateway IP address for the left participant's connection
 to the public network;
 defaults to
-<I>right</I>.
+<B>%direct</B>
+
+(meaning
+<I>right</I>).
 
 If the value is to be overridden by the
 <B>left=%defaultroute</B>
@@ -566,6 +535,48 @@
 the default and currently the only accepted value is
 <B>ike</B>
 
+<DT><B>auto</B>
+
+<DD>
+what operation, if any, should be done automatically at IPsec startup;
+currently-accepted values are
+<B>add</B>
+
+(signifying an
+<B>ipsec auto</B>
+
+<B>--add</B>),
+
+<B>route</B>
+
+(signifying that plus an
+<B>ipsec auto</B>
+
+<B>--route</B>),
+
+<B>start</B>
+
+(signifying that plus an
+<B>ipsec auto</B>
+
+<B>--up</B>),
+
+and
+<B>ignore</B>
+
+(also the default) (signifying no automatic startup operation).
+This parameter is ignored unless the
+<B>plutoload</B>
+
+or
+<B>plutostart</B>
+
+configuration parameter is set suitably; see the
+<B>config</B>
+
+<B>setup</B>
+
+discussion below.
 <DT><B>auth</B>
 
 <DD>
@@ -1244,37 +1255,50 @@
 <B>no</B>
 
 (the default).
-<DT><B>no_eroute_pass</B>
+<DT><B>packetdefault</B>
 
 <DD>
-whether a packet which reaches KLIPS (via a route into a virtual interface)
-but does not match any eroute should be passed in plaintext,
-rather than discarded;
+what should be done with
+a packet which reaches KLIPS (via a route into a virtual interface)
+but does not match any eroute;
 acceptable values are
-<B>yes</B>
+<B>pass</B>
+
+(<I>insecure unless you really know what you're doing!!!</I>),
+<B>drop</B>
 
-(<I>insecure unless you really know what you're doing!!!</I>)
+(the default),
 and
-<B>no</B>
+<B>reject</B>
 
-(the default).
-This overrides
-<B>opportunistic</B>.
+(currently same as
+<B>drop</B>,
 
-<DT><B>opportunistic</B>
+but eventually it will send an ICMP notification back
+to the sender).
+<DT><B>no_eroute_pass</B>
 
 <DD>
-whether a packet which reaches KLIPS (via a route into a virtual interface)
-but does not match any eroute should cause an attempt to signal
-<I>ipsec_pluto</I>
+obsolete parameter similar to
+<B>packetdefault</B>
+
+but with more limited functionality;
+ignored if
+<B>packetdefault</B>
 
-to create a connection for it;
+is set;
 acceptable values are
 <B>yes</B>
 
+(synonymous with
+<B>packetdefault=pass</B>)
+
 and
 <B>no</B>
 
+(synonymous with
+<B>packetdefault=drop</B>)
+
 (the default).
 <DT><B>hidetos</B>
 
@@ -1323,7 +1347,7 @@
 <H2>HISTORY</H2>
 
 Designed for the FreeS/WAN project
-&lt;<A HREF="http://www.xs4all.nl/~freeswan/">http://www.xs4all.nl/~freeswan/</A>&gt;
+&lt;<A HREF="http://www.freeswan.org">http://www.freeswan.org</A>&gt;
 by Henry Spencer.
 <A NAME="lbAL">&nbsp;</A>
 <H2>BUGS</H2>
@@ -1406,6 +1430,6 @@
 This document was created by
 <A HREF="http://localhost/cgi-bin/man/man2html">man2html</A>,
 using the manual pages.<BR>
-Time: 04:17:08 GMT, March 28, 2001
+Time: 05:16:12 GMT, June 04, 2001
 </BODY>
 </HTML>
diff -bruN freeswan-1.9.orig/doc/manpage.d/ipsec.secrets.5.html freeswan-1.9/doc/manpage.d/ipsec.secrets.5.html
--- freeswan-1.9.orig/doc/manpage.d/ipsec.secrets.5.html	Tue Mar 27 23:17:08 2001
+++ freeswan-1.9/doc/manpage.d/ipsec.secrets.5.html	Mon Jun  4 01:16:12 2001
@@ -217,6 +217,6 @@
 This document was created by
 <A HREF="http://localhost/cgi-bin/man/man2html">man2html</A>,
 using the manual pages.<BR>
-Time: 04:17:08 GMT, March 28, 2001
+Time: 05:16:12 GMT, June 04, 2001
 </BODY>
 </HTML>
diff -bruN freeswan-1.9.orig/doc/manpage.d/ipsec_addrbytesof.3.html freeswan-1.9/doc/manpage.d/ipsec_addrbytesof.3.html
--- freeswan-1.9.orig/doc/manpage.d/ipsec_addrbytesof.3.html	Tue Mar 27 23:17:08 2001
+++ freeswan-1.9/doc/manpage.d/ipsec_addrbytesof.3.html	Mon Jun  4 01:16:12 2001
@@ -227,6 +227,6 @@
 This document was created by
 <A HREF="http://localhost/cgi-bin/man/man2html">man2html</A>,
 using the manual pages.<BR>
-Time: 04:17:08 GMT, March 28, 2001
+Time: 05:16:12 GMT, June 04, 2001
 </BODY>
 </HTML>
diff -bruN freeswan-1.9.orig/doc/manpage.d/ipsec_addrbytesptr.3.html freeswan-1.9/doc/manpage.d/ipsec_addrbytesptr.3.html
--- freeswan-1.9.orig/doc/manpage.d/ipsec_addrbytesptr.3.html	Tue Mar 27 23:17:08 2001
+++ freeswan-1.9/doc/manpage.d/ipsec_addrbytesptr.3.html	Mon Jun  4 01:16:12 2001
@@ -227,6 +227,6 @@
 This document was created by
 <A HREF="http://localhost/cgi-bin/man/man2html">man2html</A>,
 using the manual pages.<BR>
-Time: 04:17:08 GMT, March 28, 2001
+Time: 05:16:12 GMT, June 04, 2001
 </BODY>
 </HTML>
diff -bruN freeswan-1.9.orig/doc/manpage.d/ipsec_addrcmp.3.html freeswan-1.9/doc/manpage.d/ipsec_addrcmp.3.html
--- freeswan-1.9.orig/doc/manpage.d/ipsec_addrcmp.3.html	Tue Mar 27 23:17:08 2001
+++ freeswan-1.9/doc/manpage.d/ipsec_addrcmp.3.html	Mon Jun  4 01:16:12 2001
@@ -269,6 +269,6 @@
 This document was created by
 <A HREF="http://localhost/cgi-bin/man/man2html">man2html</A>,
 using the manual pages.<BR>
-Time: 04:17:08 GMT, March 28, 2001
+Time: 05:16:12 GMT, June 04, 2001
 </BODY>
 </HTML>
diff -bruN freeswan-1.9.orig/doc/manpage.d/ipsec_addrinsubnet.3.html freeswan-1.9/doc/manpage.d/ipsec_addrinsubnet.3.html
--- freeswan-1.9.orig/doc/manpage.d/ipsec_addrinsubnet.3.html	Tue Mar 27 23:17:08 2001
+++ freeswan-1.9/doc/manpage.d/ipsec_addrinsubnet.3.html	Mon Jun  4 01:16:12 2001
@@ -269,6 +269,6 @@
 This document was created by
 <A HREF="http://localhost/cgi-bin/man/man2html">man2html</A>,
 using the manual pages.<BR>
-Time: 04:17:08 GMT, March 28, 2001
+Time: 05:16:12 GMT, June 04, 2001
 </BODY>
 </HTML>
diff -bruN freeswan-1.9.orig/doc/manpage.d/ipsec_addrlenof.3.html freeswan-1.9/doc/manpage.d/ipsec_addrlenof.3.html
--- freeswan-1.9.orig/doc/manpage.d/ipsec_addrlenof.3.html	Tue Mar 27 23:17:08 2001
+++ freeswan-1.9/doc/manpage.d/ipsec_addrlenof.3.html	Mon Jun  4 01:16:12 2001
@@ -227,6 +227,6 @@
 This document was created by
 <A HREF="http://localhost/cgi-bin/man/man2html">man2html</A>,
 using the manual pages.<BR>
-Time: 04:17:08 GMT, March 28, 2001
+Time: 05:16:12 GMT, June 04, 2001
 </BODY>
 </HTML>
diff -bruN freeswan-1.9.orig/doc/manpage.d/ipsec_addrtoa.3.html freeswan-1.9/doc/manpage.d/ipsec_addrtoa.3.html
--- freeswan-1.9.orig/doc/manpage.d/ipsec_addrtoa.3.html	Tue Mar 27 23:17:08 2001
+++ freeswan-1.9/doc/manpage.d/ipsec_addrtoa.3.html	Mon Jun  4 01:16:12 2001
@@ -437,6 +437,6 @@
 This document was created by
 <A HREF="http://localhost/cgi-bin/man/man2html">man2html</A>,
 using the manual pages.<BR>
-Time: 04:17:08 GMT, March 28, 2001
+Time: 05:16:12 GMT, June 04, 2001
 </BODY>
 </HTML>
diff -bruN freeswan-1.9.orig/doc/manpage.d/ipsec_addrtot.3.html freeswan-1.9/doc/manpage.d/ipsec_addrtot.3.html
--- freeswan-1.9.orig/doc/manpage.d/ipsec_addrtot.3.html	Tue Mar 27 23:17:08 2001
+++ freeswan-1.9/doc/manpage.d/ipsec_addrtot.3.html	Mon Jun  4 01:16:12 2001
@@ -563,6 +563,6 @@
 This document was created by
 <A HREF="http://localhost/cgi-bin/man/man2html">man2html</A>,
 using the manual pages.<BR>
-Time: 04:17:08 GMT, March 28, 2001
+Time: 05:16:12 GMT, June 04, 2001
 </BODY>
 </HTML>
diff -bruN freeswan-1.9.orig/doc/manpage.d/ipsec_addrtypeof.3.html freeswan-1.9/doc/manpage.d/ipsec_addrtypeof.3.html
--- freeswan-1.9.orig/doc/manpage.d/ipsec_addrtypeof.3.html	Tue Mar 27 23:17:08 2001
+++ freeswan-1.9/doc/manpage.d/ipsec_addrtypeof.3.html	Mon Jun  4 01:16:12 2001
@@ -227,6 +227,6 @@
 This document was created by
 <A HREF="http://localhost/cgi-bin/man/man2html">man2html</A>,
 using the manual pages.<BR>
-Time: 04:17:08 GMT, March 28, 2001
+Time: 05:16:12 GMT, June 04, 2001
 </BODY>
 </HTML>
diff -bruN freeswan-1.9.orig/doc/manpage.d/ipsec_anyaddr.3.html freeswan-1.9/doc/manpage.d/ipsec_anyaddr.3.html
--- freeswan-1.9.orig/doc/manpage.d/ipsec_anyaddr.3.html	Tue Mar 27 23:17:09 2001
+++ freeswan-1.9/doc/manpage.d/ipsec_anyaddr.3.html	Mon Jun  4 01:16:12 2001
@@ -161,6 +161,6 @@
 This document was created by
 <A HREF="http://localhost/cgi-bin/man/man2html">man2html</A>,
 using the manual pages.<BR>
-Time: 04:17:08 GMT, March 28, 2001
+Time: 05:16:12 GMT, June 04, 2001
 </BODY>
 </HTML>
diff -bruN freeswan-1.9.orig/doc/manpage.d/ipsec_atoaddr.3.html freeswan-1.9/doc/manpage.d/ipsec_atoaddr.3.html
--- freeswan-1.9.orig/doc/manpage.d/ipsec_atoaddr.3.html	Tue Mar 27 23:17:09 2001
+++ freeswan-1.9/doc/manpage.d/ipsec_atoaddr.3.html	Mon Jun  4 01:16:12 2001
@@ -437,6 +437,6 @@
 This document was created by
 <A HREF="http://localhost/cgi-bin/man/man2html">man2html</A>,
 using the manual pages.<BR>
-Time: 04:17:09 GMT, March 28, 2001
+Time: 05:16:12 GMT, June 04, 2001
 </BODY>
 </HTML>
diff -bruN freeswan-1.9.orig/doc/manpage.d/ipsec_atoasr.3.html freeswan-1.9/doc/manpage.d/ipsec_atoasr.3.html
--- freeswan-1.9.orig/doc/manpage.d/ipsec_atoasr.3.html	Tue Mar 27 23:17:09 2001
+++ freeswan-1.9/doc/manpage.d/ipsec_atoasr.3.html	Mon Jun  4 01:16:12 2001
@@ -284,6 +284,6 @@
 This document was created by
 <A HREF="http://localhost/cgi-bin/man/man2html">man2html</A>,
 using the manual pages.<BR>
-Time: 04:17:09 GMT, March 28, 2001
+Time: 05:16:12 GMT, June 04, 2001
 </BODY>
 </HTML>
diff -bruN freeswan-1.9.orig/doc/manpage.d/ipsec_atosa.3.html freeswan-1.9/doc/manpage.d/ipsec_atosa.3.html
--- freeswan-1.9.orig/doc/manpage.d/ipsec_atosa.3.html	Tue Mar 27 23:17:09 2001
+++ freeswan-1.9/doc/manpage.d/ipsec_atosa.3.html	Mon Jun  4 01:16:12 2001
@@ -336,6 +336,6 @@
 This document was created by
 <A HREF="http://localhost/cgi-bin/man/man2html">man2html</A>,
 using the manual pages.<BR>
-Time: 04:17:09 GMT, March 28, 2001
+Time: 05:16:12 GMT, June 04, 2001
 </BODY>
 </HTML>
diff -bruN freeswan-1.9.orig/doc/manpage.d/ipsec_atosubnet.3.html freeswan-1.9/doc/manpage.d/ipsec_atosubnet.3.html
--- freeswan-1.9.orig/doc/manpage.d/ipsec_atosubnet.3.html	Tue Mar 27 23:17:09 2001
+++ freeswan-1.9/doc/manpage.d/ipsec_atosubnet.3.html	Mon Jun  4 01:16:12 2001
@@ -437,6 +437,6 @@
 This document was created by
 <A HREF="http://localhost/cgi-bin/man/man2html">man2html</A>,
 using the manual pages.<BR>
-Time: 04:17:09 GMT, March 28, 2001
+Time: 05:16:12 GMT, June 04, 2001
 </BODY>
 </HTML>
diff -bruN freeswan-1.9.orig/doc/manpage.d/ipsec_atoul.3.html freeswan-1.9/doc/manpage.d/ipsec_atoul.3.html
--- freeswan-1.9.orig/doc/manpage.d/ipsec_atoul.3.html	Tue Mar 27 23:17:09 2001
+++ freeswan-1.9/doc/manpage.d/ipsec_atoul.3.html	Mon Jun  4 01:16:12 2001
@@ -255,6 +255,6 @@
 This document was created by
 <A HREF="http://localhost/cgi-bin/man/man2html">man2html</A>,
 using the manual pages.<BR>
-Time: 04:17:09 GMT, March 28, 2001
+Time: 05:16:12 GMT, June 04, 2001
 </BODY>
 </HTML>
diff -bruN freeswan-1.9.orig/doc/manpage.d/ipsec_auto.8.html freeswan-1.9/doc/manpage.d/ipsec_auto.8.html
--- freeswan-1.9.orig/doc/manpage.d/ipsec_auto.8.html	Tue Mar 27 23:17:09 2001
+++ freeswan-1.9/doc/manpage.d/ipsec_auto.8.html	Mon Jun  4 01:16:12 2001
@@ -3,7 +3,7 @@
 <HTML><HEAD><TITLE>Manpage of IPSEC_AUTO</TITLE>
 </HEAD><BODY>
 <H1>IPSEC_AUTO</H1>
-Section: Maintenance Commands (8)<BR>Updated: 23 March 2001<BR><A HREF="#index">Index</A>
+Section: Maintenance Commands (8)<BR>Updated: 31 May 2001<BR><A HREF="#index">Index</A>
 <A HREF="http://localhost/cgi-bin/man/man2html">Return to Main Contents</A><HR>
 
 
@@ -233,7 +233,7 @@
 to re-read the
 <I>/etc/ipsec.secrets</I>
 
-shared-secrets file,
+secret-keys file,
 which it normally reads only at startup time.
 (This is currently a synonym for
 <B>--ready</B>,
@@ -348,7 +348,7 @@
 <H2>HISTORY</H2>
 
 Written for the FreeS/WAN project
-&lt;<A HREF="http://www.xs4all.nl/~freeswan/">http://www.xs4all.nl/~freeswan/</A>&gt;
+&lt;<A HREF="http://www.freeswan.org">http://www.freeswan.org</A>&gt;
 by Henry Spencer.
 <A NAME="lbAH">&nbsp;</A>
 <H2>BUGS</H2>
@@ -394,6 +394,6 @@
 This document was created by
 <A HREF="http://localhost/cgi-bin/man/man2html">man2html</A>,
 using the manual pages.<BR>
-Time: 04:17:09 GMT, March 28, 2001
+Time: 05:16:12 GMT, June 04, 2001
 </BODY>
 </HTML>
diff -bruN freeswan-1.9.orig/doc/manpage.d/ipsec_barf.8.html freeswan-1.9/doc/manpage.d/ipsec_barf.8.html
--- freeswan-1.9.orig/doc/manpage.d/ipsec_barf.8.html	Tue Mar 27 23:17:09 2001
+++ freeswan-1.9/doc/manpage.d/ipsec_barf.8.html	Mon Jun  4 01:16:12 2001
@@ -3,7 +3,7 @@
 <HTML><HEAD><TITLE>Manpage of IPSEC_BARF</TITLE>
 </HEAD><BODY>
 <H1>IPSEC_BARF</H1>
-Section: Maintenance Commands (8)<BR>Updated: 1 June 2000<BR><A HREF="#index">Index</A>
+Section: Maintenance Commands (8)<BR>Updated: 31 May 2001<BR><A HREF="#index">Index</A>
 <A HREF="http://localhost/cgi-bin/man/man2html">Return to Main Contents</A><HR>
 
 
@@ -77,12 +77,18 @@
 <A NAME="lbAE">&nbsp;</A>
 <H2>FILES</H2>
 
-/proc/net/*, /var/log/*
+<PRE>
+/proc/net/*
+/var/log/*
+/etc/ipsec.conf
+/etc/ipsec.secrets
+</PRE>
+
 <A NAME="lbAF">&nbsp;</A>
 <H2>HISTORY</H2>
 
 Written for the Linux FreeS/WAN project
-&lt;<A HREF="http://www.xs4all.nl/~freeswan/">http://www.xs4all.nl/~freeswan/</A>&gt;
+&lt;<A HREF="http://www.freeswan.org">http://www.freeswan.org</A>&gt;
 by Henry Spencer.
 <A NAME="lbAG">&nbsp;</A>
 <H2>BUGS</H2>
@@ -121,6 +127,6 @@
 This document was created by
 <A HREF="http://localhost/cgi-bin/man/man2html">man2html</A>,
 using the manual pages.<BR>
-Time: 04:17:09 GMT, March 28, 2001
+Time: 05:16:12 GMT, June 04, 2001
 </BODY>
 </HTML>
diff -bruN freeswan-1.9.orig/doc/manpage.d/ipsec_bitstomask.3.html freeswan-1.9/doc/manpage.d/ipsec_bitstomask.3.html
--- freeswan-1.9.orig/doc/manpage.d/ipsec_bitstomask.3.html	Tue Mar 27 23:17:09 2001
+++ freeswan-1.9/doc/manpage.d/ipsec_bitstomask.3.html	Mon Jun  4 01:16:12 2001
@@ -110,6 +110,6 @@
 This document was created by
 <A HREF="http://localhost/cgi-bin/man/man2html">man2html</A>,
 using the manual pages.<BR>
-Time: 04:17:09 GMT, March 28, 2001
+Time: 05:16:12 GMT, June 04, 2001
 </BODY>
 </HTML>
diff -bruN freeswan-1.9.orig/doc/manpage.d/ipsec_broadcastof.3.html freeswan-1.9/doc/manpage.d/ipsec_broadcastof.3.html
--- freeswan-1.9.orig/doc/manpage.d/ipsec_broadcastof.3.html	Tue Mar 27 23:17:09 2001
+++ freeswan-1.9/doc/manpage.d/ipsec_broadcastof.3.html	Mon Jun  4 01:16:12 2001
@@ -96,6 +96,6 @@
 This document was created by
 <A HREF="http://localhost/cgi-bin/man/man2html">man2html</A>,
 using the manual pages.<BR>
-Time: 04:17:09 GMT, March 28, 2001
+Time: 05:16:12 GMT, June 04, 2001
 </BODY>
 </HTML>
diff -bruN freeswan-1.9.orig/doc/manpage.d/ipsec_datatot.3.html freeswan-1.9/doc/manpage.d/ipsec_datatot.3.html
--- freeswan-1.9.orig/doc/manpage.d/ipsec_datatot.3.html	Tue Mar 27 23:17:09 2001
+++ freeswan-1.9/doc/manpage.d/ipsec_datatot.3.html	Mon Jun  4 01:16:13 2001
@@ -372,6 +372,6 @@
 This document was created by
 <A HREF="http://localhost/cgi-bin/man/man2html">man2html</A>,
 using the manual pages.<BR>
-Time: 04:17:09 GMT, March 28, 2001
+Time: 05:16:13 GMT, June 04, 2001
 </BODY>
 </HTML>
diff -bruN freeswan-1.9.orig/doc/manpage.d/ipsec_eroute.5.html freeswan-1.9/doc/manpage.d/ipsec_eroute.5.html
--- freeswan-1.9.orig/doc/manpage.d/ipsec_eroute.5.html	Tue Mar 27 23:17:09 2001
+++ freeswan-1.9/doc/manpage.d/ipsec_eroute.5.html	Mon Jun  4 01:16:13 2001
@@ -40,6 +40,8 @@
 A table entry consists of:
 <DL COMPACT>
 <DT>+<DD>
+packet count,
+<DT>+<DD>
 source address with mask,
 <DT>+<DD>
 a '-&gt;' separator for visual and automated parsing between src and dst
@@ -54,6 +56,10 @@
 protocol
 (<I>proto</I>),
 <DT>+<DD>
+address family
+(<I>af</I>),
+where '.' stands for IPv4 and ':' for IPv6
+<DT>+<DD>
 Security Parameters Index
 (<I>SPI</I>),
 <DT>+<DD>
@@ -62,10 +68,6 @@
 where the packet should be forwarded after processing
 (normally the other security gateway)
 together indicate which Security Association should be used to process the packet
-<DT>+<DD>
-address family
-(<I>af</I>),
-where '.' stands for IPv4 and ':' for IPv6
 </DL>
 <P>
 
@@ -75,23 +77,50 @@
 SPIs are prefixed hexadecimal numbers where the prefix '.' is for IPv4 and the prefix ':' is for IPv6
 <P>
 
-SAIDs are written as &quot;<A HREF="mailto:protoafSPI@edst">protoafSPI@edst</A>&quot;.
+SAIDs are written as &quot;<A HREF="mailto:protoafSPI@edst">protoafSPI@edst</A>&quot;.  There are also 5
+&quot;magic&quot; SAIDs which have special meaning:
+<DL COMPACT>
+<DT>+<DD>
+<B>%drop</B>
+
+means that matches are to be dropped
+<DT>+<DD>
+<B>%reject</B>
+
+means that matches are to be dropped and an ICMP returned, if
+possible to inform
+<DT>+<DD>
+<B>%trap</B>
+
+means that matches are to trigger an ACQUIRE message to the Key
+Management daemon(s) and a hold eroute will be put in place to
+prevent subsequent packets also triggering ACQUIRE messages.
+<DT>+<DD>
+<B>%hold</B>
+
+means that matches are to stored until the eroute is replaced or
+until that eroute gets reaped
+<DT>+<DD>
+<B>%pass</B>
+
+means that matches are to allowed to pass without IPSEC processing
 <BR>
 
 
+</DL>
 <A NAME="lbAE">&nbsp;</A>
 <H2>EXAMPLES</H2>
 
 <P>
 
-<B>172.31.252.0/24    -&gt; 0.0.0.0/0          =&gt; <A HREF="mailto:tun.130@192.168.43.1">tun.130@192.168.43.1</A></B>
+<B>1867     172.31.252.0/24    -&gt; 0.0.0.0/0          =&gt; <A HREF="mailto:tun.130@192.168.43.1">tun.130@192.168.43.1</A></B>
 
 <P>
 
-means that an
+means that 1,867 packets have been sent to an
 <B>eroute</B>
 
-has been set up to protect traffic between the subnet
+that has been set up to protect traffic between the subnet
 <B>172.31.252.0</B>
 
 with a subnet mask of
@@ -117,14 +146,14 @@
 in hexadecimal.
 <P>
 
-<B>3049:1::/64    -&gt; 0:0/0          =&gt; tun:<A HREF="mailto:130@3058">130@3058</A>:4::5</B>
+<B>125      3049:1::/64    -&gt; 0:0/0          =&gt; tun:<A HREF="mailto:130@3058">130@3058</A>:4::5</B>
 
 <P>
 
-means that an
+means that 125 packets have been sent to an
 <B>eroute</B>
 
-has been set up to protect traffic between the subnet
+that has been set up to protect traffic between the subnet
 <B>3049:1::</B>
 
 with a subnet mask of
@@ -150,14 +179,14 @@
 in hexadecimal.
 <P>
 
-<B>192.168.6.0/24     -&gt; 192.168.7.0/24     =&gt; %passthrough</B>
+<B>42         192.168.6.0/24     -&gt; 192.168.7.0/24     =&gt; %passthrough</B>
 
 <P>
 
-means that an
+means that 42 packets have been sent to an
 <B>eroute</B>
 
-has been set up to pass the traffic from the subnet
+that has been set up to pass the traffic from the subnet
 <B>192.168.6.0</B>
 
 with a subnet mask of
@@ -172,7 +201,25 @@
 bits without any IPSEC processing.
 <P>
 
-<B>192.168.2.110/32   -&gt; 192.168.2.120/32   =&gt; </B>
+<B>2112     192.168.8.55/32    -&gt; 192.168.9.47/24    =&gt; %hold</B>
+
+<P>
+
+means that 2112 packets have been sent to an
+<B>eroute</B>
+
+that has been set up to hold the traffic from the host
+<B>192.168.8.55</B>
+
+and to host
+<B>192.168.9.47</B>
+
+until a key exchange from a Key Management daemon
+succeeds and puts in an SA or fails and puts in a pass
+or drop eroute depending on the default configuration.
+<P>
+
+<B>2001     192.168.2.110/32   -&gt; 192.168.2.120/32   =&gt; </B>
 
 <BR>
 
@@ -180,10 +227,10 @@
 
 <P>
 
-means that an
+means that 2001 packets have been sent to an
 <B>eroute</B>
 
-has been set up to protect traffic between the host
+that has been set up to protect traffic between the host
 <B>192.168.2.110</B>
 
 and the host
@@ -207,7 +254,7 @@
 IPPROTO_ESP).
 <P>
 
-<B>3049:1::110/128   -&gt; 3049:1::120/128   =&gt; </B>
+<B>1984     3049:1::110/128   -&gt; 3049:1::120/128   =&gt; </B>
 
 <BR>
 
@@ -215,10 +262,10 @@
 
 <P>
 
-means that an
+means that 1984 packets have been sent to an
 <B>eroute</B>
 
-has been set up to authenticate traffic between the host
+that has been set up to authenticate traffic between the host
 <B>3049:1::110</B>
 
 and the host
@@ -277,6 +324,14 @@
 
 
 
+
+
+
+
+
+
+
+
 <P>
 
 <HR>
@@ -294,6 +349,6 @@
 This document was created by
 <A HREF="http://localhost/cgi-bin/man/man2html">man2html</A>,
 using the manual pages.<BR>
-Time: 04:17:09 GMT, March 28, 2001
+Time: 05:16:13 GMT, June 04, 2001
 </BODY>
 </HTML>
diff -bruN freeswan-1.9.orig/doc/manpage.d/ipsec_eroute.8.html freeswan-1.9/doc/manpage.d/ipsec_eroute.8.html
--- freeswan-1.9.orig/doc/manpage.d/ipsec_eroute.8.html	Tue Mar 27 23:17:09 2001
+++ freeswan-1.9/doc/manpage.d/ipsec_eroute.8.html	Mon Jun  4 01:16:13 2001
@@ -152,23 +152,24 @@
 <DT>+<DD>
 Security Association IDentifier, comprised of:
 <DT>+<DD>
+protocol
+(<I>proto</I>), indicating (together with the
+effective destination and the security parameters index)
+which Security Association should be used to process the packet
+<DT>+<DD>
 address family
 (<I>af</I>),
 <DT>+<DD>
-effective destination
-(<I>edst</I>),
-where the packet should be forwarded after processing
-(normally the other security gateway)
-<DT>+<DD>
 Security Parameters Index
 (<I>spi</I>), indicating (together with the
 effective destination and protocol)
 which Security Association should be used to process the packet
+(must be larger than or equal to 0x100)
 <DT>+<DD>
-protocol
-(<I>proto</I>), indicating (together with the
-effective destination and the security parameters index)
-which Security Association should be used to process the packet
+effective destination
+(<I>edst</I>),
+where the packet should be forwarded after processing
+(normally the other security gateway)
 <DT>+<DD>
 OR
 <DT>+<DD>
@@ -178,12 +179,40 @@
 </DL>
 <P>
 
-Addresses are written as IPv4 dotted quads or IPv6 coloned hex, protocol is one
-of &quot;ah&quot;, &quot;esp&quot;, &quot;comp&quot; or &quot;tun&quot; and SPIs are prefixed hexadecimal numbers where '.' represents
-IPv4 and ':' stands for IPv6.
+Addresses are written as IPv4 dotted quads or IPv6 coloned hex,
+protocol is one of &quot;ah&quot;, &quot;esp&quot;, &quot;comp&quot; or &quot;tun&quot; and SPIs are
+prefixed hexadecimal numbers where '.' represents IPv4 and ':'
+stands for IPv6.
 <P>
 
-SAIDs are written as &quot;<A HREF="mailto:protoafSPI@address">protoafSPI@address</A>&quot;.
+SAIDs are written as &quot;<A HREF="mailto:protoafSPI@address">protoafSPI@address</A>&quot;.  There are also 5
+&quot;magic&quot; SAIDs which have special meaning:
+<DL COMPACT>
+<DT>+<DD>
+<B>%drop</B>
+
+means that matches are to be dropped
+<DT>+<DD>
+<B>%reject</B>
+
+means that matches are to be dropped and an ICMP returned, if
+possible to inform
+<DT>+<DD>
+<B>%trap</B>
+
+means that matches are to trigger an ACQUIRE message to the Key
+Management daemon(s) and a hold eroute will be put in place to
+prevent subsequent packets also triggering ACQUIRE messages.
+<DT>+<DD>
+<B>%hold</B>
+
+means that matches are to stored until the eroute is replaced or
+until that eroute gets reaped
+<DT>+<DD>
+<B>%pass</B>
+
+means that matches are to allowed to pass without IPSEC processing
+</DL>
 <P>
 
 The format of /proc/net/ipsec_eroute is listed in <A HREF="ipsec_eroute.5.html">ipsec_eroute</A>(5).
@@ -362,6 +391,11 @@
 
 
 
+
+
+
+
+
 <P>
 
 <HR>
@@ -379,6 +413,6 @@
 This document was created by
 <A HREF="http://localhost/cgi-bin/man/man2html">man2html</A>,
 using the manual pages.<BR>
-Time: 04:17:09 GMT, March 28, 2001
+Time: 05:16:13 GMT, June 04, 2001
 </BODY>
 </HTML>
diff -bruN freeswan-1.9.orig/doc/manpage.d/ipsec_four2perm.1.html freeswan-1.9/doc/manpage.d/ipsec_four2perm.1.html
--- freeswan-1.9.orig/doc/manpage.d/ipsec_four2perm.1.html	Tue Mar 27 23:17:09 2001
+++ freeswan-1.9/doc/manpage.d/ipsec_four2perm.1.html	Mon Jun  4 01:16:13 2001
@@ -52,6 +52,6 @@
 This document was created by
 <A HREF="http://localhost/cgi-bin/man/man2html">man2html</A>,
 using the manual pages.<BR>
-Time: 04:17:09 GMT, March 28, 2001
+Time: 05:16:13 GMT, June 04, 2001
 </BODY>
 </HTML>
diff -bruN freeswan-1.9.orig/doc/manpage.d/ipsec_goodmask.3.html freeswan-1.9/doc/manpage.d/ipsec_goodmask.3.html
--- freeswan-1.9.orig/doc/manpage.d/ipsec_goodmask.3.html	Tue Mar 27 23:17:09 2001
+++ freeswan-1.9/doc/manpage.d/ipsec_goodmask.3.html	Mon Jun  4 01:16:13 2001
@@ -110,6 +110,6 @@
 This document was created by
 <A HREF="http://localhost/cgi-bin/man/man2html">man2html</A>,
 using the manual pages.<BR>
-Time: 04:17:09 GMT, March 28, 2001
+Time: 05:16:13 GMT, June 04, 2001
 </BODY>
 </HTML>
diff -bruN freeswan-1.9.orig/doc/manpage.d/ipsec_hostof.3.html freeswan-1.9/doc/manpage.d/ipsec_hostof.3.html
--- freeswan-1.9.orig/doc/manpage.d/ipsec_hostof.3.html	Tue Mar 27 23:17:09 2001
+++ freeswan-1.9/doc/manpage.d/ipsec_hostof.3.html	Mon Jun  4 01:16:13 2001
@@ -96,6 +96,6 @@
 This document was created by
 <A HREF="http://localhost/cgi-bin/man/man2html">man2html</A>,
 using the manual pages.<BR>
-Time: 04:17:09 GMT, March 28, 2001
+Time: 05:16:13 GMT, June 04, 2001
 </BODY>
 </HTML>
diff -bruN freeswan-1.9.orig/doc/manpage.d/ipsec_html2four.1.html freeswan-1.9/doc/manpage.d/ipsec_html2four.1.html
--- freeswan-1.9.orig/doc/manpage.d/ipsec_html2four.1.html	Tue Mar 27 23:17:09 2001
+++ freeswan-1.9/doc/manpage.d/ipsec_html2four.1.html	Mon Jun  4 01:16:13 2001
@@ -58,6 +58,6 @@
 This document was created by
 <A HREF="http://localhost/cgi-bin/man/man2html">man2html</A>,
 using the manual pages.<BR>
-Time: 04:17:09 GMT, March 28, 2001
+Time: 05:16:13 GMT, June 04, 2001
 </BODY>
 </HTML>
diff -bruN freeswan-1.9.orig/doc/manpage.d/ipsec_initaddr.3.html freeswan-1.9/doc/manpage.d/ipsec_initaddr.3.html
--- freeswan-1.9.orig/doc/manpage.d/ipsec_initaddr.3.html	Tue Mar 27 23:17:09 2001
+++ freeswan-1.9/doc/manpage.d/ipsec_initaddr.3.html	Mon Jun  4 01:16:13 2001
@@ -227,6 +227,6 @@
 This document was created by
 <A HREF="http://localhost/cgi-bin/man/man2html">man2html</A>,
 using the manual pages.<BR>
-Time: 04:17:09 GMT, March 28, 2001
+Time: 05:16:13 GMT, June 04, 2001
 </BODY>
 </HTML>
diff -bruN freeswan-1.9.orig/doc/manpage.d/ipsec_initsaid.3.html freeswan-1.9/doc/manpage.d/ipsec_initsaid.3.html
--- freeswan-1.9.orig/doc/manpage.d/ipsec_initsaid.3.html	Tue Mar 27 23:17:09 2001
+++ freeswan-1.9/doc/manpage.d/ipsec_initsaid.3.html	Mon Jun  4 01:16:13 2001
@@ -3,7 +3,7 @@
 <HTML><HEAD><TITLE>Manpage of IPSEC_TTOSA</TITLE>
 </HEAD><BODY>
 <H1>IPSEC_TTOSA</H1>
-Section: C Library Functions (3)<BR>Updated: 15 Sept 2000<BR><A HREF="#index">Index</A>
+Section: C Library Functions (3)<BR>Updated: 27 Feb 2001<BR><A HREF="#index">Index</A>
 <A HREF="http://localhost/cgi-bin/man/man2html">Return to Main Contents</A><HR>
 
 
@@ -96,8 +96,10 @@
 
 <B>tun</B>,
 
+<B>comp</B>,
+
 or
-<B>comp</B>),
+<B>int</B>),
 
 a single character indicating the address family
 (<B>.</B>
@@ -149,6 +151,29 @@
 so the internal representation is never visible.
 <P>
 
+Similarly, the SA specifiers
+<B>%pass</B>,
+
+<B>%drop</B>,
+
+<B>%reject</B>,
+
+<B>%hold</B>,
+
+and
+<B>%trap</B>
+
+signify special ``magic'' SAs used to indicate that packets should be
+passed, dropped, rejected (dropped with ICMP notification),
+held,
+and trapped (sent up to
+<I><A HREF="ipsec_pluto.8.html">ipsec_pluto</A></I>(8))
+
+respectively.
+These forms too are known to both routines,
+so the internal representation of the magic SAs should never be visible.
+<P>
+
 The
 <B>&lt;<A HREF="file:/usr/include/freeswan.h">freeswan.h</A>&gt;</B>
 
@@ -190,6 +215,48 @@
 
 <P>
 
+<B>&lt;<A HREF="file:/usr/include/freeswan.h">freeswan.h</A>&gt;</B>
+
+also defines
+<B>SA_INT</B>
+
+to have the value
+<B>61</B>
+
+(reserved by IANA for ``any host internal protocol'')
+and
+<B>SPI_PASS</B>,
+
+<B>SPI_DROP</B>,
+
+<B>SPI_REJECT</B>,
+
+<B>SPI_HOLD</B>,
+
+and
+<B>SPI_TRAP</B>
+
+to have the values 256-260 (in <I>host</I> byte order) respectively.
+These are used in constructing the magic SAs
+(which always have address
+<B>0.0.0.0</B>).
+
+<P>
+
+If
+<I>satot</I>
+
+encounters an unknown protocol code, e.g. 77,
+it yields output using a prefix
+showing the code numerically, e.g. ``unk77''.
+This form is
+<I>not</I>
+
+recognized by
+<I>ttosa</I>.
+
+<P>
+
 The
 <I>srclen</I>
 
@@ -328,7 +395,7 @@
 <I>satot</I>
 
 are:
-unknown format; unknown protocol code.
+unknown format.
 <A NAME="lbAG">&nbsp;</A>
 <H2>HISTORY</H2>
 
@@ -375,6 +442,6 @@
 This document was created by
 <A HREF="http://localhost/cgi-bin/man/man2html">man2html</A>,
 using the manual pages.<BR>
-Time: 04:17:09 GMT, March 28, 2001
+Time: 05:16:13 GMT, June 04, 2001
 </BODY>
 </HTML>
diff -bruN freeswan-1.9.orig/doc/manpage.d/ipsec_initsubnet.3.html freeswan-1.9/doc/manpage.d/ipsec_initsubnet.3.html
--- freeswan-1.9.orig/doc/manpage.d/ipsec_initsubnet.3.html	Tue Mar 27 23:17:09 2001
+++ freeswan-1.9/doc/manpage.d/ipsec_initsubnet.3.html	Mon Jun  4 01:16:13 2001
@@ -199,6 +199,6 @@
 This document was created by
 <A HREF="http://localhost/cgi-bin/man/man2html">man2html</A>,
 using the manual pages.<BR>
-Time: 04:17:09 GMT, March 28, 2001
+Time: 05:16:13 GMT, June 04, 2001
 </BODY>
 </HTML>
diff -bruN freeswan-1.9.orig/doc/manpage.d/ipsec_isanyaddr.3.html freeswan-1.9/doc/manpage.d/ipsec_isanyaddr.3.html
--- freeswan-1.9.orig/doc/manpage.d/ipsec_isanyaddr.3.html	Tue Mar 27 23:17:09 2001
+++ freeswan-1.9/doc/manpage.d/ipsec_isanyaddr.3.html	Mon Jun  4 01:16:13 2001
@@ -161,6 +161,6 @@
 This document was created by
 <A HREF="http://localhost/cgi-bin/man/man2html">man2html</A>,
 using the manual pages.<BR>
-Time: 04:17:09 GMT, March 28, 2001
+Time: 05:16:13 GMT, June 04, 2001
 </BODY>
 </HTML>
diff -bruN freeswan-1.9.orig/doc/manpage.d/ipsec_isloopbackaddr.3.html freeswan-1.9/doc/manpage.d/ipsec_isloopbackaddr.3.html
--- freeswan-1.9.orig/doc/manpage.d/ipsec_isloopbackaddr.3.html	Tue Mar 27 23:17:09 2001
+++ freeswan-1.9/doc/manpage.d/ipsec_isloopbackaddr.3.html	Mon Jun  4 01:16:13 2001
@@ -161,6 +161,6 @@
 This document was created by
 <A HREF="http://localhost/cgi-bin/man/man2html">man2html</A>,
 using the manual pages.<BR>
-Time: 04:17:09 GMT, March 28, 2001
+Time: 05:16:13 GMT, June 04, 2001
 </BODY>
 </HTML>
diff -bruN freeswan-1.9.orig/doc/manpage.d/ipsec_isunspecaddr.3.html freeswan-1.9/doc/manpage.d/ipsec_isunspecaddr.3.html
--- freeswan-1.9.orig/doc/manpage.d/ipsec_isunspecaddr.3.html	Tue Mar 27 23:17:09 2001
+++ freeswan-1.9/doc/manpage.d/ipsec_isunspecaddr.3.html	Mon Jun  4 01:16:13 2001
@@ -161,6 +161,6 @@
 This document was created by
 <A HREF="http://localhost/cgi-bin/man/man2html">man2html</A>,
 using the manual pages.<BR>
-Time: 04:17:09 GMT, March 28, 2001
+Time: 05:16:13 GMT, June 04, 2001
 </BODY>
 </HTML>
diff -bruN freeswan-1.9.orig/doc/manpage.d/ipsec_klipsdebug.5.html freeswan-1.9/doc/manpage.d/ipsec_klipsdebug.5.html
--- freeswan-1.9.orig/doc/manpage.d/ipsec_klipsdebug.5.html	Tue Mar 27 23:17:10 2001
+++ freeswan-1.9/doc/manpage.d/ipsec_klipsdebug.5.html	Mon Jun  4 01:16:13 2001
@@ -221,6 +221,6 @@
 This document was created by
 <A HREF="http://localhost/cgi-bin/man/man2html">man2html</A>,
 using the manual pages.<BR>
-Time: 04:17:10 GMT, March 28, 2001
+Time: 05:16:13 GMT, June 04, 2001
 </BODY>
 </HTML>
diff -bruN freeswan-1.9.orig/doc/manpage.d/ipsec_klipsdebug.8.html freeswan-1.9/doc/manpage.d/ipsec_klipsdebug.8.html
--- freeswan-1.9.orig/doc/manpage.d/ipsec_klipsdebug.8.html	Tue Mar 27 23:17:10 2001
+++ freeswan-1.9/doc/manpage.d/ipsec_klipsdebug.8.html	Mon Jun  4 01:16:13 2001
@@ -256,6 +256,6 @@
 This document was created by
 <A HREF="http://localhost/cgi-bin/man/man2html">man2html</A>,
 using the manual pages.<BR>
-Time: 04:17:10 GMT, March 28, 2001
+Time: 05:16:13 GMT, June 04, 2001
 </BODY>
 </HTML>
diff -bruN freeswan-1.9.orig/doc/manpage.d/ipsec_look.8.html freeswan-1.9/doc/manpage.d/ipsec_look.8.html
--- freeswan-1.9.orig/doc/manpage.d/ipsec_look.8.html	Tue Mar 27 23:17:10 2001
+++ freeswan-1.9/doc/manpage.d/ipsec_look.8.html	Mon Jun  4 01:16:13 2001
@@ -3,7 +3,7 @@
 <HTML><HEAD><TITLE>Manpage of IPSEC_BARF</TITLE>
 </HEAD><BODY>
 <H1>IPSEC_BARF</H1>
-Section: Maintenance Commands (8)<BR>Updated: 1 June 2000<BR><A HREF="#index">Index</A>
+Section: Maintenance Commands (8)<BR>Updated: 31 May 2001<BR><A HREF="#index">Index</A>
 <A HREF="http://localhost/cgi-bin/man/man2html">Return to Main Contents</A><HR>
 
 
@@ -77,12 +77,18 @@
 <A NAME="lbAE">&nbsp;</A>
 <H2>FILES</H2>
 
-/proc/net/*, /var/log/*
+<PRE>
+/proc/net/*
+/var/log/*
+/etc/ipsec.conf
+/etc/ipsec.secrets
+</PRE>
+
 <A NAME="lbAF">&nbsp;</A>
 <H2>HISTORY</H2>
 
 Written for the Linux FreeS/WAN project
-&lt;<A HREF="http://www.xs4all.nl/~freeswan/">http://www.xs4all.nl/~freeswan/</A>&gt;
+&lt;<A HREF="http://www.freeswan.org">http://www.freeswan.org</A>&gt;
 by Henry Spencer.
 <A NAME="lbAG">&nbsp;</A>
 <H2>BUGS</H2>
@@ -121,6 +127,6 @@
 This document was created by
 <A HREF="http://localhost/cgi-bin/man/man2html">man2html</A>,
 using the manual pages.<BR>
-Time: 04:17:10 GMT, March 28, 2001
+Time: 05:16:13 GMT, June 04, 2001
 </BODY>
 </HTML>
diff -bruN freeswan-1.9.orig/doc/manpage.d/ipsec_loopbackaddr.3.html freeswan-1.9/doc/manpage.d/ipsec_loopbackaddr.3.html
--- freeswan-1.9.orig/doc/manpage.d/ipsec_loopbackaddr.3.html	Tue Mar 27 23:17:10 2001
+++ freeswan-1.9/doc/manpage.d/ipsec_loopbackaddr.3.html	Mon Jun  4 01:16:13 2001
@@ -161,6 +161,6 @@
 This document was created by
 <A HREF="http://localhost/cgi-bin/man/man2html">man2html</A>,
 using the manual pages.<BR>
-Time: 04:17:10 GMT, March 28, 2001
+Time: 05:16:13 GMT, June 04, 2001
 </BODY>
 </HTML>
diff -bruN freeswan-1.9.orig/doc/manpage.d/ipsec_manual.8.html freeswan-1.9/doc/manpage.d/ipsec_manual.8.html
--- freeswan-1.9.orig/doc/manpage.d/ipsec_manual.8.html	Tue Mar 27 23:17:10 2001
+++ freeswan-1.9/doc/manpage.d/ipsec_manual.8.html	Mon Jun  4 01:16:13 2001
@@ -404,6 +404,6 @@
 This document was created by
 <A HREF="http://localhost/cgi-bin/man/man2html">man2html</A>,
 using the manual pages.<BR>
-Time: 04:17:10 GMT, March 28, 2001
+Time: 05:16:13 GMT, June 04, 2001
 </BODY>
 </HTML>
diff -bruN freeswan-1.9.orig/doc/manpage.d/ipsec_maskof.3.html freeswan-1.9/doc/manpage.d/ipsec_maskof.3.html
--- freeswan-1.9.orig/doc/manpage.d/ipsec_maskof.3.html	Tue Mar 27 23:17:10 2001
+++ freeswan-1.9/doc/manpage.d/ipsec_maskof.3.html	Mon Jun  4 01:16:13 2001
@@ -199,6 +199,6 @@
 This document was created by
 <A HREF="http://localhost/cgi-bin/man/man2html">man2html</A>,
 using the manual pages.<BR>
-Time: 04:17:10 GMT, March 28, 2001
+Time: 05:16:13 GMT, June 04, 2001
 </BODY>
 </HTML>
diff -bruN freeswan-1.9.orig/doc/manpage.d/ipsec_masktobits.3.html freeswan-1.9/doc/manpage.d/ipsec_masktobits.3.html
--- freeswan-1.9.orig/doc/manpage.d/ipsec_masktobits.3.html	Tue Mar 27 23:17:10 2001
+++ freeswan-1.9/doc/manpage.d/ipsec_masktobits.3.html	Mon Jun  4 01:16:13 2001
@@ -110,6 +110,6 @@
 This document was created by
 <A HREF="http://localhost/cgi-bin/man/man2html">man2html</A>,
 using the manual pages.<BR>
-Time: 04:17:10 GMT, March 28, 2001
+Time: 05:16:13 GMT, June 04, 2001
 </BODY>
 </HTML>
diff -bruN freeswan-1.9.orig/doc/manpage.d/ipsec_masktocount.3.html freeswan-1.9/doc/manpage.d/ipsec_masktocount.3.html
--- freeswan-1.9.orig/doc/manpage.d/ipsec_masktocount.3.html	Tue Mar 27 23:17:10 2001
+++ freeswan-1.9/doc/manpage.d/ipsec_masktocount.3.html	Mon Jun  4 01:16:13 2001
@@ -199,6 +199,6 @@
 This document was created by
 <A HREF="http://localhost/cgi-bin/man/man2html">man2html</A>,
 using the manual pages.<BR>
-Time: 04:17:10 GMT, March 28, 2001
+Time: 05:16:13 GMT, June 04, 2001
 </BODY>
 </HTML>
diff -bruN freeswan-1.9.orig/doc/manpage.d/ipsec_networkof.3.html freeswan-1.9/doc/manpage.d/ipsec_networkof.3.html
--- freeswan-1.9.orig/doc/manpage.d/ipsec_networkof.3.html	Tue Mar 27 23:17:10 2001
+++ freeswan-1.9/doc/manpage.d/ipsec_networkof.3.html	Mon Jun  4 01:16:13 2001
@@ -199,6 +199,6 @@
 This document was created by
 <A HREF="http://localhost/cgi-bin/man/man2html">man2html</A>,
 using the manual pages.<BR>
-Time: 04:17:10 GMT, March 28, 2001
+Time: 05:16:13 GMT, June 04, 2001
 </BODY>
 </HTML>
diff -bruN freeswan-1.9.orig/doc/manpage.d/ipsec_optionsfrom.3.html freeswan-1.9/doc/manpage.d/ipsec_optionsfrom.3.html
--- freeswan-1.9.orig/doc/manpage.d/ipsec_optionsfrom.3.html	Tue Mar 27 23:17:10 2001
+++ freeswan-1.9/doc/manpage.d/ipsec_optionsfrom.3.html	Mon Jun  4 01:16:14 2001
@@ -270,6 +270,6 @@
 This document was created by
 <A HREF="http://localhost/cgi-bin/man/man2html">man2html</A>,
 using the manual pages.<BR>
-Time: 04:17:10 GMT, March 28, 2001
+Time: 05:16:14 GMT, June 04, 2001
 </BODY>
 </HTML>
diff -bruN freeswan-1.9.orig/doc/manpage.d/ipsec_pf_key.5.html freeswan-1.9/doc/manpage.d/ipsec_pf_key.5.html
--- freeswan-1.9.orig/doc/manpage.d/ipsec_pf_key.5.html	Tue Mar 27 23:17:10 2001
+++ freeswan-1.9/doc/manpage.d/ipsec_pf_key.5.html	Mon Jun  4 01:16:14 2001
@@ -168,6 +168,6 @@
 This document was created by
 <A HREF="http://localhost/cgi-bin/man/man2html">man2html</A>,
 using the manual pages.<BR>
-Time: 04:17:10 GMT, March 28, 2001
+Time: 05:16:14 GMT, June 04, 2001
 </BODY>
 </HTML>
diff -bruN freeswan-1.9.orig/doc/manpage.d/ipsec_pluto.8.html freeswan-1.9/doc/manpage.d/ipsec_pluto.8.html
--- freeswan-1.9.orig/doc/manpage.d/ipsec_pluto.8.html	Tue Mar 27 23:17:10 2001
+++ freeswan-1.9/doc/manpage.d/ipsec_pluto.8.html	Mon Jun  4 01:16:14 2001
@@ -594,12 +594,16 @@
 identity defaults to the IP address specified by <B>--host</B>.
 
 <DT><B>--host</B>&nbsp;<I>ip-address</I><DD>
+<DT><B>--host</B>&nbsp;<B>%any</B><DD>
+<DT><B>--host</B>&nbsp;<B>%opportunistic</B><DD>
 the IP address of the end (generally the public interface).
 If <B>pluto</B> is to act as a responder
 for IKE negotiations initiated from unknown IP addresses (the
 ``Road Warrior'' case), the
 IP address should be specified as <B>%any</B> (currently,
 the obsolete notation <B>0.0.0.0</B> is also accepted for this).
+If <B>pluto</B> is to opportunistically initiate the connection,
+use <B>%opportunistic</B>
 <DT><B>--ikeport</B>&nbsp;<I>port-number</I><DD>
 the UDP port that IKE listens to on that host.  The default is 500.
 (<B>pluto</B> on this machine uses the port specified by its own command
@@ -703,7 +707,8 @@
 
 If none of the <B>--encrypt</B>, <B>--authenticate</B>, <B>--compress</B>,
 or <B>--pfs</B> flags is given, the initiating the connection will
-only build an ISAKMP SA.
+only build an ISAKMP SA.  For such a connection, client subnets have
+no meaning and must not be specified.
 <P>
 
 More work is needed to allow for flexible policies.  Currently
@@ -761,6 +766,8 @@
 virtual interface.
 Once routing is set up, no packets will be
 sent ``in the clear'' to the peer's client specified in the connection.
+A TRAP shunt eroute will be installed; if outbound traffic is caught,
+Pluto will initiate the connection.
 An explicit <B>whack</B> route is not always needed: if it hasn't been
 done when an IPsec SA is being installed, one will be automatically attempted.
 <P>
@@ -1642,6 +1649,6 @@
 This document was created by
 <A HREF="http://localhost/cgi-bin/man/man2html">man2html</A>,
 using the manual pages.<BR>
-Time: 04:17:10 GMT, March 28, 2001
+Time: 05:16:14 GMT, June 04, 2001
 </BODY>
 </HTML>
diff -bruN freeswan-1.9.orig/doc/manpage.d/ipsec_portof.3.html freeswan-1.9/doc/manpage.d/ipsec_portof.3.html
--- freeswan-1.9.orig/doc/manpage.d/ipsec_portof.3.html	Tue Mar 27 23:17:10 2001
+++ freeswan-1.9/doc/manpage.d/ipsec_portof.3.html	Mon Jun  4 01:16:14 2001
@@ -138,6 +138,6 @@
 This document was created by
 <A HREF="http://localhost/cgi-bin/man/man2html">man2html</A>,
 using the manual pages.<BR>
-Time: 04:17:10 GMT, March 28, 2001
+Time: 05:16:14 GMT, June 04, 2001
 </BODY>
 </HTML>
diff -bruN freeswan-1.9.orig/doc/manpage.d/ipsec_ranbits.8.html freeswan-1.9/doc/manpage.d/ipsec_ranbits.8.html
--- freeswan-1.9.orig/doc/manpage.d/ipsec_ranbits.8.html	Tue Mar 27 23:17:10 2001
+++ freeswan-1.9/doc/manpage.d/ipsec_ranbits.8.html	Mon Jun  4 01:16:14 2001
@@ -105,7 +105,7 @@
 <H2>HISTORY</H2>
 
 Written for the Linux FreeS/WAN project
-&lt;<A HREF="http://www.xs4all.nl/~freeswan/">http://www.xs4all.nl/~freeswan/</A>&gt;
+&lt;<A HREF="http://www.freeswan.org">http://www.freeswan.org</A>&gt;
 by Henry Spencer.
 <A NAME="lbAH">&nbsp;</A>
 <H2>BUGS</H2>
@@ -142,6 +142,6 @@
 This document was created by
 <A HREF="http://localhost/cgi-bin/man/man2html">man2html</A>,
 using the manual pages.<BR>
-Time: 04:17:10 GMT, March 28, 2001
+Time: 05:16:14 GMT, June 04, 2001
 </BODY>
 </HTML>
diff -bruN freeswan-1.9.orig/doc/manpage.d/ipsec_rangetoa.3.html freeswan-1.9/doc/manpage.d/ipsec_rangetoa.3.html
--- freeswan-1.9.orig/doc/manpage.d/ipsec_rangetoa.3.html	Tue Mar 27 23:17:10 2001
+++ freeswan-1.9/doc/manpage.d/ipsec_rangetoa.3.html	Mon Jun  4 01:16:14 2001
@@ -284,6 +284,6 @@
 This document was created by
 <A HREF="http://localhost/cgi-bin/man/man2html">man2html</A>,
 using the manual pages.<BR>
-Time: 04:17:10 GMT, March 28, 2001
+Time: 05:16:14 GMT, June 04, 2001
 </BODY>
 </HTML>
diff -bruN freeswan-1.9.orig/doc/manpage.d/ipsec_rangetosubnet.3.html freeswan-1.9/doc/manpage.d/ipsec_rangetosubnet.3.html
--- freeswan-1.9.orig/doc/manpage.d/ipsec_rangetosubnet.3.html	Tue Mar 27 23:17:10 2001
+++ freeswan-1.9/doc/manpage.d/ipsec_rangetosubnet.3.html	Mon Jun  4 01:16:14 2001
@@ -111,6 +111,6 @@
 This document was created by
 <A HREF="http://localhost/cgi-bin/man/man2html">man2html</A>,
 using the manual pages.<BR>
-Time: 04:17:10 GMT, March 28, 2001
+Time: 05:16:14 GMT, June 04, 2001
 </BODY>
 </HTML>
diff -bruN freeswan-1.9.orig/doc/manpage.d/ipsec_rsasigkey.8.html freeswan-1.9/doc/manpage.d/ipsec_rsasigkey.8.html
--- freeswan-1.9.orig/doc/manpage.d/ipsec_rsasigkey.8.html	Tue Mar 27 23:17:10 2001
+++ freeswan-1.9/doc/manpage.d/ipsec_rsasigkey.8.html	Mon Jun  4 01:16:14 2001
@@ -3,7 +3,7 @@
 <HTML><HEAD><TITLE>Manpage of IPSEC_RSASIGKEY</TITLE>
 </HEAD><BODY>
 <H1>IPSEC_RSASIGKEY</H1>
-Section: Maintenance Commands (8)<BR>Updated: 23 Feb 2001<BR><A HREF="#index">Index</A>
+Section: Maintenance Commands (8)<BR>Updated: 14 May 2001<BR><A HREF="#index">Index</A>
 <A HREF="http://localhost/cgi-bin/man/man2html">Return to Main Contents</A><HR>
 
 
@@ -193,7 +193,7 @@
 <PRE>
         # RSA 2048 bits   xy.example.com   Sat Apr 15 13:53:22 2000
         # for signatures only, UNSAFE FOR ENCRYPTION
-        #pubkey=0x0103cc2a86fcf440...cf1011abb82d1
+        #pubkey=0sAQOF8tZ2NZt...Y1P+buFuFn/
         #IN KEY 0x4200 4 1 AQOF8tZ2NZt...Y1P+buFuFn/
         # (0x4200 = auth-only host-level, 4 = IPSec, 1 = RSA)
         Modulus: 0xcc2a86fcf440...cf1011abb82d1
@@ -209,13 +209,22 @@
 
 <P>
 
+The first (comment) line,
+indicating the nature and date of the key,
+and giving a host name,
+is used by
+<I><A HREF="ipsec_showhostkey.8.html">ipsec_showhostkey</A></I>(8)
+
+when generating some forms of key output.
+<P>
+
 The commented-out
 <B>pubkey=</B>
 
 line contains the public key---the public exponent and the modulus---combined
 in approximately RFC 2537 format
-(the one deviation is that the combined value is given in hex with a
-<B>0x</B>
+(the one deviation is that the combined value is given with a
+<B>0s</B>
 
 prefix, rather than in unadorned base-64),
 suitable for use in the
@@ -335,7 +344,7 @@
 <A NAME="lbAG">&nbsp;</A>
 <H2>SEE ALSO</H2>
 
-<A HREF="random.4.html">random</A>(4)
+<A HREF="random.4.html">random</A>(4), <A HREF="ipsec_showhostkey.8.html">ipsec_showhostkey</A>(8)
 <BR>
 
 <I>Applied Cryptography</I>, 2nd. ed., by Bruce Schneier, Wiley 1996.
@@ -350,7 +359,7 @@
 <H2>HISTORY</H2>
 
 Written for the Linux FreeS/WAN project
-&lt;<A HREF="http://www.xs4all.nl/~freeswan/">http://www.xs4all.nl/~freeswan/</A>&gt;
+&lt;<A HREF="http://www.freeswan.org">http://www.freeswan.org</A>&gt;
 by Henry Spencer.
 <A NAME="lbAI">&nbsp;</A>
 <H2>BUGS</H2>
@@ -402,6 +411,6 @@
 This document was created by
 <A HREF="http://localhost/cgi-bin/man/man2html">man2html</A>,
 using the manual pages.<BR>
-Time: 04:17:10 GMT, March 28, 2001
+Time: 05:16:14 GMT, June 04, 2001
 </BODY>
 </HTML>
diff -bruN freeswan-1.9.orig/doc/manpage.d/ipsec_sameaddr.3.html freeswan-1.9/doc/manpage.d/ipsec_sameaddr.3.html
--- freeswan-1.9.orig/doc/manpage.d/ipsec_sameaddr.3.html	Tue Mar 27 23:17:10 2001
+++ freeswan-1.9/doc/manpage.d/ipsec_sameaddr.3.html	Mon Jun  4 01:16:14 2001
@@ -269,6 +269,6 @@
 This document was created by
 <A HREF="http://localhost/cgi-bin/man/man2html">man2html</A>,
 using the manual pages.<BR>
-Time: 04:17:10 GMT, March 28, 2001
+Time: 05:16:14 GMT, June 04, 2001
 </BODY>
 </HTML>
diff -bruN freeswan-1.9.orig/doc/manpage.d/ipsec_sameaddrtype.3.html freeswan-1.9/doc/manpage.d/ipsec_sameaddrtype.3.html
--- freeswan-1.9.orig/doc/manpage.d/ipsec_sameaddrtype.3.html	Tue Mar 27 23:17:10 2001
+++ freeswan-1.9/doc/manpage.d/ipsec_sameaddrtype.3.html	Mon Jun  4 01:16:14 2001
@@ -269,6 +269,6 @@
 This document was created by
 <A HREF="http://localhost/cgi-bin/man/man2html">man2html</A>,
 using the manual pages.<BR>
-Time: 04:17:10 GMT, March 28, 2001
+Time: 05:16:14 GMT, June 04, 2001
 </BODY>
 </HTML>
diff -bruN freeswan-1.9.orig/doc/manpage.d/ipsec_samesaid.3.html freeswan-1.9/doc/manpage.d/ipsec_samesaid.3.html
--- freeswan-1.9.orig/doc/manpage.d/ipsec_samesaid.3.html	Tue Mar 27 23:17:11 2001
+++ freeswan-1.9/doc/manpage.d/ipsec_samesaid.3.html	Mon Jun  4 01:16:14 2001
@@ -269,6 +269,6 @@
 This document was created by
 <A HREF="http://localhost/cgi-bin/man/man2html">man2html</A>,
 using the manual pages.<BR>
-Time: 04:17:11 GMT, March 28, 2001
+Time: 05:16:14 GMT, June 04, 2001
 </BODY>
 </HTML>
diff -bruN freeswan-1.9.orig/doc/manpage.d/ipsec_samesubnet.3.html freeswan-1.9/doc/manpage.d/ipsec_samesubnet.3.html
--- freeswan-1.9.orig/doc/manpage.d/ipsec_samesubnet.3.html	Tue Mar 27 23:17:11 2001
+++ freeswan-1.9/doc/manpage.d/ipsec_samesubnet.3.html	Mon Jun  4 01:16:14 2001
@@ -269,6 +269,6 @@
 This document was created by
 <A HREF="http://localhost/cgi-bin/man/man2html">man2html</A>,
 using the manual pages.<BR>
-Time: 04:17:11 GMT, March 28, 2001
+Time: 05:16:14 GMT, June 04, 2001
 </BODY>
 </HTML>
diff -bruN freeswan-1.9.orig/doc/manpage.d/ipsec_samesubnettype.3.html freeswan-1.9/doc/manpage.d/ipsec_samesubnettype.3.html
--- freeswan-1.9.orig/doc/manpage.d/ipsec_samesubnettype.3.html	Tue Mar 27 23:17:11 2001
+++ freeswan-1.9/doc/manpage.d/ipsec_samesubnettype.3.html	Mon Jun  4 01:16:14 2001
@@ -269,6 +269,6 @@
 This document was created by
 <A HREF="http://localhost/cgi-bin/man/man2html">man2html</A>,
 using the manual pages.<BR>
-Time: 04:17:11 GMT, March 28, 2001
+Time: 05:16:14 GMT, June 04, 2001
 </BODY>
 </HTML>
diff -bruN freeswan-1.9.orig/doc/manpage.d/ipsec_satoa.3.html freeswan-1.9/doc/manpage.d/ipsec_satoa.3.html
--- freeswan-1.9.orig/doc/manpage.d/ipsec_satoa.3.html	Tue Mar 27 23:17:11 2001
+++ freeswan-1.9/doc/manpage.d/ipsec_satoa.3.html	Mon Jun  4 01:16:14 2001
@@ -336,6 +336,6 @@
 This document was created by
 <A HREF="http://localhost/cgi-bin/man/man2html">man2html</A>,
 using the manual pages.<BR>
-Time: 04:17:11 GMT, March 28, 2001
+Time: 05:16:14 GMT, June 04, 2001
 </BODY>
 </HTML>
diff -bruN freeswan-1.9.orig/doc/manpage.d/ipsec_satot.3.html freeswan-1.9/doc/manpage.d/ipsec_satot.3.html
--- freeswan-1.9.orig/doc/manpage.d/ipsec_satot.3.html	Tue Mar 27 23:17:11 2001
+++ freeswan-1.9/doc/manpage.d/ipsec_satot.3.html	Mon Jun  4 01:16:14 2001
@@ -3,7 +3,7 @@
 <HTML><HEAD><TITLE>Manpage of IPSEC_TTOSA</TITLE>
 </HEAD><BODY>
 <H1>IPSEC_TTOSA</H1>
-Section: C Library Functions (3)<BR>Updated: 15 Sept 2000<BR><A HREF="#index">Index</A>
+Section: C Library Functions (3)<BR>Updated: 27 Feb 2001<BR><A HREF="#index">Index</A>
 <A HREF="http://localhost/cgi-bin/man/man2html">Return to Main Contents</A><HR>
 
 
@@ -96,8 +96,10 @@
 
 <B>tun</B>,
 
+<B>comp</B>,
+
 or
-<B>comp</B>),
+<B>int</B>),
 
 a single character indicating the address family
 (<B>.</B>
@@ -149,6 +151,29 @@
 so the internal representation is never visible.
 <P>
 
+Similarly, the SA specifiers
+<B>%pass</B>,
+
+<B>%drop</B>,
+
+<B>%reject</B>,
+
+<B>%hold</B>,
+
+and
+<B>%trap</B>
+
+signify special ``magic'' SAs used to indicate that packets should be
+passed, dropped, rejected (dropped with ICMP notification),
+held,
+and trapped (sent up to
+<I><A HREF="ipsec_pluto.8.html">ipsec_pluto</A></I>(8))
+
+respectively.
+These forms too are known to both routines,
+so the internal representation of the magic SAs should never be visible.
+<P>
+
 The
 <B>&lt;<A HREF="file:/usr/include/freeswan.h">freeswan.h</A>&gt;</B>
 
@@ -190,6 +215,48 @@
 
 <P>
 
+<B>&lt;<A HREF="file:/usr/include/freeswan.h">freeswan.h</A>&gt;</B>
+
+also defines
+<B>SA_INT</B>
+
+to have the value
+<B>61</B>
+
+(reserved by IANA for ``any host internal protocol'')
+and
+<B>SPI_PASS</B>,
+
+<B>SPI_DROP</B>,
+
+<B>SPI_REJECT</B>,
+
+<B>SPI_HOLD</B>,
+
+and
+<B>SPI_TRAP</B>
+
+to have the values 256-260 (in <I>host</I> byte order) respectively.
+These are used in constructing the magic SAs
+(which always have address
+<B>0.0.0.0</B>).
+
+<P>
+
+If
+<I>satot</I>
+
+encounters an unknown protocol code, e.g. 77,
+it yields output using a prefix
+showing the code numerically, e.g. ``unk77''.
+This form is
+<I>not</I>
+
+recognized by
+<I>ttosa</I>.
+
+<P>
+
 The
 <I>srclen</I>
 
@@ -328,7 +395,7 @@
 <I>satot</I>
 
 are:
-unknown format; unknown protocol code.
+unknown format.
 <A NAME="lbAG">&nbsp;</A>
 <H2>HISTORY</H2>
 
@@ -375,6 +442,6 @@
 This document was created by
 <A HREF="http://localhost/cgi-bin/man/man2html">man2html</A>,
 using the manual pages.<BR>
-Time: 04:17:11 GMT, March 28, 2001
+Time: 05:16:14 GMT, June 04, 2001
 </BODY>
 </HTML>
diff -bruN freeswan-1.9.orig/doc/manpage.d/ipsec_setportof.3.html freeswan-1.9/doc/manpage.d/ipsec_setportof.3.html
--- freeswan-1.9.orig/doc/manpage.d/ipsec_setportof.3.html	Tue Mar 27 23:17:11 2001
+++ freeswan-1.9/doc/manpage.d/ipsec_setportof.3.html	Mon Jun  4 01:16:14 2001
@@ -138,6 +138,6 @@
 This document was created by
 <A HREF="http://localhost/cgi-bin/man/man2html">man2html</A>,
 using the manual pages.<BR>
-Time: 04:17:11 GMT, March 28, 2001
+Time: 05:16:14 GMT, June 04, 2001
 </BODY>
 </HTML>
diff -bruN freeswan-1.9.orig/doc/manpage.d/ipsec_setup.8.html freeswan-1.9/doc/manpage.d/ipsec_setup.8.html
--- freeswan-1.9.orig/doc/manpage.d/ipsec_setup.8.html	Tue Mar 27 23:17:11 2001
+++ freeswan-1.9/doc/manpage.d/ipsec_setup.8.html	Mon Jun  4 01:16:14 2001
@@ -3,7 +3,7 @@
 <HTML><HEAD><TITLE>Manpage of IPSEC_SETUP</TITLE>
 </HEAD><BODY>
 <H1>IPSEC_SETUP</H1>
-Section: Maintenance Commands (8)<BR>Updated: 28 Nov 2000<BR><A HREF="#index">Index</A>
+Section: Maintenance Commands (8)<BR>Updated: 31 May 2001<BR><A HREF="#index">Index</A>
 <A HREF="http://localhost/cgi-bin/man/man2html">Return to Main Contents</A><HR>
 
 
@@ -64,7 +64,8 @@
 interface(s) specified in the configuration file,
 and (if the configuration file so specifies)
 setting up manually-keyed connections and/or
-asking Pluto to negotiate tunnels to other security gateways
+asking Pluto to negotiate automatically-keyed connections
+to other security gateways
 <DT><B>stop</B>
 
 <DD>
@@ -79,6 +80,19 @@
 followed by
 <B>start</B>
 
+<DT><B>status</B>
+
+<DD>
+report the status of the subsystem;
+normally just reports
+<B>started</B>
+
+or
+<B>stopped</B>
+
+and exits with status 0,
+but will go into more detail (and exit with status 1)
+if something strange is found.
 </DL>
 <P>
 
@@ -88,6 +102,12 @@
 operation tries to clean up properly even if assorted accidents
 have occurred,
 e.g. Pluto having died without removing its lock file.
+If
+<B>stop</B>
+
+discovers that the subsystem is (supposedly) not running,
+it will complain,
+but will do its cleanup anyway before exiting with status 1.
 <P>
 
 Although a number of configuration-file parameters influence
@@ -122,7 +142,13 @@
 <A NAME="lbAG">&nbsp;</A>
 <H2>DIAGNOSTICS</H2>
 
-All output from the commands this script invokes goes both to standard
+All output from the commands
+<B>start</B>
+
+and
+<B>stop</B>
+
+invoke goes both to standard
 output and to
 <I><A HREF="syslogd.8.html">syslogd</A></I>(8)
 
@@ -136,7 +162,7 @@
 <H2>HISTORY</H2>
 
 Written for the FreeS/WAN project
-&lt;<A HREF="http://www.xs4all.nl/~freeswan/">http://www.xs4all.nl/~freeswan/</A>&gt;
+&lt;<A HREF="http://www.freeswan.org">http://www.freeswan.org</A>&gt;
 by Henry Spencer.
 <A NAME="lbAI">&nbsp;</A>
 <H2>BUGS</H2>
@@ -147,6 +173,12 @@
 injected spurious extra newlines onto standard output.
 <P>
 
+Startup failure is not consistently reported in the exit status.
+<P>
+
+The normal status report probably should include Pluto's process ID.
+<P>
+
 <HR>
 <A NAME="index">&nbsp;</A><H2>Index</H2>
 <DL>
@@ -163,6 +195,6 @@
 This document was created by
 <A HREF="http://localhost/cgi-bin/man/man2html">man2html</A>,
 using the manual pages.<BR>
-Time: 04:17:11 GMT, March 28, 2001
+Time: 05:16:14 GMT, June 04, 2001
 </BODY>
 </HTML>
diff -bruN freeswan-1.9.orig/doc/manpage.d/ipsec_showdefaults.8.html freeswan-1.9/doc/manpage.d/ipsec_showdefaults.8.html
--- freeswan-1.9.orig/doc/manpage.d/ipsec_showdefaults.8.html	Tue Mar 27 23:17:11 2001
+++ freeswan-1.9/doc/manpage.d/ipsec_showdefaults.8.html	Mon Jun  4 01:16:14 2001
@@ -59,7 +59,7 @@
 <H2>HISTORY</H2>
 
 Written for the Linux FreeS/WAN project
-&lt;<A HREF="http://www.xs4all.nl/~freeswan/">http://www.xs4all.nl/~freeswan/</A>&gt;
+&lt;<A HREF="http://www.freeswan.org">http://www.freeswan.org</A>&gt;
 by Henry Spencer.
 <P>
 
@@ -77,6 +77,6 @@
 This document was created by
 <A HREF="http://localhost/cgi-bin/man/man2html">man2html</A>,
 using the manual pages.<BR>
-Time: 04:17:11 GMT, March 28, 2001
+Time: 05:16:14 GMT, June 04, 2001
 </BODY>
 </HTML>
diff -bruN freeswan-1.9.orig/doc/manpage.d/ipsec_showhostkey.8.html freeswan-1.9/doc/manpage.d/ipsec_showhostkey.8.html
--- freeswan-1.9.orig/doc/manpage.d/ipsec_showhostkey.8.html	Tue Mar 27 23:17:11 2001
+++ freeswan-1.9/doc/manpage.d/ipsec_showhostkey.8.html	Mon Jun  4 01:16:14 2001
@@ -3,7 +3,7 @@
 <HTML><HEAD><TITLE>Manpage of IPSEC_SHOWHOSTKEY</TITLE>
 </HEAD><BODY>
 <H1>IPSEC_SHOWHOSTKEY</H1>
-Section: Maintenance Commands (8)<BR>Updated: 8 March 2001<BR><A HREF="#index">Index</A>
+Section: Maintenance Commands (8)<BR>Updated: 22 May 2001<BR><A HREF="#index">Index</A>
 <A HREF="http://localhost/cgi-bin/man/man2html">Return to Main Contents</A><HR>
 
 
@@ -25,6 +25,10 @@
 <B>--right</B>
 
 ] [
+<B>--txt</B>
+
+gateway
+] [
 <B>--file</B>
 
 secretfile
@@ -67,6 +71,29 @@
 <P>
 
 The
+<B>--txt</B>
+
+option causes the output to be in opportunistic-encryption DNS TXT record
+format,
+with the specified
+<I>gateway</I>
+
+value.
+Again, generation information is included if available.
+For example,
+<B>--txt 10.11.12.13</B>
+
+might give (with the key data trimmed for clarity):
+<P>
+
+<PRE>
+  ; RSA 2048 bits   xy.example.com   Sat Apr 15 13:53:22 2000
+      IN TXT  &quot;X-IPsec-Server(10)=10.11.12.13 AQOF8tZ2...+buFuFn/&quot;
+</PRE>
+
+<P>
+
+The
 <B>--left</B>
 
 and
@@ -124,7 +151,7 @@
 <H2>HISTORY</H2>
 
 Written for the Linux FreeS/WAN project
-&lt;<A HREF="http://www.xs4all.nl/~freeswan/">http://www.xs4all.nl/~freeswan/</A>&gt;
+&lt;<A HREF="http://www.freeswan.org">http://www.freeswan.org</A>&gt;
 by Henry Spencer.
 <A NAME="lbAI">&nbsp;</A>
 <H2>BUGS</H2>
@@ -142,6 +169,24 @@
 option, to generate a suitable output line.
 <P>
 
+The need to specify the gateway address (etc.) for
+<B>--txt</B>
+
+is annoying, but there is no good way to determine it automatically.
+<P>
+
+There should be a way to specify the priority value for TXT records;
+currently it is hardwired to
+<B>10</B>.
+
+<P>
+
+Assumes there is only one RSA key in
+<I>ipsec.secrets</I>,
+
+which is common but not necessarily universal.
+<P>
+
 <HR>
 <A NAME="index">&nbsp;</A><H2>Index</H2>
 <DL>
@@ -158,6 +203,6 @@
 This document was created by
 <A HREF="http://localhost/cgi-bin/man/man2html">man2html</A>,
 using the manual pages.<BR>
-Time: 04:17:11 GMT, March 28, 2001
+Time: 05:16:14 GMT, June 04, 2001
 </BODY>
 </HTML>
diff -bruN freeswan-1.9.orig/doc/manpage.d/ipsec_sockaddrlenof.3.html freeswan-1.9/doc/manpage.d/ipsec_sockaddrlenof.3.html
--- freeswan-1.9.orig/doc/manpage.d/ipsec_sockaddrlenof.3.html	Tue Mar 27 23:17:11 2001
+++ freeswan-1.9/doc/manpage.d/ipsec_sockaddrlenof.3.html	Mon Jun  4 01:16:14 2001
@@ -138,6 +138,6 @@
 This document was created by
 <A HREF="http://localhost/cgi-bin/man/man2html">man2html</A>,
 using the manual pages.<BR>
-Time: 04:17:11 GMT, March 28, 2001
+Time: 05:16:14 GMT, June 04, 2001
 </BODY>
 </HTML>
diff -bruN freeswan-1.9.orig/doc/manpage.d/ipsec_sockaddrof.3.html freeswan-1.9/doc/manpage.d/ipsec_sockaddrof.3.html
--- freeswan-1.9.orig/doc/manpage.d/ipsec_sockaddrof.3.html	Tue Mar 27 23:17:11 2001
+++ freeswan-1.9/doc/manpage.d/ipsec_sockaddrof.3.html	Mon Jun  4 01:16:14 2001
@@ -138,6 +138,6 @@
 This document was created by
 <A HREF="http://localhost/cgi-bin/man/man2html">man2html</A>,
 using the manual pages.<BR>
-Time: 04:17:11 GMT, March 28, 2001
+Time: 05:16:14 GMT, June 04, 2001
 </BODY>
 </HTML>
diff -bruN freeswan-1.9.orig/doc/manpage.d/ipsec_spi.5.html freeswan-1.9/doc/manpage.d/ipsec_spi.5.html
--- freeswan-1.9.orig/doc/manpage.d/ipsec_spi.5.html	Tue Mar 27 23:17:11 2001
+++ freeswan-1.9/doc/manpage.d/ipsec_spi.5.html	Mon Jun  4 01:16:15 2001
@@ -291,6 +291,6 @@
 This document was created by
 <A HREF="http://localhost/cgi-bin/man/man2html">man2html</A>,
 using the manual pages.<BR>
-Time: 04:17:11 GMT, March 28, 2001
+Time: 05:16:14 GMT, June 04, 2001
 </BODY>
 </HTML>
diff -bruN freeswan-1.9.orig/doc/manpage.d/ipsec_spi.8.html freeswan-1.9/doc/manpage.d/ipsec_spi.8.html
--- freeswan-1.9.orig/doc/manpage.d/ipsec_spi.8.html	Tue Mar 27 23:17:11 2001
+++ freeswan-1.9/doc/manpage.d/ipsec_spi.8.html	Mon Jun  4 01:16:15 2001
@@ -123,28 +123,6 @@
 <B>--src</B>
 
 src
-<B>--esp</B>
-
-<B>null-md5-96</B>|<B>null-sha1-96</B>
-
-[
-<B>--replay_window</B>
-
-replayw ]
-<B>--authkey</B>
-
-akey
-<P>
-
-<B>ipsec</B>
-
-<B>spi</B>
-
-<B>&lt;SA&gt;</B>
-
-<B>--src</B>
-
-src
 <B>--comp</B>
 
 <B>deflate</B>
@@ -443,24 +421,6 @@
 <I>akey</I>
 
 (RFC2451, RFC2404)
-<DT><B>null-md5-96</B>
-
-<DD>
-encryption using the identity transform with authentication
-provided by HMAC and MD5 (96-bit authenticator), using
-a 128-bit HMAC-MD5
-<I>akey</I>
-
-(RFC2410, RFC2403)
-<DT><B>null-sha1-96</B>
-
-<DD>
-encryption using the identity transform with authentication
-provided by HMAC and SHA1 (96-bit authenticator), using
-a 160-bit HMAC-SHA1
-<I>akey</I>
-
-(RFC2410, RFC2404)
 <DT><B>--replay_window</B> replayw
 
 <DD>
@@ -727,6 +687,9 @@
 
 
 
+
+
+
 <P>
 
 <HR>
@@ -746,6 +709,6 @@
 This document was created by
 <A HREF="http://localhost/cgi-bin/man/man2html">man2html</A>,
 using the manual pages.<BR>
-Time: 04:17:11 GMT, March 28, 2001
+Time: 05:16:15 GMT, June 04, 2001
 </BODY>
 </HTML>
diff -bruN freeswan-1.9.orig/doc/manpage.d/ipsec_spigrp.5.html freeswan-1.9/doc/manpage.d/ipsec_spigrp.5.html
--- freeswan-1.9.orig/doc/manpage.d/ipsec_spigrp.5.html	Tue Mar 27 23:17:11 2001
+++ freeswan-1.9/doc/manpage.d/ipsec_spigrp.5.html	Mon Jun  4 01:16:15 2001
@@ -185,6 +185,6 @@
 This document was created by
 <A HREF="http://localhost/cgi-bin/man/man2html">man2html</A>,
 using the manual pages.<BR>
-Time: 04:17:11 GMT, March 28, 2001
+Time: 05:16:15 GMT, June 04, 2001
 </BODY>
 </HTML>
diff -bruN freeswan-1.9.orig/doc/manpage.d/ipsec_spigrp.8.html freeswan-1.9/doc/manpage.d/ipsec_spigrp.8.html
--- freeswan-1.9.orig/doc/manpage.d/ipsec_spigrp.8.html	Tue Mar 27 23:17:11 2001
+++ freeswan-1.9/doc/manpage.d/ipsec_spigrp.8.html	Mon Jun  4 01:16:15 2001
@@ -272,6 +272,6 @@
 This document was created by
 <A HREF="http://localhost/cgi-bin/man/man2html">man2html</A>,
 using the manual pages.<BR>
-Time: 04:17:11 GMT, March 28, 2001
+Time: 05:16:15 GMT, June 04, 2001
 </BODY>
 </HTML>
diff -bruN freeswan-1.9.orig/doc/manpage.d/ipsec_subnetinsubnet.3.html freeswan-1.9/doc/manpage.d/ipsec_subnetinsubnet.3.html
--- freeswan-1.9.orig/doc/manpage.d/ipsec_subnetinsubnet.3.html	Tue Mar 27 23:17:11 2001
+++ freeswan-1.9/doc/manpage.d/ipsec_subnetinsubnet.3.html	Mon Jun  4 01:16:15 2001
@@ -269,6 +269,6 @@
 This document was created by
 <A HREF="http://localhost/cgi-bin/man/man2html">man2html</A>,
 using the manual pages.<BR>
-Time: 04:17:11 GMT, March 28, 2001
+Time: 05:16:15 GMT, June 04, 2001
 </BODY>
 </HTML>
diff -bruN freeswan-1.9.orig/doc/manpage.d/ipsec_subnetishost.3.html freeswan-1.9/doc/manpage.d/ipsec_subnetishost.3.html
--- freeswan-1.9.orig/doc/manpage.d/ipsec_subnetishost.3.html	Tue Mar 27 23:17:11 2001
+++ freeswan-1.9/doc/manpage.d/ipsec_subnetishost.3.html	Mon Jun  4 01:16:15 2001
@@ -269,6 +269,6 @@
 This document was created by
 <A HREF="http://localhost/cgi-bin/man/man2html">man2html</A>,
 using the manual pages.<BR>
-Time: 04:17:11 GMT, March 28, 2001
+Time: 05:16:15 GMT, June 04, 2001
 </BODY>
 </HTML>
diff -bruN freeswan-1.9.orig/doc/manpage.d/ipsec_subnetof.3.html freeswan-1.9/doc/manpage.d/ipsec_subnetof.3.html
--- freeswan-1.9.orig/doc/manpage.d/ipsec_subnetof.3.html	Tue Mar 27 23:17:12 2001
+++ freeswan-1.9/doc/manpage.d/ipsec_subnetof.3.html	Mon Jun  4 01:16:15 2001
@@ -96,6 +96,6 @@
 This document was created by
 <A HREF="http://localhost/cgi-bin/man/man2html">man2html</A>,
 using the manual pages.<BR>
-Time: 04:17:11 GMT, March 28, 2001
+Time: 05:16:15 GMT, June 04, 2001
 </BODY>
 </HTML>
diff -bruN freeswan-1.9.orig/doc/manpage.d/ipsec_subnettoa.3.html freeswan-1.9/doc/manpage.d/ipsec_subnettoa.3.html
--- freeswan-1.9.orig/doc/manpage.d/ipsec_subnettoa.3.html	Tue Mar 27 23:17:12 2001
+++ freeswan-1.9/doc/manpage.d/ipsec_subnettoa.3.html	Mon Jun  4 01:16:15 2001
@@ -437,6 +437,6 @@
 This document was created by
 <A HREF="http://localhost/cgi-bin/man/man2html">man2html</A>,
 using the manual pages.<BR>
-Time: 04:17:12 GMT, March 28, 2001
+Time: 05:16:15 GMT, June 04, 2001
 </BODY>
 </HTML>
diff -bruN freeswan-1.9.orig/doc/manpage.d/ipsec_subnettot.3.html freeswan-1.9/doc/manpage.d/ipsec_subnettot.3.html
--- freeswan-1.9.orig/doc/manpage.d/ipsec_subnettot.3.html	Tue Mar 27 23:17:12 2001
+++ freeswan-1.9/doc/manpage.d/ipsec_subnettot.3.html	Mon Jun  4 01:16:15 2001
@@ -563,6 +563,6 @@
 This document was created by
 <A HREF="http://localhost/cgi-bin/man/man2html">man2html</A>,
 using the manual pages.<BR>
-Time: 04:17:12 GMT, March 28, 2001
+Time: 05:16:15 GMT, June 04, 2001
 </BODY>
 </HTML>
diff -bruN freeswan-1.9.orig/doc/manpage.d/ipsec_subnettypeof.3.html freeswan-1.9/doc/manpage.d/ipsec_subnettypeof.3.html
--- freeswan-1.9.orig/doc/manpage.d/ipsec_subnettypeof.3.html	Tue Mar 27 23:17:12 2001
+++ freeswan-1.9/doc/manpage.d/ipsec_subnettypeof.3.html	Mon Jun  4 01:16:15 2001
@@ -199,6 +199,6 @@
 This document was created by
 <A HREF="http://localhost/cgi-bin/man/man2html">man2html</A>,
 using the manual pages.<BR>
-Time: 04:17:12 GMT, March 28, 2001
+Time: 05:16:15 GMT, June 04, 2001
 </BODY>
 </HTML>
diff -bruN freeswan-1.9.orig/doc/manpage.d/ipsec_tnatoaddr.3.html freeswan-1.9/doc/manpage.d/ipsec_tnatoaddr.3.html
--- freeswan-1.9.orig/doc/manpage.d/ipsec_tnatoaddr.3.html	Tue Mar 27 23:17:12 2001
+++ freeswan-1.9/doc/manpage.d/ipsec_tnatoaddr.3.html	Mon Jun  4 01:16:15 2001
@@ -563,6 +563,6 @@
 This document was created by
 <A HREF="http://localhost/cgi-bin/man/man2html">man2html</A>,
 using the manual pages.<BR>
-Time: 04:17:12 GMT, March 28, 2001
+Time: 05:16:15 GMT, June 04, 2001
 </BODY>
 </HTML>
diff -bruN freeswan-1.9.orig/doc/manpage.d/ipsec_tncfg.5.html freeswan-1.9/doc/manpage.d/ipsec_tncfg.5.html
--- freeswan-1.9.orig/doc/manpage.d/ipsec_tncfg.5.html	Tue Mar 27 23:17:12 2001
+++ freeswan-1.9/doc/manpage.d/ipsec_tncfg.5.html	Mon Jun  4 01:16:15 2001
@@ -54,13 +54,15 @@
 <DT>+<DD>
 the MTU of the ipsec virtual I/F,
 <DT>+<DD>
+the automatically adjusted effective MTU for PMTU discovery, in brackets,
+<DT>+<DD>
 a visual and machine parsable separator '-&gt;', separating the virtual I/F
 MTU and the physical I/F MTU,
 <DT>+<DD>
 the MTU of the attached physical I/F.
 <B>.SH</B>EXAMPLES
 
-<DT><B>ipsec2 -&gt; eth3 mtu=16260 -&gt; 1500</B>
+<DT><B>ipsec2 -&gt; eth3 mtu=16260(1443) -&gt; 1500</B>
 
 <DD>
 </DL>
@@ -76,10 +78,14 @@
 <B>eth3</B>
 
 with an MTU of
-<B>1500.</B>
+<B>1500</B>
+
+and that the effective MTU as a result of PMTU discovery has been
+automatically set to
+<B>1443.</B>
 
 <DL COMPACT>
-<DT><B>ipsec0 -&gt; wvlan0 mtu=1400 -&gt; 1500</B>
+<DT><B>ipsec0 -&gt; wvlan0 mtu=1400(16260) -&gt; 1500</B>
 
 <DD>
 </DL>
@@ -95,10 +101,12 @@
 <B>wvlan0</B>
 
 with an MTU of
-<B>1500.</B>
+<B>1500</B>
 
+and no PMTU packets have gotten far enough to bump down the effective MTU
+from its default of 16260.
 <DL COMPACT>
-<DT><B>ipsec3 -&gt; NULL mtu=0 -&gt; 0</B>
+<DT><B>ipsec3 -&gt; NULL mtu=0(0) -&gt; 0</B>
 
 <DD>
 </DL>
@@ -140,6 +148,9 @@
 
 
 
+
+
+
 <P>
 
 <HR>
@@ -156,6 +167,6 @@
 This document was created by
 <A HREF="http://localhost/cgi-bin/man/man2html">man2html</A>,
 using the manual pages.<BR>
-Time: 04:17:12 GMT, March 28, 2001
+Time: 05:16:15 GMT, June 04, 2001
 </BODY>
 </HTML>
diff -bruN freeswan-1.9.orig/doc/manpage.d/ipsec_tncfg.8.html freeswan-1.9/doc/manpage.d/ipsec_tncfg.8.html
--- freeswan-1.9.orig/doc/manpage.d/ipsec_tncfg.8.html	Tue Mar 27 23:17:12 2001
+++ freeswan-1.9/doc/manpage.d/ipsec_tncfg.8.html	Mon Jun  4 01:16:15 2001
@@ -187,6 +187,6 @@
 This document was created by
 <A HREF="http://localhost/cgi-bin/man/man2html">man2html</A>,
 using the manual pages.<BR>
-Time: 04:17:12 GMT, March 28, 2001
+Time: 05:16:15 GMT, June 04, 2001
 </BODY>
 </HTML>
diff -bruN freeswan-1.9.orig/doc/manpage.d/ipsec_ttoaddr.3.html freeswan-1.9/doc/manpage.d/ipsec_ttoaddr.3.html
--- freeswan-1.9.orig/doc/manpage.d/ipsec_ttoaddr.3.html	Tue Mar 27 23:17:12 2001
+++ freeswan-1.9/doc/manpage.d/ipsec_ttoaddr.3.html	Mon Jun  4 01:16:15 2001
@@ -563,6 +563,6 @@
 This document was created by
 <A HREF="http://localhost/cgi-bin/man/man2html">man2html</A>,
 using the manual pages.<BR>
-Time: 04:17:12 GMT, March 28, 2001
+Time: 05:16:15 GMT, June 04, 2001
 </BODY>
 </HTML>
diff -bruN freeswan-1.9.orig/doc/manpage.d/ipsec_ttodata.3.html freeswan-1.9/doc/manpage.d/ipsec_ttodata.3.html
--- freeswan-1.9.orig/doc/manpage.d/ipsec_ttodata.3.html	Tue Mar 27 23:17:12 2001
+++ freeswan-1.9/doc/manpage.d/ipsec_ttodata.3.html	Mon Jun  4 01:16:15 2001
@@ -372,6 +372,6 @@
 This document was created by
 <A HREF="http://localhost/cgi-bin/man/man2html">man2html</A>,
 using the manual pages.<BR>
-Time: 04:17:12 GMT, March 28, 2001
+Time: 05:16:15 GMT, June 04, 2001
 </BODY>
 </HTML>
diff -bruN freeswan-1.9.orig/doc/manpage.d/ipsec_ttosa.3.html freeswan-1.9/doc/manpage.d/ipsec_ttosa.3.html
--- freeswan-1.9.orig/doc/manpage.d/ipsec_ttosa.3.html	Tue Mar 27 23:17:12 2001
+++ freeswan-1.9/doc/manpage.d/ipsec_ttosa.3.html	Mon Jun  4 01:16:15 2001
@@ -3,7 +3,7 @@
 <HTML><HEAD><TITLE>Manpage of IPSEC_TTOSA</TITLE>
 </HEAD><BODY>
 <H1>IPSEC_TTOSA</H1>
-Section: C Library Functions (3)<BR>Updated: 15 Sept 2000<BR><A HREF="#index">Index</A>
+Section: C Library Functions (3)<BR>Updated: 27 Feb 2001<BR><A HREF="#index">Index</A>
 <A HREF="http://localhost/cgi-bin/man/man2html">Return to Main Contents</A><HR>
 
 
@@ -96,8 +96,10 @@
 
 <B>tun</B>,
 
+<B>comp</B>,
+
 or
-<B>comp</B>),
+<B>int</B>),
 
 a single character indicating the address family
 (<B>.</B>
@@ -149,6 +151,29 @@
 so the internal representation is never visible.
 <P>
 
+Similarly, the SA specifiers
+<B>%pass</B>,
+
+<B>%drop</B>,
+
+<B>%reject</B>,
+
+<B>%hold</B>,
+
+and
+<B>%trap</B>
+
+signify special ``magic'' SAs used to indicate that packets should be
+passed, dropped, rejected (dropped with ICMP notification),
+held,
+and trapped (sent up to
+<I><A HREF="ipsec_pluto.8.html">ipsec_pluto</A></I>(8))
+
+respectively.
+These forms too are known to both routines,
+so the internal representation of the magic SAs should never be visible.
+<P>
+
 The
 <B>&lt;<A HREF="file:/usr/include/freeswan.h">freeswan.h</A>&gt;</B>
 
@@ -190,6 +215,48 @@
 
 <P>
 
+<B>&lt;<A HREF="file:/usr/include/freeswan.h">freeswan.h</A>&gt;</B>
+
+also defines
+<B>SA_INT</B>
+
+to have the value
+<B>61</B>
+
+(reserved by IANA for ``any host internal protocol'')
+and
+<B>SPI_PASS</B>,
+
+<B>SPI_DROP</B>,
+
+<B>SPI_REJECT</B>,
+
+<B>SPI_HOLD</B>,
+
+and
+<B>SPI_TRAP</B>
+
+to have the values 256-260 (in <I>host</I> byte order) respectively.
+These are used in constructing the magic SAs
+(which always have address
+<B>0.0.0.0</B>).
+
+<P>
+
+If
+<I>satot</I>
+
+encounters an unknown protocol code, e.g. 77,
+it yields output using a prefix
+showing the code numerically, e.g. ``unk77''.
+This form is
+<I>not</I>
+
+recognized by
+<I>ttosa</I>.
+
+<P>
+
 The
 <I>srclen</I>
 
@@ -328,7 +395,7 @@
 <I>satot</I>
 
 are:
-unknown format; unknown protocol code.
+unknown format.
 <A NAME="lbAG">&nbsp;</A>
 <H2>HISTORY</H2>
 
@@ -375,6 +442,6 @@
 This document was created by
 <A HREF="http://localhost/cgi-bin/man/man2html">man2html</A>,
 using the manual pages.<BR>
-Time: 04:17:12 GMT, March 28, 2001
+Time: 05:16:15 GMT, June 04, 2001
 </BODY>
 </HTML>
diff -bruN freeswan-1.9.orig/doc/manpage.d/ipsec_ttosubnet.3.html freeswan-1.9/doc/manpage.d/ipsec_ttosubnet.3.html
--- freeswan-1.9.orig/doc/manpage.d/ipsec_ttosubnet.3.html	Tue Mar 27 23:17:13 2001
+++ freeswan-1.9/doc/manpage.d/ipsec_ttosubnet.3.html	Mon Jun  4 01:16:15 2001
@@ -563,6 +563,6 @@
 This document was created by
 <A HREF="http://localhost/cgi-bin/man/man2html">man2html</A>,
 using the manual pages.<BR>
-Time: 04:17:13 GMT, March 28, 2001
+Time: 05:16:15 GMT, June 04, 2001
 </BODY>
 </HTML>
diff -bruN freeswan-1.9.orig/doc/manpage.d/ipsec_ttoul.3.html freeswan-1.9/doc/manpage.d/ipsec_ttoul.3.html
--- freeswan-1.9.orig/doc/manpage.d/ipsec_ttoul.3.html	Tue Mar 27 23:17:13 2001
+++ freeswan-1.9/doc/manpage.d/ipsec_ttoul.3.html	Mon Jun  4 01:16:15 2001
@@ -305,6 +305,6 @@
 This document was created by
 <A HREF="http://localhost/cgi-bin/man/man2html">man2html</A>,
 using the manual pages.<BR>
-Time: 04:17:13 GMT, March 28, 2001
+Time: 05:16:15 GMT, June 04, 2001
 </BODY>
 </HTML>
diff -bruN freeswan-1.9.orig/doc/manpage.d/ipsec_ultoa.3.html freeswan-1.9/doc/manpage.d/ipsec_ultoa.3.html
--- freeswan-1.9.orig/doc/manpage.d/ipsec_ultoa.3.html	Tue Mar 27 23:17:13 2001
+++ freeswan-1.9/doc/manpage.d/ipsec_ultoa.3.html	Mon Jun  4 01:16:15 2001
@@ -255,6 +255,6 @@
 This document was created by
 <A HREF="http://localhost/cgi-bin/man/man2html">man2html</A>,
 using the manual pages.<BR>
-Time: 04:17:13 GMT, March 28, 2001
+Time: 05:16:15 GMT, June 04, 2001
 </BODY>
 </HTML>
diff -bruN freeswan-1.9.orig/doc/manpage.d/ipsec_ultot.3.html freeswan-1.9/doc/manpage.d/ipsec_ultot.3.html
--- freeswan-1.9.orig/doc/manpage.d/ipsec_ultot.3.html	Tue Mar 27 23:17:13 2001
+++ freeswan-1.9/doc/manpage.d/ipsec_ultot.3.html	Mon Jun  4 01:16:15 2001
@@ -305,6 +305,6 @@
 This document was created by
 <A HREF="http://localhost/cgi-bin/man/man2html">man2html</A>,
 using the manual pages.<BR>
-Time: 04:17:13 GMT, March 28, 2001
+Time: 05:16:15 GMT, June 04, 2001
 </BODY>
 </HTML>
diff -bruN freeswan-1.9.orig/doc/manpage.d/ipsec_unspecaddr.3.html freeswan-1.9/doc/manpage.d/ipsec_unspecaddr.3.html
--- freeswan-1.9.orig/doc/manpage.d/ipsec_unspecaddr.3.html	Tue Mar 27 23:17:13 2001
+++ freeswan-1.9/doc/manpage.d/ipsec_unspecaddr.3.html	Mon Jun  4 01:16:15 2001
@@ -161,6 +161,6 @@
 This document was created by
 <A HREF="http://localhost/cgi-bin/man/man2html">man2html</A>,
 using the manual pages.<BR>
-Time: 04:17:13 GMT, March 28, 2001
+Time: 05:16:15 GMT, June 04, 2001
 </BODY>
 </HTML>
diff -bruN freeswan-1.9.orig/doc/manpage.d/ipsec_version.5.html freeswan-1.9/doc/manpage.d/ipsec_version.5.html
--- freeswan-1.9.orig/doc/manpage.d/ipsec_version.5.html	Tue Mar 27 23:17:13 2001
+++ freeswan-1.9/doc/manpage.d/ipsec_version.5.html	Mon Jun  4 01:16:16 2001
@@ -95,6 +95,6 @@
 This document was created by
 <A HREF="http://localhost/cgi-bin/man/man2html">man2html</A>,
 using the manual pages.<BR>
-Time: 04:17:13 GMT, March 28, 2001
+Time: 05:16:15 GMT, June 04, 2001
 </BODY>
 </HTML>
diff -bruN freeswan-1.9.orig/doc/manpage.d/ipsec_whack.8.html freeswan-1.9/doc/manpage.d/ipsec_whack.8.html
--- freeswan-1.9.orig/doc/manpage.d/ipsec_whack.8.html	Tue Mar 27 23:17:13 2001
+++ freeswan-1.9/doc/manpage.d/ipsec_whack.8.html	Mon Jun  4 01:16:16 2001
@@ -594,12 +594,16 @@
 identity defaults to the IP address specified by <B>--host</B>.
 
 <DT><B>--host</B>&nbsp;<I>ip-address</I><DD>
+<DT><B>--host</B>&nbsp;<B>%any</B><DD>
+<DT><B>--host</B>&nbsp;<B>%opportunistic</B><DD>
 the IP address of the end (generally the public interface).
 If <B>pluto</B> is to act as a responder
 for IKE negotiations initiated from unknown IP addresses (the
 ``Road Warrior'' case), the
 IP address should be specified as <B>%any</B> (currently,
 the obsolete notation <B>0.0.0.0</B> is also accepted for this).
+If <B>pluto</B> is to opportunistically initiate the connection,
+use <B>%opportunistic</B>
 <DT><B>--ikeport</B>&nbsp;<I>port-number</I><DD>
 the UDP port that IKE listens to on that host.  The default is 500.
 (<B>pluto</B> on this machine uses the port specified by its own command
@@ -703,7 +707,8 @@
 
 If none of the <B>--encrypt</B>, <B>--authenticate</B>, <B>--compress</B>,
 or <B>--pfs</B> flags is given, the initiating the connection will
-only build an ISAKMP SA.
+only build an ISAKMP SA.  For such a connection, client subnets have
+no meaning and must not be specified.
 <P>
 
 More work is needed to allow for flexible policies.  Currently
@@ -761,6 +766,8 @@
 virtual interface.
 Once routing is set up, no packets will be
 sent ``in the clear'' to the peer's client specified in the connection.
+A TRAP shunt eroute will be installed; if outbound traffic is caught,
+Pluto will initiate the connection.
 An explicit <B>whack</B> route is not always needed: if it hasn't been
 done when an IPsec SA is being installed, one will be automatically attempted.
 <P>
@@ -1642,6 +1649,6 @@
 This document was created by
 <A HREF="http://localhost/cgi-bin/man/man2html">man2html</A>,
 using the manual pages.<BR>
-Time: 04:17:13 GMT, March 28, 2001
+Time: 05:16:16 GMT, June 04, 2001
 </BODY>
 </HTML>
diff -bruN freeswan-1.9.orig/doc/opportunism.howto freeswan-1.9/doc/opportunism.howto
--- freeswan-1.9.orig/doc/opportunism.howto	Wed Dec 31 19:00:00 1969
+++ freeswan-1.9/doc/opportunism.howto	Sun Jun  3 13:32:36 2001
@@ -0,0 +1,357 @@
+FreeS/WAN Opportunism HowTo
+===========================
+
+RCSID $Id: opportunism.howto,v 1.5 2001/06/03 17:32:36 dhr Exp $
+
+D. Hugh Redelmeier
+
+
+FreeS/WAN, the LINUX IPSEC implementation, is intended to allow
+systems to connect through secure tunnels without prearrangement.
+This HowTo is intended to be a guide to setting up a system to enable
+this feature, which we call opportunism.  Much more information about
+FreeS/WAN is provided at http://www.freeswan.org.
+
+You are expected to already have built and used FreeS/WAN.  This
+document is only intended to describe the support for opportunism
+after release 1.9.
+
+For a more complete description of the design of Opportunism, see our
+paper "Opportunistic Encryption".
+
+
+Theory
+======
+
+If opportunism is enabled, a Security Gateway running FreeS/WAN will
+intercept the first outbound packet to a particular destination (IP
+address), and try to negotiate a security tunnel suitable for traffic
+to that destination.  Note that throughout this document, the term
+"Security Gateway" is meant to include a machine that is protecting
+its own traffic.
+
+To make this work going the other way, the Security Gateway must be
+willing to negotiate with peers trying to protect traffic initiated
+from their side.
+
+The first novel problem is that our Security Gateway needs to discover
+the IP address of the other Security Gateway for the packet that
+prompted the negotiation.  Oh, and quickly discover if there is none
+-- that negotiation will be impossible.
+
+The second novel problem is that our Security Gateway needs to
+authenticate the other Security Gateway.  This authentication needs to
+ensure that the other Security Gateway is who it claims to be AND that
+it is authorized to represent the client for which it claims to be the
+gateway.
+
+The roles in a particular negotiation are:
+     Source----Initiator----...----Responder----Destination
+
+The Source and Destination are endpoints of the traffic that is to be
+protected.  The Source is the one that happened to send the first
+packet of traffic.  Neither needs to be aware of IPSEC or FreeS/WAN.
+That is the job of their respective Security Gateways, Initiator and
+Responder.  The names "Initiator" and "Responder" match those used in
+the IPSEC standards.  It is quite possible for Source and Initiator to
+be the same machine; similarly, Destination and Responder could be the
+same.  All traffic from Source or Destination must flow through their
+Security Gateways if it is to be considered for protection.  These
+roles are fluid -- they can be different for each negotiation.
+
+We use the DNS (the Domain Name System) as a distributed database to
+hold the required information.
+
+
+DNS Records Required
+====================
+
+See section 2.3 of "Opportunistic Encryption" for a fuller
+explanation.
+
+Generally, we need to add records to the reverse-map DNS entries for
+the client machine and the Security Gateway machine.  There are
+special cases that are exceptions.
+
+A Security Gateway that is going to initiate an Opportunistic
+negotiation needs to provide a way for the Responding SG to find a
+public key for the Initiator to allow authentication.  This is
+accomplished by putting the public key in a KEY record in the
+reverse-map of the Initiator.  Conveniently, the KEY record can
+be generated by the ipsec_showhostkey(8) command.  All you need to
+do is copy the output of the command
+	ipsec showhostkey
+into the zone information for the reverse-map.  Here is an example,
+with many characters of the key itself left out:
+
+	; RSA 2048 bits   xy.example.com   Sat Apr 15 13:53:22 2000
+	xy.example.com.   IN   KEY   0x4200 4 1 AQOF8tZ2...+buFuFn/
+
+Each client that is to be protected by Opportunistic Encryption must
+include a special TXT record in its reverse-map.  The
+ipsec_showhostkey(8) command is willing to do this too.  Remember:
+this command must be run on the Security Gateway where the
+ipsec.secrets file resides.  In this case, you must tell the command
+what IP address to in the TXT record:
+	ipsec showhostkey --txt 10.11.12.13
+might produce the output:
+	; RSA 2048 bits   xy.example.com   Sat Apr 15 13:53:22 2000
+	IN TXT  "X-IPsec-Server(10)=10.11.12.13 AQOF8tZ2...+buFuFn/"
+
+- the quotes matter: this is a single string, as far as DNS is concerned
+
+- the X-IPsec-Server is a prefix that signifies that the TXT record
+  contains Opportunism configuration information
+
+- the (10) specifies a precedence for this record.  This is similar
+  to MX record preferences.  Lower numbers have stronger preference.
+
+- 10.11.12.13 specifies the IP address of the Security Gateway for
+  this machine.
+
+- AQOF8tZ2...+buFuFn/ is the (shortened) encoding of the RSA Public
+  key of the Security Gateway.
+
+This output must be added to the zone information for the reverse-map
+for each client machine.  This gets a bit dull and repetitive.
+
+Unfortunately, not every administrator has control over the contents
+of the reverse-map.  The only case where we can work around this is
+where the Initiator has no suitable reverse map (but the Source
+must!).  In this case, the Source's TXT record gives @FQDN ("Fully
+Qualified Domain Name") in place of its Security Gateway's IP address.
+This FQDN must match the ID-payload used by the Initiator.
+Furthermore, a forward lookup for a KEY record on the FQDN must yield
+the Initiator's public key.  Obscure fact: the forward lookup is only
+done by a Responder, and then only when the Initiator's ID payload
+specifies the FQDN.  There is no provision for a Responder with no
+control over its reverse-map.
+
+DNS changes sometimes take a long time to propagate.
+
+
+Configuring FreeS/WAN
+=====================
+
+To enable opportunism, you must include a suitable conn in
+/etc/ipsec.conf and you must enable it.
+
+A suitable conn looks like an ordinary conn.  It more closely resembles
+a Road Warrior conn (one that has a wildcard %any specified as the
+other Security Gateway).  But in this case, both the other Security
+Gateway AND its client are unknown.
+
+conn ours-to-anyone	# for our client subnet
+	leftsubnet=10.3.2.1.0/24	# any single client in our subnet
+	also=us-to-anyone	# rest is same as for SG
+
+conn us-to-anyone	# for our Security Gatway
+	left=%defaultroute	# our SG (defaults leftnexthop too)
+	right=%opportunistic
+
+(%defaultroute only works if you have specified
+interfaces=%defaultroute.  Since this isn't the topic of the howto,
+you will have to look at the other documentation to find out how to
+handle other cases.)
+
+You can have any number of opportunistic conns, but generally it only
+makes sense to have one for each client subnet and one for the
+Security Gateway itself.
+
+Currently only one interface may be used for opportunism: Pluto knows
+nothing about routing, so would be unable to choose amongst several.
+Almost certainly our side's nexthop must be predetermined
+(%defaultroute will do that).
+
+Note: the routing done for outbound Opportunism will catch any packets
+not covered by a more specific route.  This is what you want for
+packets that are also covered by an eroute.  But packets caught by the
+route and not an eroute will be subject to the no-eroute policy of
+KLIPS, which defaults to %drop.
+
+To enable these conns for inbound opportunistic negotiation, it must be
+--added:
+	ipsec auto --add us-to-anyone
+	ipsec auto --add ours-to-anyone
+If you want this automatically done on startup, put
+	auto=add
+in the us-to-anyone conn.
+
+To enable these conns for outbound opportunistic negotiation, it must
+be both --added and --routed.  Outbound packets will then be trapped
+and will trigger negotiation:
+	ipsec auto --add us-to-anyone
+	ipsec auto --add ours-to-anyone
+	ipsec auto --route us-to-anyone
+	ipsec auto --route ours-to-anyone
+If you want this automatically done on startup, put
+	auto=route
+in the us-to-anyone conn (this feature may be renamed in the future).
+
+
+Getting DNS Through
+===================
+
+There is a serious chicken-and-egg problem.  Outbound Opportunism blocks
+communication with an IP address until it discovers whether that IP
+address can have an IPSEC connection negotiated.  This discovery takes
+DNS queries.  These DNS queries might involve communicating with
+arbitrary IP addresses.  Thus we require DNS queries to succeed before
+any communication succeeds, including those same DNS queries!  The way
+out of this conundrum is to exempt at least some DNS query IP traffic
+from Opportunism.
+
+There are several possible solutions, all of which have advantages and
+disadvantages.
+
+1. If you use a single machine, outside your Security Gateway, as DNS
+server, you can build a clear path (or even an IPSEC tunnel, but not
+opportunistically) directly to that machine.
+
+- you could use a type=passthrough conn to provide a clear path
+  between your machine and the DNS machine.
+
+- you could explicitly create an IPSEC connection to your DNS server.
+  Just be sure that it need not access DNS to find the IP addresses
+  or RSA public keys.
+
+- you could install an explicit route to the DNS machine through
+  your public interface (not ipsecN).  This will bypass KLIPS
+  processing.  You might have to adjust your firewall.  For example:
+  	route add host -net ns.example.com gw gw.example.com dev eth1
+
+2. Generally, it is better to run DNS on your Security Gateway.  This
+leads to a need for non-opportunistic paths to an arbitrary number of
+DNS servers in the internet.  One way to accomplish this is to NOT
+have outbound opportunism cover the SG itself, but only the subnet
+behind it.  In other words, leave out the 
+	ipsec auto --route us-to-anyone
+You must also add a type=passthrough eroute specifically for
+us-to-anyone (without this, the traffic will be handled by the KLIPS
+no-eroute policy).
+
+3. It is actually possible to use a single machine inside your client
+subnet as a DNS server.  The techniques listed in 1 could be used to
+let it communicate with other DNS servers without interference.  This
+might have advantages over 1 if the DNS machine *only* did DNS.
+Another technique (not often possible or reasonable) is to give this
+machine another route to the internet, one that avoids the SG.
+
+We would like to have better solutions.  Perhaps we will in the
+future.  Suggestions are welcome.
+
+
+Figuring out what is going on
+=============================
+
+Since Opportunism lets your SG operate with less supervision, you may
+be puzzled by what it is up to.  The usual tools exist, but their use
+is more important.  I like to use
+	ipsec auto --status
+and also to examine the kernel's eroute table.
+
+The "file" /proc/net/ipsec_eroute contains a description of all the
+eroutes in the kernel (see also ipsec_look(8)).  Here is an example:
+
+10         10.3.2.1.0/24    -> 0.0.0.0/0          => %trap
+259        10.3.2.1.115/32  -> 10.19.75.161/32    => tun0x1002@10.19.75.145
+71         10.44.73.97/32   -> 0.0.0.0/0          => %trap
+4119       10.44.73.97/32   -> 10.114.121.41/32   => %pass
+
+You read each line as: a packet from within the first subnet, destined
+for the second subnet, will be processed by the Security Association
+Identity (SAID) specified last.  The first column is the number of
+(outbound) packets processed by this eroute.
+
+For shunt eroutes, the SAID is printed as just the type of shunt:
+%pass	pass the packet through with no processing
+%drop	discard the packet
+%reject	discard the packet and notify sender
+%hold	keep the last packet; discard others
+%trap	cause any trapped packet to generate a PF_KEY ACQUIRE
+	to request negotiation; install a corresponding %hold
+	shunt and attach this packet to the %hold
+
+For other eroutes, the SAID is printed as a triple: protocol (three
+letters), SPI (32-bit number in hex), and destination IP address.
+Protocols include:
+
+tun	IP in IP encapsulation (used for most tunnels)
+esp	ESP encapsulation -- part of an IPSEC SA group
+ah	AH packet authentication -- part of an IPSEC SA group
+
+So, looking at our sample eroutes:
+
+10         10.3.2.1.0/24    -> 0.0.0.0/0          => %trap
+
+	This is a TRAP (int0x104) shunt eroute.  It was installed by
+	Pluto so that it can catch all traffic from its client subnet
+	to the world at large.  Ten outbound packets have been trapped.
+
+259        10.3.2.1.115/32  -> 10.19.75.161/32    => tun0x1002@10.19.75.145
+
+	This is a tunnel eroute: packets from 10.3.2.1.115 (within
+	our client subnet) going to 10.19.75.161 will be encrypted
+	and sent to the peer SG 10.19.75.145.  This was the product
+	of an Opportunistic negotiation (a hint is that each client
+	subnet has only one member).  259 packets have been sent
+	through this tunnel.
+
+71         10.44.73.97/32   -> 0.0.0.0/0          => %trap
+
+	This is another TRAP shunt eroute.  It is to catch traffic
+	from the Security Gateway to the world.  It has caught
+	71 outbound packets.
+
+4119       10.44.73.97/32   -> 10.114.121.41/32   => %pass
+
+	This is a %pass (0x100) shunt eroute.  It was installed when an
+	attempted Opportunistic negotiation failed because the reverse
+	domain of 10.114.121.41 had no suitable TXT record.  4119
+	outbound packets have been passed.
+
+
+Important Limitations
+=====================
+
+Pluto's DNS lookup is synchronous (single-threaded).  Not only does
+this slow things down, but it turns out that in extreme cases where
+there are a lot of ACQUIRE messages from KLIPS at once, some of those
+messages can be lost and communications will be blocked by the %hold
+eroute that Pluto doesn't know about.  Pluto now looks every 2 minutes
+for any %holds that it missed.
+
+DNS lookup is not verified -- we don't use Secure DNS.  A spoofed DNS
+could compromise Opportunism.
+
+There are several new opportunities for Denial of Service attacks.
+For example, a Bad Guy could spray our system with pings with forged
+source addresses.  For each unique source address, our system would do
+a (synchronous!) DNS lookup.
+
+Once a %pass eroute is added for a failed negotiation, it will stay
+until it has been inactive for about 15 minutes.  The only activity
+that counts is outbound -- not surprising since a %pass only affects
+outbound traffic.
+
+If a destination's DNS entry specifies the information we need for
+negotiation, Pluto will not let communications proceed without
+negotiating a Security Tunnel.
+
+There is currently no way to tear down a tunnel that is no longer in
+use.  To add insult to injury, when the lifetime is about to be
+exceeded, the initiating Pluto will rekey!  Restarting will clear
+these out.
+
+If one side of a Security Tunnel restarts, but doesn't initiate
+negotiation with the other side, the other side will not be able to
+communicate with it until it thinks the tunnel needs rekeying due to
+lifetime.
+
+KLIPS does not implement inbound policy checking.  This means that a
+message from one peer can be forged by another peer.  So you ought not
+to trust information more just because it appears to have come from a
+source covered by a Security Tunnel.  This makes it difficult to
+safely combine a VPN with Opportunism.
+
+It isn't clear what firewall policies make sense with Opportunism.
diff -bruN freeswan-1.9.orig/doc/pkix/CA-regenerate-flatfile.sh freeswan-1.9/doc/pkix/CA-regenerate-flatfile.sh
--- freeswan-1.9.orig/doc/pkix/CA-regenerate-flatfile.sh	Wed Dec 31 19:00:00 1969
+++ freeswan-1.9/doc/pkix/CA-regenerate-flatfile.sh	Mon Jun  4 11:34:31 2001
@@ -0,0 +1,20 @@
+#!/bin/sh
+if [ -d /var/lib/ssl ]; then
+  cd /var/lib/ssl
+elif [ -d /usr/lib/ssl ]; then
+  cd /usr/lib/ssl
+elif [ -d /usr/local/lib/ssl ]; then
+  cd /usr/local/lib/ssl
+elif [ -d /usr/share/ssl ]; then
+  cd /usr/share/ssl
+else
+  echo "ERROR: Cannot determine location of ssl directory."
+  exit 1
+fi
+
+for ii in certs/*.pem cacert.pem crl.pem;
+do
+  cat $ii | \
+  perl -e '$printme = 0; while (<>) { if (/---BEGIN/) {$printme = 1;}; if ($printme) {print STDOUT $_;} }; print STDOUT "\n";' \
+  >> flatfile.txt
+done
diff -bruN freeswan-1.9.orig/doc/pkix/README.certificates freeswan-1.9/doc/pkix/README.certificates
--- freeswan-1.9.orig/doc/pkix/README.certificates	Wed Dec 31 19:00:00 1969
+++ freeswan-1.9/doc/pkix/README.certificates	Mon Jun  4 11:34:31 2001
@@ -0,0 +1,452 @@
+	     Readme for certificate setup under FreeS/WAN
+
+			     Neil Dunbar
+			  5th November, 1999
+
+The certificate patches are (almost) always against the most recent
+snapshots available from
+ftp://ftp.xs4all.nl/~freeswan/snapshot.tar.gz. The patches are
+available from ftp://hplose.hpl.hp.com/pub/nd/pluto-openssl.tar.gz.
+
+The patches count on your having OpenSSL-0.9.3 or above installed on
+your system. Check out http://www.openssl.org for details on how to
+get OpenSSL. NB: the patches will *not* work on OpenSSL-0.9.2 or
+below.
+
+1. Applying the patches
+
+To apply the patches, cd to the build directory for the snapshot,
+which is generally freeswan-snap1999MonthDayb, and untar the
+pluto-openssl.tar.gz.
+
+Then type 'patch -p0 < pluto.diff', followed by 'patch -p0 <
+utils.diff'.
+
+2. Building and Installing FreeS/WAN
+
+Go to the pluto directory in the snapshot source directory, and edit
+the Makefile. Find the line OPENSSLROOT=.... and change the value of
+that variable to be the location of where you have installed the
+includes and libraries for OpenSSL. By default this is set to
+/usr/local/ssl.
+
+After that, build the system as per the FreeS/WAN installation notes.
+
+Installation, similarly, is no different to the normal method.
+
+3. Configuring FreeS/WAN
+
+In order to allow Pluto to use digital signatures, rather than
+preshared secrets to generate key material for IPsec, there are
+several options within the connection section of the file
+/etc/ipsec.conf which need to be set.
+
+For examples, we assume the host to host connection as follows
+
+	      west === westhop ...... easthop ==== east
+
+3.1 certfile
+
+The certfile setting should be set to the full path name of the file
+which contains the certificate whose private key will be used to
+perform the digital signatures. This file must be set in order for
+pluto to send the certificate to the other side, if requested. The
+certificate can  be in PEM or DER format.
+
+Example : /etc/ipsec/west.certificate.pem
+
+3.2 keyfile
+
+This setting should be set to the full path name to the file which
+contains the key which will be used to perform the digital
+signature.
+
+The key file can be stored in several formats, but at the moment, only
+unencrypted private keys can be used. If you use an encrypted one, the
+key load will fail, and signature/public key modes will cease to be
+available.
+
+The key files can be stored in DER or PEM format, using the OpenSSL
+private key format, which is specific to OpenSSL. Alternatively, the
+key can be stored in PKCS-8 format, which is system independent. The
+problem is that, for the moment, the OpenSSL key generation
+applications only store keys in OpenSSL format. To convert a key file
+into PKCS-8 form, use the following command (assuming that the file
+key.pem stores the OpenSSL private key in PEM format).
+
+openssl -nocrypt -topk8 -in key.pem -inform PEM -outform DER \
+	-out key.pk8
+
+(If the original key is in DER format, change '-inform PEM' to
+'-inform DER'. Similarly, if you want a PEM PKCS-8 file, change
+'-outform DER' to '-outform PEM).
+
+The key can be either an RSA or DSA key. Note that if an RSA key is
+loaded, DSS signature modes will not be offered (or accepted) from the
+other side. Similarly, a DSA key will prevent RSA modes from being
+selected.
+
+Example : /etc/ipsec/west.key.pk8
+
+3.3 peerfile
+
+This option is obsolete. It used to specify the path to certificates
+used to start public key authentication mode. This function has been
+subsumed by the certpath option.
+
+Do not use peerfile any more.
+
+3.4 certpath
+
+This gives a comma separated list of maps (see README.xmap) which can
+be used to look up certificates and/or CRLs by specifying their
+subject names, issuer names and such like.
+
+At the moment, the XMAP types are file, dir, db, ldap.
+
+Example : ldap:/etc/ldap.conf:ldap_ipsec,dir:/etc/ipsec
+
+(The first item specifies an LDAP directory lookup, whose details are
+specified in the file /etc/ldap.conf, and the identifier of which LDAP
+lookup to use within that file is 'ldap_ipsec'. The second specifies a
+local directory called /etc/ipsec, which should have files and
+symbolic links which index the relevant certificates in the
+directory).
+
+For the format of ldap files, and certificate directories, read the
+file README.xmap.
+
+3.5 certopts
+
+This setting is a comma separated list which gives a set of switches
+which control the behaviour of the public key encryption/signatures
+within pluto.
+
+To set an option in the list, one simply includes its name.
+
+To clear an option in the list, one includes its name, with a '!'
+symbol before the name.
+
+Example : !send,!pkcs7,!pk,strict,dss-sha,dss-alt
+
+The example means: turn ON the options 'strict', 'dss-sha' and
+'dss-alt', but turn OFF the options 'send', 'pkcs7' and 'pk'.
+
+The options are as follows
+
+3.5.1 'send'
+
+Set this option if you want your side of the connection to send its
+certificate to the other side as part of the main mode
+negotiations. This certificate must be in the set of certificates
+which the other side is expecting on this connection.
+
+3.5.2 'pkcs7'
+
+***NOT IMPLEMENTED YET***
+
+When sending a certificate, if this option is set, a PKCS7 encoding
+for the certificate will be chosen. If not set, a standard DER
+encoding of the X.509 certificate will be used.
+
+3.5.3 'pk'
+
+When choosing between digital signature and public key encryption
+ISAKMP methods, this option forces pluto to select public key
+encryption. If not set, pluto will choose digital signature methods.
+
+Note that this option used to be called 'rsa', but this name makes
+little sense, since both RSA and El Gamal encryption methods are
+selected by this option.
+
+3.5.3 'rev'
+
+If using public key encryption for Phase 1 negotiations, this option
+makes pluto prefer to use the revised mode method, rather than the
+standard public key mode. Revised public key mode uses fewer public
+key encryptions and transmits fewer bytes in the protocol (since
+public key ciphertexts are much larger than their symmetric key
+counterparts). Probably not a bad idea to use this one all the time if
+you want ID protection.
+
+3.5.4 'strict'
+
+This option forces verification to be very strict on the acceptability
+of certificates from the peer. If 'strict' mode is on, the following
+conditions must apply to the peer's certificate --
+
+1. For every signing certificate in the chain up to the root CA
+   certificate a valid CRL *must* be present. If a CRL is not
+   available, or the CRL is not valid (badly signed, expired, etc),
+   the verification of the certificate will fail.
+
+2. The name on the certificate must bear some relation to the name of
+   the peer, as given in the ISAKMP ID field. Assuming that the name
+   of the peer is an IPv4 address, which is the only supported one,
+   then the Common Name on the subject of the certificate must start
+   with the fully qualified domain name of the peer. Failing that, the
+   subjectAltName extension must contain an entry of type IP, which is
+   equal to the IP address given as the peer's name, or it must
+   contain an entry of type DNS, which must be equal to the name of
+   the resoved FQDN of the IP address given as the peer's name. If any
+   of these conditions are met, the certificate will be accepted. If
+   none of these conditions succeed, the verification will fail.
+
+If strict mode is not set, and these conditions fail, then debugging
+warnings will be logged, but verification will succeed. Be warned that
+this makes the setup less secure than would strict mode.
+
+3.5.5 'dss-sha'
+
+RFC2409 stipulates that the DSS signature method requires the output
+of a SHA1 hash to sign and send to the other side. It does not say
+whether this hash is a keyed one (eg HMAC) or unkeyed (ie plain SHA1).
+
+A subsequent document, draft-ietf-ipsec-ike-01.txt, given a formula
+for the plain SHA1 output. However, as Tero Kivinen of SSH has pointed
+out, most implementations of IKE use the standard HMAC method.
+
+This option forces pluto to use the plain SHA1 method outlined in the
+draft document. Clearing this option forces the HMAC method to be
+used.
+
+3.5.6 'dss-alt'
+
+RFC2409 stipulates that the encoding of a DSS signature should be 'r
+followed by s'. It does not say what format this should take. ANSI
+document X9.30 states that DSS output should be the DER encoding of
+the ASN.1 construct -
+
+ SEQUENCE {
+  r INTEGER;
+  s INTEGER;
+ };
+
+This puts some wrapper bytes around the 160 bit integers r and s, so
+that the signature is some 45-48 bytes long (depending on leading
+zeros within the integers).
+
+draft-ietf-ipsec-ike-01.txt states that the signature should be a
+single 320 bit string, with r occupying the first 160 bits and s
+occupying the next 160, without wrappers, such that all signatures are
+exactly 40 bytes long.
+
+By using the 'dss-alt' option, pluto is forced into the draft document
+mode of operation. By clearing it, the X9.30 implementation is used.
+
+4. Creating the certificates
+
+This section summarises the far more useful guide within the OpenSSL
+documentation, but should serve to generate the certificates and keys
+required for a connection. The document assumes that OpenSSL has been
+compiled and installed in /usr/local/ssl. Furthermore, it assumes that
+that configuration file for OpenSSL is stored in
+/usr/local/ssl/lib/openssl.cnf. If this is not the case, all 'openssl
+<command>' entries should be replaced by 'openssl <command> -config
+/path/to/openssl.cnf'.
+
+I am heavily indebted to Peter Onion of BT Labs for his efforts to
+debug and clarify this documentation. Peter: Your efforts are much
+appreciated.
+
+NB: This isn't the "correct" way to generate certs/CRLs. It's just my
+own recipe (largely from memory - it's been a while!) for doing
+so. It's not efficient, and you really should read the OpenSSL docs
+for better guidance.
+
+4.1 Edit openssl.cnf
+
+Ensure that the following settings for the CA_default section are more
+or less as follows -
+
+dir             = /usr/local/ssl
+certs           = $dir/certs
+crl_dir         = $dir/crl
+database        = $dir/index.txt
+new_certs_dir   = $dir/newcerts
+ 
+certificate     = $dir/cacert.pem
+serial          = $dir/serial
+crl             = $dir/crl.pem
+private_key     = $dir/private/cakey.pem
+RANDFILE        = $dir/private/.rand
+
+Fill in the default fields (country, organization, etc) as seems right
+for your setup.
+
+Create a file ca.ext containing the following -
+
+-----------------------------------
+# Extensions for a typical CA - PKIX recommendation.
+ 
+subjectKeyIdentifier=hash
+ 
+authorityKeyIdentifier=keyid:always,issuer:always
+basicConstraints = CA:true 
+keyUsage = cRLSign, keyCertSign
+nsCertType = sslCA, emailCA
+subjectAltName=email:copy
+----------------------------------
+
+4.2 Make the CA certificate
+
+Go to the directory /usr/local/ssl
+
+Generate your CA cert by the usual method
+
+openssl req -new -newkey rsa:1024 \
+  -keyout /usr/local/ssl/private/cakey.pem \
+  -out careq.pem
+
+Now sign the CA cert, citing the extensions for [v3_ca]
+
+openssl x509 -CAcreateserial -signkey private/cakey.pem -req \
+  -in careq.pem -out cacert.pem -days 2000 -extfile ca.ext
+
+This creates the self signed certificate which can be used to sign
+further certificates. Ensure that this cacert.pem file is made widely
+available to all hosts which will communicate via IPsec.
+
+4.3 Make an empty certificate database
+
+Execute the following commands, whilst in the directory /usr/local/ssl
+
+touch index.txt
+
+echo "01" > serial
+
+This creates the database, and starts issued certificates with the
+serial number starting at 1.
+
+4.4 Generate a CRL
+
+Use the command
+
+openssl ca -gencrl -out crl.pem
+
+to generate an (initially empty) CRL.  You should always have a
+current CRL, even if nothing has been revoked, since that proves
+*actively* that no certificates have been cancelled. Without a CRL,
+you are forced into the assumption that no certificates have been
+revoked.
+
+The CRL is placed in /usr/local/ssl/crl.pem. Distribute this file to
+all hosts holding the cacert.pem file. (Or, if you have an LDAP
+directory handy, publish the CRL there, so that all hosts can contact
+it).
+
+4.5 Generate the host certificate requests.
+
+On each host, generate a key and certificate request with the
+following command (I'll assume that ipsec certificates are in the
+directory /etc/ipsec, which must exist beforehand).
+
+I'll assume that the host is called foo, and lives in .mydomain.com,
+and has IP address aa.bb.cc.dd.
+
+openssl req -new -newkey rsa:1024 \
+  -nodes -keyout /etc/ipsec/foo.key -out foo.req.pem
+
+Fill in the fields for the subject name, and ensure that the common
+name section is set to 'foo.mydomain.com IPsec certificate #1', or
+some such thing - either way, it should start with foo.mydomain.com.
+
+See section 3.2 (keyfile) on converting private key files to the
+standard PKCS-8 format (which pluto can also understand). If you do
+this, you can delete the original private key file 'foo.key', once you
+have a PKCS-8 equivalent of it.
+
+Change the file permissions on foo.key to be 400 - Owner read only,
+and change to owner to be root.
+
+Transport the file foo.req.pem to the host which will sign certificate
+requests. This should be done via some secure method of
+transmission. In an ideal setup, your CA host shouldn't be connected
+to any network at all - but that's a site specific decision)
+
+4.6 Sign the certificate requests.
+
+On the CA host, edit the openssl.cnf file such that there is a section
+[svr_cert] at the bottom of the file with the following contents. 
+
+[ svr_cert ]
+basicConstraints=CA:FALSE
+nsCertType = server
+keyUsage = nonRepudiation, digitalSignature, keyEncipherment
+nsComment = $ENV::NSCOMMENT
+subjectKeyIdentifier=hash
+authorityKeyIdentifier=keyid,issuer:always
+subjectAltName=email:copy,DNS:$ENV::HOSTFQDN,IP:$ENV::HOSTIP
+issuerAltName=issuer:copy       
+
+If this is not already done, alter the x509_extensions in the
+[CA_default] section such that it looks like -
+
+x509_extensions = $ENV::EXTENSION
+
+Now sign the request with the wrapper script 'signIPSEC', which
+is produced below. The script was written by Peter Onion.
+
+-----------------8<-------CUT HERE------8<----------------------------
+#! /bin/bash
+
+# Simple wrapper for "openssl ca" that sets environment to pass in
+# values for the svr_cert extension
+# P.J.Onion  23/9/1999
+
+if test $# -ne 3 ; then
+        echo "Usage: signIPSEC hostname ipaddress reqfile"
+        exit 1
+fi
+
+
+HOSTFQDN=$1
+HOSTIP=$2
+NSCOMMENT="IPsec Certificate for $1"
+EXTENSION=svr_cert
+
+export HOSTFQDN HOSTIP NSCOMMENT EXTENSION
+# Change /usr/local/ssl to be the directory in which OpenSSL
+# is installed.
+
+/usr/local/ssl/bin/openssl ca -in $3
+
+-----------8<----------CUT TO HERE --------8<-------------------------
+
+
+In the case above, you would do
+
+signIPSEC foo.mydomain.com 192.168.1.5 foo.req
+
+(assuming that foo.mydomain.com has the IP address 192.168.1.5, and
+that foo.req contains the PEM certificate request).
+
+Check the details that it prints, and commit the new certificate to
+the database. The new certificate will be in the directory
+/usr/local/ssl/newcerts. Tranport this file back to the requesting
+host and place it in the file /etc/ipsec/foo.pem. You can delete the
+file foo.req.pem now.
+
+Once the certificate has been delivered, move the file from newcerts
+into certs and run the command
+
+c_rehash /usr/local/ssl/certs
+
+to create the hashed directory.
+
+4.7 Renewing a certificate
+
+When you want to replace a certificate stored in file foo.pem, issue
+the command
+
+openssl ca -revoke foo.pem
+
+This changes the database to reflect the fact that the certificate has
+been cancelled, but does not update the CRL. Do that with the
+instructions in section 4.4. Make sure that the new CRL is propagated
+to all participating hosts.
+
+Now create the key/request/certificate as per sections 4.5 onwards.
+
+   ******************* End of document ********************
+
diff -bruN freeswan-1.9.orig/doc/pkix/README.certopts freeswan-1.9/doc/pkix/README.certopts
--- freeswan-1.9.orig/doc/pkix/README.certopts	Wed Dec 31 19:00:00 1969
+++ freeswan-1.9/doc/pkix/README.certopts	Mon Jun  4 11:34:31 2001
@@ -0,0 +1,22 @@
+The current options available within this PKIX package are:
+
+send 	-> If using RSASIG or RPKE, send your certificate to the peer.
+	   This option is usually optional.
+
+pk	-> Use PKE authentication
+
+pk,rev	-> Use RPKE authentication
+
+strict	-> Strict authenticate. There _must_ be a CRL available, and it
+	   must be valid.
+
+I recommend always sending the optional certificate to the peer, as well 
+as using "strict" at all times to make sure the connection is truly 
+fully authenticated.
+	certopts=send,strict,pk,rev
+
+For more information on these certopts options, please refer to Neil Dunbar's
+README.certificates document.
+
+-- Luc Lanthier
+luc.lanthier@rebel.com 
diff -bruN freeswan-1.9.orig/doc/pkix/README.xmap freeswan-1.9/doc/pkix/README.xmap
--- freeswan-1.9.orig/doc/pkix/README.xmap	Wed Dec 31 19:00:00 1969
+++ freeswan-1.9/doc/pkix/README.xmap	Mon Jun  4 11:34:31 2001
@@ -0,0 +1,398 @@
+			     README.xmap
+
+			     Neil Dunbar
+			  21st October, 1999
+
+1. Introduction
+
+As of the October release of the pluto-openssl patches, the
+certificate paths parameter has been replaced by a list of
+XMAPs. XMAPs are an abstraction of a dictionary lookup, which are
+designed to look up public key information. This includes X.509
+certificates, X.509 certificate revocation lists, and, in theory,
+simple public key values (NB: raw public keys are not supported yet).
+
+An XMAP is similar to the X509_LOOKUP system employed within OpenSSL
+to specify file and directory lookup. Indeed, XMAP has two mechanisms
+for lookup via file and directory, as well as others.
+
+The specification for an XMAP consists of a text string of the format
+<type>:<details>. The type denotes the sort of search which the XMAP
+library will carry out, and the details give appropriate parameter
+information so that the search can execute. As an example, a file XMAP
+on the file /etc/ipsec/certs.txt would have the form
+"file:/etc/ipsec/certs.txt".
+
+2. XMAP lookup
+
+(Programmer stuff - ignore if not interested)
+
+A lookup is a search which is identified by three parameters: the type
+of the thing being looked for, the search identifier and a search
+parameter (which is governed by the search identifier).
+
+The result of the search is a list (actually an OpenSSL STACK) of type
+X509_OBJECT (all of which fit the search criteria specified, sorted to
+be age order [most recent first, oldest last]. The type X509_OBJECT is
+defined in the OpenSSL header file x509_vfy.h. Note: this is NOT the
+same as the file X509_OBJECTS defined in x509.h. The C type
+declaration is reproduced here.
+
+typedef struct x509_object_st {
+   /* one of the above types */
+   int type;
+   union  {
+     char *ptr;
+     X509 *x509;
+     X509_CRL *crl;
+     EVP_PKEY *pkey;
+   } data; 
+} X509_OBJECT;
+
+Thus, if an X.509 certificate is stored in such an object, the type
+field will be set to X509_LU_X509, and <object>.data.x509 holds a
+pointer to the actual certificate data.
+
+Thus, to iterate through all certificates returned in a search, a C
+program fragment would look like the following.
+
+XMAP *xmap;
+int i;
+STACK_OF(X509_OBJECT) *sk;
+X509_OBJECT *obj;
+X509 *x;
+ :
+ :
+sk = XMAP_lookup(xmap, X509_LU_X509, <search id>, <search parameter>);
+for (i=0; i<sk_X509_OBJECT_num(sk); i++) {
+    obj = sk_X509_OBJECT_value(sk, i);
+    x = obj->data.x509;
+
+    /* Operations on the certificate 'x' */
+} 
+
+3. XMAP Search types
+
+The various search types are detailed in the following sections. The
+list of items are sorted (if possible) in date descending order, ie
+the most recent object is first in the return list, and the oldest
+object comes last. All duplicates are removed from the return list.
+
+3.1 "subject" (returns X.509 cert)
+
+The search looks for a certificate whose name is the the same as the
+X.509 name given in the parameter to the search.
+
+3.2 "issuer" (returns X.509 CRL)
+
+The search looks for a certificate revocation list (CRL) whose issuer
+is the same as the X.509 given as a search parameter.
+
+3.3 "uid" (returns X.509 cert)
+
+The search looks for the certificates which are listed as belonging to
+the user whose ID is given by the null terminated character string
+given as the search parameter.
+
+3.4 "dns" (returns X.509 cert)
+
+The search returns a list of the certificates which are listed as
+belonging to the fully qualified domain name (FQDN) as given in the
+search parameter, which is a null terminated character string.
+
+NB: Any certificate MUST have a subjectAltName which includes a DNS
+entry which is the same as the search string. This requirement is in
+addition to any indexing which is required for the individual XMAP
+search type.
+
+3.5 "ip" (returns X.509 cert)
+
+The search returns a list of the certificates which are listed as
+belonging to the IPv4 address given as a search parameter. The search
+parameter is a 4 octet string, which gives the IP address in network
+order; for example the ip address 15.144.59.30 would have the search
+parameter (in hex) 0F903B1E.
+
+As with DNS indexed certificates, the certificates must contain a
+subjectAltName with the correct IP entry within it.
+
+3.6 "ca" (returns X.509 cert)
+
+This search returns all CA certificates indexed in the list. A CA
+certificate is one which has a basicConstraints extension with the CA
+flag set to true. Also the CA has the subjectName and issuerName set
+to be the same.
+
+There is no search parameter for this search. It should be set to NULL
+in the XMAP_lookup() call.
+
+4. XMAP Types
+
+There are currently four types of XMAP: File, Directory, Berkeley DB
+and LDAP. Respectively, their type specifiers are "file", "dir", "db"
+and "ldap". Each subsection will detail the exact representation and
+expectations of the XMAP.
+
+4.1 File
+
+Type Specifier: "file"
+Syntax: file:<file name>
+
+This implements a simple flat file structure for lookups. The file can
+contain as many certificates in PEM format as desired. In order to
+index them, certain fields should be prepended to the certificates.
+
+For example a file might look like this.
+
+-----BEGIN CERTIFICATE-----
+MIIEHzCCAwegAwIBAgIBADANBgkqhkiG9w0BAQQFADCBpzELMAkGA1UEBhMCR0Ix
+HQ0Qb72dPlXYO20xtdMR9fX92PfSQSgAulNITYzusd8KE6yvJ8+HEbUuwXLHXZh4
+  :
+  :
+  :
+pk/Bv8iFUiZhH8EAr6SvF0AkpULi46bVcoQlr36Ax59uQ8OcJeNmljKYdbrN5uFL
+62In
+-----END CERTIFICATE-----
+
+uid: nd
+-----BEGIN CERTIFICATE-----
+MIIETDCCA7WgAwIBAgIQE9hfeRmSr51Wzgvm4B19JjANBgkqhkiG9w0BAQQFADCB
+njEPMA0GA1UEChMGaHAuY29tMRowGAYDVQQLExFJVCBJbmZyYXN0cnVjdHVyZTEL
+  :
+  :
+  :
+6pZk+pEpZ5S55lFP1QspTsBVbrBgsEuGFyGpHTo9sIEaQYxfRGNEvW+ZaEPU1HKo
+YVkAahuv5T21GdvouWdelA6l6uWMK/hfsQo9PdpBLDaUrwH5lkDuXcNk+LHZvVDt
+-----END CERTIFICATE-----                                       
+
+-----BEGIN X509 CRL-----
+MIICLTCCARUwDQYJKoZIhvcNAQEEBQAwgacxCzAJBgNVBAYTAkdCMR4wHAYDVQQI
+ExVTb3V0aCBHbG91Y2VzdGVyc2hpcmUxEDAOBgNVBAcTB0JyaXN0b2wxJTAjBgNV
+  :
+  :
+  :
+++lOGcX1WTtZ2dnV6Lb5r5xQ3IGavf2TKnu1/nCyAKFlF34+j7/+fIxT4iQiEDjk
+Z8Q76UEWVRMw7Tk63aAf0Yf5qaI1Tpd+SKhSTgc4arJH
+-----END X509 CRL-----
+
+ip: 15.144.59.30
+dns: pinky.hpl.hp.com
+-----BEGIN CERTIFICATE-----
+MIIHgTCCBmmgAwIBAgIBCjANBgkqhkiG9w0BAQQFADCBpzELMAkGA1UEBhMCR0Ix
+HjAcBgNVBAgTFVNvdXRoIEdsb3VjZXN0ZXJzaGlyZTEQMA4GA1UEBxMHQnJpc3Rv
+  :
+  :
+  :
+KkW/kYOxRrmg9KGnSVOolD1ueLYg9D4CtY30r1JGE/wixmIvQEP8JEv+X6Cr4Wiu
+VfENrF8=
+-----END CERTIFICATE-----
+
+This example indexes the fourth certificate as belonging to the IP
+address 15.144.59.30, as well as the DNS name "pinky.hpl.hp.com". The
+second certificate belongs to the user ID "nd".
+
+The file also contains a CRL embedded within it.
+
+Note: indexed searches in files are done by simple linear search. It's
+not an efficient means for searching serious amounts of data - use the
+other types for anything other than trivial data.
+
+
+4.2 Directory
+
+Type Specifier: "dir"
+Syntax: dir:<path to directory>
+
+The directory type is a derivation of the hashed directory used in the
+OpenSSL applications. The certificates are stored within a single
+level directory. Each certificate (or CRL) is stored in exactly one
+file in the directory. These files can be in either DER or PEM format,
+unlike the flat file above. To index the files for subject and issuer
+searches, you need to make a symbolic link from a hashed
+representation of the X.509 name of the certificate subject name (or
+CRL issuer name).
+
+To do this, you should execute the command -
+
+[for certificate files -- all on one line]
+
+ln -s certificate.pem
+  `openssl x509 -noout -hash -in certificate.pem`.cert.0
+
+NB: The .0 on the end is an arbitrary extension to the link name in
+case there might be a hash clash in the directory. You can call it
+anythin you like, but the ".cert" extension MUST be present -- unlike
+standard OpenSSL hash directories.
+
+[ for CRL files ]
+ln -s crl.pem
+  `openssl crl -noout -hash -in certificate.pem`.crl.0
+
+Again, the .0 is a differentiating extension, but the ".crl" is
+mandatory for marking out certificates.
+
+To index other attributes, you should make links which have the
+following appearance -
+
+uid-<user ID>.cert.0 [ denotes a user file ]
+dns-<fully qualified domain name>.cert.0 [ a DNS indexed cert ]
+ip-<IPv4 dotted form address>.cert.0 [ an IP indexed cert ]
+
+For example, assume that file pinky.pem held the certificate for DNS
+pinky.hpl.hp.com and/or IP address 15.144.59.30, the links would look
+like -
+
+dns-pinky.hpl.hp.com.cert.0  )__________\. pinky.pem
+ip-15.144.59.30.cert.0       )          /
+
+CA certificates don't need to be indexed. CA searches are performed by
+loading every certificate file in the directory and checking for a CA
+certificate, so it's failrly slow for this type of search.
+
+What Directories *are* good for is converting into a Berkeley DB file
+database - which is the fastest of all searches.
+
+-- ADDENDUM -- 20001016, Luc Lanthier
+
+I've created a short and ugly shell script 'rehashcertdir' which will 
+do this work for you. Usage:
+
+  ipsec rehashcertdir <directory>
+
+
+
+3.3 - Berkeley DB searches
+
+Type Specifier: "db"
+Syntax: db:<path to db file>
+
+Assuming you have a Berkeley DB 1.85 library available on your system,
+you can index the certificates/CRLs in a DB hash file, which provides
+the fastest lookup of any of the methods.
+
+The internal details of the DB file are maintained in a separate file
+(README.XMAP.DB -- to be written -- nd). To make a DB file, you should
+create a directory as in the above section, then run the utility
+command "dir2hash" as follows, assuming that the directory to be
+hashed is called "my_dir" and the output DB file should be called
+certs.db :-
+
+  ipsec dir2hash -o dbhash.db my_dir
+
+Note: You don't have to make the hashed, DNS or IP links as in the
+directory above (they are automatically figured out by the dir2hash
+program from the subjectNames and subjectAltNames of the
+certificates/CRLs). You DO have to index the uid entries manually,
+since the certificates don't necessarily have the means of
+indentifying which users they belong to.
+
+Note that IPsec knows nothing of uid's and doesn;t use them yet, so a
+perfectly valid IPsec DB file can be mafe by putting all the
+certificates into a directory without any links at all, then running
+dir2hash on the directory.
+
+However, this still creates a single file which must be copied to all
+hosts participating in the IPsec process. Therefore, this mechanism
+will not scale past a few, easily managed hosts. For scalability you
+should use LDAP.
+
+3.4 - LDAP searches
+
+Type Specifier: "ldap"
+Syntax: ldap:<LDAP config file>:<LDAP identifier>
+
+Assuming that you have at least one LDAP server available on your
+network, you can make a config file (which is NOT the same as
+ipsec.conf) to specify how to search for entries in one or more LDAP
+servers. A single ldap configuration file can hold search details for
+many ldap servers. Each server specification must be identified by a
+unique ldap ID. This ID can be any alphanumeric string. If the LDAP
+identifier is omitted, then the first specification in the file will
+be used by default.
+
+The entries in the configuration file can be of the following form:
+
+<ID>_host_name: <FQDN of the LDAP server host. Default: localhost>
+
+<ID>_port: <port number on the server. Default: 389>
+
+<ID>_base: <base search string for server. Default: NONE>
+
+<ID>_timeout: <timeout for searches, in seconds: Default: 10>
+
+<ID>_bindDN: <DN to bind to the LDAP server as: Default: "">
+
+<ID>_bindPW: <Password for the bind DN: Default: "">
+
+Note that you MUST supply a base search string: the software cannot
+guess a reasonable default. Also, the bind DN and password is the only
+supported authentication mechanism. PLEASE don't put the LDAP server
+on a host which needs to reached via IPsec. If you're relying on it to
+serve all certificates, the LDAP connection won't work (since the
+IPsec connection might not be up yet).
+
+For each search type, you must specify the filter string and
+attributes which should be searched for from the LDAP directory.
+
+The filter string specification has the form
+
+<ID>_filter:<search index>:<return type>: <LDAP search filter>
+
+where <search index> is either "uid", "subject", "issuer", "dns" or
+"ip" as above, and <return type> is either "cert" (for X.509
+certificates) or "crl" for CRL searches. Either the <search index> or
+<return type> can be set to "*", which is a wildcard, meaning any
+index or any return type.
+
+Similarly, the attribute specification looks like:
+
+<ID>_attributes:<search index>:<return type>: <list of attributes>
+
+The <search string> and <return type> are as above, with the list of
+attributes a comma separated list of attributes.
+
+For an example, let us use the following file
+
+ldapnd_host_name = ldap.hpl.hp.com
+ldapnd_base = o=Hewlett-Packard Laboratories, c=GB
+ldapnd_filter:uid = (uid=%s)
+
+ldapnd_attributes:*:crl = certificaterevocationlist, certificaterevocationlist;binary
+
+ldapnd_filter:*:crl = (&(objectclass=certificationAuthority)(cn=%s))
+
+ldapnd_filter:ca = (objectclass=certificationauthority)
+
+ldapnd_filter:dns = (&(objectclass=hostRecord)(dNSRecord=%s))
+ldapnd_attributes:dns = servercertificate, servercertificate;binary
+
+ldapnd_filter:ip = (&(objectclass=hostRecord)(ipv4Address=%s))   
+ldapnd_attributes:ip = servercertificate, servercertificate;binary
+
+This stipulates an anonymous bind search of the LDAP server on
+ldap.hpl.hp.com port 389 (the default), whose base for searches is
+"o=Hewlett-Packard Laboratories,c=GB".
+
+For DNS searches, the filter used will be
+
+"(&(objectClass=hostRecord)(dNSRecord=%s))"
+
+where "%s" will be replaced by the DNS name being searched for. In the
+case of a search for pinky.hpl.hp.com, the search string will be -
+
+"(&(objectClass=hostRecord)(dNSRecord=pinky.hpl.hp.com))"
+
+For IP address searches, the filter used will be
+
+"(&(objectclass=hostRecord)(ipv4Address=%s))"
+
+Again, searching for the host with IP address 15.144.59.30, the host
+search filter will be -
+
+"(&(objectclass=hostRecord)(ipv4Address=15.144.59.30))"
+
+In both DNS and IP searches, the search will return the attributes
+"serverCertificate" and "serverCertificate;binary".
+
+Note that the return type is missing from many of the
+specifications. Return types default to "cert".
diff -bruN freeswan-1.9.orig/doc/pkix/examples/arm-devel.key freeswan-1.9/doc/pkix/examples/arm-devel.key
--- freeswan-1.9.orig/doc/pkix/examples/arm-devel.key	Wed Dec 31 19:00:00 1969
+++ freeswan-1.9/doc/pkix/examples/arm-devel.key	Mon Jun  4 11:34:31 2001
@@ -0,0 +1,15 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIICXgIBAAKBgQCoqQwsIfybAtb0mMfD3NGNMZH7ckGrCehSm741ddjw9rW6igzZ
+AptaqQ2Y5raPl0XrF+MQI8SQkfTtzP92/ZU9eqbEWbBFRfYLqckMd21eU9GHDVl5
+UPmUwWSOXuE4lK58f2heEFE975yf9CsIvOuas33FsiuYtO5UEmzapAVAnQIDAQAB
+AoGAXUzWvPs4IBAcFUcHCyR2j6LiXLTB+voKGNirCivdDL+NnFmN7eZxRl/Kc9D9
+IMXQGdMm+uCudkMnuPz0PUDeczQST46jiTlG5vkQdj3zpmz/x73t5I4E8vFSX6A4
+gKREFeGxSCEm0THNusBKk1Q+huHUDKw4mFh85MTopy32McECQQDVWcc3BMlDICG2
+6bFc3+1ieeVIKoD2GnJR7b/GU57umLFyDmSFwOkTTt7VWp3jV/81Oy+xBe3cC8Fm
+mFC/e45VAkEAymA9ke8XFduafs2Q+nsbfx4QI+f8lAd51pBR4A4J+W50JLO1/WqC
+PwOXwVPRCPyzHiY9B8L9KPrFKSwVedihKQJBAKnGCl/+wAVZcVqztf649pbRdyGp
+KPwt6WDGtz+j1Sn6eeHQEC/bZd2Geo3+0PtTT/NVCMtuc2wSMrFobYEiWg0CQQCl
+lf9qw5049jlAHYTNXiNObFO6fVuN51wKcoV7dSE2JOkFCsISuq4dTxxBRApadyE7
+vv/atPGdMSpXGMntq5GZAkEA1PJ0w4WSC3sW3guq4WzDLWqmbK2pOvC40ATZR67y
+lYC1okanKDsRam0remPY7xWZ8WACJx5KOIvYgXhX+dNXPg==
+-----END RSA PRIVATE KEY-----
diff -bruN freeswan-1.9.orig/doc/pkix/examples/arm-devel.pem freeswan-1.9/doc/pkix/examples/arm-devel.pem
--- freeswan-1.9.orig/doc/pkix/examples/arm-devel.pem	Wed Dec 31 19:00:00 1969
+++ freeswan-1.9/doc/pkix/examples/arm-devel.pem	Mon Jun  4 11:34:31 2001
@@ -0,0 +1,79 @@
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number: 1 (0x1)
+        Signature Algorithm: md5WithRSAEncryption
+        Issuer: C=CA, ST=Ontario, L=Ottawa, O=Rebel.com, OU=SoftEng, CN=CA_arm-devel/Email=luc.lanthier@rebel.com
+        Validity
+            Not Before: Feb 14 20:59:13 2001 GMT
+            Not After : Feb 14 20:59:13 2002 GMT
+        Subject: C=CA, ST=Ontario, O=Rebel.com, OU=SoftEng, CN=arm-devel.netwinder.org/Email=luc.lanthier@rebel.com
+        Subject Public Key Info:
+            Public Key Algorithm: rsaEncryption
+            RSA Public Key: (1024 bit)
+                Modulus (1024 bit):
+                    00:a8:a9:0c:2c:21:fc:9b:02:d6:f4:98:c7:c3:dc:
+                    d1:8d:31:91:fb:72:41:ab:09:e8:52:9b:be:35:75:
+                    d8:f0:f6:b5:ba:8a:0c:d9:02:9b:5a:a9:0d:98:e6:
+                    b6:8f:97:45:eb:17:e3:10:23:c4:90:91:f4:ed:cc:
+                    ff:76:fd:95:3d:7a:a6:c4:59:b0:45:45:f6:0b:a9:
+                    c9:0c:77:6d:5e:53:d1:87:0d:59:79:50:f9:94:c1:
+                    64:8e:5e:e1:38:94:ae:7c:7f:68:5e:10:51:3d:ef:
+                    9c:9f:f4:2b:08:bc:eb:9a:b3:7d:c5:b2:2b:98:b4:
+                    ee:54:12:6c:da:a4:05:40:9d
+                Exponent: 65537 (0x10001)
+        X509v3 extensions:
+            X509v3 Basic Constraints: 
+                CA:FALSE
+            Netscape Cert Type: 
+                SSL Server
+            X509v3 Key Usage: 
+                Digital Signature, Non Repudiation, Key Encipherment
+            Netscape Comment: 
+                IPsec Certificate for arm-devel.netwinder.org
+            X509v3 Subject Key Identifier: 
+                98:76:ED:A5:41:7C:28:3C:C8:63:0F:09:F7:DE:9E:B2:00:B6:36:FE
+            X509v3 Authority Key Identifier: 
+                keyid:7A:38:75:E9:B9:94:AB:B6:00:C5:36:81:EA:A5:60:3E:FA:FE:E4:E1
+                DirName:/C=CA/ST=Ontario/L=Ottawa/O=Rebel.com/OU=SoftEng/CN=CA_arm-devel/Email=luc.lanthier@rebel.com
+                serial:00
+
+            X509v3 Subject Alternative Name: 
+                email:luc.lanthier@rebel.com, DNS:arm-devel.netwinder.org, IP Address:10.8.49.122
+            X509v3 Issuer Alternative Name: 
+                email:luc.lanthier@rebel.com
+    Signature Algorithm: md5WithRSAEncryption
+        bb:a9:1a:f4:e3:55:c8:f6:e7:d6:32:cb:a2:2f:6d:58:a3:5d:
+        8f:5a:0d:95:53:c7:bf:06:e7:3b:ca:99:48:99:2f:55:28:5a:
+        9e:37:ef:3b:44:73:1e:e0:61:93:43:f8:04:6b:06:1e:68:e5:
+        3e:a2:10:53:94:2f:66:76:fc:66:93:d4:5e:76:cf:2d:18:e2:
+        ff:eb:c0:77:c9:d5:4d:00:60:34:50:59:69:b9:7d:07:fb:ca:
+        8b:6e:ee:5c:d2:d9:06:2f:ee:df:d8:09:12:76:bc:b5:17:80:
+        a8:d6:a7:25:59:5c:b4:65:cb:29:b1:cd:77:29:e9:c4:03:00:
+        ea:c4
+-----BEGIN CERTIFICATE-----
+MIIEUTCCA7qgAwIBAgIBATANBgkqhkiG9w0BAQQFADCBlDELMAkGA1UEBhMCQ0Ex
+EDAOBgNVBAgTB09udGFyaW8xDzANBgNVBAcTBk90dGF3YTESMBAGA1UEChMJUmVi
+ZWwuY29tMRAwDgYDVQQLEwdTb2Z0RW5nMRUwEwYDVQQDFAxDQV9hcm0tZGV2ZWwx
+JTAjBgkqhkiG9w0BCQEWFmx1Yy5sYW50aGllckByZWJlbC5jb20wHhcNMDEwMjE0
+MjA1OTEzWhcNMDIwMjE0MjA1OTEzWjCBjjELMAkGA1UEBhMCQ0ExEDAOBgNVBAgT
+B09udGFyaW8xEjAQBgNVBAoTCVJlYmVsLmNvbTEQMA4GA1UECxMHU29mdEVuZzEg
+MB4GA1UEAxMXYXJtLWRldmVsLm5ldHdpbmRlci5vcmcxJTAjBgkqhkiG9w0BCQEW
+Fmx1Yy5sYW50aGllckByZWJlbC5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJ
+AoGBAKipDCwh/JsC1vSYx8Pc0Y0xkftyQasJ6FKbvjV12PD2tbqKDNkCm1qpDZjm
+to+XResX4xAjxJCR9O3M/3b9lT16psRZsEVF9gupyQx3bV5T0YcNWXlQ+ZTBZI5e
+4TiUrnx/aF4QUT3vnJ/0Kwi865qzfcWyK5i07lQSbNqkBUCdAgMBAAGjggG1MIIB
+sTAJBgNVHRMEAjAAMBEGCWCGSAGG+EIBAQQEAwIGQDALBgNVHQ8EBAMCBeAwPAYJ
+YIZIAYb4QgENBC8WLUlQc2VjIENlcnRpZmljYXRlIGZvciBhcm0tZGV2ZWwubmV0
+d2luZGVyLm9yZzAdBgNVHQ4EFgQUmHbtpUF8KDzIYw8J996esgC2Nv4wgcEGA1Ud
+IwSBuTCBtoAUejh16bmUq7YAxTaB6qVgPvr+5OGhgZqkgZcwgZQxCzAJBgNVBAYT
+AkNBMRAwDgYDVQQIEwdPbnRhcmlvMQ8wDQYDVQQHEwZPdHRhd2ExEjAQBgNVBAoT
+CVJlYmVsLmNvbTEQMA4GA1UECxMHU29mdEVuZzEVMBMGA1UEAxQMQ0FfYXJtLWRl
+dmVsMSUwIwYJKoZIhvcNAQkBFhZsdWMubGFudGhpZXJAcmViZWwuY29tggEAMEAG
+A1UdEQQ5MDeBFmx1Yy5sYW50aGllckByZWJlbC5jb22CF2FybS1kZXZlbC5uZXR3
+aW5kZXIub3JnhwQKCDF6MCEGA1UdEgQaMBiBFmx1Yy5sYW50aGllckByZWJlbC5j
+b20wDQYJKoZIhvcNAQEEBQADgYEAu6ka9ONVyPbn1jLLoi9tWKNdj1oNlVPHvwbn
+O8qZSJkvVShanjfvO0RzHuBhk0P4BGsGHmjlPqIQU5QvZnb8ZpPUXnbPLRji/+vA
+d8nVTQBgNFBZabl9B/vKi27uXNLZBi/u39gJEna8tReAqNanJVlctGXLKbHNdynp
+xAMA6sQ=
+-----END CERTIFICATE-----
diff -bruN freeswan-1.9.orig/doc/pkix/examples/arm-devel.req.pem freeswan-1.9/doc/pkix/examples/arm-devel.req.pem
--- freeswan-1.9.orig/doc/pkix/examples/arm-devel.req.pem	Wed Dec 31 19:00:00 1969
+++ freeswan-1.9/doc/pkix/examples/arm-devel.req.pem	Mon Jun  4 11:34:31 2001
@@ -0,0 +1,13 @@
+-----BEGIN CERTIFICATE REQUEST-----
+MIIB4DCCAUkCAQAwgZ8xCzAJBgNVBAYTAkNBMRAwDgYDVQQIEwdPbnRhcmlvMQ8w
+DQYDVQQHEwZPdHRhd2ExEjAQBgNVBAoTCVJlYmVsLmNvbTEQMA4GA1UECxMHU29m
+dEVuZzEgMB4GA1UEAxMXYXJtLWRldmVsLm5ldHdpbmRlci5vcmcxJTAjBgkqhkiG
+9w0BCQEWFmx1Yy5sYW50aGllckByZWJlbC5jb20wgZ8wDQYJKoZIhvcNAQEBBQAD
+gY0AMIGJAoGBAKipDCwh/JsC1vSYx8Pc0Y0xkftyQasJ6FKbvjV12PD2tbqKDNkC
+m1qpDZjmto+XResX4xAjxJCR9O3M/3b9lT16psRZsEVF9gupyQx3bV5T0YcNWXlQ
++ZTBZI5e4TiUrnx/aF4QUT3vnJ/0Kwi865qzfcWyK5i07lQSbNqkBUCdAgMBAAGg
+ADANBgkqhkiG9w0BAQQFAAOBgQCNEgKfb3Qwtk7rgHcLiUCcXA4w4XFyHxRA8GEO
+N/sJVOFq6mV2wVHEmhYalMQTXs3KXNucppQ3ZtHhiLCxzuHSe1Cs6q3iBXPaOPsY
+L6I2gJ/wQ49E11HYtMSzDjcAbxV3zWWd42Xk8mNNrhT2r1h+g30DQEgFjXkXhbpt
+1R+0uA==
+-----END CERTIFICATE REQUEST-----
diff -bruN freeswan-1.9.orig/doc/pkix/examples/db-pk-rw.conf freeswan-1.9/doc/pkix/examples/db-pk-rw.conf
--- freeswan-1.9.orig/doc/pkix/examples/db-pk-rw.conf	Wed Dec 31 19:00:00 1969
+++ freeswan-1.9/doc/pkix/examples/db-pk-rw.conf	Mon Jun  4 11:34:31 2001
@@ -0,0 +1,16 @@
+conn test
+	left=0.0.0.0
+	leftupdown=/usr/lib/ipsec/updown.netwinder
+	right=10.8.49.122
+	rightnexthop=10.8.54.1
+	rightupdown=/usr/lib/ipsec/updown.netwinder
+	authby=cert
+	auto=add
+	certfile=/etc/ipsec/pubcert.pem
+	keyfile=/etc/ipsec/privkey.pem
+	certpath=db:/etc/ipsec/dir_dbhash.db
+	certopts=send,strict,pk
+	#right DN: /C=CA/ST=Ontario/O=Rebel.com/OU=SoftEng/CN=arm-devel.netwinder.org/Email=luc.lanthier@rebel.com
+	rightid=@~30818E310B30090603550406130243413110300E060355040813074F6E746172696F31123010060355040A1309526562656C2E636F6D3110300E060355040B1307536F6674456E673120301E0603550403131761726D2D646576656C2E6E657477696E6465722E6F72673125302306092A864886F70D01090116166C75632E6C616E746869657240726562656C2E636F6D
+	#left DN: /C=CA/ST=Ontario/O=Rebel.com/OU=SoftEng/CN=arm1.netwinder.org/Email=firesoul@netwinder.org
+	leftid=@~308189310B30090603550406130243413110300E060355040813074F6E746172696F31123010060355040A1309526562656C2E636F6D3110300E060355040B1307536F6674456E67311B30190603550403131261726D312E6E657477696E6465722E6F72673125302306092A864886F70D010901161666697265736F756C406E657477696E6465722E6F7267
diff -bruN freeswan-1.9.orig/doc/pkix/examples/db-pk.conf freeswan-1.9/doc/pkix/examples/db-pk.conf
--- freeswan-1.9.orig/doc/pkix/examples/db-pk.conf	Wed Dec 31 19:00:00 1969
+++ freeswan-1.9/doc/pkix/examples/db-pk.conf	Mon Jun  4 11:34:31 2001
@@ -0,0 +1,17 @@
+conn test
+	left=10.1.49.124
+	leftnexthop=10.1.1.7
+	leftupdown=/usr/lib/ipsec/updown.netwinder
+	right=10.8.49.122
+	rightnexthop=10.8.54.1
+	rightupdown=/usr/lib/ipsec/updown.netwinder
+	authby=cert
+	auto=add
+	certfile=/etc/ipsec/pubcert.pem
+	keyfile=/etc/ipsec/privkey.pem
+	certpath=db:/etc/ipsec/dir_dbhash.db
+	certopts=send,strict,pk
+	#right DN: /C=CA/ST=Ontario/O=Rebel.com/OU=SoftEng/CN=arm-devel.netwinder.org/Email=luc.lanthier@rebel.com
+	rightid=@~30818E310B30090603550406130243413110300E060355040813074F6E746172696F31123010060355040A1309526562656C2E636F6D3110300E060355040B1307536F6674456E673120301E0603550403131761726D2D646576656C2E6E657477696E6465722E6F72673125302306092A864886F70D01090116166C75632E6C616E746869657240726562656C2E636F6D
+	#left DN: /C=CA/ST=Ontario/O=Rebel.com/OU=SoftEng/CN=arm1.netwinder.org/Email=firesoul@netwinder.org
+	leftid=@~308189310B30090603550406130243413110300E060355040813074F6E746172696F31123010060355040A1309526562656C2E636F6D3110300E060355040B1307536F6674456E67311B30190603550403131261726D312E6E657477696E6465722E6F72673125302306092A864886F70D010901161666697265736F756C406E657477696E6465722E6F7267
diff -bruN freeswan-1.9.orig/doc/pkix/examples/db-rpk-rw.conf freeswan-1.9/doc/pkix/examples/db-rpk-rw.conf
--- freeswan-1.9.orig/doc/pkix/examples/db-rpk-rw.conf	Wed Dec 31 19:00:00 1969
+++ freeswan-1.9/doc/pkix/examples/db-rpk-rw.conf	Mon Jun  4 11:34:31 2001
@@ -0,0 +1,16 @@
+conn test
+	left=0.0.0.0
+	leftupdown=/usr/lib/ipsec/updown.netwinder
+	right=10.8.49.122
+	rightnexthop=10.8.54.1
+	rightupdown=/usr/lib/ipsec/updown.netwinder
+	authby=cert
+	auto=add
+	certfile=/etc/ipsec/pubcert.pem
+	keyfile=/etc/ipsec/privkey.pem
+	certpath=db:/etc/ipsec/dir_dbhash.db
+	certopts=send,strict,pk,rev
+	#right DN: /C=CA/ST=Ontario/O=Rebel.com/OU=SoftEng/CN=arm-devel.netwinder.org/Email=luc.lanthier@rebel.com
+	rightid=@~30818E310B30090603550406130243413110300E060355040813074F6E746172696F31123010060355040A1309526562656C2E636F6D3110300E060355040B1307536F6674456E673120301E0603550403131761726D2D646576656C2E6E657477696E6465722E6F72673125302306092A864886F70D01090116166C75632E6C616E746869657240726562656C2E636F6D
+	#left DN: /C=CA/ST=Ontario/O=Rebel.com/OU=SoftEng/CN=arm1.netwinder.org/Email=firesoul@netwinder.org
+	leftid=@~308189310B30090603550406130243413110300E060355040813074F6E746172696F31123010060355040A1309526562656C2E636F6D3110300E060355040B1307536F6674456E67311B30190603550403131261726D312E6E657477696E6465722E6F72673125302306092A864886F70D010901161666697265736F756C406E657477696E6465722E6F7267
diff -bruN freeswan-1.9.orig/doc/pkix/examples/db-rpk.conf freeswan-1.9/doc/pkix/examples/db-rpk.conf
--- freeswan-1.9.orig/doc/pkix/examples/db-rpk.conf	Wed Dec 31 19:00:00 1969
+++ freeswan-1.9/doc/pkix/examples/db-rpk.conf	Mon Jun  4 11:34:31 2001
@@ -0,0 +1,17 @@
+conn test
+	left=10.1.49.124
+	leftnexthop=10.1.1.7
+	leftupdown=/usr/lib/ipsec/updown.netwinder
+	right=10.8.49.122
+	rightnexthop=10.8.54.1
+	rightupdown=/usr/lib/ipsec/updown.netwinder
+	authby=cert
+	auto=add
+	certfile=/etc/ipsec/pubcert.pem
+	keyfile=/etc/ipsec/privkey.pem
+	certpath=db:/etc/ipsec/dir_dbhash.db
+	certopts=send,strict,pk,rev
+	#right DN: /C=CA/ST=Ontario/O=Rebel.com/OU=SoftEng/CN=arm-devel.netwinder.org/Email=luc.lanthier@rebel.com
+	rightid=@~30818E310B30090603550406130243413110300E060355040813074F6E746172696F31123010060355040A1309526562656C2E636F6D3110300E060355040B1307536F6674456E673120301E0603550403131761726D2D646576656C2E6E657477696E6465722E6F72673125302306092A864886F70D01090116166C75632E6C616E746869657240726562656C2E636F6D
+	#left DN: /C=CA/ST=Ontario/O=Rebel.com/OU=SoftEng/CN=arm1.netwinder.org/Email=firesoul@netwinder.org
+	leftid=@~308189310B30090603550406130243413110300E060355040813074F6E746172696F31123010060355040A1309526562656C2E636F6D3110300E060355040B1307536F6674456E67311B30190603550403131261726D312E6E657477696E6465722E6F72673125302306092A864886F70D010901161666697265736F756C406E657477696E6465722E6F7267
diff -bruN freeswan-1.9.orig/doc/pkix/examples/db-rsasig-rw.conf freeswan-1.9/doc/pkix/examples/db-rsasig-rw.conf
--- freeswan-1.9.orig/doc/pkix/examples/db-rsasig-rw.conf	Wed Dec 31 19:00:00 1969
+++ freeswan-1.9/doc/pkix/examples/db-rsasig-rw.conf	Mon Jun  4 11:34:31 2001
@@ -0,0 +1,16 @@
+conn test
+	left=0.0.0.0
+	leftupdown=/usr/lib/ipsec/updown.netwinder
+	right=10.8.49.122
+	rightnexthop=10.8.54.1
+	rightupdown=/usr/lib/ipsec/updown.netwinder
+	authby=cert
+	auto=add
+	certfile=/etc/ipsec/pubcert.pem
+	keyfile=/etc/ipsec/privkey.pem
+	certpath=db:/etc/ipsec/dir_dbhash.db
+	certopts=send
+	#right DN: /C=CA/ST=Ontario/O=Rebel.com/OU=SoftEng/CN=arm-devel.netwinder.org/Email=luc.lanthier@rebel.com
+	rightid=@~30818E310B30090603550406130243413110300E060355040813074F6E746172696F31123010060355040A1309526562656C2E636F6D3110300E060355040B1307536F6674456E673120301E0603550403131761726D2D646576656C2E6E657477696E6465722E6F72673125302306092A864886F70D01090116166C75632E6C616E746869657240726562656C2E636F6D
+	#left DN: /C=CA/ST=Ontario/O=Rebel.com/OU=SoftEng/CN=arm1.netwinder.org/Email=firesoul@netwinder.org
+	leftid=@~308189310B30090603550406130243413110300E060355040813074F6E746172696F31123010060355040A1309526562656C2E636F6D3110300E060355040B1307536F6674456E67311B30190603550403131261726D312E6E657477696E6465722E6F72673125302306092A864886F70D010901161666697265736F756C406E657477696E6465722E6F7267
diff -bruN freeswan-1.9.orig/doc/pkix/examples/db-rsasig.conf freeswan-1.9/doc/pkix/examples/db-rsasig.conf
--- freeswan-1.9.orig/doc/pkix/examples/db-rsasig.conf	Wed Dec 31 19:00:00 1969
+++ freeswan-1.9/doc/pkix/examples/db-rsasig.conf	Mon Jun  4 11:34:31 2001
@@ -0,0 +1,17 @@
+conn test
+	left=10.1.49.124
+	leftnexthop=10.1.1.7
+	leftupdown=/usr/lib/ipsec/updown.netwinder
+	right=10.8.49.122
+	rightnexthop=10.8.54.1
+	rightupdown=/usr/lib/ipsec/updown.netwinder
+	authby=cert
+	auto=add
+	certfile=/etc/ipsec/pubcert.pem
+	keyfile=/etc/ipsec/privkey.pem
+	certpath=db:/etc/ipsec/dir_dbhash.db
+	certopts=send
+	#right DN: /C=CA/ST=Ontario/O=Rebel.com/OU=SoftEng/CN=arm-devel.netwinder.org/Email=luc.lanthier@rebel.com
+	rightid=@~30818E310B30090603550406130243413110300E060355040813074F6E746172696F31123010060355040A1309526562656C2E636F6D3110300E060355040B1307536F6674456E673120301E0603550403131761726D2D646576656C2E6E657477696E6465722E6F72673125302306092A864886F70D01090116166C75632E6C616E746869657240726562656C2E636F6D
+	#left DN: /C=CA/ST=Ontario/O=Rebel.com/OU=SoftEng/CN=arm1.netwinder.org/Email=firesoul@netwinder.org
+	leftid=@~308189310B30090603550406130243413110300E060355040813074F6E746172696F31123010060355040A1309526562656C2E636F6D3110300E060355040B1307536F6674456E67311B30190603550403131261726D312E6E657477696E6465722E6F72673125302306092A864886F70D010901161666697265736F756C406E657477696E6465722E6F7267
diff -bruN freeswan-1.9.orig/doc/pkix/examples/dir/60601ae4.cert.0 freeswan-1.9/doc/pkix/examples/dir/60601ae4.cert.0
--- freeswan-1.9.orig/doc/pkix/examples/dir/60601ae4.cert.0	Wed Dec 31 19:00:00 1969
+++ freeswan-1.9/doc/pkix/examples/dir/60601ae4.cert.0	Mon Jun  4 11:34:31 2001
@@ -0,0 +1,78 @@
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number: 2 (0x2)
+        Signature Algorithm: md5WithRSAEncryption
+        Issuer: C=CA, ST=Ontario, L=Ottawa, O=Rebel.com, OU=SoftEng, CN=CA_arm-devel/Email=luc.lanthier@rebel.com
+        Validity
+            Not Before: Feb 14 21:00:11 2001 GMT
+            Not After : Feb 14 21:00:11 2002 GMT
+        Subject: C=CA, ST=Ontario, O=Rebel.com, OU=SoftEng, CN=arm1.netwinder.org/Email=firesoul@netwinder.org
+        Subject Public Key Info:
+            Public Key Algorithm: rsaEncryption
+            RSA Public Key: (1024 bit)
+                Modulus (1024 bit):
+                    00:e2:2b:ad:70:6b:29:e7:83:be:af:12:50:4b:a4:
+                    26:02:60:ed:f9:bd:49:51:86:96:18:9c:10:f1:0c:
+                    7d:bd:b9:22:8e:66:6a:f4:96:e5:8d:e2:c4:11:1e:
+                    64:8e:59:1e:b1:a2:64:15:fa:a6:17:9a:59:f3:9f:
+                    9f:c8:c9:17:b8:a7:87:55:70:8f:de:25:78:e6:e0:
+                    4c:82:ae:f1:47:14:77:fa:5b:3e:4d:e5:05:5e:31:
+                    09:62:56:f8:3b:94:51:b2:e3:7e:bb:8f:6e:dc:ea:
+                    64:2e:2f:65:8e:41:18:0e:cf:9d:8a:b8:0a:86:6c:
+                    6a:88:be:58:ce:be:b3:32:c1
+                Exponent: 65537 (0x10001)
+        X509v3 extensions:
+            X509v3 Basic Constraints: 
+                CA:FALSE
+            Netscape Cert Type: 
+                SSL Server
+            X509v3 Key Usage: 
+                Digital Signature, Non Repudiation, Key Encipherment
+            Netscape Comment: 
+                IPsec Certificate for arm1.netwinder.org
+            X509v3 Subject Key Identifier: 
+                82:A2:6E:58:0D:B6:98:EF:D9:A0:68:9D:D0:C0:70:59:B3:6A:32:99
+            X509v3 Authority Key Identifier: 
+                keyid:7A:38:75:E9:B9:94:AB:B6:00:C5:36:81:EA:A5:60:3E:FA:FE:E4:E1
+                DirName:/C=CA/ST=Ontario/L=Ottawa/O=Rebel.com/OU=SoftEng/CN=CA_arm-devel/Email=luc.lanthier@rebel.com
+                serial:00
+
+            X509v3 Subject Alternative Name: 
+                email:firesoul@netwinder.org, DNS:arm1.netwinder.org, IP Address:10.1.49.124
+            X509v3 Issuer Alternative Name: 
+                email:luc.lanthier@rebel.com
+    Signature Algorithm: md5WithRSAEncryption
+        c3:68:19:5f:60:12:18:6f:48:87:f9:97:d2:a3:0f:bc:e4:d0:
+        59:37:69:17:28:32:55:7d:5c:7a:35:ff:e1:67:05:f5:31:80:
+        27:cc:3a:37:28:47:46:ec:d9:b0:f9:69:ac:ce:6d:89:94:19:
+        16:38:64:bb:da:67:68:c5:e3:26:e3:66:98:b2:45:bf:0d:16:
+        2b:95:0c:1a:cc:65:8c:c5:f4:ba:2f:2b:5a:f4:ad:9a:71:92:
+        de:e5:77:c4:08:96:7c:c3:25:25:fe:43:b0:f3:f9:65:1f:fa:
+        6c:2d:2e:e2:1f:18:75:03:51:33:94:61:29:59:1a:9c:7c:71:
+        42:e1
+-----BEGIN CERTIFICATE-----
+MIIEQjCCA6ugAwIBAgIBAjANBgkqhkiG9w0BAQQFADCBlDELMAkGA1UEBhMCQ0Ex
+EDAOBgNVBAgTB09udGFyaW8xDzANBgNVBAcTBk90dGF3YTESMBAGA1UEChMJUmVi
+ZWwuY29tMRAwDgYDVQQLEwdTb2Z0RW5nMRUwEwYDVQQDFAxDQV9hcm0tZGV2ZWwx
+JTAjBgkqhkiG9w0BCQEWFmx1Yy5sYW50aGllckByZWJlbC5jb20wHhcNMDEwMjE0
+MjEwMDExWhcNMDIwMjE0MjEwMDExWjCBiTELMAkGA1UEBhMCQ0ExEDAOBgNVBAgT
+B09udGFyaW8xEjAQBgNVBAoTCVJlYmVsLmNvbTEQMA4GA1UECxMHU29mdEVuZzEb
+MBkGA1UEAxMSYXJtMS5uZXR3aW5kZXIub3JnMSUwIwYJKoZIhvcNAQkBFhZmaXJl
+c291bEBuZXR3aW5kZXIub3JnMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDi
+K61waynng76vElBLpCYCYO35vUlRhpYYnBDxDH29uSKOZmr0luWN4sQRHmSOWR6x
+omQV+qYXmlnzn5/IyRe4p4dVcI/eJXjm4EyCrvFHFHf6Wz5N5QVeMQliVvg7lFGy
+4367j27c6mQuL2WOQRgOz52KuAqGbGqIvljOvrMywQIDAQABo4IBqzCCAacwCQYD
+VR0TBAIwADARBglghkgBhvhCAQEEBAMCBkAwCwYDVR0PBAQDAgXgMDcGCWCGSAGG
++EIBDQQqFihJUHNlYyBDZXJ0aWZpY2F0ZSBmb3IgYXJtMS5uZXR3aW5kZXIub3Jn
+MB0GA1UdDgQWBBSCom5YDbaY79mgaJ3QwHBZs2oymTCBwQYDVR0jBIG5MIG2gBR6
+OHXpuZSrtgDFNoHqpWA++v7k4aGBmqSBlzCBlDELMAkGA1UEBhMCQ0ExEDAOBgNV
+BAgTB09udGFyaW8xDzANBgNVBAcTBk90dGF3YTESMBAGA1UEChMJUmViZWwuY29t
+MRAwDgYDVQQLEwdTb2Z0RW5nMRUwEwYDVQQDFAxDQV9hcm0tZGV2ZWwxJTAjBgkq
+hkiG9w0BCQEWFmx1Yy5sYW50aGllckByZWJlbC5jb22CAQAwOwYDVR0RBDQwMoEW
+ZmlyZXNvdWxAbmV0d2luZGVyLm9yZ4ISYXJtMS5uZXR3aW5kZXIub3JnhwQKATF8
+MCEGA1UdEgQaMBiBFmx1Yy5sYW50aGllckByZWJlbC5jb20wDQYJKoZIhvcNAQEE
+BQADgYEAw2gZX2ASGG9Ih/mX0qMPvOTQWTdpFygyVX1cejX/4WcF9TGAJ8w6NyhH
+RuzZsPlprM5tiZQZFjhku9pnaMXjJuNmmLJFvw0WK5UMGsxljMX0ui8rWvStmnGS
+3uV3xAiWfMMlJf5DsPP5ZR/6bC0u4h8YdQNRM5RhKVkanHxxQuE=
+-----END CERTIFICATE-----
diff -bruN freeswan-1.9.orig/doc/pkix/examples/dir/arm-devel.pem freeswan-1.9/doc/pkix/examples/dir/arm-devel.pem
--- freeswan-1.9.orig/doc/pkix/examples/dir/arm-devel.pem	Wed Dec 31 19:00:00 1969
+++ freeswan-1.9/doc/pkix/examples/dir/arm-devel.pem	Mon Jun  4 11:34:31 2001
@@ -0,0 +1,79 @@
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number: 1 (0x1)
+        Signature Algorithm: md5WithRSAEncryption
+        Issuer: C=CA, ST=Ontario, L=Ottawa, O=Rebel.com, OU=SoftEng, CN=CA_arm-devel/Email=luc.lanthier@rebel.com
+        Validity
+            Not Before: Feb 14 20:59:13 2001 GMT
+            Not After : Feb 14 20:59:13 2002 GMT
+        Subject: C=CA, ST=Ontario, O=Rebel.com, OU=SoftEng, CN=arm-devel.netwinder.org/Email=luc.lanthier@rebel.com
+        Subject Public Key Info:
+            Public Key Algorithm: rsaEncryption
+            RSA Public Key: (1024 bit)
+                Modulus (1024 bit):
+                    00:a8:a9:0c:2c:21:fc:9b:02:d6:f4:98:c7:c3:dc:
+                    d1:8d:31:91:fb:72:41:ab:09:e8:52:9b:be:35:75:
+                    d8:f0:f6:b5:ba:8a:0c:d9:02:9b:5a:a9:0d:98:e6:
+                    b6:8f:97:45:eb:17:e3:10:23:c4:90:91:f4:ed:cc:
+                    ff:76:fd:95:3d:7a:a6:c4:59:b0:45:45:f6:0b:a9:
+                    c9:0c:77:6d:5e:53:d1:87:0d:59:79:50:f9:94:c1:
+                    64:8e:5e:e1:38:94:ae:7c:7f:68:5e:10:51:3d:ef:
+                    9c:9f:f4:2b:08:bc:eb:9a:b3:7d:c5:b2:2b:98:b4:
+                    ee:54:12:6c:da:a4:05:40:9d
+                Exponent: 65537 (0x10001)
+        X509v3 extensions:
+            X509v3 Basic Constraints: 
+                CA:FALSE
+            Netscape Cert Type: 
+                SSL Server
+            X509v3 Key Usage: 
+                Digital Signature, Non Repudiation, Key Encipherment
+            Netscape Comment: 
+                IPsec Certificate for arm-devel.netwinder.org
+            X509v3 Subject Key Identifier: 
+                98:76:ED:A5:41:7C:28:3C:C8:63:0F:09:F7:DE:9E:B2:00:B6:36:FE
+            X509v3 Authority Key Identifier: 
+                keyid:7A:38:75:E9:B9:94:AB:B6:00:C5:36:81:EA:A5:60:3E:FA:FE:E4:E1
+                DirName:/C=CA/ST=Ontario/L=Ottawa/O=Rebel.com/OU=SoftEng/CN=CA_arm-devel/Email=luc.lanthier@rebel.com
+                serial:00
+
+            X509v3 Subject Alternative Name: 
+                email:luc.lanthier@rebel.com, DNS:arm-devel.netwinder.org, IP Address:10.8.49.122
+            X509v3 Issuer Alternative Name: 
+                email:luc.lanthier@rebel.com
+    Signature Algorithm: md5WithRSAEncryption
+        bb:a9:1a:f4:e3:55:c8:f6:e7:d6:32:cb:a2:2f:6d:58:a3:5d:
+        8f:5a:0d:95:53:c7:bf:06:e7:3b:ca:99:48:99:2f:55:28:5a:
+        9e:37:ef:3b:44:73:1e:e0:61:93:43:f8:04:6b:06:1e:68:e5:
+        3e:a2:10:53:94:2f:66:76:fc:66:93:d4:5e:76:cf:2d:18:e2:
+        ff:eb:c0:77:c9:d5:4d:00:60:34:50:59:69:b9:7d:07:fb:ca:
+        8b:6e:ee:5c:d2:d9:06:2f:ee:df:d8:09:12:76:bc:b5:17:80:
+        a8:d6:a7:25:59:5c:b4:65:cb:29:b1:cd:77:29:e9:c4:03:00:
+        ea:c4
+-----BEGIN CERTIFICATE-----
+MIIEUTCCA7qgAwIBAgIBATANBgkqhkiG9w0BAQQFADCBlDELMAkGA1UEBhMCQ0Ex
+EDAOBgNVBAgTB09udGFyaW8xDzANBgNVBAcTBk90dGF3YTESMBAGA1UEChMJUmVi
+ZWwuY29tMRAwDgYDVQQLEwdTb2Z0RW5nMRUwEwYDVQQDFAxDQV9hcm0tZGV2ZWwx
+JTAjBgkqhkiG9w0BCQEWFmx1Yy5sYW50aGllckByZWJlbC5jb20wHhcNMDEwMjE0
+MjA1OTEzWhcNMDIwMjE0MjA1OTEzWjCBjjELMAkGA1UEBhMCQ0ExEDAOBgNVBAgT
+B09udGFyaW8xEjAQBgNVBAoTCVJlYmVsLmNvbTEQMA4GA1UECxMHU29mdEVuZzEg
+MB4GA1UEAxMXYXJtLWRldmVsLm5ldHdpbmRlci5vcmcxJTAjBgkqhkiG9w0BCQEW
+Fmx1Yy5sYW50aGllckByZWJlbC5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJ
+AoGBAKipDCwh/JsC1vSYx8Pc0Y0xkftyQasJ6FKbvjV12PD2tbqKDNkCm1qpDZjm
+to+XResX4xAjxJCR9O3M/3b9lT16psRZsEVF9gupyQx3bV5T0YcNWXlQ+ZTBZI5e
+4TiUrnx/aF4QUT3vnJ/0Kwi865qzfcWyK5i07lQSbNqkBUCdAgMBAAGjggG1MIIB
+sTAJBgNVHRMEAjAAMBEGCWCGSAGG+EIBAQQEAwIGQDALBgNVHQ8EBAMCBeAwPAYJ
+YIZIAYb4QgENBC8WLUlQc2VjIENlcnRpZmljYXRlIGZvciBhcm0tZGV2ZWwubmV0
+d2luZGVyLm9yZzAdBgNVHQ4EFgQUmHbtpUF8KDzIYw8J996esgC2Nv4wgcEGA1Ud
+IwSBuTCBtoAUejh16bmUq7YAxTaB6qVgPvr+5OGhgZqkgZcwgZQxCzAJBgNVBAYT
+AkNBMRAwDgYDVQQIEwdPbnRhcmlvMQ8wDQYDVQQHEwZPdHRhd2ExEjAQBgNVBAoT
+CVJlYmVsLmNvbTEQMA4GA1UECxMHU29mdEVuZzEVMBMGA1UEAxQMQ0FfYXJtLWRl
+dmVsMSUwIwYJKoZIhvcNAQkBFhZsdWMubGFudGhpZXJAcmViZWwuY29tggEAMEAG
+A1UdEQQ5MDeBFmx1Yy5sYW50aGllckByZWJlbC5jb22CF2FybS1kZXZlbC5uZXR3
+aW5kZXIub3JnhwQKCDF6MCEGA1UdEgQaMBiBFmx1Yy5sYW50aGllckByZWJlbC5j
+b20wDQYJKoZIhvcNAQEEBQADgYEAu6ka9ONVyPbn1jLLoi9tWKNdj1oNlVPHvwbn
+O8qZSJkvVShanjfvO0RzHuBhk0P4BGsGHmjlPqIQU5QvZnb8ZpPUXnbPLRji/+vA
+d8nVTQBgNFBZabl9B/vKi27uXNLZBi/u39gJEna8tReAqNanJVlctGXLKbHNdynp
+xAMA6sQ=
+-----END CERTIFICATE-----
diff -bruN freeswan-1.9.orig/doc/pkix/examples/dir/arm1.pem freeswan-1.9/doc/pkix/examples/dir/arm1.pem
--- freeswan-1.9.orig/doc/pkix/examples/dir/arm1.pem	Wed Dec 31 19:00:00 1969
+++ freeswan-1.9/doc/pkix/examples/dir/arm1.pem	Mon Jun  4 11:34:31 2001
@@ -0,0 +1,78 @@
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number: 2 (0x2)
+        Signature Algorithm: md5WithRSAEncryption
+        Issuer: C=CA, ST=Ontario, L=Ottawa, O=Rebel.com, OU=SoftEng, CN=CA_arm-devel/Email=luc.lanthier@rebel.com
+        Validity
+            Not Before: Feb 14 21:00:11 2001 GMT
+            Not After : Feb 14 21:00:11 2002 GMT
+        Subject: C=CA, ST=Ontario, O=Rebel.com, OU=SoftEng, CN=arm1.netwinder.org/Email=firesoul@netwinder.org
+        Subject Public Key Info:
+            Public Key Algorithm: rsaEncryption
+            RSA Public Key: (1024 bit)
+                Modulus (1024 bit):
+                    00:e2:2b:ad:70:6b:29:e7:83:be:af:12:50:4b:a4:
+                    26:02:60:ed:f9:bd:49:51:86:96:18:9c:10:f1:0c:
+                    7d:bd:b9:22:8e:66:6a:f4:96:e5:8d:e2:c4:11:1e:
+                    64:8e:59:1e:b1:a2:64:15:fa:a6:17:9a:59:f3:9f:
+                    9f:c8:c9:17:b8:a7:87:55:70:8f:de:25:78:e6:e0:
+                    4c:82:ae:f1:47:14:77:fa:5b:3e:4d:e5:05:5e:31:
+                    09:62:56:f8:3b:94:51:b2:e3:7e:bb:8f:6e:dc:ea:
+                    64:2e:2f:65:8e:41:18:0e:cf:9d:8a:b8:0a:86:6c:
+                    6a:88:be:58:ce:be:b3:32:c1
+                Exponent: 65537 (0x10001)
+        X509v3 extensions:
+            X509v3 Basic Constraints: 
+                CA:FALSE
+            Netscape Cert Type: 
+                SSL Server
+            X509v3 Key Usage: 
+                Digital Signature, Non Repudiation, Key Encipherment
+            Netscape Comment: 
+                IPsec Certificate for arm1.netwinder.org
+            X509v3 Subject Key Identifier: 
+                82:A2:6E:58:0D:B6:98:EF:D9:A0:68:9D:D0:C0:70:59:B3:6A:32:99
+            X509v3 Authority Key Identifier: 
+                keyid:7A:38:75:E9:B9:94:AB:B6:00:C5:36:81:EA:A5:60:3E:FA:FE:E4:E1
+                DirName:/C=CA/ST=Ontario/L=Ottawa/O=Rebel.com/OU=SoftEng/CN=CA_arm-devel/Email=luc.lanthier@rebel.com
+                serial:00
+
+            X509v3 Subject Alternative Name: 
+                email:firesoul@netwinder.org, DNS:arm1.netwinder.org, IP Address:10.1.49.124
+            X509v3 Issuer Alternative Name: 
+                email:luc.lanthier@rebel.com
+    Signature Algorithm: md5WithRSAEncryption
+        c3:68:19:5f:60:12:18:6f:48:87:f9:97:d2:a3:0f:bc:e4:d0:
+        59:37:69:17:28:32:55:7d:5c:7a:35:ff:e1:67:05:f5:31:80:
+        27:cc:3a:37:28:47:46:ec:d9:b0:f9:69:ac:ce:6d:89:94:19:
+        16:38:64:bb:da:67:68:c5:e3:26:e3:66:98:b2:45:bf:0d:16:
+        2b:95:0c:1a:cc:65:8c:c5:f4:ba:2f:2b:5a:f4:ad:9a:71:92:
+        de:e5:77:c4:08:96:7c:c3:25:25:fe:43:b0:f3:f9:65:1f:fa:
+        6c:2d:2e:e2:1f:18:75:03:51:33:94:61:29:59:1a:9c:7c:71:
+        42:e1
+-----BEGIN CERTIFICATE-----
+MIIEQjCCA6ugAwIBAgIBAjANBgkqhkiG9w0BAQQFADCBlDELMAkGA1UEBhMCQ0Ex
+EDAOBgNVBAgTB09udGFyaW8xDzANBgNVBAcTBk90dGF3YTESMBAGA1UEChMJUmVi
+ZWwuY29tMRAwDgYDVQQLEwdTb2Z0RW5nMRUwEwYDVQQDFAxDQV9hcm0tZGV2ZWwx
+JTAjBgkqhkiG9w0BCQEWFmx1Yy5sYW50aGllckByZWJlbC5jb20wHhcNMDEwMjE0
+MjEwMDExWhcNMDIwMjE0MjEwMDExWjCBiTELMAkGA1UEBhMCQ0ExEDAOBgNVBAgT
+B09udGFyaW8xEjAQBgNVBAoTCVJlYmVsLmNvbTEQMA4GA1UECxMHU29mdEVuZzEb
+MBkGA1UEAxMSYXJtMS5uZXR3aW5kZXIub3JnMSUwIwYJKoZIhvcNAQkBFhZmaXJl
+c291bEBuZXR3aW5kZXIub3JnMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDi
+K61waynng76vElBLpCYCYO35vUlRhpYYnBDxDH29uSKOZmr0luWN4sQRHmSOWR6x
+omQV+qYXmlnzn5/IyRe4p4dVcI/eJXjm4EyCrvFHFHf6Wz5N5QVeMQliVvg7lFGy
+4367j27c6mQuL2WOQRgOz52KuAqGbGqIvljOvrMywQIDAQABo4IBqzCCAacwCQYD
+VR0TBAIwADARBglghkgBhvhCAQEEBAMCBkAwCwYDVR0PBAQDAgXgMDcGCWCGSAGG
++EIBDQQqFihJUHNlYyBDZXJ0aWZpY2F0ZSBmb3IgYXJtMS5uZXR3aW5kZXIub3Jn
+MB0GA1UdDgQWBBSCom5YDbaY79mgaJ3QwHBZs2oymTCBwQYDVR0jBIG5MIG2gBR6
+OHXpuZSrtgDFNoHqpWA++v7k4aGBmqSBlzCBlDELMAkGA1UEBhMCQ0ExEDAOBgNV
+BAgTB09udGFyaW8xDzANBgNVBAcTBk90dGF3YTESMBAGA1UEChMJUmViZWwuY29t
+MRAwDgYDVQQLEwdTb2Z0RW5nMRUwEwYDVQQDFAxDQV9hcm0tZGV2ZWwxJTAjBgkq
+hkiG9w0BCQEWFmx1Yy5sYW50aGllckByZWJlbC5jb22CAQAwOwYDVR0RBDQwMoEW
+ZmlyZXNvdWxAbmV0d2luZGVyLm9yZ4ISYXJtMS5uZXR3aW5kZXIub3JnhwQKATF8
+MCEGA1UdEgQaMBiBFmx1Yy5sYW50aGllckByZWJlbC5jb20wDQYJKoZIhvcNAQEE
+BQADgYEAw2gZX2ASGG9Ih/mX0qMPvOTQWTdpFygyVX1cejX/4WcF9TGAJ8w6NyhH
+RuzZsPlprM5tiZQZFjhku9pnaMXjJuNmmLJFvw0WK5UMGsxljMX0ui8rWvStmnGS
+3uV3xAiWfMMlJf5DsPP5ZR/6bC0u4h8YdQNRM5RhKVkanHxxQuE=
+-----END CERTIFICATE-----
diff -bruN freeswan-1.9.orig/doc/pkix/examples/dir/b2dc4b6f.cert.0 freeswan-1.9/doc/pkix/examples/dir/b2dc4b6f.cert.0
--- freeswan-1.9.orig/doc/pkix/examples/dir/b2dc4b6f.cert.0	Wed Dec 31 19:00:00 1969
+++ freeswan-1.9/doc/pkix/examples/dir/b2dc4b6f.cert.0	Mon Jun  4 11:34:31 2001
@@ -0,0 +1,79 @@
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number: 1 (0x1)
+        Signature Algorithm: md5WithRSAEncryption
+        Issuer: C=CA, ST=Ontario, L=Ottawa, O=Rebel.com, OU=SoftEng, CN=CA_arm-devel/Email=luc.lanthier@rebel.com
+        Validity
+            Not Before: Feb 14 20:59:13 2001 GMT
+            Not After : Feb 14 20:59:13 2002 GMT
+        Subject: C=CA, ST=Ontario, O=Rebel.com, OU=SoftEng, CN=arm-devel.netwinder.org/Email=luc.lanthier@rebel.com
+        Subject Public Key Info:
+            Public Key Algorithm: rsaEncryption
+            RSA Public Key: (1024 bit)
+                Modulus (1024 bit):
+                    00:a8:a9:0c:2c:21:fc:9b:02:d6:f4:98:c7:c3:dc:
+                    d1:8d:31:91:fb:72:41:ab:09:e8:52:9b:be:35:75:
+                    d8:f0:f6:b5:ba:8a:0c:d9:02:9b:5a:a9:0d:98:e6:
+                    b6:8f:97:45:eb:17:e3:10:23:c4:90:91:f4:ed:cc:
+                    ff:76:fd:95:3d:7a:a6:c4:59:b0:45:45:f6:0b:a9:
+                    c9:0c:77:6d:5e:53:d1:87:0d:59:79:50:f9:94:c1:
+                    64:8e:5e:e1:38:94:ae:7c:7f:68:5e:10:51:3d:ef:
+                    9c:9f:f4:2b:08:bc:eb:9a:b3:7d:c5:b2:2b:98:b4:
+                    ee:54:12:6c:da:a4:05:40:9d
+                Exponent: 65537 (0x10001)
+        X509v3 extensions:
+            X509v3 Basic Constraints: 
+                CA:FALSE
+            Netscape Cert Type: 
+                SSL Server
+            X509v3 Key Usage: 
+                Digital Signature, Non Repudiation, Key Encipherment
+            Netscape Comment: 
+                IPsec Certificate for arm-devel.netwinder.org
+            X509v3 Subject Key Identifier: 
+                98:76:ED:A5:41:7C:28:3C:C8:63:0F:09:F7:DE:9E:B2:00:B6:36:FE
+            X509v3 Authority Key Identifier: 
+                keyid:7A:38:75:E9:B9:94:AB:B6:00:C5:36:81:EA:A5:60:3E:FA:FE:E4:E1
+                DirName:/C=CA/ST=Ontario/L=Ottawa/O=Rebel.com/OU=SoftEng/CN=CA_arm-devel/Email=luc.lanthier@rebel.com
+                serial:00
+
+            X509v3 Subject Alternative Name: 
+                email:luc.lanthier@rebel.com, DNS:arm-devel.netwinder.org, IP Address:10.8.49.122
+            X509v3 Issuer Alternative Name: 
+                email:luc.lanthier@rebel.com
+    Signature Algorithm: md5WithRSAEncryption
+        bb:a9:1a:f4:e3:55:c8:f6:e7:d6:32:cb:a2:2f:6d:58:a3:5d:
+        8f:5a:0d:95:53:c7:bf:06:e7:3b:ca:99:48:99:2f:55:28:5a:
+        9e:37:ef:3b:44:73:1e:e0:61:93:43:f8:04:6b:06:1e:68:e5:
+        3e:a2:10:53:94:2f:66:76:fc:66:93:d4:5e:76:cf:2d:18:e2:
+        ff:eb:c0:77:c9:d5:4d:00:60:34:50:59:69:b9:7d:07:fb:ca:
+        8b:6e:ee:5c:d2:d9:06:2f:ee:df:d8:09:12:76:bc:b5:17:80:
+        a8:d6:a7:25:59:5c:b4:65:cb:29:b1:cd:77:29:e9:c4:03:00:
+        ea:c4
+-----BEGIN CERTIFICATE-----
+MIIEUTCCA7qgAwIBAgIBATANBgkqhkiG9w0BAQQFADCBlDELMAkGA1UEBhMCQ0Ex
+EDAOBgNVBAgTB09udGFyaW8xDzANBgNVBAcTBk90dGF3YTESMBAGA1UEChMJUmVi
+ZWwuY29tMRAwDgYDVQQLEwdTb2Z0RW5nMRUwEwYDVQQDFAxDQV9hcm0tZGV2ZWwx
+JTAjBgkqhkiG9w0BCQEWFmx1Yy5sYW50aGllckByZWJlbC5jb20wHhcNMDEwMjE0
+MjA1OTEzWhcNMDIwMjE0MjA1OTEzWjCBjjELMAkGA1UEBhMCQ0ExEDAOBgNVBAgT
+B09udGFyaW8xEjAQBgNVBAoTCVJlYmVsLmNvbTEQMA4GA1UECxMHU29mdEVuZzEg
+MB4GA1UEAxMXYXJtLWRldmVsLm5ldHdpbmRlci5vcmcxJTAjBgkqhkiG9w0BCQEW
+Fmx1Yy5sYW50aGllckByZWJlbC5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJ
+AoGBAKipDCwh/JsC1vSYx8Pc0Y0xkftyQasJ6FKbvjV12PD2tbqKDNkCm1qpDZjm
+to+XResX4xAjxJCR9O3M/3b9lT16psRZsEVF9gupyQx3bV5T0YcNWXlQ+ZTBZI5e
+4TiUrnx/aF4QUT3vnJ/0Kwi865qzfcWyK5i07lQSbNqkBUCdAgMBAAGjggG1MIIB
+sTAJBgNVHRMEAjAAMBEGCWCGSAGG+EIBAQQEAwIGQDALBgNVHQ8EBAMCBeAwPAYJ
+YIZIAYb4QgENBC8WLUlQc2VjIENlcnRpZmljYXRlIGZvciBhcm0tZGV2ZWwubmV0
+d2luZGVyLm9yZzAdBgNVHQ4EFgQUmHbtpUF8KDzIYw8J996esgC2Nv4wgcEGA1Ud
+IwSBuTCBtoAUejh16bmUq7YAxTaB6qVgPvr+5OGhgZqkgZcwgZQxCzAJBgNVBAYT
+AkNBMRAwDgYDVQQIEwdPbnRhcmlvMQ8wDQYDVQQHEwZPdHRhd2ExEjAQBgNVBAoT
+CVJlYmVsLmNvbTEQMA4GA1UECxMHU29mdEVuZzEVMBMGA1UEAxQMQ0FfYXJtLWRl
+dmVsMSUwIwYJKoZIhvcNAQkBFhZsdWMubGFudGhpZXJAcmViZWwuY29tggEAMEAG
+A1UdEQQ5MDeBFmx1Yy5sYW50aGllckByZWJlbC5jb22CF2FybS1kZXZlbC5uZXR3
+aW5kZXIub3JnhwQKCDF6MCEGA1UdEgQaMBiBFmx1Yy5sYW50aGllckByZWJlbC5j
+b20wDQYJKoZIhvcNAQEEBQADgYEAu6ka9ONVyPbn1jLLoi9tWKNdj1oNlVPHvwbn
+O8qZSJkvVShanjfvO0RzHuBhk0P4BGsGHmjlPqIQU5QvZnb8ZpPUXnbPLRji/+vA
+d8nVTQBgNFBZabl9B/vKi27uXNLZBi/u39gJEna8tReAqNanJVlctGXLKbHNdynp
+xAMA6sQ=
+-----END CERTIFICATE-----
diff -bruN freeswan-1.9.orig/doc/pkix/examples/dir/cacert.pem freeswan-1.9/doc/pkix/examples/dir/cacert.pem
--- freeswan-1.9.orig/doc/pkix/examples/dir/cacert.pem	Wed Dec 31 19:00:00 1969
+++ freeswan-1.9/doc/pkix/examples/dir/cacert.pem	Mon Jun  4 11:34:31 2001
@@ -0,0 +1,23 @@
+-----BEGIN CERTIFICATE-----
+MIID2jCCA0OgAwIBAgIBADANBgkqhkiG9w0BAQQFADCBlDELMAkGA1UEBhMCQ0Ex
+EDAOBgNVBAgTB09udGFyaW8xDzANBgNVBAcTBk90dGF3YTESMBAGA1UEChMJUmVi
+ZWwuY29tMRAwDgYDVQQLEwdTb2Z0RW5nMRUwEwYDVQQDFAxDQV9hcm0tZGV2ZWwx
+JTAjBgkqhkiG9w0BCQEWFmx1Yy5sYW50aGllckByZWJlbC5jb20wHhcNMDEwMjE0
+MTk0NTAyWhcNMDYwODA3MTk0NTAyWjCBlDELMAkGA1UEBhMCQ0ExEDAOBgNVBAgT
+B09udGFyaW8xDzANBgNVBAcTBk90dGF3YTESMBAGA1UEChMJUmViZWwuY29tMRAw
+DgYDVQQLEwdTb2Z0RW5nMRUwEwYDVQQDFAxDQV9hcm0tZGV2ZWwxJTAjBgkqhkiG
+9w0BCQEWFmx1Yy5sYW50aGllckByZWJlbC5jb20wgZ8wDQYJKoZIhvcNAQEBBQAD
+gY0AMIGJAoGBANWu/vkaR1M1bvP2Y80Dv105n3VHmOqZcyy9fnbaXXc92nKbBMib
+bsuUdfWdjOuC34BjfNuC9DU3rP8jZNBg+qeyAie6G7Q1R3atroqYvaFFhEbU1OnZ
+vBigB39dOIjfFiHbeqNCqlxLlrMJwkBJtkLdiktuf6Rqp+nnX6ymxz1BAgMBAAGj
+ggE4MIIBNDAdBgNVHQ4EFgQUejh16bmUq7YAxTaB6qVgPvr+5OEwgcEGA1UdIwSB
+uTCBtoAUejh16bmUq7YAxTaB6qVgPvr+5OGhgZqkgZcwgZQxCzAJBgNVBAYTAkNB
+MRAwDgYDVQQIEwdPbnRhcmlvMQ8wDQYDVQQHEwZPdHRhd2ExEjAQBgNVBAoTCVJl
+YmVsLmNvbTEQMA4GA1UECxMHU29mdEVuZzEVMBMGA1UEAxQMQ0FfYXJtLWRldmVs
+MSUwIwYJKoZIhvcNAQkBFhZsdWMubGFudGhpZXJAcmViZWwuY29tggEAMAwGA1Ud
+EwQFMAMBAf8wCwYDVR0PBAQDAgEGMBEGCWCGSAGG+EIBAQQEAwIBBjAhBgNVHREE
+GjAYgRZsdWMubGFudGhpZXJAcmViZWwuY29tMA0GCSqGSIb3DQEBBAUAA4GBAHzh
+QeKz7deGehWh7KtZ1tNNu1gWxeW4fwjHUT/xkoepd0XclIIRoKH+2h6w5QG3p2Up
+9TLxWlS8SB0tR0FiVu1WD658vOZjDTqqL9EVdEgSCrWX26KaMhNLrYzT3nzqq9VR
+QYqYZDAD3Z345UweqfCJBgxrim03x++bsEq9tP4Y
+-----END CERTIFICATE-----
diff -bruN freeswan-1.9.orig/doc/pkix/examples/dir/crl.pem freeswan-1.9/doc/pkix/examples/dir/crl.pem
--- freeswan-1.9.orig/doc/pkix/examples/dir/crl.pem	Wed Dec 31 19:00:00 1969
+++ freeswan-1.9/doc/pkix/examples/dir/crl.pem	Mon Jun  4 11:34:31 2001
@@ -0,0 +1,10 @@
+-----BEGIN X509 CRL-----
+MIIBWjCBxDANBgkqhkiG9w0BAQQFADCBlDELMAkGA1UEBhMCQ0ExEDAOBgNVBAgT
+B09udGFyaW8xDzANBgNVBAcTBk90dGF3YTESMBAGA1UEChMJUmViZWwuY29tMRAw
+DgYDVQQLEwdTb2Z0RW5nMRUwEwYDVQQDFAxDQV9hcm0tZGV2ZWwxJTAjBgkqhkiG
+9w0BCQEWFmx1Yy5sYW50aGllckByZWJlbC5jb20XDTAxMDIxNDE5NDUzN1oXDTAx
+MDMxNjE5NDUzN1owDQYJKoZIhvcNAQEEBQADgYEAcM3oRcSVw2rf7AQbcX0WqsEh
+YEHnMUNur13Wd2ai7b6KSKxHj+O/WWSupH3IDPL1TEKwdWLG9+MtbhKhBh8WNzQh
+7Nl/NzTgdCh0xDBoJDGG7zN7WDNQ1WGbaAkjDUJm6ty92zlpFkF4Gg2B1dl8WwYK
+LSSaMtj6/VV4CuhzFMg=
+-----END X509 CRL-----
diff -bruN freeswan-1.9.orig/doc/pkix/examples/dir/dns-arm-devel.netwinder.org.cert.0 freeswan-1.9/doc/pkix/examples/dir/dns-arm-devel.netwinder.org.cert.0
--- freeswan-1.9.orig/doc/pkix/examples/dir/dns-arm-devel.netwinder.org.cert.0	Wed Dec 31 19:00:00 1969
+++ freeswan-1.9/doc/pkix/examples/dir/dns-arm-devel.netwinder.org.cert.0	Mon Jun  4 11:34:31 2001
@@ -0,0 +1,79 @@
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number: 1 (0x1)
+        Signature Algorithm: md5WithRSAEncryption
+        Issuer: C=CA, ST=Ontario, L=Ottawa, O=Rebel.com, OU=SoftEng, CN=CA_arm-devel/Email=luc.lanthier@rebel.com
+        Validity
+            Not Before: Feb 14 20:59:13 2001 GMT
+            Not After : Feb 14 20:59:13 2002 GMT
+        Subject: C=CA, ST=Ontario, O=Rebel.com, OU=SoftEng, CN=arm-devel.netwinder.org/Email=luc.lanthier@rebel.com
+        Subject Public Key Info:
+            Public Key Algorithm: rsaEncryption
+            RSA Public Key: (1024 bit)
+                Modulus (1024 bit):
+                    00:a8:a9:0c:2c:21:fc:9b:02:d6:f4:98:c7:c3:dc:
+                    d1:8d:31:91:fb:72:41:ab:09:e8:52:9b:be:35:75:
+                    d8:f0:f6:b5:ba:8a:0c:d9:02:9b:5a:a9:0d:98:e6:
+                    b6:8f:97:45:eb:17:e3:10:23:c4:90:91:f4:ed:cc:
+                    ff:76:fd:95:3d:7a:a6:c4:59:b0:45:45:f6:0b:a9:
+                    c9:0c:77:6d:5e:53:d1:87:0d:59:79:50:f9:94:c1:
+                    64:8e:5e:e1:38:94:ae:7c:7f:68:5e:10:51:3d:ef:
+                    9c:9f:f4:2b:08:bc:eb:9a:b3:7d:c5:b2:2b:98:b4:
+                    ee:54:12:6c:da:a4:05:40:9d
+                Exponent: 65537 (0x10001)
+        X509v3 extensions:
+            X509v3 Basic Constraints: 
+                CA:FALSE
+            Netscape Cert Type: 
+                SSL Server
+            X509v3 Key Usage: 
+                Digital Signature, Non Repudiation, Key Encipherment
+            Netscape Comment: 
+                IPsec Certificate for arm-devel.netwinder.org
+            X509v3 Subject Key Identifier: 
+                98:76:ED:A5:41:7C:28:3C:C8:63:0F:09:F7:DE:9E:B2:00:B6:36:FE
+            X509v3 Authority Key Identifier: 
+                keyid:7A:38:75:E9:B9:94:AB:B6:00:C5:36:81:EA:A5:60:3E:FA:FE:E4:E1
+                DirName:/C=CA/ST=Ontario/L=Ottawa/O=Rebel.com/OU=SoftEng/CN=CA_arm-devel/Email=luc.lanthier@rebel.com
+                serial:00
+
+            X509v3 Subject Alternative Name: 
+                email:luc.lanthier@rebel.com, DNS:arm-devel.netwinder.org, IP Address:10.8.49.122
+            X509v3 Issuer Alternative Name: 
+                email:luc.lanthier@rebel.com
+    Signature Algorithm: md5WithRSAEncryption
+        bb:a9:1a:f4:e3:55:c8:f6:e7:d6:32:cb:a2:2f:6d:58:a3:5d:
+        8f:5a:0d:95:53:c7:bf:06:e7:3b:ca:99:48:99:2f:55:28:5a:
+        9e:37:ef:3b:44:73:1e:e0:61:93:43:f8:04:6b:06:1e:68:e5:
+        3e:a2:10:53:94:2f:66:76:fc:66:93:d4:5e:76:cf:2d:18:e2:
+        ff:eb:c0:77:c9:d5:4d:00:60:34:50:59:69:b9:7d:07:fb:ca:
+        8b:6e:ee:5c:d2:d9:06:2f:ee:df:d8:09:12:76:bc:b5:17:80:
+        a8:d6:a7:25:59:5c:b4:65:cb:29:b1:cd:77:29:e9:c4:03:00:
+        ea:c4
+-----BEGIN CERTIFICATE-----
+MIIEUTCCA7qgAwIBAgIBATANBgkqhkiG9w0BAQQFADCBlDELMAkGA1UEBhMCQ0Ex
+EDAOBgNVBAgTB09udGFyaW8xDzANBgNVBAcTBk90dGF3YTESMBAGA1UEChMJUmVi
+ZWwuY29tMRAwDgYDVQQLEwdTb2Z0RW5nMRUwEwYDVQQDFAxDQV9hcm0tZGV2ZWwx
+JTAjBgkqhkiG9w0BCQEWFmx1Yy5sYW50aGllckByZWJlbC5jb20wHhcNMDEwMjE0
+MjA1OTEzWhcNMDIwMjE0MjA1OTEzWjCBjjELMAkGA1UEBhMCQ0ExEDAOBgNVBAgT
+B09udGFyaW8xEjAQBgNVBAoTCVJlYmVsLmNvbTEQMA4GA1UECxMHU29mdEVuZzEg
+MB4GA1UEAxMXYXJtLWRldmVsLm5ldHdpbmRlci5vcmcxJTAjBgkqhkiG9w0BCQEW
+Fmx1Yy5sYW50aGllckByZWJlbC5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJ
+AoGBAKipDCwh/JsC1vSYx8Pc0Y0xkftyQasJ6FKbvjV12PD2tbqKDNkCm1qpDZjm
+to+XResX4xAjxJCR9O3M/3b9lT16psRZsEVF9gupyQx3bV5T0YcNWXlQ+ZTBZI5e
+4TiUrnx/aF4QUT3vnJ/0Kwi865qzfcWyK5i07lQSbNqkBUCdAgMBAAGjggG1MIIB
+sTAJBgNVHRMEAjAAMBEGCWCGSAGG+EIBAQQEAwIGQDALBgNVHQ8EBAMCBeAwPAYJ
+YIZIAYb4QgENBC8WLUlQc2VjIENlcnRpZmljYXRlIGZvciBhcm0tZGV2ZWwubmV0
+d2luZGVyLm9yZzAdBgNVHQ4EFgQUmHbtpUF8KDzIYw8J996esgC2Nv4wgcEGA1Ud
+IwSBuTCBtoAUejh16bmUq7YAxTaB6qVgPvr+5OGhgZqkgZcwgZQxCzAJBgNVBAYT
+AkNBMRAwDgYDVQQIEwdPbnRhcmlvMQ8wDQYDVQQHEwZPdHRhd2ExEjAQBgNVBAoT
+CVJlYmVsLmNvbTEQMA4GA1UECxMHU29mdEVuZzEVMBMGA1UEAxQMQ0FfYXJtLWRl
+dmVsMSUwIwYJKoZIhvcNAQkBFhZsdWMubGFudGhpZXJAcmViZWwuY29tggEAMEAG
+A1UdEQQ5MDeBFmx1Yy5sYW50aGllckByZWJlbC5jb22CF2FybS1kZXZlbC5uZXR3
+aW5kZXIub3JnhwQKCDF6MCEGA1UdEgQaMBiBFmx1Yy5sYW50aGllckByZWJlbC5j
+b20wDQYJKoZIhvcNAQEEBQADgYEAu6ka9ONVyPbn1jLLoi9tWKNdj1oNlVPHvwbn
+O8qZSJkvVShanjfvO0RzHuBhk0P4BGsGHmjlPqIQU5QvZnb8ZpPUXnbPLRji/+vA
+d8nVTQBgNFBZabl9B/vKi27uXNLZBi/u39gJEna8tReAqNanJVlctGXLKbHNdynp
+xAMA6sQ=
+-----END CERTIFICATE-----
diff -bruN freeswan-1.9.orig/doc/pkix/examples/dir/dns-arm1.netwinder.org.cert.0 freeswan-1.9/doc/pkix/examples/dir/dns-arm1.netwinder.org.cert.0
--- freeswan-1.9.orig/doc/pkix/examples/dir/dns-arm1.netwinder.org.cert.0	Wed Dec 31 19:00:00 1969
+++ freeswan-1.9/doc/pkix/examples/dir/dns-arm1.netwinder.org.cert.0	Mon Jun  4 11:34:31 2001
@@ -0,0 +1,78 @@
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number: 2 (0x2)
+        Signature Algorithm: md5WithRSAEncryption
+        Issuer: C=CA, ST=Ontario, L=Ottawa, O=Rebel.com, OU=SoftEng, CN=CA_arm-devel/Email=luc.lanthier@rebel.com
+        Validity
+            Not Before: Feb 14 21:00:11 2001 GMT
+            Not After : Feb 14 21:00:11 2002 GMT
+        Subject: C=CA, ST=Ontario, O=Rebel.com, OU=SoftEng, CN=arm1.netwinder.org/Email=firesoul@netwinder.org
+        Subject Public Key Info:
+            Public Key Algorithm: rsaEncryption
+            RSA Public Key: (1024 bit)
+                Modulus (1024 bit):
+                    00:e2:2b:ad:70:6b:29:e7:83:be:af:12:50:4b:a4:
+                    26:02:60:ed:f9:bd:49:51:86:96:18:9c:10:f1:0c:
+                    7d:bd:b9:22:8e:66:6a:f4:96:e5:8d:e2:c4:11:1e:
+                    64:8e:59:1e:b1:a2:64:15:fa:a6:17:9a:59:f3:9f:
+                    9f:c8:c9:17:b8:a7:87:55:70:8f:de:25:78:e6:e0:
+                    4c:82:ae:f1:47:14:77:fa:5b:3e:4d:e5:05:5e:31:
+                    09:62:56:f8:3b:94:51:b2:e3:7e:bb:8f:6e:dc:ea:
+                    64:2e:2f:65:8e:41:18:0e:cf:9d:8a:b8:0a:86:6c:
+                    6a:88:be:58:ce:be:b3:32:c1
+                Exponent: 65537 (0x10001)
+        X509v3 extensions:
+            X509v3 Basic Constraints: 
+                CA:FALSE
+            Netscape Cert Type: 
+                SSL Server
+            X509v3 Key Usage: 
+                Digital Signature, Non Repudiation, Key Encipherment
+            Netscape Comment: 
+                IPsec Certificate for arm1.netwinder.org
+            X509v3 Subject Key Identifier: 
+                82:A2:6E:58:0D:B6:98:EF:D9:A0:68:9D:D0:C0:70:59:B3:6A:32:99
+            X509v3 Authority Key Identifier: 
+                keyid:7A:38:75:E9:B9:94:AB:B6:00:C5:36:81:EA:A5:60:3E:FA:FE:E4:E1
+                DirName:/C=CA/ST=Ontario/L=Ottawa/O=Rebel.com/OU=SoftEng/CN=CA_arm-devel/Email=luc.lanthier@rebel.com
+                serial:00
+
+            X509v3 Subject Alternative Name: 
+                email:firesoul@netwinder.org, DNS:arm1.netwinder.org, IP Address:10.1.49.124
+            X509v3 Issuer Alternative Name: 
+                email:luc.lanthier@rebel.com
+    Signature Algorithm: md5WithRSAEncryption
+        c3:68:19:5f:60:12:18:6f:48:87:f9:97:d2:a3:0f:bc:e4:d0:
+        59:37:69:17:28:32:55:7d:5c:7a:35:ff:e1:67:05:f5:31:80:
+        27:cc:3a:37:28:47:46:ec:d9:b0:f9:69:ac:ce:6d:89:94:19:
+        16:38:64:bb:da:67:68:c5:e3:26:e3:66:98:b2:45:bf:0d:16:
+        2b:95:0c:1a:cc:65:8c:c5:f4:ba:2f:2b:5a:f4:ad:9a:71:92:
+        de:e5:77:c4:08:96:7c:c3:25:25:fe:43:b0:f3:f9:65:1f:fa:
+        6c:2d:2e:e2:1f:18:75:03:51:33:94:61:29:59:1a:9c:7c:71:
+        42:e1
+-----BEGIN CERTIFICATE-----
+MIIEQjCCA6ugAwIBAgIBAjANBgkqhkiG9w0BAQQFADCBlDELMAkGA1UEBhMCQ0Ex
+EDAOBgNVBAgTB09udGFyaW8xDzANBgNVBAcTBk90dGF3YTESMBAGA1UEChMJUmVi
+ZWwuY29tMRAwDgYDVQQLEwdTb2Z0RW5nMRUwEwYDVQQDFAxDQV9hcm0tZGV2ZWwx
+JTAjBgkqhkiG9w0BCQEWFmx1Yy5sYW50aGllckByZWJlbC5jb20wHhcNMDEwMjE0
+MjEwMDExWhcNMDIwMjE0MjEwMDExWjCBiTELMAkGA1UEBhMCQ0ExEDAOBgNVBAgT
+B09udGFyaW8xEjAQBgNVBAoTCVJlYmVsLmNvbTEQMA4GA1UECxMHU29mdEVuZzEb
+MBkGA1UEAxMSYXJtMS5uZXR3aW5kZXIub3JnMSUwIwYJKoZIhvcNAQkBFhZmaXJl
+c291bEBuZXR3aW5kZXIub3JnMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDi
+K61waynng76vElBLpCYCYO35vUlRhpYYnBDxDH29uSKOZmr0luWN4sQRHmSOWR6x
+omQV+qYXmlnzn5/IyRe4p4dVcI/eJXjm4EyCrvFHFHf6Wz5N5QVeMQliVvg7lFGy
+4367j27c6mQuL2WOQRgOz52KuAqGbGqIvljOvrMywQIDAQABo4IBqzCCAacwCQYD
+VR0TBAIwADARBglghkgBhvhCAQEEBAMCBkAwCwYDVR0PBAQDAgXgMDcGCWCGSAGG
++EIBDQQqFihJUHNlYyBDZXJ0aWZpY2F0ZSBmb3IgYXJtMS5uZXR3aW5kZXIub3Jn
+MB0GA1UdDgQWBBSCom5YDbaY79mgaJ3QwHBZs2oymTCBwQYDVR0jBIG5MIG2gBR6
+OHXpuZSrtgDFNoHqpWA++v7k4aGBmqSBlzCBlDELMAkGA1UEBhMCQ0ExEDAOBgNV
+BAgTB09udGFyaW8xDzANBgNVBAcTBk90dGF3YTESMBAGA1UEChMJUmViZWwuY29t
+MRAwDgYDVQQLEwdTb2Z0RW5nMRUwEwYDVQQDFAxDQV9hcm0tZGV2ZWwxJTAjBgkq
+hkiG9w0BCQEWFmx1Yy5sYW50aGllckByZWJlbC5jb22CAQAwOwYDVR0RBDQwMoEW
+ZmlyZXNvdWxAbmV0d2luZGVyLm9yZ4ISYXJtMS5uZXR3aW5kZXIub3JnhwQKATF8
+MCEGA1UdEgQaMBiBFmx1Yy5sYW50aGllckByZWJlbC5jb20wDQYJKoZIhvcNAQEE
+BQADgYEAw2gZX2ASGG9Ih/mX0qMPvOTQWTdpFygyVX1cejX/4WcF9TGAJ8w6NyhH
+RuzZsPlprM5tiZQZFjhku9pnaMXjJuNmmLJFvw0WK5UMGsxljMX0ui8rWvStmnGS
+3uV3xAiWfMMlJf5DsPP5ZR/6bC0u4h8YdQNRM5RhKVkanHxxQuE=
+-----END CERTIFICATE-----
diff -bruN freeswan-1.9.orig/doc/pkix/examples/dir/eb7e7e69.cert.0 freeswan-1.9/doc/pkix/examples/dir/eb7e7e69.cert.0
--- freeswan-1.9.orig/doc/pkix/examples/dir/eb7e7e69.cert.0	Wed Dec 31 19:00:00 1969
+++ freeswan-1.9/doc/pkix/examples/dir/eb7e7e69.cert.0	Mon Jun  4 11:34:31 2001
@@ -0,0 +1,23 @@
+-----BEGIN CERTIFICATE-----
+MIID2jCCA0OgAwIBAgIBADANBgkqhkiG9w0BAQQFADCBlDELMAkGA1UEBhMCQ0Ex
+EDAOBgNVBAgTB09udGFyaW8xDzANBgNVBAcTBk90dGF3YTESMBAGA1UEChMJUmVi
+ZWwuY29tMRAwDgYDVQQLEwdTb2Z0RW5nMRUwEwYDVQQDFAxDQV9hcm0tZGV2ZWwx
+JTAjBgkqhkiG9w0BCQEWFmx1Yy5sYW50aGllckByZWJlbC5jb20wHhcNMDEwMjE0
+MTk0NTAyWhcNMDYwODA3MTk0NTAyWjCBlDELMAkGA1UEBhMCQ0ExEDAOBgNVBAgT
+B09udGFyaW8xDzANBgNVBAcTBk90dGF3YTESMBAGA1UEChMJUmViZWwuY29tMRAw
+DgYDVQQLEwdTb2Z0RW5nMRUwEwYDVQQDFAxDQV9hcm0tZGV2ZWwxJTAjBgkqhkiG
+9w0BCQEWFmx1Yy5sYW50aGllckByZWJlbC5jb20wgZ8wDQYJKoZIhvcNAQEBBQAD
+gY0AMIGJAoGBANWu/vkaR1M1bvP2Y80Dv105n3VHmOqZcyy9fnbaXXc92nKbBMib
+bsuUdfWdjOuC34BjfNuC9DU3rP8jZNBg+qeyAie6G7Q1R3atroqYvaFFhEbU1OnZ
+vBigB39dOIjfFiHbeqNCqlxLlrMJwkBJtkLdiktuf6Rqp+nnX6ymxz1BAgMBAAGj
+ggE4MIIBNDAdBgNVHQ4EFgQUejh16bmUq7YAxTaB6qVgPvr+5OEwgcEGA1UdIwSB
+uTCBtoAUejh16bmUq7YAxTaB6qVgPvr+5OGhgZqkgZcwgZQxCzAJBgNVBAYTAkNB
+MRAwDgYDVQQIEwdPbnRhcmlvMQ8wDQYDVQQHEwZPdHRhd2ExEjAQBgNVBAoTCVJl
+YmVsLmNvbTEQMA4GA1UECxMHU29mdEVuZzEVMBMGA1UEAxQMQ0FfYXJtLWRldmVs
+MSUwIwYJKoZIhvcNAQkBFhZsdWMubGFudGhpZXJAcmViZWwuY29tggEAMAwGA1Ud
+EwQFMAMBAf8wCwYDVR0PBAQDAgEGMBEGCWCGSAGG+EIBAQQEAwIBBjAhBgNVHREE
+GjAYgRZsdWMubGFudGhpZXJAcmViZWwuY29tMA0GCSqGSIb3DQEBBAUAA4GBAHzh
+QeKz7deGehWh7KtZ1tNNu1gWxeW4fwjHUT/xkoepd0XclIIRoKH+2h6w5QG3p2Up
+9TLxWlS8SB0tR0FiVu1WD658vOZjDTqqL9EVdEgSCrWX26KaMhNLrYzT3nzqq9VR
+QYqYZDAD3Z345UweqfCJBgxrim03x++bsEq9tP4Y
+-----END CERTIFICATE-----
diff -bruN freeswan-1.9.orig/doc/pkix/examples/dir/eb7e7e69.crl.0 freeswan-1.9/doc/pkix/examples/dir/eb7e7e69.crl.0
--- freeswan-1.9.orig/doc/pkix/examples/dir/eb7e7e69.crl.0	Wed Dec 31 19:00:00 1969
+++ freeswan-1.9/doc/pkix/examples/dir/eb7e7e69.crl.0	Mon Jun  4 11:34:31 2001
@@ -0,0 +1,10 @@
+-----BEGIN X509 CRL-----
+MIIBWjCBxDANBgkqhkiG9w0BAQQFADCBlDELMAkGA1UEBhMCQ0ExEDAOBgNVBAgT
+B09udGFyaW8xDzANBgNVBAcTBk90dGF3YTESMBAGA1UEChMJUmViZWwuY29tMRAw
+DgYDVQQLEwdTb2Z0RW5nMRUwEwYDVQQDFAxDQV9hcm0tZGV2ZWwxJTAjBgkqhkiG
+9w0BCQEWFmx1Yy5sYW50aGllckByZWJlbC5jb20XDTAxMDIxNDE5NDUzN1oXDTAx
+MDMxNjE5NDUzN1owDQYJKoZIhvcNAQEEBQADgYEAcM3oRcSVw2rf7AQbcX0WqsEh
+YEHnMUNur13Wd2ai7b6KSKxHj+O/WWSupH3IDPL1TEKwdWLG9+MtbhKhBh8WNzQh
+7Nl/NzTgdCh0xDBoJDGG7zN7WDNQ1WGbaAkjDUJm6ty92zlpFkF4Gg2B1dl8WwYK
+LSSaMtj6/VV4CuhzFMg=
+-----END X509 CRL-----
diff -bruN freeswan-1.9.orig/doc/pkix/examples/dir/ip-10.1.49.124.cert.0 freeswan-1.9/doc/pkix/examples/dir/ip-10.1.49.124.cert.0
--- freeswan-1.9.orig/doc/pkix/examples/dir/ip-10.1.49.124.cert.0	Wed Dec 31 19:00:00 1969
+++ freeswan-1.9/doc/pkix/examples/dir/ip-10.1.49.124.cert.0	Mon Jun  4 11:34:31 2001
@@ -0,0 +1,78 @@
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number: 2 (0x2)
+        Signature Algorithm: md5WithRSAEncryption
+        Issuer: C=CA, ST=Ontario, L=Ottawa, O=Rebel.com, OU=SoftEng, CN=CA_arm-devel/Email=luc.lanthier@rebel.com
+        Validity
+            Not Before: Feb 14 21:00:11 2001 GMT
+            Not After : Feb 14 21:00:11 2002 GMT
+        Subject: C=CA, ST=Ontario, O=Rebel.com, OU=SoftEng, CN=arm1.netwinder.org/Email=firesoul@netwinder.org
+        Subject Public Key Info:
+            Public Key Algorithm: rsaEncryption
+            RSA Public Key: (1024 bit)
+                Modulus (1024 bit):
+                    00:e2:2b:ad:70:6b:29:e7:83:be:af:12:50:4b:a4:
+                    26:02:60:ed:f9:bd:49:51:86:96:18:9c:10:f1:0c:
+                    7d:bd:b9:22:8e:66:6a:f4:96:e5:8d:e2:c4:11:1e:
+                    64:8e:59:1e:b1:a2:64:15:fa:a6:17:9a:59:f3:9f:
+                    9f:c8:c9:17:b8:a7:87:55:70:8f:de:25:78:e6:e0:
+                    4c:82:ae:f1:47:14:77:fa:5b:3e:4d:e5:05:5e:31:
+                    09:62:56:f8:3b:94:51:b2:e3:7e:bb:8f:6e:dc:ea:
+                    64:2e:2f:65:8e:41:18:0e:cf:9d:8a:b8:0a:86:6c:
+                    6a:88:be:58:ce:be:b3:32:c1
+                Exponent: 65537 (0x10001)
+        X509v3 extensions:
+            X509v3 Basic Constraints: 
+                CA:FALSE
+            Netscape Cert Type: 
+                SSL Server
+            X509v3 Key Usage: 
+                Digital Signature, Non Repudiation, Key Encipherment
+            Netscape Comment: 
+                IPsec Certificate for arm1.netwinder.org
+            X509v3 Subject Key Identifier: 
+                82:A2:6E:58:0D:B6:98:EF:D9:A0:68:9D:D0:C0:70:59:B3:6A:32:99
+            X509v3 Authority Key Identifier: 
+                keyid:7A:38:75:E9:B9:94:AB:B6:00:C5:36:81:EA:A5:60:3E:FA:FE:E4:E1
+                DirName:/C=CA/ST=Ontario/L=Ottawa/O=Rebel.com/OU=SoftEng/CN=CA_arm-devel/Email=luc.lanthier@rebel.com
+                serial:00
+
+            X509v3 Subject Alternative Name: 
+                email:firesoul@netwinder.org, DNS:arm1.netwinder.org, IP Address:10.1.49.124
+            X509v3 Issuer Alternative Name: 
+                email:luc.lanthier@rebel.com
+    Signature Algorithm: md5WithRSAEncryption
+        c3:68:19:5f:60:12:18:6f:48:87:f9:97:d2:a3:0f:bc:e4:d0:
+        59:37:69:17:28:32:55:7d:5c:7a:35:ff:e1:67:05:f5:31:80:
+        27:cc:3a:37:28:47:46:ec:d9:b0:f9:69:ac:ce:6d:89:94:19:
+        16:38:64:bb:da:67:68:c5:e3:26:e3:66:98:b2:45:bf:0d:16:
+        2b:95:0c:1a:cc:65:8c:c5:f4:ba:2f:2b:5a:f4:ad:9a:71:92:
+        de:e5:77:c4:08:96:7c:c3:25:25:fe:43:b0:f3:f9:65:1f:fa:
+        6c:2d:2e:e2:1f:18:75:03:51:33:94:61:29:59:1a:9c:7c:71:
+        42:e1
+-----BEGIN CERTIFICATE-----
+MIIEQjCCA6ugAwIBAgIBAjANBgkqhkiG9w0BAQQFADCBlDELMAkGA1UEBhMCQ0Ex
+EDAOBgNVBAgTB09udGFyaW8xDzANBgNVBAcTBk90dGF3YTESMBAGA1UEChMJUmVi
+ZWwuY29tMRAwDgYDVQQLEwdTb2Z0RW5nMRUwEwYDVQQDFAxDQV9hcm0tZGV2ZWwx
+JTAjBgkqhkiG9w0BCQEWFmx1Yy5sYW50aGllckByZWJlbC5jb20wHhcNMDEwMjE0
+MjEwMDExWhcNMDIwMjE0MjEwMDExWjCBiTELMAkGA1UEBhMCQ0ExEDAOBgNVBAgT
+B09udGFyaW8xEjAQBgNVBAoTCVJlYmVsLmNvbTEQMA4GA1UECxMHU29mdEVuZzEb
+MBkGA1UEAxMSYXJtMS5uZXR3aW5kZXIub3JnMSUwIwYJKoZIhvcNAQkBFhZmaXJl
+c291bEBuZXR3aW5kZXIub3JnMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDi
+K61waynng76vElBLpCYCYO35vUlRhpYYnBDxDH29uSKOZmr0luWN4sQRHmSOWR6x
+omQV+qYXmlnzn5/IyRe4p4dVcI/eJXjm4EyCrvFHFHf6Wz5N5QVeMQliVvg7lFGy
+4367j27c6mQuL2WOQRgOz52KuAqGbGqIvljOvrMywQIDAQABo4IBqzCCAacwCQYD
+VR0TBAIwADARBglghkgBhvhCAQEEBAMCBkAwCwYDVR0PBAQDAgXgMDcGCWCGSAGG
++EIBDQQqFihJUHNlYyBDZXJ0aWZpY2F0ZSBmb3IgYXJtMS5uZXR3aW5kZXIub3Jn
+MB0GA1UdDgQWBBSCom5YDbaY79mgaJ3QwHBZs2oymTCBwQYDVR0jBIG5MIG2gBR6
+OHXpuZSrtgDFNoHqpWA++v7k4aGBmqSBlzCBlDELMAkGA1UEBhMCQ0ExEDAOBgNV
+BAgTB09udGFyaW8xDzANBgNVBAcTBk90dGF3YTESMBAGA1UEChMJUmViZWwuY29t
+MRAwDgYDVQQLEwdTb2Z0RW5nMRUwEwYDVQQDFAxDQV9hcm0tZGV2ZWwxJTAjBgkq
+hkiG9w0BCQEWFmx1Yy5sYW50aGllckByZWJlbC5jb22CAQAwOwYDVR0RBDQwMoEW
+ZmlyZXNvdWxAbmV0d2luZGVyLm9yZ4ISYXJtMS5uZXR3aW5kZXIub3JnhwQKATF8
+MCEGA1UdEgQaMBiBFmx1Yy5sYW50aGllckByZWJlbC5jb20wDQYJKoZIhvcNAQEE
+BQADgYEAw2gZX2ASGG9Ih/mX0qMPvOTQWTdpFygyVX1cejX/4WcF9TGAJ8w6NyhH
+RuzZsPlprM5tiZQZFjhku9pnaMXjJuNmmLJFvw0WK5UMGsxljMX0ui8rWvStmnGS
+3uV3xAiWfMMlJf5DsPP5ZR/6bC0u4h8YdQNRM5RhKVkanHxxQuE=
+-----END CERTIFICATE-----
diff -bruN freeswan-1.9.orig/doc/pkix/examples/dir/ip-10.8.49.122.cert.0 freeswan-1.9/doc/pkix/examples/dir/ip-10.8.49.122.cert.0
--- freeswan-1.9.orig/doc/pkix/examples/dir/ip-10.8.49.122.cert.0	Wed Dec 31 19:00:00 1969
+++ freeswan-1.9/doc/pkix/examples/dir/ip-10.8.49.122.cert.0	Mon Jun  4 11:34:31 2001
@@ -0,0 +1,79 @@
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number: 1 (0x1)
+        Signature Algorithm: md5WithRSAEncryption
+        Issuer: C=CA, ST=Ontario, L=Ottawa, O=Rebel.com, OU=SoftEng, CN=CA_arm-devel/Email=luc.lanthier@rebel.com
+        Validity
+            Not Before: Feb 14 20:59:13 2001 GMT
+            Not After : Feb 14 20:59:13 2002 GMT
+        Subject: C=CA, ST=Ontario, O=Rebel.com, OU=SoftEng, CN=arm-devel.netwinder.org/Email=luc.lanthier@rebel.com
+        Subject Public Key Info:
+            Public Key Algorithm: rsaEncryption
+            RSA Public Key: (1024 bit)
+                Modulus (1024 bit):
+                    00:a8:a9:0c:2c:21:fc:9b:02:d6:f4:98:c7:c3:dc:
+                    d1:8d:31:91:fb:72:41:ab:09:e8:52:9b:be:35:75:
+                    d8:f0:f6:b5:ba:8a:0c:d9:02:9b:5a:a9:0d:98:e6:
+                    b6:8f:97:45:eb:17:e3:10:23:c4:90:91:f4:ed:cc:
+                    ff:76:fd:95:3d:7a:a6:c4:59:b0:45:45:f6:0b:a9:
+                    c9:0c:77:6d:5e:53:d1:87:0d:59:79:50:f9:94:c1:
+                    64:8e:5e:e1:38:94:ae:7c:7f:68:5e:10:51:3d:ef:
+                    9c:9f:f4:2b:08:bc:eb:9a:b3:7d:c5:b2:2b:98:b4:
+                    ee:54:12:6c:da:a4:05:40:9d
+                Exponent: 65537 (0x10001)
+        X509v3 extensions:
+            X509v3 Basic Constraints: 
+                CA:FALSE
+            Netscape Cert Type: 
+                SSL Server
+            X509v3 Key Usage: 
+                Digital Signature, Non Repudiation, Key Encipherment
+            Netscape Comment: 
+                IPsec Certificate for arm-devel.netwinder.org
+            X509v3 Subject Key Identifier: 
+                98:76:ED:A5:41:7C:28:3C:C8:63:0F:09:F7:DE:9E:B2:00:B6:36:FE
+            X509v3 Authority Key Identifier: 
+                keyid:7A:38:75:E9:B9:94:AB:B6:00:C5:36:81:EA:A5:60:3E:FA:FE:E4:E1
+                DirName:/C=CA/ST=Ontario/L=Ottawa/O=Rebel.com/OU=SoftEng/CN=CA_arm-devel/Email=luc.lanthier@rebel.com
+                serial:00
+
+            X509v3 Subject Alternative Name: 
+                email:luc.lanthier@rebel.com, DNS:arm-devel.netwinder.org, IP Address:10.8.49.122
+            X509v3 Issuer Alternative Name: 
+                email:luc.lanthier@rebel.com
+    Signature Algorithm: md5WithRSAEncryption
+        bb:a9:1a:f4:e3:55:c8:f6:e7:d6:32:cb:a2:2f:6d:58:a3:5d:
+        8f:5a:0d:95:53:c7:bf:06:e7:3b:ca:99:48:99:2f:55:28:5a:
+        9e:37:ef:3b:44:73:1e:e0:61:93:43:f8:04:6b:06:1e:68:e5:
+        3e:a2:10:53:94:2f:66:76:fc:66:93:d4:5e:76:cf:2d:18:e2:
+        ff:eb:c0:77:c9:d5:4d:00:60:34:50:59:69:b9:7d:07:fb:ca:
+        8b:6e:ee:5c:d2:d9:06:2f:ee:df:d8:09:12:76:bc:b5:17:80:
+        a8:d6:a7:25:59:5c:b4:65:cb:29:b1:cd:77:29:e9:c4:03:00:
+        ea:c4
+-----BEGIN CERTIFICATE-----
+MIIEUTCCA7qgAwIBAgIBATANBgkqhkiG9w0BAQQFADCBlDELMAkGA1UEBhMCQ0Ex
+EDAOBgNVBAgTB09udGFyaW8xDzANBgNVBAcTBk90dGF3YTESMBAGA1UEChMJUmVi
+ZWwuY29tMRAwDgYDVQQLEwdTb2Z0RW5nMRUwEwYDVQQDFAxDQV9hcm0tZGV2ZWwx
+JTAjBgkqhkiG9w0BCQEWFmx1Yy5sYW50aGllckByZWJlbC5jb20wHhcNMDEwMjE0
+MjA1OTEzWhcNMDIwMjE0MjA1OTEzWjCBjjELMAkGA1UEBhMCQ0ExEDAOBgNVBAgT
+B09udGFyaW8xEjAQBgNVBAoTCVJlYmVsLmNvbTEQMA4GA1UECxMHU29mdEVuZzEg
+MB4GA1UEAxMXYXJtLWRldmVsLm5ldHdpbmRlci5vcmcxJTAjBgkqhkiG9w0BCQEW
+Fmx1Yy5sYW50aGllckByZWJlbC5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJ
+AoGBAKipDCwh/JsC1vSYx8Pc0Y0xkftyQasJ6FKbvjV12PD2tbqKDNkCm1qpDZjm
+to+XResX4xAjxJCR9O3M/3b9lT16psRZsEVF9gupyQx3bV5T0YcNWXlQ+ZTBZI5e
+4TiUrnx/aF4QUT3vnJ/0Kwi865qzfcWyK5i07lQSbNqkBUCdAgMBAAGjggG1MIIB
+sTAJBgNVHRMEAjAAMBEGCWCGSAGG+EIBAQQEAwIGQDALBgNVHQ8EBAMCBeAwPAYJ
+YIZIAYb4QgENBC8WLUlQc2VjIENlcnRpZmljYXRlIGZvciBhcm0tZGV2ZWwubmV0
+d2luZGVyLm9yZzAdBgNVHQ4EFgQUmHbtpUF8KDzIYw8J996esgC2Nv4wgcEGA1Ud
+IwSBuTCBtoAUejh16bmUq7YAxTaB6qVgPvr+5OGhgZqkgZcwgZQxCzAJBgNVBAYT
+AkNBMRAwDgYDVQQIEwdPbnRhcmlvMQ8wDQYDVQQHEwZPdHRhd2ExEjAQBgNVBAoT
+CVJlYmVsLmNvbTEQMA4GA1UECxMHU29mdEVuZzEVMBMGA1UEAxQMQ0FfYXJtLWRl
+dmVsMSUwIwYJKoZIhvcNAQkBFhZsdWMubGFudGhpZXJAcmViZWwuY29tggEAMEAG
+A1UdEQQ5MDeBFmx1Yy5sYW50aGllckByZWJlbC5jb22CF2FybS1kZXZlbC5uZXR3
+aW5kZXIub3JnhwQKCDF6MCEGA1UdEgQaMBiBFmx1Yy5sYW50aGllckByZWJlbC5j
+b20wDQYJKoZIhvcNAQEEBQADgYEAu6ka9ONVyPbn1jLLoi9tWKNdj1oNlVPHvwbn
+O8qZSJkvVShanjfvO0RzHuBhk0P4BGsGHmjlPqIQU5QvZnb8ZpPUXnbPLRji/+vA
+d8nVTQBgNFBZabl9B/vKi27uXNLZBi/u39gJEna8tReAqNanJVlctGXLKbHNdynp
+xAMA6sQ=
+-----END CERTIFICATE-----
diff -bruN freeswan-1.9.orig/doc/pkix/examples/dir-pk-rw.conf freeswan-1.9/doc/pkix/examples/dir-pk-rw.conf
--- freeswan-1.9.orig/doc/pkix/examples/dir-pk-rw.conf	Wed Dec 31 19:00:00 1969
+++ freeswan-1.9/doc/pkix/examples/dir-pk-rw.conf	Mon Jun  4 11:34:31 2001
@@ -0,0 +1,16 @@
+conn test
+	left=0.0.0.0
+	leftupdown=/usr/lib/ipsec/updown.netwinder
+	right=10.8.49.122
+	rightnexthop=10.8.54.1
+	rightupdown=/usr/lib/ipsec/updown.netwinder
+	authby=cert
+	auto=add
+	certfile=/etc/ipsec/pubcert.pem
+	keyfile=/etc/ipsec/privkey.pem
+	certpath=dir:/etc/ipsec/dir
+	certopts=send,strict,pk
+	#right DN: /C=CA/ST=Ontario/O=Rebel.com/OU=SoftEng/CN=arm-devel.netwinder.org/Email=luc.lanthier@rebel.com
+	rightid=@~30818E310B30090603550406130243413110300E060355040813074F6E746172696F31123010060355040A1309526562656C2E636F6D3110300E060355040B1307536F6674456E673120301E0603550403131761726D2D646576656C2E6E657477696E6465722E6F72673125302306092A864886F70D01090116166C75632E6C616E746869657240726562656C2E636F6D
+	#left DN: /C=CA/ST=Ontario/O=Rebel.com/OU=SoftEng/CN=arm1.netwinder.org/Email=firesoul@netwinder.org
+	leftid=@~308189310B30090603550406130243413110300E060355040813074F6E746172696F31123010060355040A1309526562656C2E636F6D3110300E060355040B1307536F6674456E67311B30190603550403131261726D312E6E657477696E6465722E6F72673125302306092A864886F70D010901161666697265736F756C406E657477696E6465722E6F7267
diff -bruN freeswan-1.9.orig/doc/pkix/examples/dir-pk.conf freeswan-1.9/doc/pkix/examples/dir-pk.conf
--- freeswan-1.9.orig/doc/pkix/examples/dir-pk.conf	Wed Dec 31 19:00:00 1969
+++ freeswan-1.9/doc/pkix/examples/dir-pk.conf	Mon Jun  4 11:34:31 2001
@@ -0,0 +1,17 @@
+conn test
+	left=10.1.49.124
+	leftnexthop=10.1.1.7
+	leftupdown=/usr/lib/ipsec/updown.netwinder
+	right=10.8.49.122
+	rightnexthop=10.8.54.1
+	rightupdown=/usr/lib/ipsec/updown.netwinder
+	authby=cert
+	auto=add
+	certfile=/etc/ipsec/pubcert.pem
+	keyfile=/etc/ipsec/privkey.pem
+	certpath=dir:/etc/ipsec/dir
+	certopts=send,strict,pk
+	#right DN: /C=CA/ST=Ontario/O=Rebel.com/OU=SoftEng/CN=arm-devel.netwinder.org/Email=luc.lanthier@rebel.com
+	rightid=@~30818E310B30090603550406130243413110300E060355040813074F6E746172696F31123010060355040A1309526562656C2E636F6D3110300E060355040B1307536F6674456E673120301E0603550403131761726D2D646576656C2E6E657477696E6465722E6F72673125302306092A864886F70D01090116166C75632E6C616E746869657240726562656C2E636F6D
+	#left DN: /C=CA/ST=Ontario/O=Rebel.com/OU=SoftEng/CN=arm1.netwinder.org/Email=firesoul@netwinder.org
+	leftid=@~308189310B30090603550406130243413110300E060355040813074F6E746172696F31123010060355040A1309526562656C2E636F6D3110300E060355040B1307536F6674456E67311B30190603550403131261726D312E6E657477696E6465722E6F72673125302306092A864886F70D010901161666697265736F756C406E657477696E6465722E6F7267
diff -bruN freeswan-1.9.orig/doc/pkix/examples/dir-rpk-rw.conf freeswan-1.9/doc/pkix/examples/dir-rpk-rw.conf
--- freeswan-1.9.orig/doc/pkix/examples/dir-rpk-rw.conf	Wed Dec 31 19:00:00 1969
+++ freeswan-1.9/doc/pkix/examples/dir-rpk-rw.conf	Mon Jun  4 11:34:31 2001
@@ -0,0 +1,16 @@
+conn test
+	left=0.0.0.0
+	leftupdown=/usr/lib/ipsec/updown.netwinder
+	right=10.8.49.122
+	rightnexthop=10.8.54.1
+	rightupdown=/usr/lib/ipsec/updown.netwinder
+	authby=cert
+	auto=add
+	certfile=/etc/ipsec/pubcert.pem
+	keyfile=/etc/ipsec/privkey.pem
+	certpath=dir:/etc/ipsec/dir
+	certopts=send,strict,pk,rev
+	#right DN: /C=CA/ST=Ontario/O=Rebel.com/OU=SoftEng/CN=arm-devel.netwinder.org/Email=luc.lanthier@rebel.com
+	rightid=@~30818E310B30090603550406130243413110300E060355040813074F6E746172696F31123010060355040A1309526562656C2E636F6D3110300E060355040B1307536F6674456E673120301E0603550403131761726D2D646576656C2E6E657477696E6465722E6F72673125302306092A864886F70D01090116166C75632E6C616E746869657240726562656C2E636F6D
+	#left DN: /C=CA/ST=Ontario/O=Rebel.com/OU=SoftEng/CN=arm1.netwinder.org/Email=firesoul@netwinder.org
+	leftid=@~308189310B30090603550406130243413110300E060355040813074F6E746172696F31123010060355040A1309526562656C2E636F6D3110300E060355040B1307536F6674456E67311B30190603550403131261726D312E6E657477696E6465722E6F72673125302306092A864886F70D010901161666697265736F756C406E657477696E6465722E6F7267
diff -bruN freeswan-1.9.orig/doc/pkix/examples/dir-rpk.conf freeswan-1.9/doc/pkix/examples/dir-rpk.conf
--- freeswan-1.9.orig/doc/pkix/examples/dir-rpk.conf	Wed Dec 31 19:00:00 1969
+++ freeswan-1.9/doc/pkix/examples/dir-rpk.conf	Mon Jun  4 11:34:31 2001
@@ -0,0 +1,17 @@
+conn test
+	left=10.1.49.124
+	leftnexthop=10.1.1.7
+	leftupdown=/usr/lib/ipsec/updown.netwinder
+	right=10.8.49.122
+	rightnexthop=10.8.54.1
+	rightupdown=/usr/lib/ipsec/updown.netwinder
+	authby=cert
+	auto=add
+	certfile=/etc/ipsec/pubcert.pem
+	keyfile=/etc/ipsec/privkey.pem
+	certpath=dir:/etc/ipsec/dir
+	certopts=send,strict,pk,rev
+	#right DN: /C=CA/ST=Ontario/O=Rebel.com/OU=SoftEng/CN=arm-devel.netwinder.org/Email=luc.lanthier@rebel.com
+	rightid=@~30818E310B30090603550406130243413110300E060355040813074F6E746172696F31123010060355040A1309526562656C2E636F6D3110300E060355040B1307536F6674456E673120301E0603550403131761726D2D646576656C2E6E657477696E6465722E6F72673125302306092A864886F70D01090116166C75632E6C616E746869657240726562656C2E636F6D
+	#left DN: /C=CA/ST=Ontario/O=Rebel.com/OU=SoftEng/CN=arm1.netwinder.org/Email=firesoul@netwinder.org
+	leftid=@~308189310B30090603550406130243413110300E060355040813074F6E746172696F31123010060355040A1309526562656C2E636F6D3110300E060355040B1307536F6674456E67311B30190603550403131261726D312E6E657477696E6465722E6F72673125302306092A864886F70D010901161666697265736F756C406E657477696E6465722E6F7267
diff -bruN freeswan-1.9.orig/doc/pkix/examples/dir-rsasig-rw.conf freeswan-1.9/doc/pkix/examples/dir-rsasig-rw.conf
--- freeswan-1.9.orig/doc/pkix/examples/dir-rsasig-rw.conf	Wed Dec 31 19:00:00 1969
+++ freeswan-1.9/doc/pkix/examples/dir-rsasig-rw.conf	Mon Jun  4 11:34:31 2001
@@ -0,0 +1,16 @@
+conn test
+	left=0.0.0.0
+	leftupdown=/usr/lib/ipsec/updown.netwinder
+	right=10.8.49.122
+	rightnexthop=10.8.54.1
+	rightupdown=/usr/lib/ipsec/updown.netwinder
+	authby=cert
+	auto=add
+	certfile=/etc/ipsec/pubcert.pem
+	keyfile=/etc/ipsec/privkey.pem
+	certpath=dir:/etc/ipsec/dir
+	certopts=send
+	#right DN: /C=CA/ST=Ontario/O=Rebel.com/OU=SoftEng/CN=arm-devel.netwinder.org/Email=luc.lanthier@rebel.com
+	rightid=@~30818E310B30090603550406130243413110300E060355040813074F6E746172696F31123010060355040A1309526562656C2E636F6D3110300E060355040B1307536F6674456E673120301E0603550403131761726D2D646576656C2E6E657477696E6465722E6F72673125302306092A864886F70D01090116166C75632E6C616E746869657240726562656C2E636F6D
+	#left DN: /C=CA/ST=Ontario/O=Rebel.com/OU=SoftEng/CN=arm1.netwinder.org/Email=firesoul@netwinder.org
+	leftid=@~308189310B30090603550406130243413110300E060355040813074F6E746172696F31123010060355040A1309526562656C2E636F6D3110300E060355040B1307536F6674456E67311B30190603550403131261726D312E6E657477696E6465722E6F72673125302306092A864886F70D010901161666697265736F756C406E657477696E6465722E6F7267
diff -bruN freeswan-1.9.orig/doc/pkix/examples/dir-rsasig.conf freeswan-1.9/doc/pkix/examples/dir-rsasig.conf
--- freeswan-1.9.orig/doc/pkix/examples/dir-rsasig.conf	Wed Dec 31 19:00:00 1969
+++ freeswan-1.9/doc/pkix/examples/dir-rsasig.conf	Mon Jun  4 11:34:31 2001
@@ -0,0 +1,17 @@
+conn test
+	left=10.1.49.124
+	leftnexthop=10.1.1.7
+	leftupdown=/usr/lib/ipsec/updown.netwinder
+	right=10.8.49.122
+	rightnexthop=10.8.54.1
+	rightupdown=/usr/lib/ipsec/updown.netwinder
+	authby=cert
+	auto=add
+	certfile=/etc/ipsec/pubcert.pem
+	keyfile=/etc/ipsec/privkey.pem
+	certpath=dir:/etc/ipsec/dir
+	certopts=send
+	#right DN: /C=CA/ST=Ontario/O=Rebel.com/OU=SoftEng/CN=arm-devel.netwinder.org/Email=luc.lanthier@rebel.com
+	rightid=@~30818E310B30090603550406130243413110300E060355040813074F6E746172696F31123010060355040A1309526562656C2E636F6D3110300E060355040B1307536F6674456E673120301E0603550403131761726D2D646576656C2E6E657477696E6465722E6F72673125302306092A864886F70D01090116166C75632E6C616E746869657240726562656C2E636F6D
+	#left DN: /C=CA/ST=Ontario/O=Rebel.com/OU=SoftEng/CN=arm1.netwinder.org/Email=firesoul@netwinder.org
+	leftid=@~308189310B30090603550406130243413110300E060355040813074F6E746172696F31123010060355040A1309526562656C2E636F6D3110300E060355040B1307536F6674456E67311B30190603550403131261726D312E6E657477696E6465722E6F72673125302306092A864886F70D010901161666697265736F756C406E657477696E6465722E6F7267
diff -bruN freeswan-1.9.orig/doc/pkix/examples/ff-pk-rw.conf freeswan-1.9/doc/pkix/examples/ff-pk-rw.conf
--- freeswan-1.9.orig/doc/pkix/examples/ff-pk-rw.conf	Wed Dec 31 19:00:00 1969
+++ freeswan-1.9/doc/pkix/examples/ff-pk-rw.conf	Mon Jun  4 11:34:31 2001
@@ -0,0 +1,16 @@
+conn test
+	left=0.0.0.0
+	leftupdown=/usr/lib/ipsec/updown.netwinder
+	right=10.8.49.122
+	rightnexthop=10.8.54.1
+	rightupdown=/usr/lib/ipsec/updown.netwinder
+	authby=cert
+	auto=add
+	certfile=/etc/ipsec/pubcert.pem
+	keyfile=/etc/ipsec/privkey.pem
+	certpath=file:/etc/ipsec/flatfile.txt
+	certopts=send,strict,pk
+	#right DN: /C=CA/ST=Ontario/O=Rebel.com/OU=SoftEng/CN=arm-devel.netwinder.org/Email=luc.lanthier@rebel.com
+	rightid=@~30818E310B30090603550406130243413110300E060355040813074F6E746172696F31123010060355040A1309526562656C2E636F6D3110300E060355040B1307536F6674456E673120301E0603550403131761726D2D646576656C2E6E657477696E6465722E6F72673125302306092A864886F70D01090116166C75632E6C616E746869657240726562656C2E636F6D
+	#left DN: /C=CA/ST=Ontario/O=Rebel.com/OU=SoftEng/CN=arm1.netwinder.org/Email=firesoul@netwinder.org
+	leftid=@~308189310B30090603550406130243413110300E060355040813074F6E746172696F31123010060355040A1309526562656C2E636F6D3110300E060355040B1307536F6674456E67311B30190603550403131261726D312E6E657477696E6465722E6F72673125302306092A864886F70D010901161666697265736F756C406E657477696E6465722E6F7267
diff -bruN freeswan-1.9.orig/doc/pkix/examples/ff-pk.conf freeswan-1.9/doc/pkix/examples/ff-pk.conf
--- freeswan-1.9.orig/doc/pkix/examples/ff-pk.conf	Wed Dec 31 19:00:00 1969
+++ freeswan-1.9/doc/pkix/examples/ff-pk.conf	Mon Jun  4 11:34:31 2001
@@ -0,0 +1,17 @@
+conn test
+	left=10.1.49.124
+	leftnexthop=10.1.1.7
+	leftupdown=/usr/lib/ipsec/updown.netwinder
+	right=10.8.49.122
+	rightnexthop=10.8.54.1
+	rightupdown=/usr/lib/ipsec/updown.netwinder
+	authby=cert
+	auto=add
+	certfile=/etc/ipsec/pubcert.pem
+	keyfile=/etc/ipsec/privkey.pem
+	certpath=file:/etc/ipsec/flatfile.txt
+	certopts=send,strict,pk
+	#right DN: /C=CA/ST=Ontario/O=Rebel.com/OU=SoftEng/CN=arm-devel.netwinder.org/Email=luc.lanthier@rebel.com
+	rightid=@~30818E310B30090603550406130243413110300E060355040813074F6E746172696F31123010060355040A1309526562656C2E636F6D3110300E060355040B1307536F6674456E673120301E0603550403131761726D2D646576656C2E6E657477696E6465722E6F72673125302306092A864886F70D01090116166C75632E6C616E746869657240726562656C2E636F6D
+	#left DN: /C=CA/ST=Ontario/O=Rebel.com/OU=SoftEng/CN=arm1.netwinder.org/Email=firesoul@netwinder.org
+	leftid=@~308189310B30090603550406130243413110300E060355040813074F6E746172696F31123010060355040A1309526562656C2E636F6D3110300E060355040B1307536F6674456E67311B30190603550403131261726D312E6E657477696E6465722E6F72673125302306092A864886F70D010901161666697265736F756C406E657477696E6465722E6F7267
diff -bruN freeswan-1.9.orig/doc/pkix/examples/ff-rpk-rw.conf freeswan-1.9/doc/pkix/examples/ff-rpk-rw.conf
--- freeswan-1.9.orig/doc/pkix/examples/ff-rpk-rw.conf	Wed Dec 31 19:00:00 1969
+++ freeswan-1.9/doc/pkix/examples/ff-rpk-rw.conf	Mon Jun  4 11:34:31 2001
@@ -0,0 +1,16 @@
+conn test
+	left=0.0.0.0
+	leftupdown=/usr/lib/ipsec/updown.netwinder
+	right=10.8.49.122
+	rightnexthop=10.8.54.1
+	rightupdown=/usr/lib/ipsec/updown.netwinder
+	authby=cert
+	auto=add
+	certfile=/etc/ipsec/pubcert.pem
+	keyfile=/etc/ipsec/privkey.pem
+	certpath=file:/etc/ipsec/flatfile.txt
+	certopts=send,strict,pk,rev
+	#right DN: /C=CA/ST=Ontario/O=Rebel.com/OU=SoftEng/CN=arm-devel.netwinder.org/Email=luc.lanthier@rebel.com
+	rightid=@~30818E310B30090603550406130243413110300E060355040813074F6E746172696F31123010060355040A1309526562656C2E636F6D3110300E060355040B1307536F6674456E673120301E0603550403131761726D2D646576656C2E6E657477696E6465722E6F72673125302306092A864886F70D01090116166C75632E6C616E746869657240726562656C2E636F6D
+	#left DN: /C=CA/ST=Ontario/O=Rebel.com/OU=SoftEng/CN=arm1.netwinder.org/Email=firesoul@netwinder.org
+	leftid=@~308189310B30090603550406130243413110300E060355040813074F6E746172696F31123010060355040A1309526562656C2E636F6D3110300E060355040B1307536F6674456E67311B30190603550403131261726D312E6E657477696E6465722E6F72673125302306092A864886F70D010901161666697265736F756C406E657477696E6465722E6F7267
diff -bruN freeswan-1.9.orig/doc/pkix/examples/ff-rpk.conf freeswan-1.9/doc/pkix/examples/ff-rpk.conf
--- freeswan-1.9.orig/doc/pkix/examples/ff-rpk.conf	Wed Dec 31 19:00:00 1969
+++ freeswan-1.9/doc/pkix/examples/ff-rpk.conf	Mon Jun  4 11:34:31 2001
@@ -0,0 +1,17 @@
+conn test
+	left=10.1.49.124
+	leftnexthop=10.1.1.7
+	leftupdown=/usr/lib/ipsec/updown.netwinder
+	right=10.8.49.122
+	rightnexthop=10.8.54.1
+	rightupdown=/usr/lib/ipsec/updown.netwinder
+	authby=cert
+	auto=add
+	certfile=/etc/ipsec/pubcert.pem
+	keyfile=/etc/ipsec/privkey.pem
+	certpath=file:/etc/ipsec/flatfile.txt
+	certopts=send,strict,pk,rev
+	#right DN: /C=CA/ST=Ontario/O=Rebel.com/OU=SoftEng/CN=arm-devel.netwinder.org/Email=luc.lanthier@rebel.com
+	rightid=@~30818E310B30090603550406130243413110300E060355040813074F6E746172696F31123010060355040A1309526562656C2E636F6D3110300E060355040B1307536F6674456E673120301E0603550403131761726D2D646576656C2E6E657477696E6465722E6F72673125302306092A864886F70D01090116166C75632E6C616E746869657240726562656C2E636F6D
+	#left DN: /C=CA/ST=Ontario/O=Rebel.com/OU=SoftEng/CN=arm1.netwinder.org/Email=firesoul@netwinder.org
+	leftid=@~308189310B30090603550406130243413110300E060355040813074F6E746172696F31123010060355040A1309526562656C2E636F6D3110300E060355040B1307536F6674456E67311B30190603550403131261726D312E6E657477696E6465722E6F72673125302306092A864886F70D010901161666697265736F756C406E657477696E6465722E6F7267
diff -bruN freeswan-1.9.orig/doc/pkix/examples/ff-rsasig-rw.conf freeswan-1.9/doc/pkix/examples/ff-rsasig-rw.conf
--- freeswan-1.9.orig/doc/pkix/examples/ff-rsasig-rw.conf	Wed Dec 31 19:00:00 1969
+++ freeswan-1.9/doc/pkix/examples/ff-rsasig-rw.conf	Mon Jun  4 11:34:31 2001
@@ -0,0 +1,16 @@
+conn test
+	left=0.0.0.0
+	leftupdown=/usr/lib/ipsec/updown.netwinder
+	right=10.8.49.122
+	rightnexthop=10.8.54.1
+	rightupdown=/usr/lib/ipsec/updown.netwinder
+	authby=cert
+	auto=add
+	certfile=/etc/ipsec/pubcert.pem
+	keyfile=/etc/ipsec/privkey.pem
+	certpath=file:/etc/ipsec/flatfile.txt
+	certopts=send
+	#right DN: /C=CA/ST=Ontario/O=Rebel.com/OU=SoftEng/CN=arm-devel.netwinder.org/Email=luc.lanthier@rebel.com
+	rightid=@~30818E310B30090603550406130243413110300E060355040813074F6E746172696F31123010060355040A1309526562656C2E636F6D3110300E060355040B1307536F6674456E673120301E0603550403131761726D2D646576656C2E6E657477696E6465722E6F72673125302306092A864886F70D01090116166C75632E6C616E746869657240726562656C2E636F6D
+	#left DN: /C=CA/ST=Ontario/O=Rebel.com/OU=SoftEng/CN=arm1.netwinder.org/Email=firesoul@netwinder.org
+	leftid=@~308189310B30090603550406130243413110300E060355040813074F6E746172696F31123010060355040A1309526562656C2E636F6D3110300E060355040B1307536F6674456E67311B30190603550403131261726D312E6E657477696E6465722E6F72673125302306092A864886F70D010901161666697265736F756C406E657477696E6465722E6F7267
diff -bruN freeswan-1.9.orig/doc/pkix/examples/ff-rsasig.conf freeswan-1.9/doc/pkix/examples/ff-rsasig.conf
--- freeswan-1.9.orig/doc/pkix/examples/ff-rsasig.conf	Wed Dec 31 19:00:00 1969
+++ freeswan-1.9/doc/pkix/examples/ff-rsasig.conf	Mon Jun  4 11:34:31 2001
@@ -0,0 +1,17 @@
+conn test
+	left=10.1.49.124
+	leftnexthop=10.1.1.7
+	leftupdown=/usr/lib/ipsec/updown.netwinder
+	right=10.8.49.122
+	rightnexthop=10.8.54.1
+	rightupdown=/usr/lib/ipsec/updown.netwinder
+	authby=cert
+	auto=add
+	certfile=/etc/ipsec/pubcert.pem
+	keyfile=/etc/ipsec/privkey.pem
+	certpath=file:/etc/ipsec/flatfile.txt
+	certopts=send
+	#right DN: /C=CA/ST=Ontario/O=Rebel.com/OU=SoftEng/CN=arm-devel.netwinder.org/Email=luc.lanthier@rebel.com
+	rightid=@~30818E310B30090603550406130243413110300E060355040813074F6E746172696F31123010060355040A1309526562656C2E636F6D3110300E060355040B1307536F6674456E673120301E0603550403131761726D2D646576656C2E6E657477696E6465722E6F72673125302306092A864886F70D01090116166C75632E6C616E746869657240726562656C2E636F6D
+	#left DN: /C=CA/ST=Ontario/O=Rebel.com/OU=SoftEng/CN=arm1.netwinder.org/Email=firesoul@netwinder.org
+	leftid=@~308189310B30090603550406130243413110300E060355040813074F6E746172696F31123010060355040A1309526562656C2E636F6D3110300E060355040B1307536F6674456E67311B30190603550403131261726D312E6E657477696E6465722E6F72673125302306092A864886F70D010901161666697265736F756C406E657477696E6465722E6F7267
diff -bruN freeswan-1.9.orig/doc/pkix/examples/flatfile.txt freeswan-1.9/doc/pkix/examples/flatfile.txt
--- freeswan-1.9.orig/doc/pkix/examples/flatfile.txt	Wed Dec 31 19:00:00 1969
+++ freeswan-1.9/doc/pkix/examples/flatfile.txt	Mon Jun  4 11:34:31 2001
@@ -0,0 +1,92 @@
+ip: 10.8.49.122
+dns: arm-devel.netwinder.org
+-----BEGIN CERTIFICATE-----
+MIIEUTCCA7qgAwIBAgIBATANBgkqhkiG9w0BAQQFADCBlDELMAkGA1UEBhMCQ0Ex
+EDAOBgNVBAgTB09udGFyaW8xDzANBgNVBAcTBk90dGF3YTESMBAGA1UEChMJUmVi
+ZWwuY29tMRAwDgYDVQQLEwdTb2Z0RW5nMRUwEwYDVQQDFAxDQV9hcm0tZGV2ZWwx
+JTAjBgkqhkiG9w0BCQEWFmx1Yy5sYW50aGllckByZWJlbC5jb20wHhcNMDEwMjE0
+MjA1OTEzWhcNMDIwMjE0MjA1OTEzWjCBjjELMAkGA1UEBhMCQ0ExEDAOBgNVBAgT
+B09udGFyaW8xEjAQBgNVBAoTCVJlYmVsLmNvbTEQMA4GA1UECxMHU29mdEVuZzEg
+MB4GA1UEAxMXYXJtLWRldmVsLm5ldHdpbmRlci5vcmcxJTAjBgkqhkiG9w0BCQEW
+Fmx1Yy5sYW50aGllckByZWJlbC5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJ
+AoGBAKipDCwh/JsC1vSYx8Pc0Y0xkftyQasJ6FKbvjV12PD2tbqKDNkCm1qpDZjm
+to+XResX4xAjxJCR9O3M/3b9lT16psRZsEVF9gupyQx3bV5T0YcNWXlQ+ZTBZI5e
+4TiUrnx/aF4QUT3vnJ/0Kwi865qzfcWyK5i07lQSbNqkBUCdAgMBAAGjggG1MIIB
+sTAJBgNVHRMEAjAAMBEGCWCGSAGG+EIBAQQEAwIGQDALBgNVHQ8EBAMCBeAwPAYJ
+YIZIAYb4QgENBC8WLUlQc2VjIENlcnRpZmljYXRlIGZvciBhcm0tZGV2ZWwubmV0
+d2luZGVyLm9yZzAdBgNVHQ4EFgQUmHbtpUF8KDzIYw8J996esgC2Nv4wgcEGA1Ud
+IwSBuTCBtoAUejh16bmUq7YAxTaB6qVgPvr+5OGhgZqkgZcwgZQxCzAJBgNVBAYT
+AkNBMRAwDgYDVQQIEwdPbnRhcmlvMQ8wDQYDVQQHEwZPdHRhd2ExEjAQBgNVBAoT
+CVJlYmVsLmNvbTEQMA4GA1UECxMHU29mdEVuZzEVMBMGA1UEAxQMQ0FfYXJtLWRl
+dmVsMSUwIwYJKoZIhvcNAQkBFhZsdWMubGFudGhpZXJAcmViZWwuY29tggEAMEAG
+A1UdEQQ5MDeBFmx1Yy5sYW50aGllckByZWJlbC5jb22CF2FybS1kZXZlbC5uZXR3
+aW5kZXIub3JnhwQKCDF6MCEGA1UdEgQaMBiBFmx1Yy5sYW50aGllckByZWJlbC5j
+b20wDQYJKoZIhvcNAQEEBQADgYEAu6ka9ONVyPbn1jLLoi9tWKNdj1oNlVPHvwbn
+O8qZSJkvVShanjfvO0RzHuBhk0P4BGsGHmjlPqIQU5QvZnb8ZpPUXnbPLRji/+vA
+d8nVTQBgNFBZabl9B/vKi27uXNLZBi/u39gJEna8tReAqNanJVlctGXLKbHNdynp
+xAMA6sQ=
+-----END CERTIFICATE-----
+
+ip: 10.1.49.124
+dns: arm1.netwinder.org
+-----BEGIN CERTIFICATE-----
+MIIEQjCCA6ugAwIBAgIBAjANBgkqhkiG9w0BAQQFADCBlDELMAkGA1UEBhMCQ0Ex
+EDAOBgNVBAgTB09udGFyaW8xDzANBgNVBAcTBk90dGF3YTESMBAGA1UEChMJUmVi
+ZWwuY29tMRAwDgYDVQQLEwdTb2Z0RW5nMRUwEwYDVQQDFAxDQV9hcm0tZGV2ZWwx
+JTAjBgkqhkiG9w0BCQEWFmx1Yy5sYW50aGllckByZWJlbC5jb20wHhcNMDEwMjE0
+MjEwMDExWhcNMDIwMjE0MjEwMDExWjCBiTELMAkGA1UEBhMCQ0ExEDAOBgNVBAgT
+B09udGFyaW8xEjAQBgNVBAoTCVJlYmVsLmNvbTEQMA4GA1UECxMHU29mdEVuZzEb
+MBkGA1UEAxMSYXJtMS5uZXR3aW5kZXIub3JnMSUwIwYJKoZIhvcNAQkBFhZmaXJl
+c291bEBuZXR3aW5kZXIub3JnMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDi
+K61waynng76vElBLpCYCYO35vUlRhpYYnBDxDH29uSKOZmr0luWN4sQRHmSOWR6x
+omQV+qYXmlnzn5/IyRe4p4dVcI/eJXjm4EyCrvFHFHf6Wz5N5QVeMQliVvg7lFGy
+4367j27c6mQuL2WOQRgOz52KuAqGbGqIvljOvrMywQIDAQABo4IBqzCCAacwCQYD
+VR0TBAIwADARBglghkgBhvhCAQEEBAMCBkAwCwYDVR0PBAQDAgXgMDcGCWCGSAGG
++EIBDQQqFihJUHNlYyBDZXJ0aWZpY2F0ZSBmb3IgYXJtMS5uZXR3aW5kZXIub3Jn
+MB0GA1UdDgQWBBSCom5YDbaY79mgaJ3QwHBZs2oymTCBwQYDVR0jBIG5MIG2gBR6
+OHXpuZSrtgDFNoHqpWA++v7k4aGBmqSBlzCBlDELMAkGA1UEBhMCQ0ExEDAOBgNV
+BAgTB09udGFyaW8xDzANBgNVBAcTBk90dGF3YTESMBAGA1UEChMJUmViZWwuY29t
+MRAwDgYDVQQLEwdTb2Z0RW5nMRUwEwYDVQQDFAxDQV9hcm0tZGV2ZWwxJTAjBgkq
+hkiG9w0BCQEWFmx1Yy5sYW50aGllckByZWJlbC5jb22CAQAwOwYDVR0RBDQwMoEW
+ZmlyZXNvdWxAbmV0d2luZGVyLm9yZ4ISYXJtMS5uZXR3aW5kZXIub3JnhwQKATF8
+MCEGA1UdEgQaMBiBFmx1Yy5sYW50aGllckByZWJlbC5jb20wDQYJKoZIhvcNAQEE
+BQADgYEAw2gZX2ASGG9Ih/mX0qMPvOTQWTdpFygyVX1cejX/4WcF9TGAJ8w6NyhH
+RuzZsPlprM5tiZQZFjhku9pnaMXjJuNmmLJFvw0WK5UMGsxljMX0ui8rWvStmnGS
+3uV3xAiWfMMlJf5DsPP5ZR/6bC0u4h8YdQNRM5RhKVkanHxxQuE=
+-----END CERTIFICATE-----
+
+-----BEGIN CERTIFICATE-----
+MIID2jCCA0OgAwIBAgIBADANBgkqhkiG9w0BAQQFADCBlDELMAkGA1UEBhMCQ0Ex
+EDAOBgNVBAgTB09udGFyaW8xDzANBgNVBAcTBk90dGF3YTESMBAGA1UEChMJUmVi
+ZWwuY29tMRAwDgYDVQQLEwdTb2Z0RW5nMRUwEwYDVQQDFAxDQV9hcm0tZGV2ZWwx
+JTAjBgkqhkiG9w0BCQEWFmx1Yy5sYW50aGllckByZWJlbC5jb20wHhcNMDEwMjE0
+MTk0NTAyWhcNMDYwODA3MTk0NTAyWjCBlDELMAkGA1UEBhMCQ0ExEDAOBgNVBAgT
+B09udGFyaW8xDzANBgNVBAcTBk90dGF3YTESMBAGA1UEChMJUmViZWwuY29tMRAw
+DgYDVQQLEwdTb2Z0RW5nMRUwEwYDVQQDFAxDQV9hcm0tZGV2ZWwxJTAjBgkqhkiG
+9w0BCQEWFmx1Yy5sYW50aGllckByZWJlbC5jb20wgZ8wDQYJKoZIhvcNAQEBBQAD
+gY0AMIGJAoGBANWu/vkaR1M1bvP2Y80Dv105n3VHmOqZcyy9fnbaXXc92nKbBMib
+bsuUdfWdjOuC34BjfNuC9DU3rP8jZNBg+qeyAie6G7Q1R3atroqYvaFFhEbU1OnZ
+vBigB39dOIjfFiHbeqNCqlxLlrMJwkBJtkLdiktuf6Rqp+nnX6ymxz1BAgMBAAGj
+ggE4MIIBNDAdBgNVHQ4EFgQUejh16bmUq7YAxTaB6qVgPvr+5OEwgcEGA1UdIwSB
+uTCBtoAUejh16bmUq7YAxTaB6qVgPvr+5OGhgZqkgZcwgZQxCzAJBgNVBAYTAkNB
+MRAwDgYDVQQIEwdPbnRhcmlvMQ8wDQYDVQQHEwZPdHRhd2ExEjAQBgNVBAoTCVJl
+YmVsLmNvbTEQMA4GA1UECxMHU29mdEVuZzEVMBMGA1UEAxQMQ0FfYXJtLWRldmVs
+MSUwIwYJKoZIhvcNAQkBFhZsdWMubGFudGhpZXJAcmViZWwuY29tggEAMAwGA1Ud
+EwQFMAMBAf8wCwYDVR0PBAQDAgEGMBEGCWCGSAGG+EIBAQQEAwIBBjAhBgNVHREE
+GjAYgRZsdWMubGFudGhpZXJAcmViZWwuY29tMA0GCSqGSIb3DQEBBAUAA4GBAHzh
+QeKz7deGehWh7KtZ1tNNu1gWxeW4fwjHUT/xkoepd0XclIIRoKH+2h6w5QG3p2Up
+9TLxWlS8SB0tR0FiVu1WD658vOZjDTqqL9EVdEgSCrWX26KaMhNLrYzT3nzqq9VR
+QYqYZDAD3Z345UweqfCJBgxrim03x++bsEq9tP4Y
+-----END CERTIFICATE-----
+
+-----BEGIN X509 CRL-----
+MIIBWjCBxDANBgkqhkiG9w0BAQQFADCBlDELMAkGA1UEBhMCQ0ExEDAOBgNVBAgT
+B09udGFyaW8xDzANBgNVBAcTBk90dGF3YTESMBAGA1UEChMJUmViZWwuY29tMRAw
+DgYDVQQLEwdTb2Z0RW5nMRUwEwYDVQQDFAxDQV9hcm0tZGV2ZWwxJTAjBgkqhkiG
+9w0BCQEWFmx1Yy5sYW50aGllckByZWJlbC5jb20XDTAxMDIxNDE5NDUzN1oXDTAx
+MDMxNjE5NDUzN1owDQYJKoZIhvcNAQEEBQADgYEAcM3oRcSVw2rf7AQbcX0WqsEh
+YEHnMUNur13Wd2ai7b6KSKxHj+O/WWSupH3IDPL1TEKwdWLG9+MtbhKhBh8WNzQh
+7Nl/NzTgdCh0xDBoJDGG7zN7WDNQ1WGbaAkjDUJm6ty92zlpFkF4Gg2B1dl8WwYK
+LSSaMtj6/VV4CuhzFMg=
+-----END X509 CRL-----
+
diff -bruN freeswan-1.9.orig/doc/pkix/examples/ipsec.conf freeswan-1.9/doc/pkix/examples/ipsec.conf
--- freeswan-1.9.orig/doc/pkix/examples/ipsec.conf	Wed Dec 31 19:00:00 1969
+++ freeswan-1.9/doc/pkix/examples/ipsec.conf	Mon Jun  4 11:34:31 2001
@@ -0,0 +1,60 @@
+# /etc/ipsec.conf - FreeS/WAN IPSEC configuration file
+
+# More elaborate and more varied sample configurations can be found
+# in doc/examples.
+
+# basic configuration
+config setup
+	# THIS SETTING MUST BE CORRECT or almost nothing will work;
+	# %defaultroute is okay for most simple cases.
+	interfaces=%defaultroute
+	# Debug-logging controls:  "none" for (almost) none, "all" for lots.
+	klipsdebug=none
+	#plutodebug=all
+	#plutodebug=crypt
+	plutodebug=none
+	# Use auto= parameters in conn descriptions to control startup actions.
+	plutoload=%search
+	plutostart=%search
+
+# defaults for subsequent connection descriptions
+conn %default
+	# How persistent to be in (re)keying negotiations (0 means very).
+	keyingtries=3
+	# Authentication by RSA signature keys
+	authby=rsasig
+
+#Standard connection types.
+#include /etc/ipsec/psk.conf
+#include /etc/ipsec/rsasig.conf
+#include /etc/ipsec/rsasig-rw.conf
+#
+# PKIX ########
+# LDAP lookups
+#include /etc/ipsec/ldap-rsasig.conf
+#include /etc/ipsec/ldap-rsasig-rw.conf
+#include /etc/ipsec/ldap-pk.conf
+include /etc/ipsec/ldap-pk-rw.conf
+#include /etc/ipsec/ldap-rpk.conf
+#include /etc/ipsec/ldap-rpk-rw.conf
+# dir lookups
+#include /etc/ipsec/dir-rsasig.conf
+#include /etc/ipsec/dir-rsasig-rw.conf
+#include /etc/ipsec/dir-pk.conf
+#include /etc/ipsec/dir-pk-rw.conf
+#include /etc/ipsec/dir-rpk.conf
+#include /etc/ipsec/dir-rpk-rw.conf
+# db lookups
+#include /etc/ipsec/db-rsasig.conf
+#include /etc/ipsec/db-rsasig-rw.conf
+#include /etc/ipsec/db-pk.conf
+#include /etc/ipsec/db-pk-rw.conf
+#include /etc/ipsec/db-rpk.conf
+#include /etc/ipsec/db-rpk-rw.conf
+# flatfile lookups
+#include /etc/ipsec/ff-rsasig.conf
+#include /etc/ipsec/ff-rsasig-rw.conf
+#include /etc/ipsec/ff-pk.conf
+#include /etc/ipsec/ff-pk-rw.conf
+#include /etc/ipsec/ff-rpk.conf
+#include /etc/ipsec/ff-rpk-rw.conf
diff -bruN freeswan-1.9.orig/doc/pkix/examples/ldap-pk-rw.conf freeswan-1.9/doc/pkix/examples/ldap-pk-rw.conf
--- freeswan-1.9.orig/doc/pkix/examples/ldap-pk-rw.conf	Wed Dec 31 19:00:00 1969
+++ freeswan-1.9/doc/pkix/examples/ldap-pk-rw.conf	Mon Jun  4 11:34:31 2001
@@ -0,0 +1,16 @@
+conn test
+	left=0.0.0.0
+	leftupdown=/usr/lib/ipsec/updown.netwinder
+	right=10.8.49.122
+	rightnexthop=10.8.54.1
+	rightupdown=/usr/lib/ipsec/updown.netwinder
+	authby=cert
+	auto=add
+	certfile=/etc/ipsec/pubcert.pem
+	keyfile=/etc/ipsec/privkey.pem
+	certpath=ldap:/etc/ipsec/ldap.cnf:ldapdevel
+	certopts=send,strict,pk
+	#right DN: /C=CA/ST=Ontario/O=Rebel.com/OU=SoftEng/CN=arm-devel.netwinder.org/Email=luc.lanthier@rebel.com
+	rightid=@~30818E310B30090603550406130243413110300E060355040813074F6E746172696F31123010060355040A1309526562656C2E636F6D3110300E060355040B1307536F6674456E673120301E0603550403131761726D2D646576656C2E6E657477696E6465722E6F72673125302306092A864886F70D01090116166C75632E6C616E746869657240726562656C2E636F6D
+	#left DN: /C=CA/ST=Ontario/O=Rebel.com/OU=SoftEng/CN=arm1.netwinder.org/Email=firesoul@netwinder.org
+	leftid=@~308189310B30090603550406130243413110300E060355040813074F6E746172696F31123010060355040A1309526562656C2E636F6D3110300E060355040B1307536F6674456E67311B30190603550403131261726D312E6E657477696E6465722E6F72673125302306092A864886F70D010901161666697265736F756C406E657477696E6465722E6F7267
diff -bruN freeswan-1.9.orig/doc/pkix/examples/ldap-pk.conf freeswan-1.9/doc/pkix/examples/ldap-pk.conf
--- freeswan-1.9.orig/doc/pkix/examples/ldap-pk.conf	Wed Dec 31 19:00:00 1969
+++ freeswan-1.9/doc/pkix/examples/ldap-pk.conf	Mon Jun  4 11:34:31 2001
@@ -0,0 +1,17 @@
+conn test
+	left=10.1.49.124
+	leftnexthop=10.1.1.7
+	leftupdown=/usr/lib/ipsec/updown.netwinder
+	right=10.8.49.122
+	rightnexthop=10.8.54.1
+	rightupdown=/usr/lib/ipsec/updown.netwinder
+	authby=cert
+	auto=add
+	certfile=/etc/ipsec/pubcert.pem
+	keyfile=/etc/ipsec/privkey.pem
+	certpath=ldap:/etc/ipsec/ldap.cnf:ldapdevel
+	certopts=send,strict,pk
+	#right DN: /C=CA/ST=Ontario/O=Rebel.com/OU=SoftEng/CN=arm-devel.netwinder.org/Email=luc.lanthier@rebel.com
+	rightid=@~30818E310B30090603550406130243413110300E060355040813074F6E746172696F31123010060355040A1309526562656C2E636F6D3110300E060355040B1307536F6674456E673120301E0603550403131761726D2D646576656C2E6E657477696E6465722E6F72673125302306092A864886F70D01090116166C75632E6C616E746869657240726562656C2E636F6D
+	#left DN: /C=CA/ST=Ontario/O=Rebel.com/OU=SoftEng/CN=arm1.netwinder.org/Email=firesoul@netwinder.org
+	leftid=@~308189310B30090603550406130243413110300E060355040813074F6E746172696F31123010060355040A1309526562656C2E636F6D3110300E060355040B1307536F6674456E67311B30190603550403131261726D312E6E657477696E6465722E6F72673125302306092A864886F70D010901161666697265736F756C406E657477696E6465722E6F7267
diff -bruN freeswan-1.9.orig/doc/pkix/examples/ldap-rpk-rw.conf freeswan-1.9/doc/pkix/examples/ldap-rpk-rw.conf
--- freeswan-1.9.orig/doc/pkix/examples/ldap-rpk-rw.conf	Wed Dec 31 19:00:00 1969
+++ freeswan-1.9/doc/pkix/examples/ldap-rpk-rw.conf	Mon Jun  4 11:34:31 2001
@@ -0,0 +1,16 @@
+conn test
+	left=0.0.0.0
+	leftupdown=/usr/lib/ipsec/updown.netwinder
+	right=10.8.49.122
+	rightnexthop=10.8.54.1
+	rightupdown=/usr/lib/ipsec/updown.netwinder
+	authby=cert
+	auto=add
+	certfile=/etc/ipsec/pubcert.pem
+	keyfile=/etc/ipsec/privkey.pem
+	certpath=ldap:/etc/ipsec/ldap.cnf:ldapdevel
+	certopts=send,strict,pk,rev
+	#right DN: /C=CA/ST=Ontario/O=Rebel.com/OU=SoftEng/CN=arm-devel.netwinder.org/Email=luc.lanthier@rebel.com
+	rightid=@~30818E310B30090603550406130243413110300E060355040813074F6E746172696F31123010060355040A1309526562656C2E636F6D3110300E060355040B1307536F6674456E673120301E0603550403131761726D2D646576656C2E6E657477696E6465722E6F72673125302306092A864886F70D01090116166C75632E6C616E746869657240726562656C2E636F6D
+	#left DN: /C=CA/ST=Ontario/O=Rebel.com/OU=SoftEng/CN=arm1.netwinder.org/Email=firesoul@netwinder.org
+	leftid=@~308189310B30090603550406130243413110300E060355040813074F6E746172696F31123010060355040A1309526562656C2E636F6D3110300E060355040B1307536F6674456E67311B30190603550403131261726D312E6E657477696E6465722E6F72673125302306092A864886F70D010901161666697265736F756C406E657477696E6465722E6F7267
diff -bruN freeswan-1.9.orig/doc/pkix/examples/ldap-rpk.conf freeswan-1.9/doc/pkix/examples/ldap-rpk.conf
--- freeswan-1.9.orig/doc/pkix/examples/ldap-rpk.conf	Wed Dec 31 19:00:00 1969
+++ freeswan-1.9/doc/pkix/examples/ldap-rpk.conf	Mon Jun  4 11:34:31 2001
@@ -0,0 +1,17 @@
+conn test
+	left=10.1.49.124
+	leftnexthop=10.1.1.7
+	leftupdown=/usr/lib/ipsec/updown.netwinder
+	right=10.8.49.122
+	rightnexthop=10.8.54.1
+	rightupdown=/usr/lib/ipsec/updown.netwinder
+	authby=cert
+	auto=add
+	certfile=/etc/ipsec/pubcert.pem
+	keyfile=/etc/ipsec/privkey.pem
+	certpath=ldap:/etc/ipsec/ldap.cnf:ldapdevel
+	certopts=send,strict,pk,rev
+	#right DN: /C=CA/ST=Ontario/O=Rebel.com/OU=SoftEng/CN=arm-devel.netwinder.org/Email=luc.lanthier@rebel.com
+	rightid=@~30818E310B30090603550406130243413110300E060355040813074F6E746172696F31123010060355040A1309526562656C2E636F6D3110300E060355040B1307536F6674456E673120301E0603550403131761726D2D646576656C2E6E657477696E6465722E6F72673125302306092A864886F70D01090116166C75632E6C616E746869657240726562656C2E636F6D
+	#left DN: /C=CA/ST=Ontario/O=Rebel.com/OU=SoftEng/CN=arm1.netwinder.org/Email=firesoul@netwinder.org
+	leftid=@~308189310B30090603550406130243413110300E060355040813074F6E746172696F31123010060355040A1309526562656C2E636F6D3110300E060355040B1307536F6674456E67311B30190603550403131261726D312E6E657477696E6465722E6F72673125302306092A864886F70D010901161666697265736F756C406E657477696E6465722E6F7267
diff -bruN freeswan-1.9.orig/doc/pkix/examples/ldap-rsasig-rw.conf freeswan-1.9/doc/pkix/examples/ldap-rsasig-rw.conf
--- freeswan-1.9.orig/doc/pkix/examples/ldap-rsasig-rw.conf	Wed Dec 31 19:00:00 1969
+++ freeswan-1.9/doc/pkix/examples/ldap-rsasig-rw.conf	Mon Jun  4 11:34:31 2001
@@ -0,0 +1,16 @@
+conn test
+	left=0.0.0.0
+	leftupdown=/usr/lib/ipsec/updown.netwinder
+	right=10.8.49.122
+	rightnexthop=10.8.54.1
+	rightupdown=/usr/lib/ipsec/updown.netwinder
+	authby=cert
+	auto=add
+	certfile=/etc/ipsec/pubcert.pem
+	keyfile=/etc/ipsec/privkey.pem
+	certpath=ldap:/etc/ipsec/ldap.cnf:ldapdevel
+	certopts=send
+	#right DN: /C=CA/ST=Ontario/O=Rebel.com/OU=SoftEng/CN=arm-devel.netwinder.org/Email=luc.lanthier@rebel.com
+	rightid=@~30818E310B30090603550406130243413110300E060355040813074F6E746172696F31123010060355040A1309526562656C2E636F6D3110300E060355040B1307536F6674456E673120301E0603550403131761726D2D646576656C2E6E657477696E6465722E6F72673125302306092A864886F70D01090116166C75632E6C616E746869657240726562656C2E636F6D
+	#left DN: /C=CA/ST=Ontario/O=Rebel.com/OU=SoftEng/CN=arm1.netwinder.org/Email=firesoul@netwinder.org
+	leftid=@~308189310B30090603550406130243413110300E060355040813074F6E746172696F31123010060355040A1309526562656C2E636F6D3110300E060355040B1307536F6674456E67311B30190603550403131261726D312E6E657477696E6465722E6F72673125302306092A864886F70D010901161666697265736F756C406E657477696E6465722E6F7267
diff -bruN freeswan-1.9.orig/doc/pkix/examples/ldap-rsasig.conf freeswan-1.9/doc/pkix/examples/ldap-rsasig.conf
--- freeswan-1.9.orig/doc/pkix/examples/ldap-rsasig.conf	Wed Dec 31 19:00:00 1969
+++ freeswan-1.9/doc/pkix/examples/ldap-rsasig.conf	Mon Jun  4 11:34:31 2001
@@ -0,0 +1,17 @@
+conn test
+	left=10.1.49.124
+	leftnexthop=10.1.1.7
+	leftupdown=/usr/lib/ipsec/updown.netwinder
+	right=10.8.49.122
+	rightnexthop=10.8.54.1
+	rightupdown=/usr/lib/ipsec/updown.netwinder
+	authby=cert
+	auto=add
+	certfile=/etc/ipsec/pubcert.pem
+	keyfile=/etc/ipsec/privkey.pem
+	certpath=ldap:/etc/ipsec/ldap.cnf:ldapdevel
+	certopts=send
+	#right DN: /C=CA/ST=Ontario/O=Rebel.com/OU=SoftEng/CN=arm-devel.netwinder.org/Email=luc.lanthier@rebel.com
+	rightid=@~30818E310B30090603550406130243413110300E060355040813074F6E746172696F31123010060355040A1309526562656C2E636F6D3110300E060355040B1307536F6674456E673120301E0603550403131761726D2D646576656C2E6E657477696E6465722E6F72673125302306092A864886F70D01090116166C75632E6C616E746869657240726562656C2E636F6D
+	#left DN: /C=CA/ST=Ontario/O=Rebel.com/OU=SoftEng/CN=arm1.netwinder.org/Email=firesoul@netwinder.org
+	leftid=@~308189310B30090603550406130243413110300E060355040813074F6E746172696F31123010060355040A1309526562656C2E636F6D3110300E060355040B1307536F6674456E67311B30190603550403131261726D312E6E657477696E6465722E6F72673125302306092A864886F70D010901161666697265736F756C406E657477696E6465722E6F7267
diff -bruN freeswan-1.9.orig/doc/pkix/examples/ldap.cnf freeswan-1.9/doc/pkix/examples/ldap.cnf
--- freeswan-1.9.orig/doc/pkix/examples/ldap.cnf	Wed Dec 31 19:00:00 1969
+++ freeswan-1.9/doc/pkix/examples/ldap.cnf	Mon Jun  4 11:34:31 2001
@@ -0,0 +1,20 @@
+ldapdevel_host_name = 10.8.49.122
+ldapdevel_base = dc=netwinder,dc=org
+ldapdevel_filter:uid = (uid=%s)
+
+ldapdevel_attributes:*:crl = certificaterevocationlist, certificaterevocationlist;binary
+ldapdevel_filter:*:crl = (&(objectclass=certificationAuthority)(cn=CA))
+
+ldapdevel_filter:ca = (objectclass=certificationauthority)
+
+ldapdevel_filter:dns = (&(objectclass=hostRecord)(dNSRecord=%s))
+ldapdevel_attributes:dns = servercertificate, servercertificate;binary
+
+ldapdevel_filter:ip = (&(objectclass=hostRecord)(ipv4Address=%s))
+ldapdevel_attributes:ip = servercertificate, servercertificate;binary
+
+ldapdevel_filter:subject = (&(objectclass=hostRecord)(subject=%s))
+ldapdevel_attributes:subject = servercertificate, servercertificate;binary
+
+ldapdevel_filter:issuer = (&(objectclass=hostRecord)(issuer=%s))
+ldapdevel_attributes:issuer = servercertificate, servercertificate;binary
diff -bruN freeswan-1.9.orig/doc/pkix/examples/privkey.pem freeswan-1.9/doc/pkix/examples/privkey.pem
--- freeswan-1.9.orig/doc/pkix/examples/privkey.pem	Wed Dec 31 19:00:00 1969
+++ freeswan-1.9/doc/pkix/examples/privkey.pem	Mon Jun  4 11:34:31 2001
@@ -0,0 +1,15 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIICXgIBAAKBgQCoqQwsIfybAtb0mMfD3NGNMZH7ckGrCehSm741ddjw9rW6igzZ
+AptaqQ2Y5raPl0XrF+MQI8SQkfTtzP92/ZU9eqbEWbBFRfYLqckMd21eU9GHDVl5
+UPmUwWSOXuE4lK58f2heEFE975yf9CsIvOuas33FsiuYtO5UEmzapAVAnQIDAQAB
+AoGAXUzWvPs4IBAcFUcHCyR2j6LiXLTB+voKGNirCivdDL+NnFmN7eZxRl/Kc9D9
+IMXQGdMm+uCudkMnuPz0PUDeczQST46jiTlG5vkQdj3zpmz/x73t5I4E8vFSX6A4
+gKREFeGxSCEm0THNusBKk1Q+huHUDKw4mFh85MTopy32McECQQDVWcc3BMlDICG2
+6bFc3+1ieeVIKoD2GnJR7b/GU57umLFyDmSFwOkTTt7VWp3jV/81Oy+xBe3cC8Fm
+mFC/e45VAkEAymA9ke8XFduafs2Q+nsbfx4QI+f8lAd51pBR4A4J+W50JLO1/WqC
+PwOXwVPRCPyzHiY9B8L9KPrFKSwVedihKQJBAKnGCl/+wAVZcVqztf649pbRdyGp
+KPwt6WDGtz+j1Sn6eeHQEC/bZd2Geo3+0PtTT/NVCMtuc2wSMrFobYEiWg0CQQCl
+lf9qw5049jlAHYTNXiNObFO6fVuN51wKcoV7dSE2JOkFCsISuq4dTxxBRApadyE7
+vv/atPGdMSpXGMntq5GZAkEA1PJ0w4WSC3sW3guq4WzDLWqmbK2pOvC40ATZR67y
+lYC1okanKDsRam0remPY7xWZ8WACJx5KOIvYgXhX+dNXPg==
+-----END RSA PRIVATE KEY-----
diff -bruN freeswan-1.9.orig/doc/pkix/examples/psk.conf freeswan-1.9/doc/pkix/examples/psk.conf
--- freeswan-1.9.orig/doc/pkix/examples/psk.conf	Wed Dec 31 19:00:00 1969
+++ freeswan-1.9/doc/pkix/examples/psk.conf	Mon Jun  4 11:34:31 2001
@@ -0,0 +1,9 @@
+conn test
+	left=10.1.49.124
+	leftnexthop=10.1.1.7
+	leftupdown=/usr/lib/ipsec/updown.netwinder
+	right=10.8.49.122
+	rightnexthop=10.8.54.1
+	rightupdown=/usr/lib/ipsec/updown.netwinder
+	authby=psk
+	auto=add
diff -bruN freeswan-1.9.orig/doc/pkix/examples/pubcert.pem freeswan-1.9/doc/pkix/examples/pubcert.pem
--- freeswan-1.9.orig/doc/pkix/examples/pubcert.pem	Wed Dec 31 19:00:00 1969
+++ freeswan-1.9/doc/pkix/examples/pubcert.pem	Mon Jun  4 11:34:31 2001
@@ -0,0 +1,79 @@
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number: 1 (0x1)
+        Signature Algorithm: md5WithRSAEncryption
+        Issuer: C=CA, ST=Ontario, L=Ottawa, O=Rebel.com, OU=SoftEng, CN=CA_arm-devel/Email=luc.lanthier@rebel.com
+        Validity
+            Not Before: Feb 14 20:59:13 2001 GMT
+            Not After : Feb 14 20:59:13 2002 GMT
+        Subject: C=CA, ST=Ontario, O=Rebel.com, OU=SoftEng, CN=arm-devel.netwinder.org/Email=luc.lanthier@rebel.com
+        Subject Public Key Info:
+            Public Key Algorithm: rsaEncryption
+            RSA Public Key: (1024 bit)
+                Modulus (1024 bit):
+                    00:a8:a9:0c:2c:21:fc:9b:02:d6:f4:98:c7:c3:dc:
+                    d1:8d:31:91:fb:72:41:ab:09:e8:52:9b:be:35:75:
+                    d8:f0:f6:b5:ba:8a:0c:d9:02:9b:5a:a9:0d:98:e6:
+                    b6:8f:97:45:eb:17:e3:10:23:c4:90:91:f4:ed:cc:
+                    ff:76:fd:95:3d:7a:a6:c4:59:b0:45:45:f6:0b:a9:
+                    c9:0c:77:6d:5e:53:d1:87:0d:59:79:50:f9:94:c1:
+                    64:8e:5e:e1:38:94:ae:7c:7f:68:5e:10:51:3d:ef:
+                    9c:9f:f4:2b:08:bc:eb:9a:b3:7d:c5:b2:2b:98:b4:
+                    ee:54:12:6c:da:a4:05:40:9d
+                Exponent: 65537 (0x10001)
+        X509v3 extensions:
+            X509v3 Basic Constraints: 
+                CA:FALSE
+            Netscape Cert Type: 
+                SSL Server
+            X509v3 Key Usage: 
+                Digital Signature, Non Repudiation, Key Encipherment
+            Netscape Comment: 
+                IPsec Certificate for arm-devel.netwinder.org
+            X509v3 Subject Key Identifier: 
+                98:76:ED:A5:41:7C:28:3C:C8:63:0F:09:F7:DE:9E:B2:00:B6:36:FE
+            X509v3 Authority Key Identifier: 
+                keyid:7A:38:75:E9:B9:94:AB:B6:00:C5:36:81:EA:A5:60:3E:FA:FE:E4:E1
+                DirName:/C=CA/ST=Ontario/L=Ottawa/O=Rebel.com/OU=SoftEng/CN=CA_arm-devel/Email=luc.lanthier@rebel.com
+                serial:00
+
+            X509v3 Subject Alternative Name: 
+                email:luc.lanthier@rebel.com, DNS:arm-devel.netwinder.org, IP Address:10.8.49.122
+            X509v3 Issuer Alternative Name: 
+                email:luc.lanthier@rebel.com
+    Signature Algorithm: md5WithRSAEncryption
+        bb:a9:1a:f4:e3:55:c8:f6:e7:d6:32:cb:a2:2f:6d:58:a3:5d:
+        8f:5a:0d:95:53:c7:bf:06:e7:3b:ca:99:48:99:2f:55:28:5a:
+        9e:37:ef:3b:44:73:1e:e0:61:93:43:f8:04:6b:06:1e:68:e5:
+        3e:a2:10:53:94:2f:66:76:fc:66:93:d4:5e:76:cf:2d:18:e2:
+        ff:eb:c0:77:c9:d5:4d:00:60:34:50:59:69:b9:7d:07:fb:ca:
+        8b:6e:ee:5c:d2:d9:06:2f:ee:df:d8:09:12:76:bc:b5:17:80:
+        a8:d6:a7:25:59:5c:b4:65:cb:29:b1:cd:77:29:e9:c4:03:00:
+        ea:c4
+-----BEGIN CERTIFICATE-----
+MIIEUTCCA7qgAwIBAgIBATANBgkqhkiG9w0BAQQFADCBlDELMAkGA1UEBhMCQ0Ex
+EDAOBgNVBAgTB09udGFyaW8xDzANBgNVBAcTBk90dGF3YTESMBAGA1UEChMJUmVi
+ZWwuY29tMRAwDgYDVQQLEwdTb2Z0RW5nMRUwEwYDVQQDFAxDQV9hcm0tZGV2ZWwx
+JTAjBgkqhkiG9w0BCQEWFmx1Yy5sYW50aGllckByZWJlbC5jb20wHhcNMDEwMjE0
+MjA1OTEzWhcNMDIwMjE0MjA1OTEzWjCBjjELMAkGA1UEBhMCQ0ExEDAOBgNVBAgT
+B09udGFyaW8xEjAQBgNVBAoTCVJlYmVsLmNvbTEQMA4GA1UECxMHU29mdEVuZzEg
+MB4GA1UEAxMXYXJtLWRldmVsLm5ldHdpbmRlci5vcmcxJTAjBgkqhkiG9w0BCQEW
+Fmx1Yy5sYW50aGllckByZWJlbC5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJ
+AoGBAKipDCwh/JsC1vSYx8Pc0Y0xkftyQasJ6FKbvjV12PD2tbqKDNkCm1qpDZjm
+to+XResX4xAjxJCR9O3M/3b9lT16psRZsEVF9gupyQx3bV5T0YcNWXlQ+ZTBZI5e
+4TiUrnx/aF4QUT3vnJ/0Kwi865qzfcWyK5i07lQSbNqkBUCdAgMBAAGjggG1MIIB
+sTAJBgNVHRMEAjAAMBEGCWCGSAGG+EIBAQQEAwIGQDALBgNVHQ8EBAMCBeAwPAYJ
+YIZIAYb4QgENBC8WLUlQc2VjIENlcnRpZmljYXRlIGZvciBhcm0tZGV2ZWwubmV0
+d2luZGVyLm9yZzAdBgNVHQ4EFgQUmHbtpUF8KDzIYw8J996esgC2Nv4wgcEGA1Ud
+IwSBuTCBtoAUejh16bmUq7YAxTaB6qVgPvr+5OGhgZqkgZcwgZQxCzAJBgNVBAYT
+AkNBMRAwDgYDVQQIEwdPbnRhcmlvMQ8wDQYDVQQHEwZPdHRhd2ExEjAQBgNVBAoT
+CVJlYmVsLmNvbTEQMA4GA1UECxMHU29mdEVuZzEVMBMGA1UEAxQMQ0FfYXJtLWRl
+dmVsMSUwIwYJKoZIhvcNAQkBFhZsdWMubGFudGhpZXJAcmViZWwuY29tggEAMEAG
+A1UdEQQ5MDeBFmx1Yy5sYW50aGllckByZWJlbC5jb22CF2FybS1kZXZlbC5uZXR3
+aW5kZXIub3JnhwQKCDF6MCEGA1UdEgQaMBiBFmx1Yy5sYW50aGllckByZWJlbC5j
+b20wDQYJKoZIhvcNAQEEBQADgYEAu6ka9ONVyPbn1jLLoi9tWKNdj1oNlVPHvwbn
+O8qZSJkvVShanjfvO0RzHuBhk0P4BGsGHmjlPqIQU5QvZnb8ZpPUXnbPLRji/+vA
+d8nVTQBgNFBZabl9B/vKi27uXNLZBi/u39gJEna8tReAqNanJVlctGXLKbHNdynp
+xAMA6sQ=
+-----END CERTIFICATE-----
diff -bruN freeswan-1.9.orig/doc/pkix/examples/rsasig-rw.conf freeswan-1.9/doc/pkix/examples/rsasig-rw.conf
--- freeswan-1.9.orig/doc/pkix/examples/rsasig-rw.conf	Wed Dec 31 19:00:00 1969
+++ freeswan-1.9/doc/pkix/examples/rsasig-rw.conf	Mon Jun  4 11:34:31 2001
@@ -0,0 +1,12 @@
+conn test
+	left=0.0.0.0
+	leftupdown=/usr/lib/ipsec/updown.netwinder
+	leftrsasigkey=0x010383adc0c40d031b8b51445074a015b6f6575221df37a23c597acafa7b588eccaeac2a705ca95c7062b7808849728a9083daf7e8f73335ecfdbfe18dda96b4c6b9c47cc695d1d9c20a92ce652cb0cd8b71af87cfb84d4ef5e02f13ef2233da2c98e5147b9092a5ef9f2789defb0b45d47570c1662bf8f159ae8e82107850184055
+	leftid="@arm1.netwinder.org"
+	right=10.8.49.122
+	rightnexthop=10.8.54.1
+	rightupdown=/usr/lib/ipsec/updown.netwinder
+	rightrsasigkey=0x0103e39df4e5d9cdfb1bd781cc516b99053af9d39f97230e663ecdf77cb14764fcd7aadb274b2da2eaa6c8b7f3764e1b87a5ae5d9f7cafdad01dd95518da017794fcf7c86f435f7b7ce45429414d9c099ebb91d8a3f54514be78f9b801b02608e8299a5d19a3a4fa5510d0d318b692c649dc3b37287153852a9ac81891d140a38a0d
+	rightid="@arm-devel.netwinder.org"
+	authby=rsasig
+	auto=add
diff -bruN freeswan-1.9.orig/doc/pkix/examples/rsasig.conf freeswan-1.9/doc/pkix/examples/rsasig.conf
--- freeswan-1.9.orig/doc/pkix/examples/rsasig.conf	Wed Dec 31 19:00:00 1969
+++ freeswan-1.9/doc/pkix/examples/rsasig.conf	Mon Jun  4 11:34:31 2001
@@ -0,0 +1,13 @@
+conn test
+	left=10.1.49.124
+	leftnexthop=10.1.1.7
+	leftupdown=/usr/lib/ipsec/updown.netwinder
+	leftrsasigkey=0x010383adc0c40d031b8b51445074a015b6f6575221df37a23c597acafa7b588eccaeac2a705ca95c7062b7808849728a9083daf7e8f73335ecfdbfe18dda96b4c6b9c47cc695d1d9c20a92ce652cb0cd8b71af87cfb84d4ef5e02f13ef2233da2c98e5147b9092a5ef9f2789defb0b45d47570c1662bf8f159ae8e82107850184055
+	leftid="@arm1.netwinder.org"
+	right=10.8.49.122
+	rightnexthop=10.8.54.1
+	rightupdown=/usr/lib/ipsec/updown.netwinder
+	rightrsasigkey=0x0103e39df4e5d9cdfb1bd781cc516b99053af9d39f97230e663ecdf77cb14764fcd7aadb274b2da2eaa6c8b7f3764e1b87a5ae5d9f7cafdad01dd95518da017794fcf7c86f435f7b7ce45429414d9c099ebb91d8a3f54514be78f9b801b02608e8299a5d19a3a4fa5510d0d318b692c649dc3b37287153852a9ac81891d140a38a0d
+	rightid="@arm-devel.netwinder.org"
+	authby=rsasig
+	auto=add
diff -bruN freeswan-1.9.orig/doc/pkix/ldap-ca.quickstart freeswan-1.9/doc/pkix/ldap-ca.quickstart
--- freeswan-1.9.orig/doc/pkix/ldap-ca.quickstart	Wed Dec 31 19:00:00 1969
+++ freeswan-1.9/doc/pkix/ldap-ca.quickstart	Mon Jun  4 11:34:31 2001
@@ -0,0 +1,340 @@
+
+Quick commands and files based on how I set up my own LDAP CA.
+-- Luc Lanthier, 20001004
+-- revised: 20010301
+
+A more complete explanation can be found in the README.xmap file written
+by the original freeswan-pkix patch author, Neil Dunbar.
+
+Building and LDAP server is nothing simple. Easiest is installing the base 
+package or compiling it yourself. But after that, it's editing, creating, or
+modifying many configuration files or scripts.
+
+Here's a list of some of the config files or scripts you will encounter 
+in this document:
+  LDIF.sh
+  LDIF
+  slapd.oc-x509.conf
+  slapd.at-x509.conf
+  slapd.conf
+  regen-ldap_ca.sh
+  ldap.cnf
+  ipsec.conf
+  /etc/ipsec/*
+  /etc/rc.d/rc.local
+
+
+Your best bet is to following the LDAP documentation and use this document as
+a source of information, with examples.
+
+
+
+1A- Building openldap software:
+-----------------------------------------------------------------
+# The following containing version numbers is just an example.
+# If you compile from source, you can expect the config files to
+# be found in /usr/local/etc/openldap
+cd /usr/src
+tar xfvz openldap-stable-20000704.tgz 
+cd openldap-1.2.11
+./configure --enable-shared --with-gnu-ld --enable-ldapd 
+make depend
+make
+cd tests
+make
+cd ..
+make install
+
+1B- Installing openldap software from RPMs:
+-----------------------------------------------------------------
+Make sure the following are installed. Version numbers are merely a 
+suggestion.
+  openldap-1.2.9-6_nw1.armv4l.rpm
+  openldap-devel-1.2.9-6_nw1.armv4l.rpm
+The config files should be found under "/etc/openldap".
+
+
+
+2: Creating LDIF files:
+-----------------------------------------------------------------
+A LDIF file contains the information to add to the LDAP directory
+database in a simplified manner.
+
+Use your favorite editor and create an LDIF file that contains:
+            dn: dc=<MY-DOMAIN>, dc=<COM> 
+            objectclass: dcObject 
+            objectclass: organization 
+            o: <MY ORGANIZATION> 
+            dc: <MY-DOMAIN> 
+
+            dn: cn=Manager, dc=<MY-DOMAIN>, dc=<COM> 
+            objectclass: organizationalRole 
+            cn: Manager
+
+Now, you may run ldapadd(1) to insert these entries into your directory.
+            ldapadd -D "cn=Manager, dc=<MY-DOMAIN>, dc=<COM>" -W -f example.ldif
+
+
+Now we're ready to verify the added entries are in your directory. You 
+can use any LDAP client to do this, but our example uses the 
+ldapsearch(1) tool. Remember to replace dc=example,dc=com with the correct 
+values for your site:
+            ldapsearch -b 'dc=example,dc=com' '(objectclass=*)'
+
+-----------------------------------------------------------------
+
+
+3- How I created my own LDIF file
+-----------------------------------------------------------------
+Try to keep track of which certificate belongs to which host while
+creating the CA. The CA will only store the certificates in a 
+simplified naming format.
+ie: /usr/share/ssl/certs/01.pem
+
+If you forget, query the certificate, and look at the CN part of the 
+subject line. If created correctly, the CommonName will contain 
+the hostname.
+
+=========================
+[root@arm-devel ipsec]# openssl x509 -in /usr/share/ssl/certs/01.pem \
+	-noout -subject
+subject=/C=CA/ST=Ontario/O=Rebel.com/OU=SoftEng/CN=arm-devel.netwinder.org/Email=luc.lanthier@rebel.com
+=========================
+
+To save me time, I created a shell script much like the following to speed up
+the generation of LDIF files.
+----------- LDIF.sh:
+#!/usr/bin/bash
+
+function openssl_out ()
+{
+  openssl x509 -in $1 -inform PEM -outform DER | \
+    ldif -b servercertificate 
+  openssl x509 -in $1 -noout -subject | \
+    sed -e 's/^subject=/subject: /'
+  openssl x509 -in $1 -noout -issuer | \
+    sed -e 's/^issuer=/issuer: /'
+}
+
+###### First, create entries for manager and CA.
+cat <<EOM
+dn: dc=netwinder, dc=org
+objectclass: dcObject 
+objectclass: organization 
+o: Rebel.com
+dc: SoftEng
+
+dn: cn=Manager, dc=netwinder, dc=org
+objectclass: organizationalRole 
+cn: Manager
+
+dn: cn=CA, dc=netwinder, dc=org
+cn: CA
+objectclass: certificationAuthority
+EOM
+
+# the crl and the certs HAVE to be in DER format.
+openssl crl -in /var/lib/ssl/crl.pem -inform PEM -outform DER | \
+	ldif -b certificationrevocationlist 
+openssl x509 -in /var/lib/ssl/cacert.pem -inform PEM -outform DER | \
+	ldif -b cACertificate 
+echo
+############################
+## Good! Now that the entry for the CA's done, let's create an entry for it,
+## as a host. (hostRecord)
+############################
+
+cat <<EOM
+dn: cn=phoenix, dc=netwinder, dc=org
+cn: phoenix
+objectclass: hostRecord
+ipv4Address: 10.8.49.100
+EOM
+openssl_out /var/lib/ssl/cacert.pem
+echo "dNSRecord: phoenix.netwinder.org"
+echo
+
+###########################################
+## now we create entries for the hosts.
+###########################################
+cat <<EOM
+dn: cn=sticky, dc=netwinder, dc=org
+cn: sticky
+objectclass: hostRecord
+ipv4Address: 10.1.49.233
+EOM
+openssl_out /var/lib/ssl/certs/01.pem
+echo "dNSRecord: sticky.netwinder.org"
+echo
+####################################
+
+cat <<EOM
+dn: cn=x86rack1, dc=netwinder, dc=org
+cn: x86rack1
+objectclass: hostRecord
+ipv4Address: 10.8.49.101
+EOM
+
+openssl_out /var/lib/ssl/certs/08.pem
+echo "dNSRecord: x86rack1.netwinder.org"
+echo
+#######################
+# etc..
+-----------------------------------------------------------------
+
+
+
+4- Additional files to set up:
+Use your better judgement and be aware of paths, domains, etc.
+
+----------- Create: /usr/local/etc/openldap/slapd.oc-x509.conf 
+==========================================
+objectclass hostRecord
+	requires
+		objectClass
+	allows
+		dNSRecord,
+		ipv4Address,
+		servercertificate,
+		subject
+==========================================
+
+------------ Create: /usr/local/etc/openldap/slapd.at-x509.conf 
+==========================================
+attribute	servercertificate			bin
+==========================================
+
+------------ Edit: /usr/local/etc/openldap/slapd.conf 
+==========================================
+#
+# See slapd.conf(5) for details on configuration options.
+# This file should NOT be world readable.
+#
+include		/usr/local/etc/openldap/slapd.at.conf
+include		/usr/local/etc/openldap/slapd.oc.conf
+schemacheck	off
+#referral	ldap://root.openldap.org/
+
+pidfile		/usr/local/var/slapd.pid
+argsfile	/usr/local/var/slapd.args
+
+#################
+# x509
+include		/usr/local/etc/openldap/slapd.at-x509.conf
+include		/usr/local/etc/openldap/slapd.oc-x509.conf
+
+#######################################################################
+# ldbm database definitions
+#######################################################################
+
+database	ldbm
+suffix		"dc=netwinder, dc=org"
+#suffix		"o=My Organization Name, c=US"
+rootdn		"cn=Manager, dc=netwinder, dc=org"
+#rootdn		"cn=Manager, o=My Organization Name, c=US"
+# cleartext passwords, especially for the rootdn, should
+# be avoid.  See slapd.conf(5) for details.
+rootpw		ipsecsecret
+# database directory
+# this directory MUST exist prior to running slapd AND
+# should only be accessable by the slapd/tools  Mode 700 recommended.
+#directory	/usr/local/var/openldap-ldbm
+directory	/var/lib/ssl/ldap-ldbm
+
+index default pres,eq
+index objectClass,uid
+index cn,sn eq,sub,approx
+==========================================
+-----------------------------------------------------------------
+
+
+
+5- How I regen'd my ldap DB:
+-----------------------------------------------------------------
+I created a shell script which stops the LDAP daemon, deletes the 
+LDAP dir, and recreates it from scratch reusing my LDIF.sh script.
+You can manage your LDAP dir any which way you want, but that's just
+how I decided to attack this problem.
+Make the file executable and place it in a reachable path.. maybe 
+'/usr/local/bin'?
+Don't forget to doublecheck filepaths and domains used in the file.
+It's just a template.
+-- regen-ldap_ca.sh ---------------------------------------------
+#!/bin/sh
+cd /usr/share/ssl/
+mkdir -p ldap-ldbm
+killall slapd
+rm -f ldap-ldbm/*
+LDIF.sh > LDIF
+ldif2ldbm -i LDIF
+slapd -s 1
+-----------------------------------------------------------------
+
+
+6- How I access the ldap DB from freeswan, the config files:
+-----------------------------------------------------------------
+The following file is used by FreeSWAN's pkix ldap lookup. 
+"ldapnd" in the front of each name is the name of the server the lookup
+is done on. If you wish to access 2 or more different ldap servers, just 
+copy the entire section a second time, while using the new header name.
+Keep in mind to change the domain and server hostname IP address.
+-- /etc/ipsec/ldap.cnf ------------------------------------------
+ldapnd_host_name = 10.8.49.100
+ldapnd_base = dc=netwinder,dc=org
+ldapnd_filter:uid = (uid=%s)
+
+ldapnd_attributes:*:crl = certificaterevocationlist, certificaterevocationlist;binary
+ldapnd_filter:*:crl = (&(objectclass=certificationAuthority)(cn=CA))
+
+ldapnd_filter:ca = (objectclass=certificationauthority)
+
+ldapnd_filter:dns = (&(objectclass=hostRecord)(dNSRecord=%s))
+ldapnd_attributes:dns = servercertificate, servercertificate;binary
+
+ldapnd_filter:ip = (&(objectclass=hostRecord)(ipv4Address=%s))
+ldapnd_attributes:ip = servercertificate, servercertificate;binary
+
+ldapnd_filter:subject = (&(objectclass=hostRecord)(subject=%s))
+ldapnd_attributes:subject = servercertificate, servercertificate;binary
+
+ldapnd_filter:issuer = (&(objectclass=hostRecord)(issuer=%s))
+ldapnd_attributes:issuer = servercertificate, servercertificate;binary
+-----------------------------------------------------------------
+
+The following is an example config entry for freeswan to use. You
+can either enter these settings in '/etc/ipsec.conf', or create
+a separate file with these settings to use. '/etc/ipsec.conf' can load
+separate files with 'include <path_and_filename>' commands.
+-- freeswan config ----------------------------------------------
+conn test_host-host
+	left=10.1.49.233
+	leftnexthop=10.1.1.7
+	leftupdown=/usr/lib/ipsec/updown.firewall
+	right=10.8.49.101
+	rightupdown=/usr/lib/ipsec/updown.firewall
+	rightnexthop=10.8.54.1
+	auto=add
+	authby=cert
+	# certfile: full path to private key
+	certfile=/etc/ipsec/pubcert.pem
+	# keyfile: full path to public key in unencrypted format
+	keyfile=/etc/ipsec/privkey.pem
+	certpath=ldap:/etc/ipsec/ldap.cnf:ldapnd
+	certopts=send,pk,rev
+	#The certificate are found using IKE's ID_DER_ASN1_DN ID payload
+	#You can provide the info by running:
+	#  ipsec fswcert -d a -l /etc/ipsec/[hostleft].pem
+	#left DN: /C=CA/ST=Ontario/O=Rebel.com/OU=x86eng/CN=Luc Lanthier/Email=firesoul@netwinder.org
+	leftid=@~308182310B30090603550406130243413110300E060355040813074F6E746172696F31123010060355040A1309526562656C2E636F6D310F300D060355040B1306783836656E67311530130603550403130C4C7563204C616E74686965723125302306092A864886F70D010901161666697265736F756C406E657477696E6465722E6F7267
+	#  ipsec fswcert -d a -l /etc/ipsec/[hostright].pem
+	#right DN: /C=CA/ST=Ontario/O=Rebel.com/OU=SE/CN=Luc Lanthier/Email=firesoul@pet.notbsd.org
+	rightid=@~307F310B30090603550406130243413110300E060355040813074F6E746172696F31123010060355040A1309526562656C2E636F6D310B3009060355040B13025345311530130603550403130C4C7563204C616E74686965723126302406092A864886F70D010901161766697265736F756C407065742E6E6F746273642E6F7267
+-----------------------------------------------------------------
+
+The certificate are found using IKE's ID_DER_ASN1_DN ID payload
+You can provide the info by running on each respective host:
+-----------------------------------------------------------------
+ipsec fswcert -d a -l /etc/ipsec/[hostleft].pem
+ipsec fswcert -d a -r /etc/ipsec/[hostright].pem
+
+
diff -bruN freeswan-1.9.orig/doc/pkix/openssl-ca.quickstart freeswan-1.9/doc/pkix/openssl-ca.quickstart
--- freeswan-1.9.orig/doc/pkix/openssl-ca.quickstart	Wed Dec 31 19:00:00 1969
+++ freeswan-1.9/doc/pkix/openssl-ca.quickstart	Mon Jun  4 11:34:31 2001
@@ -0,0 +1,237 @@
+This document is much like a quickstart, but in an even shorter form.
+These are the steps I took to create an opensourced CA capable of signing 
+certificates.
+
+How I set up a CA on RedHat 6.2 and used it:
+
+
+1- install openssl on the CA. 
+If the openssl package is already installed, then ignore this 
+section. Please note: requires 0.9.5a. I doubt FreeSWAN will
+run with openssl 0.9.6.
+----------------------------------------------------------------
+cd /usr/src/redhat/SRPMS
+scp root@10.8.49.101:/usr/src/redhat/SRPMS/openssl*.src.rpm .
+rpm --rebuild openssl-0.9.5a-1.src.rpm
+cd ../RPMS/i386/
+rpm -i openssl-*
+
+
+2- Setting up the openssl CA.
+The openssl RPM already create a /var/lib/ssl directory. If you installed
+openssl from source, look for it in either /usr/ssl, /usr/local/ssl,
+or even /usr/share/ssl.
+----------------------------------------------------------------
+cd /var/lib/ssl
+# Note! Newer redhat openssl RPMs created the dir in /usr/share/ssl
+
+# will simplify finding global conf files.
+ln -s /etc etc 
+
+# see README.certificates, section 4.1, for instructions
+# on the creation/addition of openssl.cnf 
+# Note! Since Redhat redid its openssl packages, openssl.cnf is present.
+# Use it instead.
+vi /etc/openssl.cnf
+
+# see README.certificates, section 4.1, for instructions
+# on the CA extensions to define in ca.ext
+vi ca.ext 
+
+openssl req -new -newkey rsa:1024 -keyout \
+	private/cakey.pem -out careq.pem
+# Please enter in a password to be able to use the CA's signing cert once 
+# it is generated. Only that password will unlock it for use.
+# Data may be asked of you to enter.
+# ____________________________________________________________________
+# --- Country Name (2 letter code) [AU]:
+# --- State or Province Name (full name) [Some-State]:
+# --- Locality Name (eg, city) []:
+# **important** The OrgName must match on ALL certs which will be signed
+# by this self-signed cert.
+#   --- Organization Name (eg, company) [Internet Widgits Pty Ltd]:
+# --- Organizational Unit Name (eg, section) []:
+# **Note** Try to use the machine's FQDN as common name. Not your own
+# name. :
+#   --- Common Name (eg, your name or your server's hostname) []:
+# --- Email Address []:
+# ____________________________________________________________________
+#
+# Unimportant:
+# Please enter the following 'extra' attributes
+# to be sent with your certificate request
+# A challenge password []:
+# An optional company name []:
+
+# sign our own CA certificate.
+openssl x509 -CAcreateserial -signkey private/cakey.pem -req \
+	-in careq.pem -out cacert.pem -days 2000 -extfile ca.ext
+
+touch index.txt
+echo "01" > serial
+openssl ca -gencrl -out crl.pem; # distribute/make available to all hosts.
+
+
+3- adding cacert.pem and crl.pem to hosts (OPTIONAL)
+Unless you are using LDAP lookup, you will have to make the certificate
+available on all the client hosts. Of course, make sure the destination 
+directory exists.
+----------------------------------------------------------------
+scp crl.pem 10.1.49.233:/etc/ipsec
+scp cacert.pem 10.1.49.233:/etc/ipsec
+scp crl.pem 10.8.49.101:/etc/ipsec
+scp cacert.pem 10.8.49.101:/etc/ipsec
+
+
+4- Each client host -- generate certificate requests.
+The CA's signing certificate is ready. Now we can create the client
+certificates. 
+NOTE: a CA can also be its own client if a separate certificate
+is generated. Both the cacert.pem and the host certificates must be
+made available as standard host certificates, as if they were 2 separate
+hosts.
+----------------------------------------------------------------
+mkdir -p /etc/ipsec
+cd /etc/ipsec
+
+# Make sure the info entered for the "CommonName" for each client 
+#   is DIFFERENT, usually containing the hostname.
+# Make sure the "OrgName" used is the same as the one used 
+#   for cacert.pem's creation.
+# Make sure you don't create this certificate with a password.
+#  This certificate must be available for use without user intervention.
+#  (that includes password entry)
+openssl req -new -newkey rsa:1024 -nodes -keyout \
+	`hostname`.key -out `hostname`.req.pem
+############################
+# OR DSA: (still unsupported. left note in to remember how to do it)
+# openssl dsaparam 1024 -out dsa_params.txt
+# chmod 400 dsa_params.txt
+#openssl req -new -newkey dsa:dsa_params.txt -nodes -keyout \
+#        /etc/ipsec/`hostname`.key -out /etc/ipsec/`hostname`.req.pem
+#remember that all parties must use DSA
+############################
+
+# how about a generic name on each host for ease?
+ln -fs `hostname`.key privkey.pem
+ln -fs `hostname`.pem pubcert.pem; # will be created soon.
+
+# protect the private key.
+chmod 400 `hostname`.key
+
+
+
+5- Signing certificates on the CA host
+Signing the certificates is a necessary step in the pkix CA setup,
+but first, you must give your CA the ability.
+You may find the signIPSEC script handy.
+----------------------------------------------------------------
+###########################
+# Create/Undate the following ONCE.
+# Once again, note the paths may be wrong.
+vi /etc/openssl.cnf; # (see README.certificates section 4.6)
+
+# Either create signIPSEC, or copy it from the current directory.
+#   to /usr/local/bin on the CA host.
+vi /usr/local/bin/signIPSEC; # (see README.certificates section 4.6)
+
+chmod 700 /usr/local/bin/signIPSEC
+# use: signIPSEC foo.mydomain.com 192.168.1.5 foo.req
+
+# Once again, CD to the correct path.
+cd /var/lib/ssl/
+mkdir -p newcerts
+
+# The following steps can be reused over and over, for each host to add
+#
+# 1- copy over the unsigned public cert from the host.
+scp root@10.1.49.233:/etc/ipsec/*.req.pem .
+#
+# 2- sign it with the correct values.
+signIPSEC sticky.netwinder.org 10.1.49.233 sticky.req.pem
+#
+# 3- copy the newly signed certificate to the host.
+scp newcerts/`cat serial.old`.pem root@10.1.49.233:/etc/ipsec/sticky.pem
+#
+# 4- rehash the current database of certificates handled by the CA.
+mv newcerts/* certs/
+c_rehash certs
+
+
+
+6- CA host: prepping flat file for client hosts
+Here's a short script for quick generations of text flatfiles needed
+by the various clients. LDAP lookup is prefered, but flatfile is available
+for testing or simplicity.
+The script is available as "CA-regenerate-flatfile.sh".
+----------------------------------------------------------------
+#!/bin/sh -x
+
+if [ -d /var/lib/ssl ]; then
+  cd /var/lib/ssl
+elif [ -d /usr/lib/ssl ]; then
+  cd /usr/lib/ssl
+elif [ -d /usr/local/lib/ssl ]; then
+  cd /usr/local/lib/ssl
+elif [ -d /usr/share/ssl ]; then
+  cd /usr/share/ssl
+else
+  echo "ERROR: Cannot determine location of ssl directory."
+  exit 1
+fi
+
+cat /dev/null > flatfile.txt
+
+for ii in certs/*.pem cacert.pem crl.pem;
+do
+  if [ "`basename $ii`" != "crl.pem" ] && [ "`basename $ii`" != "cacert.pem" ];
+  then
+    perl -e "open(IN, \"openssl x509 -in $ii -noout -text \|\"); \
+      @IN = <IN>; \
+      foreach (@IN) { \
+        if (/IP Address:(\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3})/) { \
+          print \"ip: \$1\\n\"; \
+        } \
+        if (/DNS:([^, ]*).*$/) { \
+          print \"dns: \$1\\n\"; \
+        } \
+      };" >> flatfile.txt
+  fi
+  cat $ii | \
+  perl -e '$printme = 0; while (<>) { if (/---BEGIN/) {$printme = 1;}; if ($printme) {print STDOUT $_;} }; print STDOUT "\n";' \
+  >> flatfile.txt
+done
+----------------------------------------------------------------
+
+# the flatfile is created. Send to Client hosts.
+scp flatfile.txt root@10.1.49.233:/etc/ipsec
+scp flatfile.txt root@10.8.49.101:/etc/ipsec
+
+
+
+7- revoking a certificate
+Sometimes it becomes necessary to revoke a certificate. 
+----------------------------------------------------------------
+# First, find out which certificate has to be revoked. If properly
+# generated, the CommonName (CN) will be the certificate's owner 
+# hostname. Replace "WANTED_HOSTNAME" by the hostname to look for.
+cd /var/lib/ssl/
+(
+for certs in certs/*.pem; do 
+  echo -n "$certs: " 
+  openssl x509 -in $certs -noout -subject
+done
+) | grep WANTED_HOSTNAME
+
+# Example output:
+# 02.pem: subject=/C=CA/ST=Ontario/O=Rebel.com/OU=SoftEng/CN=arm1.netwinder.org/Email=firesoul@netwinder.org
+
+# next, proceed to revoke the certificate.
+# once again, double-check the paths.
+openssl ca -revoke /var/lib/ssl/certs/02.pem 
+openssl ca -gencrl -out /var/lib/ssl/crl.pem
+
+# If we're using LDAP, the new crl.pem will be used automatically.
+# Otherwise, it has to be copied to each one of the client hosts.
+scp crl.pem root@10.1.49.233:/etc/ipsec
+scp crl.pem root@10.8.49.101:/etc/ipsec
diff -bruN freeswan-1.9.orig/doc/pkix/signIPSEC freeswan-1.9/doc/pkix/signIPSEC
--- freeswan-1.9.orig/doc/pkix/signIPSEC	Wed Dec 31 19:00:00 1969
+++ freeswan-1.9/doc/pkix/signIPSEC	Mon Jun  4 11:34:31 2001
@@ -0,0 +1,38 @@
+#!/bin/bash
+
+# Simple wrapper for "openssl ca" that sets environment to pass in
+# values for the svr_cert extension
+# P.J.Onion  23/9/1999
+# updated by: Luc Lanthier   20010214
+if [ -d /var/lib/ssl ]; then
+  SSLDIR="/var/lib/ssl";
+elif [ -d /usr/lib/ssl ]; then
+  SSLDIR="/usr/lib/ssl";
+elif [ -d /usr/local/lib/ssl ]; then
+  SSLDIR="/usr/local/lib/ssl";
+elif [ -d /usr/share/ssl ]; then
+  SSLDIR="/usr/share/ssl";
+else
+  echo "ERROR: Cannot determine location of ssl directory."
+  exit 1
+fi
+
+
+if test $# -ne 3 ; then
+        echo "Usage: $0 hostname ipaddress reqfile"
+        exit 1
+fi
+
+
+HOSTFQDN=$1
+HOSTIP=$2
+NSCOMMENT="IPsec Certificate for $1"
+EXTENSION=svr_cert
+
+export HOSTFQDN HOSTIP NSCOMMENT EXTENSION
+if (which openssl &> /dev/null) ; then
+  openssl ca -in $3
+else
+  echo "ERROR: Cannot locate/execute openssl binary."
+  exit 1
+fi
diff -bruN freeswan-1.9.orig/doc/politics.html freeswan-1.9/doc/politics.html
--- freeswan-1.9.orig/doc/politics.html	Tue Mar 27 23:16:51 2001
+++ freeswan-1.9/doc/politics.html	Mon Jun  4 01:15:56 2001
@@ -62,19 +62,18 @@
 general-purpose digital computers. </LI>
 <LI>Ultra made codebreaking a large-scale enterprise, producing 
 intelligence on an industrial scale. This was not a &quot;black chamber&quot;, 
-not some hidden room in some obscure government building with a small 
-crew of code-breakers. The whole operation -- from intercept operators 
-all over the world grabbing copies of enemy communications, through 
-large-scale code-breaking and analysis of the decrypted material (with 
-an enormous set of files for cross-referencing), to delivery of 
-intelligence to field commanders -- was huge, and very carefully 
-managed. </LI>
+not a hidden room in some obscure government building with a small crew 
+of code-breakers. The whole operation -- from wholesale interception of 
+enemy communications by stations around the world, through large-scale 
+code-breaking and analysis of the decrypted material (with an enormous 
+set of files for cross-referencing), to delivery of intelligence to 
+field commanders -- was huge, and very carefully managed. </LI>
 </UL>
 <P> So by the end of the war, Allied code-breakers were expert at 
 large-scale mechanised code-breaking. The payoffs were enormous. </P>
 <H4><A name="postwar">Postwar and Cold War</A></H4>
  The wartime innovations were enthusiastically adopted by post-war and 
-Cold War signals intelligence agencies. Presumably most nations now 
+Cold War signals intelligence agencies. Presumably many nations now 
 have some agency capable of sophisticated attacks on communications 
 security, and quite a few engage in such activity on a large scale. 
 <P> America's <A href="glossary.html#NSA">NSA</A>, for example, is said 
@@ -95,7 +94,7 @@
 electronic mail, or tapping into the huge volumes of data on new media 
 such as fiber optics or satellite links. None of these targets existed 
 in 1950. All of them can be attacked today, and almost certainly are 
-being attacked on a large scale. </P>
+being attacked. </P>
 <P> The Ultra story was not made public until the 1970s. Much of the 
 recent history of codes and code-breaking has not been made public, and 
 some of it may never be. Two important books are: </P>
@@ -127,22 +126,28 @@
 networking becoming ubiquitous, cryptography is now important to almost 
 everyone. Among the developments since the 1970s: </P>
 <UL>
-<LI>the US gov't established the <A href="glossary.html#DES">DES</A>
- standard, a <A href="glossary.html#block">block cipher</A> for 
-cryptographic protection of unclassfied documents </LI>
-<LI><A href="glossary.html#public">public key</A> cryptography invented 
-by Diffie and Hellman </LI>
-<LI>academic conferences such as <A href="http://www-cse.ucsd.edu/users/mihir/crypto2k.html">
-Crypto</A>, <A href="http://www.esat.kuleuven.ac.be/cosic/eurocrypt2000/">
-Eurocrypt</A>, ... </LI>
-<LI>companies offerring cryptographic products: <A href="glossary.html#RSAco">
+<LI>The US gov't established the Data Encryption Standard, <A href="glossary.html#DES">
+DES</A> standard, a <A href="glossary.html#block">block cipher</A> for 
+cryptographic protection of unclassfied documents. It has also been 
+widely used in industry. </LI>
+<LI><A href="glossary.html#public">Public key</A> cryptography was 
+invented by Diffie and Hellman. </LI>
+<LI>Academic conferences such as <A href="http://www-cse.ucsd.edu/users/mihir/crypto2k.html">
+Crypto</A> and <A href="http://www.esat.kuleuven.ac.be/cosic/eurocrypt2000/">
+Eurocrypt</A> began. </LI>
+<LI>Several companies began offerring cryptographic products: <A href="glossary.html#RSAco">
 RSA</A>, <A href="glossary.html#PGPI">PGP</A>, the many vendors with <A href="glossary.html#PKI">
 PKI</A> products, ... </LI>
-<LI>crypto in other products: operating systems, word processors, ... </LI>
-<LI>network protocols based on crypto: <A href="glossary.html#SSH"> SSH</A>
-, <A href="glossary.html#SSL">SSL</A>, <A href="glossary.html#IPSEC">
+<LI>Cryptography appeared in other products: operating systems, word 
+processors, ... </LI>
+<LI>Network protocols based on crypto were developed: <A href="glossary.html#SSH">
+ SSH</A>, <A href="glossary.html#SSL">SSL</A>, <A href="glossary.html#IPSEC">
  IPSEC</A>, ... </LI>
-<LI>widespread use of cryptography to secure bank cards, terminals, ... </LI>
+<LI>Crytography came into widespread use to secure bank cards, 
+terminals, ... </LI>
+<LI>The US government replaced <A href="glossary.html#DES">DES</A> with 
+the much stronger Advanced Encryption Standard, <A href="glossary.html#AES">
+AES</A></LI>
 </UL>
 <P> This has led to a complex ongoing battle between various mainly 
 government groups wanting to control the spread of crypto and various 
@@ -203,14 +208,20 @@
 communication systems, but that it is an activity of the  investigative 
 authorities and intelligence services of many countries with 
  governments of different political signature. </BLOCKQUOTE> Even if 
-they have nothing on the scale of Echelon, most or all intelligence 
-agencies and  police forces certainly have some interception 
-capability. </LI>
+they have nothing on the scale of Echelon, most intelligence agencies 
+and  police forces certainly have some interception capability. </LI>
+<LI><A href="glossary.html#NSA">NSA</A> tapping of submarine 
+communication cables, described  in <A href="http://www.zdnet.com/zdnn/stories/news/0,4586,2764372,00.html">
+this article</A></LI>
 <LI>A proposal for international co-operation on <A href="http://www.heise.de/tp/english/special/enfo/4306/1.html">
  Internet surveillance</A>.</LI>
 <LI>Alleged <A href="http://cryptome.org/nsa-sabotage.htm">sabotage</A>
  of security  products by the <A href="glossary.html#NSA">NSA</A> (the 
 US signals intelligence agency).</LI>
+<LI>The German armed forces and some government departments will stop 
+using American software for fear of NSA  &quot;back doors&quot;, according to 
+this <A href="http://www.theregister.co.uk/content/4/17679.html">news 
+story</A>. </LI>
 <LI>The British Regulation of Investigatory Powers bill. See  this <A href="http://www.fipr.org/rip/index.html">
 web page.</A> and  perhaps this <A href="http://ars.userfriendly.org/cartoons/?id=20000806&amp;mode=classic">
 cartoon</A>.</LI>
@@ -244,6 +255,8 @@
 <UL>
 <LI>industrial espionage, as for example in this <A href="http://www.zdnet.com/zdnn/stories/news/0,4586,2626931,00.html">
 news story</A></LI>
+<LI>attacks by organised criminals, as in this <A href="http://www.sans.org/newlook/alerts/NTE-bank.htm">
+ large-scale attack</A></LI>
 <LI>collection of personal data by various companies. 
 <UL>
 <LI>for example, consider the various corporate winners of Privacy 
@@ -603,11 +616,13 @@
 held by some third party and turned over to law enforcement or security 
 agencies under some conditions.</P>
 <PRE>
-Mary had cryptography
-Her keys were in escrow
-And everything that Mary said
-The feds were sure to know
+  Mary had cryptography
+  Her keys were in escrow
+  And everything that Mary said
+  The feds were sure to know
 </PRE>
+ (If anyone knows the origin of that ditty, let <A href="mailto:sandy@storm.ca">
+let me know</A> so I can credit the author.) 
 <P> There is an excellent paper available on <A href="http://www.cdt.org/crypto/risks98/">
 Risks of Escrowed Encryption</A>, from a group of cryptographic 
 luminaries which included our project leader.</P>
@@ -626,14 +641,18 @@
 <P> FreeS/WAN does not support escrowed encryption, and never will.</P>
 <H3><A name="shortkeys">Limited key lengths</A></H3>
 <P> Various governments, and some vendors, have also made persistent 
-attempts to convince people that weak systems are sufficient for some 
-data, that strong cryptography should be reserved for cases where the 
-extra overheads are justified. This is nonsense.</P>
+attempts to convince people that: </P>
+<UL>
+<LI>weak systems are sufficient for some data </LI>
+<LI>strong cryptography should be reserved for cases where the extra 
+overheads are justified </LI>
+</UL>
+<STRONG> This is nonsense</STRONG>.
 <P> Weak systems touted include:</P>
 <UL>
 <LI>the ludicrously weak (deliberately crippled) 40-bit ciphers that 
 until  recently were all various <A href="#exlaw">export laws</A>
- allowed.</LI>
+ allowed</LI>
 <LI>56-bit single DES, discussed <A href="#desnotsecure">below</A></LI>
 <LI>64-bit symmetric ciphers and 512-bit RSA, the maximums for 
 unrestricted  export under various current laws</LI>
@@ -665,9 +684,12 @@
 the bulk of the work is done  by a symmetric cipher. The effect of 
 increasing the cost of the public  key operations is typically 
 negligible because the public key operations  use only a tiny fraction 
-of total resources. For example, if public key  operations use use 1% 
-of the time in a hybrid system and you triple the  cost of public key 
-operations, the overall effect is a 2% rise in system  cost.</LI>
+of total resources. </LI>
+<P> For example, suppose public key  operations use use 1% of the time 
+in a hybrid system and you triple the  cost of public key operations. 
+The cost of symmetric cipher operations  is unchanged at 99% of the 
+original total cost, so the overall effect is a  jump from 99 + 1 = 100 
+to 99 + 3 = 102, a 2% rise in system cost.</P>
 </UL>
 <P> In short, <STRONG>there has never been any technical reason to use 
 inadequate ciphers</STRONG>. The only reason there has ever been for 
diff -bruN freeswan-1.9.orig/doc/roadmap.html freeswan-1.9/doc/roadmap.html
--- freeswan-1.9.orig/doc/roadmap.html	Tue Mar 27 23:16:51 2001
+++ freeswan-1.9/doc/roadmap.html	Mon Jun  4 01:15:56 2001
@@ -18,7 +18,7 @@
 <DL>
 <DT><A href="ipsec.html#klips">KLIPS</A></DT>
 <DD>the kernel code</DD>
-<DT><A href="#pluto">Pluto</A></DT>
+<DT><A href="glossary.html#pluto">Pluto</A></DT>
 <DD>the user-level key-management daemon</DD>
 </DL>
 <P>plus assorted odds and ends. </P>
diff -bruN freeswan-1.9.orig/doc/src/compat.html freeswan-1.9/doc/src/compat.html
--- freeswan-1.9.orig/doc/src/compat.html	Sun Mar 11 23:13:14 2001
+++ freeswan-1.9/doc/src/compat.html	Sun Jun  3 22:41:05 2001
@@ -3,21 +3,23 @@
 
 <h1><a name="compat">Linux FreeS/WAN Compatibility Guide</a></h1>
 
-  <p>
+<p>
 Most of this document is quoted directly from the Linux FreeS/WAN
 <a href="mail.html">mailing list</a>. Thanks very much to the community of
   testers, patchers and commenters there, especially the ones quoted below but
   also various contributors we haven't quoted.</p>
 
-  <h2><a name="spec">Implemented parts of the IPSEC Specification</a></h2>
+<h2><a name="spec">Implemented parts of the IPSEC Specification</a></h2>
 
-  <p>In general, do not expect Linux FreeS/WAN to do everything yet. This is a
-  work-in-progress and some parts of the IPSEC specification are not yet
-  implemented.</p>
+<p>
+In general, do not expect Linux FreeS/WAN to do everything yet. This is a
+work-in-progress and some parts of the IPSEC specification are not yet
+implemented.</p>
 
-  <h3><a name="in">In Linux FreeS/WAN</a></h3>
+<h3><a name="in">In Linux FreeS/WAN</a></h3>
 
-  <p>Things we do, as of version 1.9:</p>
+<p>
+Things we do, as of version 1.9:</p>
   <ul>
     <li>key management methods
       <dl>
@@ -57,10 +59,6 @@
        </dl>   
     <li>encryption transforms
       <dl>
-        <dt>null encryption (to use ESP as an authentication-only service)
-          <dd>We implement this since the RFCs require it. Since it is
-              obviously insecure, we disable it by default. It can be enabled
-              with a kernel configuration option.</dd>
           <dt><a href="glossary.html#DES">DES</a></dt>
             <dd>DES is in the source code since it is needed to implement
               3DES, but single DES is not made available to users because <a
@@ -96,9 +94,10 @@
 	</dl>
   </ul>
 
-  <p>
+<p>
 All combinations of implemented transforms are supported. Note that some
-  form of authentication is recommended whenever encryption is used.</p>
+form of packet-level <strong>authentication is required whenever encryption
+is used</strong>. Without it, the encryption will not be secure.</p>
 
 <h3><a name="dropped">Deliberately ommitted</a></h3>
 
@@ -108,15 +107,16 @@
 <p>
 Things we deliberately omit which are required in the RFCs are:</p>
 <ul>
+<li>null encryption (to use ESP as an authentication-only service)
 <li>single DES
 <li>DH group 1, a 768-bit modp group
 </ul>
 <p>
-Since these are the only encryption algorithm and DH group the RFCs require, it
+Since these are the only encryption algorithms and DH group the RFCs require, it
 is possible in theory to have a standards-conforming implementation which will
 not interpoperate with FreeS/WAN. Such an implementation would be inherently
 insecure, so we do not consider this a problem. Anyway, most implementations
-sensibly include more secure options as well, so dropping
+sensibly include more secure options as well, so dropping null encryption,
 single DES and Group 1 does not greatly hinder interoperation in practice.</p>
 <p>
 We also do not implement some optional features allowed by the RFCs:
@@ -133,9 +133,10 @@
 Windows 2000 where aggressive mode is the default. Typically, these are easily
 solved with a configuration change that overrides that default.</p> 
 
-  <h3><a name="not">Not (yet) in Linux FreeS/WAN</a></h3>
+<h3><a name="not">Not (yet) in Linux FreeS/WAN</a></h3>
 
-  <p>Things we don't yet do, as of version 1.9:</p>
+<p>
+Things we don't yet do, as of version 1.91:</p>
   <ul>
     <li>key management methods
       <ul>
@@ -164,6 +165,9 @@
           href="glossary.html#BIND">BIND</a> provide much of what we need but they are not
           yet widespread and our code to communicate with them is not
           ready.</p>
+<p>
+<strong>Update:</strong> As of 1.91, we have beta-testable code for opportunistic encryption.
+See our <a href="config.html#oppex">configuration document</a>.
         </li>
       </ul>
     </li>
@@ -186,6 +190,20 @@
       <p>No optional additional authentication transforms are currently
       implemented and we do not forsee a need to add any soon.</p>
     </li>
+  <li>Policy checking on decrypted packets
+  <p>
+   To fully comply with the RFCs, it is not enough just to accept only packets
+   which survive any firewall rules in place to limit what IPSEC packets get in,
+   and then pass KLIPS authentication. That is what FreeS/WAN currently does.
+   <p>
+   We should also apply additional tests, for example ensuring that all packets
+   emerging from a particular tunnel have sourcen and destination addresses that
+   fall within the subnets defined for that tunnel, and that packets with those
+   addresses that did not emerge from the appropriate tunnel are disallowed.
+   <p>
+   This will be done as part of the KLIPS rewrite currently in progress. See
+   these <a href="intro.html#applied">links</a> and the
+   <a href="mail.html">design mailing list</a> for discussion.  
   </ul>
 
   <h2><a name="pfkey">Our PF-Key implementation</a></h2>
@@ -206,41 +224,49 @@
 
   <h3><a name="pfk.port">PF-Key portability</a></h3>
 
-  <p>PF-Key came out of Berkeley Unix work and is used in the various BSD IPSEC
-  implementations. We assume also in This means there is some hope of
-  porting our Pluto(8) to one of the BSD distributions or running their
-  photurisd(8) on Linux if you prefer <a href="glossary.html#photuris">Photuris</a> key
-  management over IKE.</p>
-
-  <p>It is, however, more complex than that. The three PF-Key implementations
-  we have looked at -- ours, OpenBSD and KAME -- all have extensions beyond
-  the RFC, and the extensions are different. There have been discussions aimed
-  at sorting out the differences, perhaps for a version three PF-Key spec. All
-  players are in favour of this, but everyone involved is busy and it is not
-  clear whether or when these discussions might bear fruit.</p>
+<p>
+PF-Key came out of Berkeley Unix work and is used in the various BSD IPSEC
+implementations, and in Solaris. This means there is some hope of
+porting our Pluto(8) to one of the BSD distributions, or of running their
+photurisd(8) on Linux if you prefer <a href="glossary.html#photuris">Photuris</a> key
+management over IKE.</p>
+
+<p>
+It is, however, more complex than that. The PK-Key RFC deliberately deals
+only with keying, not policy management. The three PF-Key implementations
+we have looked at -- ours, OpenBSD and KAME -- all have extensions to deal
+with security policy, and the extensions are different. There have been
+discussions aimed at sorting out the differences, perhaps for a version
+three PF-Key spec. All players are in favour of this, but everyone involved
+is busy and it is not clear whether or when these discussions might bear
+fruit.</p>
 
-  <h2><a name="otherk">Kernels other than 2.0.38 and 2.2.18</a></h2>
+<h2><a name="otherk">Kernels other than 2.0.38 and 2.2.18</a></h2>
 
-  <p>We develop and test on:</p>
+<p>
+We develop and test on:</p>
   <ul>
-    <li>Redhat 5.2 with a 2.0.38 kernel.</li>
-    <li>Redhat 6.1 with a 2.2.18 kernel.</li>
+    <li>Redhat 6.1 with a 2.2.19 kernel.</li>
+    <li>Redhat 7.1 with a 2.4.4 kernel.</li>
+
   </ul>
 <p>
-  This is what we recommend.
+This is what we recommend.
 
   <h3><a name="kernel">Other 2.0.x Intel Kernels</a></h3>
 
 <p>
 Consider upgrading to the 2.2 kernel series. If you want to stay with
-the 2.0 series, then we strongly recommend 2.0.38. It has some security
-patches not present in earlier 2.0 kernels.</p>
-
+the 2.0 series, then we strongly recommend 2.0.39. Some useful security
+patches were added in 2.0.38.</p>
 <p>
 Various versions of the code have run at various times on most 2.0.xx
-kernels, but the current version is tested only on 2.0.38 and is unlikely to
-compile on older kernels. Some of our patches for older kernels are shipped
-in 2.0.37 and later, so they are no longer provided in FreeS/WAN.</p>
+kernels, but the current version is only lightly tested on 2.0.39, and
+not at all on older kernels.
+<p>
+Some of our patches for older kernels are shipped in 2.0.37 and later,
+so they are no longer provided in FreeS/WAN. This means recent versions
+of FreeS/WAN will probably not compile om anything earlier than 2.0.37.</p>
 
   <h3><a name="2.2">2.2 and 2.4 Kernels</a></h3>
   <dl>
@@ -253,13 +279,14 @@
       <dd>runs on 2.0, 2.2 or 2.4 kernels</dd>
   </dl>
 <p>
-We suggest the latest 2.2 kernel (2.2.18 at time of writing) for production use.
+We suggest the latest 2.2 kernel or 2.4 (2.2.19 or 2.4.5 at time of writing)
+for production use.
 
-  <h2><a name="otherdist">Intel Linux distributions other than Redhat 5.x and 6.x</a></h2>
+  <h2><a name="otherdist">Intel Linux distributions other than Redhat</a></h2>
 
   <p>
-We develop and test on Redhat 5.2 for 2.0 kernels, and on Redhat 6.1 for
-2.2, so minor changes may be required for other distributions.</p>
+We develop and test on Redhat 6.1 for 2.2 kernels, and on Redhat 7.1 for
+2.4, so minor changes may be required for other distributions.</p>
 
 <h3><a name="rh7">Redhat 7.0</h3>
 <p>
@@ -307,8 +334,9 @@
 
   <h3><a name="suse">SuSE Linux</a></h3>
 
-  <p>SuSE 6.3 and later versions, at least in Europe, ship with FreeS/WAN
-  included.</p>
+<p>
+SuSE 6.3 and later versions, at least in Europe, ship with FreeS/WAN
+included.</p>
 
   <p>Here are some notes for an earlier SuSE version.</p>
 
@@ -698,9 +726,8 @@
 information, check the <a href="mail.html">mailing list</a>.</p>
 
 <p>
-In short, Linux currently has both IPv6 support and IPSEC support, but <strong>the two
-do not work together yet</strong>. We, and others, are working on integrating
-them, but it is a substantial job.
+The first release of Linux IPv6 with FreeS/WAN support is now 
+<a href="http://www.ipv6.iabg.de/downloadframe/index.html">available</a>.
 
 
 
diff -bruN freeswan-1.9.orig/doc/src/config.html freeswan-1.9/doc/src/config.html
--- freeswan-1.9.orig/doc/src/config.html	Sun Mar 11 23:13:14 2001
+++ freeswan-1.9/doc/src/config.html	Sun Jun  3 22:41:05 2001
@@ -594,14 +594,6 @@
 the tunnel is an older version, the restriction will still apply there, so some
 caution is still required.
 
-  <p>The <var>conn %default</var> section shipped in our example file includes
-  parameters for manual keying. These are <strong>completely
-  insecure</strong>, intended only for testing. We recommend you leave these
-  in place during testing since it is sometimes useful to be able to test with
-  manual keying. Once testing is done, however, delete the test keys or ensure
-  that they are commented out with # characters. Production use of manual
-  keying is not recommended, but is possible and is described in a
-  <a href="#prodman">later section</a>.</p>
 
   <h3><a name="edit.conn">Editing a connection description</a></h3>
 
@@ -675,9 +667,10 @@
   someone can subvert the DNS service, then they can redirect packets whose
   addresses are looked up via that service.</p>
 
-  <p>Many of the variables in this file come in pairs such as "leftsubnet: and
-  "rightsubnet", one for each end of the connection. The variables on the left
-  side are:</p>
+<p>
+Many of the variables in this file come in pairs such as "leftsubnet: and
+"rightsubnet", one for each end of the connection. The variables on the left
+side are:</p>
   <dl>
     <dt>left</dt>
       <dd>The gateway's external interface, the one it uses to talk to the
@@ -708,14 +701,16 @@
       <dd>Addresses for the machines which left is protecting.
         <ul>
           <li>Often something like 101.202.203.0/24 to indicate that a subnet
-            resides behind left.</li>
+            resides behind left. Often this subnet will be directly connected
+            to left, but this not necessary. The only requirement is that left
+            must be able to route to it.</li>
           <li>If you omit the leftsubnet line, then left is both the security
             gateway and the only client on that end.</li>
         </ul>
         For some applications, you may want to create two connections, one to
         protect traffic from the subnet behind left and another to protect
         traffic from the left gateway itself. This takes two connection
-        descriptions.</dd>
+        descriptions. See <a href="#multitunnel">below</a>.</dd>
     <dt>leftfirewall</dt>
       <dd>Set to "yes" if there is a firewall in play that suppresses
         forwarding, for example if a subnet behind left uses non-routable
@@ -1016,22 +1011,185 @@
 
 <h3><a name="oppex">Opportunistic encryption</a></h3>
 
+We use the term <a href="glossary.html">opportunistic encryption</a> for
+encryption which does not rely on any pre-arranged connection, hence does
+not require that the administrators of the two gateways involved communicate
+with each other (for example, to exchange keys) before their systems can
+create a secure connection.
+<p>
+The idea is that each gateway check the destinations of outgoing packets,
+see if an encrypted connection is possible and, if so, take the opportuntity
+to encrypt. The opportunity will exist whenever the admins on both ends have
+set their systems up for opportunistic encryption.  
+<p>
+This makes encryption the default behaviour, and could greatly
+increase the overall security of the Internet if it were widely enough adopted.
+See our documents:
+<dl>
+<dt><a href="politics.html">history and politics</a>
+<dd>for the reasons we want to do this
+<dt><a href="ipsec.html#traffic.resist">IPSEC protocols</a>
+<dd>for discussion of the general principle of encrypting as much as possible
+</dl> 
+<p>
+The gateways must be able to authenticate each other for IPSEC to be secure.
+For opportunistic encryption, we rely on the domain name system,
+<a href="glossary.html">DNS</a>, to provide the RSA keys needed for this
+authentication.  Note, that currently this is not entirely secure because
+<strong>the DNS mechanism it relies on is not fully secure</strong>.
+Eventually, as <a href="glossary.html#SDNS">secure DNS</a> becomes widely
+deployed, this will change.
+<h4><a name="opp.status">Status</a></h4>
+
+The team have been working on this for some time, and testing internally.
+As of late May, 2001 this code is ready for wider testing. <strong>We
+encourage everyone to try it.</strong>
+<p>
+The main documentation items so far are:
+<ul>
+<li>an <a href="opportunism.howto">Opportunism HowTo</a> by Pluto programmer
+Hugh Redelmeier
+<li>a design document by Hugh and technical lead Henry Spencer.
+A <a href="intro.html#applied">link</a> to this is in our introduction.
+</ul>
+I am playing catch up; HTML documentation so far is neither complete nor
+particularly clear. What I have so far is below.
 <p>
-This section is currently just a placeholder for the opportunistic
-encryption documentation I'll write when the design has solidified
-somewhat.</p> 
+Note that both software and documentation for this are changing quickly.
+You may want the latest snapshot for opportunism experiments.
+<p> 
+<strong>We do not yet recommend this code for production use</strong>.
+You should still protect your critical data with explicitly configured
+IPSEC tunnels, rather than relying on opportunistic for everything at
+this stage. 
+</p> 
 
-<h4><a name="dnskey">Putting public keys in DNS</a></h4>
+<h4><a name="dns.background">Some DNS background</a></h4>
 
-  <p>Release 1.4 had the first experimental code to support fetching public
-  key information from the other system's DNS entries. Even in 1.6, this is
-  still experimental code. You cannot trust it for production use until</p>
-  <ul>
-    <li>both our code is much better tested (you can help with that!)</li>
-    <li>and <a href="glossary.html#SDNS">secure DNS</a> is widely deployed</li>
-  </ul>
+<p>
+Opportunism requires that the gateway systems be able to fetch public keys, and
+other IPSEC-related information, from each other's DNS (domain name service)
+records.
+<p>
+DNS is a distributed database that maps names to IP addresses and vice versa.
+A system named gateway.example.com with IP address 10.20.30.40 should have at
+least two DNS records:
+<dl>
+<dt>gateway.example.com. IN A 10.20.30.40
+<dd>used to look up the name and get an IP address
+<dt>40.30.20.10.in-addr.arpa. IN PTR gateway.example.com.
+<dd>used for reverse lookups, looking up the name associated with an address.
+Notice that the digits here are in reverse order; the actual address is
+10.20.30.40 but we use 40.30.20.10 here.
+</dl>
+Some syntactic details are:
+<ul>
+<li>the IN indicates that these records are for <strong>In</strong>ternet addresses
+<li>The final periods in '.com.' and '.arpa.' are required. They indicate the
+root of the domain name system.
+</ul>
+For much more detail, see the
+<a href="http://www.linuxdoc.org/LDP/nag2/index.html">Linux Network Administrator's Guide</a>
+or a DNS <a href="biblio.html#DNS.book">reference book</a>.
+<p>
+The capitalised strings after IN indicate the type of record. Possible types include:
+<ul>
+<li><strong>A</strong>ddress
+<li><strong>P</strong>oin<strong>T</strong>e<strong>R</strong>
+<li><strong>C</strong>anonical <strong>NAME</strong>, records to support aliasing, 
+multiple names for one address
+<li><strong>MX</strong>, used in mail handling
+<li><strong>SIG</strong>nature, used in <a href="glossary.html#SDNS">secure DNS</a>
+<li><strong>KEY</strong>, used in <a href="glossary.html#SDNS">secure DNS</a>
+<li><strong>T</strong>e<strong>XT</strong>, a multi-purpose record type
+</ul>
+To set up for opportunistic encryption, you add some KEY and TXT records to your
+DNS data.
 
-  <p>The relevant lines in the config file would look like this:</p>
+<h4><a name="dnskey">Putting IPSEC information in DNS</a></h4>
+
+There are two types of DNS record to be added:
+<ul>
+<li>each gateway must have a KEY record which other gateways can query to
+fetch its RSA authentication key
+<li>any client whose communications are to be protected by a gateway
+must have a TXT record pointing to that machine as an authorised IPSEC gateway
+</ul>
+<a href="manpage.d/ipsec_rsasigkey.8.html">ipsec_rsasigkey(8)</a> provides
+the key in DNS record format as a comment. You need to cut and paste the
+comment from <a href="manpage.d/ipsec.secrets.5.html">ipsec.secrets(5)</a>
+(or wherever you have the private key)
+into the appropriate place in the DNS records.
+<p> 
+There are two ways to handle this, depending on whether or not you control
+the reverse lookup (in-addr.arpa.) sections of the DNS files for your gateway.
+You must have control of the reverse DNS information for clients or this
+cannot work at all.
+
+<h5>If you control the gateway's reverse map</h5>
+
+If you control the gateway's reverse map, you just add a KEY record there.
+Here is an example, with many characters of the key itself left out:
+<pre>
+40.30.20.10.in-addr.arpa. IN KEY 0x4200 4 1 AQNJjkKlIk9...nYyUkKK8
+</pre>
+This allows lookups on the IP address of the gateway to retrieve the key.
+<p>
+A client that wishes to be protected by Opportunistic Encryption must
+include a special TXT record in its reverse-map. If you control the
+gateway's reverse map, example client records would look like this:
+<pre>
+42.42.42.10.in-addr.arpa. IN PTR deepthought.example.com.
+42.42.42.10.in-addr.arpa. IN TXT "X-IPsec-Server(10)=10.20.30.40 AQNJjkKlIk9...nYyUkKK8"
+</pre>
+which can also be written as just:
+<pre>
+42.42.42.10.in-addr.arpa. IN PTR deepthought.example.com.
+                          IN TXT "X-IPsec-Server(10)=10.20.30.40 AQNJjkKlIk9...nYyUkKK8"
+</pre>
+
+This provides the IP address of the security gateway and the public key
+which the gateway will use to authenticate itself. This is the preferred
+variant. Using it, the remote system does one lookup and gets everything
+it needs for IKE negotiations.
+
+<h5>If you <em>don't</em> control the gateway's reverse map</h5>
+
+The approach must be slightly different if you do not have control over the
+contents of the reverse map for your gateway. Perhaps your ISP controls that,
+and provides no way for you to put data into their maps. Without that, you
+cannot set your gateway up to respond to incoming opportunistic requests
+(short of changing ISPs, which you might consider).
+<p>
+However, suppose a friend over at example.org will let you put things in
+their maps. That will allow you to set your gateway up to handle opportunistic
+connections for which it is the initiator.
+<p>
+You still need to be able to put data in the reverse map for your clients.
+However, that data is slightly different:
+<pre>
+42.42.42.10.in-addr.arpa. IN PTR deepthought.example.com.
+                          IN TXT "X-IPsec-Server(10)=something.example.org"
+</pre>
+Over at example.org, your friend inserts these lines in the DNS data files:
+<pre>
+something.example.org. IN A 10.20.30.40
+                       IN KEY 0x4200 4 1 AQNJjkKlIk9...nYyUkKK8
+</pre>
+Your gateway must identify itself in IKE as something.example.org, not
+as gateway.example.com. You set that up via <var>leftid=</var> or
+<var>rightid=</var> entries in <a href="manpage.d/ipsec.conf.5.html">ipsec.conf(5)</a>.
+<p>
+With this arrangement, the remote gateway does two lookups. First it does a
+reverse lookup on the client IP address and finds the gateway name 
+"something.example.org". Then it looks up that name to get the IP address
+and key for the gateway.
+
+
+
+<h4><a name="opp.config">ipsec.conf entries for opportunism</a></h4>
+
+The relevant lines in the config file would look like this:</p>
 <pre>
         leftid=@gateway.example.com
         leftrsasigkey=%dns
@@ -1379,13 +1537,13 @@
 listen to the traffic between the gateways.</p>
 
 <p>
-This really has to be done from a third machine, not from one of the
-gateways. On the gateways you'll see packets at intermediate stages of
-processing and the result will be confusing. Also, both tcpdump(8) and
-nmap(8) use the libpcap library. Some versions of that library (e.g. the
-ones that shipped with Redhat 5) do not recognise ipsec? devices and will
-generate "bad physical medium" error messages if you try to use it with
-them.</p>
+This is most easily done from a third machine, rather than from one of the
+gateways. On the gateways you may see packets at intermediate stages of
+processing and the result may be confusing.
+<p>
+If the results make no sense at all, or you see "bad physical medium" error
+messages, you probably have an outdated version of tcpdump(8) that does
+not handle IPSEC at all. See our <a href="faq.html#tcpdump">FAQ</a>.</p>
 
 <p>
 The packets should, except for some of the header information, be utterly
@@ -2136,6 +2294,49 @@
 gateways with a subnet behind them. To get that functionality, you must upgrade
 to Windows 2000 server or the commercially available PGP products.
 
+<h4><a name="advroute">One tunnel plus advanced routing</a></h4>
+
+It is also possible to use the new routing features in 2.2 and later
+kernels to avoid most needs for multple tunnels. Here is one mailing
+list message on the topic:
+<pre>
+Subject: Re: linux-ipsec: IPSec packets not entering tunnel?
+   Date: Mon, 20 Nov 2000
+   From: Justin Guyett &lt;jfg@sonicity.com&gt;
+
+On Mon, 20 Nov 2000, Claudia Schmeing wrote:
+
+&gt; Right                                                         Left
+&gt;                      "home"                "office"
+&gt; 10.92.10.0/24 ---- 24.93.85.110 ========= 216.175.164.91 ---- 10.91.10.24/24
+&gt;
+&gt; I've created all four tunnels, and can ping to test each of them,
+&gt; *except* homegate-officenet.
+
+I keep wondering why people create all four tunnels.  Why not route
+traffic generated from home to 10.91.10.24/24 out ipsec0 with iproute2?
+And 99% of the time you don't need to access "office" directly, which
+means you can eliminate all but the subnet&lt;-&gt;subnet connection.
+</pre>
+and FreeS/WAN technical lead Henry Spencer's comment:
+<pre>
+&gt; I keep wondering why people create all four tunnels.  Why not route
+&gt; traffic generated from home to 10.91.10.24/24 out ipsec0 with iproute2?
+
+This is feasible, given some iproute2 attention to source addresses, but
+it isn't something we've documented yet... (partly because we're still
+making some attempt to support 2.0.xx kernels, which can't do this, but
+mostly because we haven't caught up with it yet).
+
+&gt; And 99% of the time you don't need to access "office" directly, which
+&gt; means you can eliminate all but the subnet&lt;-&gt;subnet connection.
+
+Correct in principle, but people will keep trying to ping to or from the
+gateways during testing, and sometimes they want to run services on the
+gateway machines too.
+
+</pre>
+
 <h3><a name="biggate">Many tunnels from a single gateway</a></h3>
 
 <p>
@@ -2481,34 +2682,49 @@
 <h3><a name="unencrypted">Unencrypted tunnels</a></h3>
 
 <p>
-Sometimes you will want to create a tunnel without encryption. The IPSEC
-protocols provide two ways to do this, either using <a href="glossary.html#AH">AH</a>
-without <a href="glossary.html#ESP">ESP</a> or using ESP with null encryption. With Linux
-FreeS/WAN, these are currently supported for manually keyed connections, but
-not with automatic keying, so we'll look at other solutions here.</p>
+Sometimes you might want to create a tunnel without encryption. Often this is
+a bad idea, even if you have some data which need not be private. See
+this <a href="ipsec.html#traffic.resist">discussion</a>. 
+<p>
+The IPSEC protocols provide two ways to do build such tunnels,
+<ul>
+<li>using <a href="glossary.html#AH">AH</a> without <a href="glossary.html#ESP">ESP</a>
+<li>using ESP with null encryption.
+</ul>
+Linux FreeS/WAN allows AH-only for manually keyed connections, but
+not with automatic keying, and does not support null encryption, so we'll look
+at other solutions here.</p>
 
 <p>
 One situation in which this comes up is when otherwise some data would be
-  encrypted twice. Alice wants a secure tunnel from her machine to Bob's.
-  Since she's behind one security gateway and he's behind another, part of the
-  tunnel that they build passes through the tunnel that their site admins have
-  built between the gateways. All of Alice and Bob's messages are encrypted
-  twice.</p>
+encrypted twice. Alice wants a secure tunnel from her machine to Bob's.
+Since she's behind one security gateway and he's behind another, part of the
+tunnel that they build passes through the tunnel that their site admins have
+built between the gateways. All of Alice and Bob's messages are encrypted
+twice.</p>
 
-  <p>There are several ways to handle this.</p>
+<p>
+There are several ways to handle this.</p>
   <ul>
     <li>Just accept the overhead of double encryption. The site admins might
-      choose this if policy says encrypt everything, if they don't entirely
-      trust Alice and Bob, or if they don't feel the saved cycles are worth
-      the time they'd need to build a non-encrypted tunnel for Alice and Bob's
-      packets.</li>
+      choose this if any of the following apply:
+    <ul>
+	<li>policy says encrypt everything (usually, it should)
+	<li>they don't entirely trust Alice and Bob (usually, if they don't have to, they
+       shouldn't)
+	<li>if they don't feel the saved cycles are worth the time they'd need to
+      build a non-encrypted tunnel for Alice and Bob's packets (often, they aren't)
+    </ul>
     <li>Use a plain IP-in-IP tunnel. These are not well documented. A good
       starting point is in the Linux kernel source tree, in
       /usr/src/linux/drivers/net/README.tunnel.</li>
-    <li>Use a manually-keyed AH-only tunnel. This is recommended over ESP with
-      null encryption.</li>
+    <li>Use a manually-keyed AH-only tunnel.</li>
   </ul>
-
+<p>
+Note that if Alice and Bob want end-to-end security, they must build a tunnel
+end-to-end between their machines or use some other end-to-end tool such as
+PGP or SSL that suits their data. The only question is whether the admins
+build some special unencrypted tunnel for those already-encrypted packets.
  
 
 
diff -bruN freeswan-1.9.orig/doc/src/faq.html freeswan-1.9/doc/src/faq.html
--- freeswan-1.9.orig/doc/src/faq.html	Wed Mar 14 19:12:33 2001
+++ freeswan-1.9/doc/src/faq.html	Sun Jun  3 22:41:06 2001
@@ -36,6 +36,9 @@
 Can different FreeS/WAN versions talk to each other?</a></li>
 <li><a href="#versions">
 Does FreeS/WAN run on my version of Linux?</a></li>
+<li><a href="#k.versions">
+Does FreeS/WAN run on the latest kernel version?</a></li>
+
 <li><a href="#modify.faq">
 Can I modify FreeS/WAN to ...?</a></li>
 <li><a href="#contrib.faq">
@@ -48,6 +51,10 @@
 <li><a href="#compile.faq">Compilation problems</a></li>
 <ul>
 <li><a href="#gmp.h_missing">gmp.h: No such file or directory</a></li>
+
+<li><a href="#noVM">... virtual memory exhausted</a></li>
+
+
 </ul>
 
 <li><a href="#setup.faq">
@@ -66,10 +73,10 @@
 <li><a href="#firewall_ate">The firewall ate my packets!</a></li>
 <li><a href="#dropconn">Dropped connections</a></li>
 
-
- 
 <li><a href="#tcpdump">
 TCPdump on the gateway shows strange things</a></li>
+<li><a href="#no_trace">
+Traceroute does not show anything between the gateways</a></li>
 </ul>
 
 <li><a href="#man4debug">Testing in stages</a></li>
@@ -93,12 +100,20 @@
 Interpreting error messages</a></li>
 <ul>
 <li><a href="#unreachable">SIOCADDRT:Network is unreachable</a></li>
+<li><a href="#noKLIPS">ipsec_setup: Fatal error, kernel appears to lack KLIPS</a></li>
+
 <li><a href="#conn_name">Connection names in Pluto error messages</a></li>
 
 <li><a href="#cantorient">Pluto: ... can't orient connection</a></li>
 
 <li><a href="#noconn">
 Pluto: ... no connection is known</a></li>
+<li><a href="#nosuit">
+Pluto: ... no suitable connection ...</a></li>
+
+<li><a href="#noconn.auth">
+Pluto: ... no connection has been authorized</a></li>
+
 <li><a href="#noDESsupport">
 Pluto: ... OAKLEY_DES_CBC is not supported.</a>
 <li> <a href="#notransform">Pluto: ... no acceptable transform</a></li>
@@ -111,6 +126,9 @@
 ipsec_setup: Cannot adjust kernel flags</a></li>
 <li><a href="#SAused">
 ... trouble writing to /dev/ipsec ... SA already in use</a></li>
+<li><a href="#ignore">
+... ignoring ... payload</a></li>
+<li><a href="#dup_address">ipsec_setup: ... interfaces ... and ... share address ...</a></li>
 
 </ul>
 
@@ -123,24 +141,19 @@
 <li><a href="#road.masq">Can I assign a road warrior an address on my net?</a></li>
 
 <li><a href="#QoS">Can I use Quality of Service routing with FreeS/WAN?</a></li>
+<li><a href="#deadtunnel">Can I recognise dead tunnels and shut them down?</a></li>
+<li><a href="#demanddial">Can I build tunnels over a demand-dialed link?</a></li>
+
 <li><a href="#PKIcert">
 Does FreeS/WAN support X.509 or other PKI certificates?</a></li>
 <li><a href="#Radius">
 Does FreeS/WAN support Radius or other user authentication?</a></li>
 
-<li><a href="#noDES">
+<li><a href="#noDES.faq">
 Does FreeS/WAN support single DES encryption?</a></li>
-<ul>
-<li><a href="#DESstandard">
-But isn't DES support part of the IPSEC standard?</a></li>
-
-<li><a href="#DESonly">
-I have to talk to .... which offers only DES. How do I do this?</a></li>
 </ul>
 
-</ul>
-
-<li><a href="#spam">Why don't you restrict the mailing list to reduce spam?</a></li>
+<li><a href="#spam">Why don't you restrict the mailing lists to reduce spam?</a></li>
 </ul>
 
 <hr>
@@ -257,6 +270,36 @@
 Note, however, that we do not test this often and have never tested on
 multiprocessor machines of other architectures.
 
+
+<a name=k.versions>
+<h3>Does FreeS/WAN run on the latest kernel version?</h3>
+
+Quite often, no.
+<p>
+Released versions of FreeS/WAN generally run on whatever production
+kernels were current at the time of the release. For example, FreeS/WAN
+1.91 runs on kernel 2.2.19 or 2.4.5. Often they will run on slightly
+earlier or later kernels as well, but we test on the current production
+kernels, so those are strongly recommended.
+<p>
+The kernel is under active development and it is not uncommon for
+changes to appear that cause problems for FreeS/WAN. For example,
+2.4.6 or 2.4.7 may have changes that break FreeS/WAN 1.91. Or not;
+you can't tell in advance. When such changes appear, we put a fix
+in the FreeS/WAN snapshots, and distribute it with our next release.
+<p>
+However, this is not a top priority for us, and it may take
+anything from a few days to several weeks for such a problem to find
+its way to the top of our kernel programmer's todo list. In the
+meanwhile, you have two choices: either stick with a slightly older
+kernel, or fix the problem yourself and send us a patch.
+<p>
+We don't even try to keep up with kernel changes outside the main
+2.2 and 2.4 branches, such as the 2.4.x-ac patched versions from
+Alan Cox or (when they appear) the 2.5 series of development kernels.
+We'd rather work on developing the FreeS/WAN code than on chasing
+these moving targets. 
+ 
 <h3><a name="modify.faq">Can I modify FreeS/WAN to ...?</a></h3>
 
 You are free to modify FreeS/WAN in any way. See the discussion of
@@ -264,6 +307,30 @@
 
 <h3><a name="contrib.faq">Can I contribute to the project?</a></h3>
 
+In general, we welcome contributions from the community. Various contributed
+patches, either to fix bugs or to add features, have been incorporated into
+our distribution. Other patches, not yet included in the distribution, are
+listed in our <a href="web.html#patch">web links</a> section.
+<p>
+Users have also contributed heavily to documentation, both by creating their
+own <a href="intro.html#howto">HowTos</a> and by posting things on the
+<a href="mail.html">mailing lists</a> which I have quoted in these HTML docs.
+<p>
+There are, however, some caveats.
+<p>
+FreeS/WAN is being implemented in Canada, by Canadians, largely to ensure
+that is it is entirely free of export restrictions. See this
+<a href="politics.html#status">discussion</a>. We <strong>cannot accept
+code contributions from US residents or citizens</strong>, not even one-line
+bugs fixes. The reasons for this were recently discussed extensively on the
+mailing list, in a thread starting
+<a href="http://www.sandelman.ottawa.on.ca/linux-ipsec/html/2001/01/msg00111.html">here</a>.
+<p>
+Not all contributions are of interest to us. The project has a set of
+fairly ambitious and quite specific goals, described in our
+<a href="intro.html#goals">introduction</a>. Contributions that lead toward
+these goals are likely to be welcomed enthusiastically. Other contributions
+may be seen as lower priority, or even as a distraction. 
 
 <h3><a name="ddoc.faq">Is there detailed design documentation?</a></h3>
 
@@ -300,6 +367,22 @@
 For more information and the latest version, see the
 <a href="http://www.swox.com/gmp/">GMP home page</a>.
 
+<h3><a name="noVM">... virtual memory exhausted</a></h3>
+
+We have had several reports of this message appearing, all on SPARC
+Linux. Here is a mailing message on a solution:
+<pre>
+&gt; ipsec_sha1.c: In function `SHA1Transform':
+&gt; ipsec_sha1.c:95: virtual memory exhausted
+
+I'm seeing exactly the same problem on an Ultra with 256MB ram and 500
+MB swap.  Except I am compiling version 1.5 and its Red Hat 6.2.
+
+I can get around this by using -O instead of -O2 for the optimization
+level.  So it is probably a bug in the optimizer on the sparc complier. 
+I'll try and chase this down on the sparc lists.
+</pre>
+
 <h2><a name="setup.faq">Life's little mysteries</a></h2>
 
 FreeS/WAN is a fairly complex product. (Neither the networks it
@@ -530,8 +613,8 @@
        there, which may be preferable to having them  sent elsewhere
        based  on  a  more  general  route (e.g., a default
        route).
-<blockquote>
 </blockquote>
+<blockquote>
        Normally, pluto's route to a destination remains in  place
        when  a  --down  operation  is used to take the connection
        down (or if connection setup, or later automatic rekeying,
@@ -542,6 +625,7 @@
        route can be removed using the --unroute operation (and is
        implicitly removed by --delete).
 </blockquote>
+<p>
 See also this mailing list
 <a href="http://www.sandelman.ottawa.on.ca/linux-ipsec/html/2000/11/msg00523.html">message</a>.
 
@@ -570,7 +654,7 @@
 number of reasons, ranging from hardware failures to various software
 problems such as the path MTU problems discussed
 <a href="#pmtu.broken">elsewhere in the FAQ</a>. Fortunately, various
-diagnostic tools exist that help you sort many of the possible problems.</p>
+diagnostic tools exist that help you sort out many of the possible problems.</p>
 <p>
 There is one situation, however, where FreeS/WAN (using default settings) may
 destroy a connection for no readily apparent reason. This occurs
@@ -580,7 +664,7 @@
 In this situation, the first tunnel comes up fine and works until the
 second is established. At that point, because of the way we track
 connections internally, the first tunnel ceases to exist as far as this
-gateway is concerned. Of course the far end does not know that and a storm
+gateway is concerned. Of course the far end does not know that, and a storm
 of error messages appears on both systems as it tries to use the tunnel.</p>
 <p>
 If the far end gives up, goes back to square one and negotiates a new
@@ -669,6 +753,78 @@
 Internet.
 </p>
 
+<h3><a name="no_trace">Traceroute does not show anything between the gateways</a></h3>
+
+As far as traceroute can see, the two gateways are one hop apart; the data packet
+goes directly from one to the other through the tunnel. Of course the outer packets
+that implement the tunnel pass through whatever lies between the gateways, but 
+those packets are built and dismantled by the gateways. Traceroute does not see
+them and cannot report anything about their path.
+<p>
+Here is a mailing list message with more detail.
+<pre>
+Date: Mon, 14 May 2001
+To: linux-ipsec@freeswan.org
+From: "John S. Denker" &lt;jsd@research.att.com&lt;
+Subject: Re: traceroute: one virtual hop
+
+At 02:20 PM 5/14/01 -0400, Claudia Schmeing wrote:
+&gt;
+&gt;&gt; &gt; A bonus question: traceroute in subnet to subnet enviroment looks like:
+&gt;&gt; &gt; 
+&gt;&gt; &gt; traceroute to andris.dmz (172.20.24.10), 30 hops max, 38 byte packets
+&gt;&gt; &gt; 1  drama (172.20.1.1)  0.716 ms  0.942 ms  0.434 ms
+&gt;&gt; &gt; 2  * * *
+&gt;&gt; &gt; 3  andris.dmz (172.20.24.10)  73.576 ms  78.858 ms  79.434 ms
+&gt;&gt; &gt; 
+&gt;&gt; &gt; Why aren't there the other hosts which take part in the delivery during 
+&gt;    * * * ?
+&gt;
+&gt;If there is an ipsec tunnel between GateA and Gate B, this tunnel forms a 
+&gt;'virtual wire'.  When it is tunneled, the original packet becomes an inner 
+&gt;packet, and new ESP and/or AH headers are added to create an outer packet 
+&gt;around it. You can see an example of how this is done for AH at 
+&gt;doc/ipsec.html#AH . For ESP it is similar.
+&gt;
+&gt;Think about the packet's path from the inner packet's perspective.
+&gt;It leaves the subnet, goes into the tunnel, and re-emerges in the second
+&gt;subnet. This perspective is also the only one available to the
+&gt;'traceroute' command when the IPSec tunnel is up.
+
+Claudia got this exactly right.  Let me just expand on a couple of points:
+
+*) GateB is exactly one (virtual) hop away from GateA.  This is how it
+would be if there were a physically private wire from A to B.  The
+virtually private connection should work the same, and it does.
+
+*) While the information is in transit from GateA to GateB, the hop count
+of the outer header (the "envelope") is being decremented.  The hop count
+of the inner header (the "contents" of the envelope) is not decremented and
+should not be decremented.  The hop count of the outer header is not
+derived from and should not be derived from the hop count of the inner header.
+
+Indeed, even if the packets did time out in transit along the tunnel, there
+would be no way for traceroute to find out what happened.  Just as
+information cannot leak _out_ of the tunnel to the outside, information
+cannot leak _into_ the tunnel from outside, and this includes ICMP messages
+from routers along the path.
+
+There are some cases where one might wish for information about what is
+happening at the IP layer (below the tunnel layer) -- but the protocol
+makes no provision for this.  This raises all sorts of conceptual issues.
+AFAIK nobody has ever cared enough to really figure out what _should_
+happen, let alone implement it and standardize it.
+
+*) I consider the "* * *" to be a slight bug.  One might wish for it to be
+replaced by "GateB GateB GateB".  It has to do with treating host-to-subnet
+traffic different from subnet-to-subnet traffic (and other gory details).
+I fervently hope KLIPS2 will make this problem go away.
+
+*) If you want to ask questions about the link from GateA to GateB at the
+IP level (below the tunnel level), you have to ssh to GateA and launch a
+traceroute from there.
+</pre>
+
 <h2><a name="man4debug">Testing in stages</a></h2>
 
   <p>
@@ -730,13 +886,19 @@
 <p>
 Other possibilities:</p>
   <ul>
-    <li>mis-configuration of auto connection in the /etc/ipsec.conf file</li>
+    <li>mis-configuration of auto connection in the /etc/ipsec.conf file.
+      <p>One common
+      configuration error is forgetting that you need <var>auto=add</var> to load the
+      connection description on the receiving end so it recognises the connection
+      when the other end asks for it.</li>
     <li>error in shared secret in /etc/ipsec.secrets</li>
     <li>one gateway lacks a route to the other so Pluto's UDP packets are
     lost</li>
     <li>bugs in Pluto</li>
     <li>incompatibilities between Pluto's <a href="glossary.html#IKE">IKE</a>
-      implementation and the IKE at the other end of the tunnel.</li>
+      implementation and the IKE at the other end of the tunnel.
+      <p>Some possibile problems
+      are discussed in out <a href="interop.html#interop.problem">interoperation</a> document.</li>
   </ul>
 
 
@@ -839,6 +1001,38 @@
 Since the above message was written, we have modified the updown script
 to provide a better diagnostic for this problem. Check <var>/var/log/messages</var>.
 
+<h3><a name="noKLIPS">ipsec_setup: Fatal error, kernel appears to lack KLIPS</a></h3>
+
+This message indicates an installation failure. The kernel you are running does
+not contain the KLIPS (kernel IPSEC) code.<p>
+<p>
+Here is one of Claudia's messages on the topic:
+<pre>
+&gt; I tried to install freeswan 1.8 on my mandrake 7.2 test box. ...
+
+&gt; It does show version and some output for whack.
+
+Yes, because the Pluto (daemon) part of ipsec is installed correctly, but
+as we see below the kernel portion is not.
+
+&gt; However, I get the following from /var/log/messages:
+&gt; 
+&gt; Mar 11 22:11:55 pavillion ipsec_setup: Starting FreeS/WAN IPSEC 1.8...
+&gt; Mar 11 22:12:02 pavillion ipsec_setup: modprobe: Can't locate module ipsec
+&gt; Mar 11 22:12:02 pavillion ipsec_setup: Fatal error, kernel appears to lack
+&gt; KLIPS.
+
+This is your problem. You have not successfully installed a kernel with
+IPSec machinery in it. 
+
+Did you build Linux FreeS/WAN as a module? If so, you need to ensure that 
+your new module has been installed in the directory where your kernel 
+loader normally finds your modules. If not, you need to ensure
+that the new IPSec-enabled kernel is being loaded correctly.
+
+See also doc/install.html, and INSTALL in the distro.
+</pre>
+
 <h3><a name="conn_name">Connection names in Pluto error messages</a></h3>
 
 <p>
@@ -890,8 +1084,10 @@
 matches what the remote system has requested.
 The most common cause is a configuration error on one end or the other.
 <p>
-The match involves the <var>left</var>, <var>right</var>, <var>leftsubnet</var>
-and <var>rightsubnet</var> parameters and must be exact. For example, if your
+Parameters involved in this match are <var>left</var>, <var>right</var>, <var>leftsubnet</var>
+and <var>rightsubnet</var>.
+<p>
+<strong>The match must be exact</strong>. For example, if your
 left subnet is a.b.c.0/24 then neither a single machine in that net nor a
 smaller subnet such as a.b.c.64/26 will be considered a match.
 <p>
@@ -925,14 +1121,97 @@
 exactly match what pluto is looking for, and it does not.
 </pre>
 
+<h3><a name="nosuit">Pluto: ... no suitable connection ...</a></h3>
+
+This is similar to the <a href=#noconn>no connection known</a>
+error, but occurs at a different point in Pluto processing.
+<p>
+Here is one of Claudia's messages explaining the problem:
+<pre>
+You write,
+
+> What could be the reason of the following error? 
+> "no suitable connection for peer '@xforce'"
+
+When a connection is initiated by the peer, Pluto must choose which entry in 
+the conf file best matches the incoming connection. A preliminary choice is 
+made on the basis of source and destination IPs, since that information is 
+available at that time. 
+
+A payload containing an ID arrives later in the negotiation. Based on this
+id and the *id= parameters, Pluto refines its conn selection. ...
+
+The message "no suitable connection" indicates that in this refining step,
+Pluto does not find a connection that matches that ID.
+
+Please see "Selecting a connection when responding" in man ipsec_pluto for
+more details.
+</pre>
+<p>
+See also <a href="#conn_name">Connection names in Pluto error messages</a>.
+
+<h3><a name="noconn.auth">Pluto: ... no connection has been authorized</a></h3>
+
+Here is one of Claudia's messages discussing this problem:
+<pre>
+You write,
+
+&gt;  May 22 10:46:31 debian Pluto[25834]: packet from x.y.z.p:10014: 
+&gt;  initial Main Mode message from x.y.z.p:10014 
+                            but no connection has been authorized
+
+This error occurs early in the connection negotiation process,
+at the first step of IKE negotiation (Main Mode), which is itself the 
+first of two negotiation phases involved in creating an IPSec connection.
+
+Here, Linux FreeS/WAN receives a packet from a potential peer, which 
+requests that they begin discussing a connection.
+
+The "no connection has been authorized" means that there is no connection 
+description in Linux FreeS/WAN's internal database that can be used to 
+link your ipsec interface with that peer.
+
+
+
+"But of course I configured that connection!" 
+
+It may be that the appropriate connection description exists in ipsec.conf 
+but has not been added to the database with ipsec auto --add myconn or the 
+auto=add method. Or, the connection description may be misconfigured.
+
+The only parameters that are relevant in this decision are left= and right= .
+Local and remote ports are also taken into account -- we see that the port 
+is printed in the message above -- but there is no way to control these
+in ipsec.conf.
+
+
+Failure at "no connection has been authorized" is similar to the
+"no connection is known for..." error in the FAQ, and the "no suitable
+connection" error described in the snapshot's FAQ. In all three cases,
+Linux FreeS/WAN is trying to match parameters received in the
+negotiation with the connection description in the local config file.
+
+As it receives more information, its matches take more parameters into 
+account, and become more precise:  first the pair of potential peers,
+then the peer IDs, then the endpoints (including any subnets).
+
+The "no suitable connection for peer *" occurs toward the end of IKE 
+(Main Mode) negotiation, when the IDs are matched.
+
+"no connection is known for a/b===c...d" is seen at the beginning of IPSec 
+(Quick Mode, phase 2) negotiation, when the connections are matched using
+left, right, and any information about the subnets.
+</pre>
+
+
 <h3><a name="noDESsupport">Pluto: ... OAKLEY_DES_CBC is not supported.</a></h3>
 
 This message occurs when the other system attempts to negotiate a connection
 using single DES, which we do not support because it is
 <a href="politics.html#desnotsecure">insecure</a>.
 <p>
-Another FAQ section describes <a href="#noDES">how to deal with</a> systems
-that attempt to use single DES.
+Our interoperation document has suggestions for 
+<a href="interop.html#noDES">how to deal with</a> systems that attempt to use single DES.
 
 <h3> <a name="notransform">Pluto: ... no acceptable transform</h3>
 
@@ -947,7 +1226,7 @@
 FreeS/WAN does not support that. (see <a href="#noDES">below</a> for DES
 problems)  
 </ul>
-A more detailed explanation, from Pluto programmer Hugh Redelmaier:</p>
+A more detailed explanation, from Pluto programmer Hugh Redelmeier:</p>
 
 <pre>
 Background:
@@ -1134,6 +1413,57 @@
 This problem is also discussed in this FAQ under the heading
 <a href="#spi_error">One manual connection works, but second one fails</a>.
 
+<h3><a name="ignore">... ignoring ... payload</a></h3>
+
+This message is harmless. The IKE protocol provides for a number of optional
+messages types:
+<ul>
+<li>delete SA
+<li>initial contact
+<li>vendor ID
+<li> ...
+</ul> 
+An implementation is never required to send these, but they are allowed to. 
+The receiver is not required to do anything with them. FreeS/WAN ignores
+them, but notifies you via the logs.
+<p>
+For the &quot;ignoring delete SA Payload&quot; message, see also the discussion
+below of cleaning up <a href="#deadtunnel">dead tunnels</a>.
+
+<h3><a name="dup_address">ipsec_setup: ... interfaces ... and ... share address ...</a></h3>
+
+This is a fatal error. FreeS/WAN cannot cope with two or more interfaces using
+the same IP address. You must re-configure to avoid this.
+<p>
+A mailing list message on the topic from Pluto developer Hugh Redelmeier:
+<pre>
+| I'm trying to get freeswan working between two machine where one has a ppp
+| interface.
+| I've already suceeded with  two machines with ethernet ports but  the ppp
+| interface is causing me problems.
+|  basically when I run ipsec start  i get
+| ipsec_setup: Starting FreeS/WAN IPSEC 1.7...
+| ipsec_setup: 003 IP interfaces ppp1 and ppp0 share address 192.168.0.10!
+| ipsec_setup: 003 IP interfaces ppp1 and ppp2 share address 192.168.0.10!
+| ipsec_setup: 003 IP interfaces ppp0 and ppp2 share address 192.168.0.10!
+| ipsec_setup: 003 no public interfaces found
+|
+| followed by lots of cannot work out interface for connection messages
+|
+| now I can specify the interface in ipsec.conf to be ppp0 , but this does
+| not affect the above behaviour. A quick look in server.c indicates that the
+| interfaces value  is not used but some sort of raw detect happens.
+|
+| I guess I could prevent the formation of the extra ppp interfaces or
+| allocate them different ip but I'd  rather not. if at all possible. Any
+| suggestions please.
+
+Pluto won't touch an interface that shares an IP address with another.
+This will eventually change, but it probably won't happen soon.
+
+For now, you will have to give the ppp1 and ppp2 different addresses.
+</pre>
+
 <h2><a name="canI">Can I ...</a></h2>
 
 <h3><a name="reload">Can I reload connection info without restarting?</a></h3>
@@ -1163,6 +1493,9 @@
 There may be more bits to look for, depending on what you are trying
 to do.
 </pre> 
+<p>
+Another useful command here is <nobr><var>ipsec auto --replace &lt;conn_name&gt;</var></nobr>
+which re-reads data for a named connection. 
 
 <h3><a name="masq.faq">Can I use several masqueraded subnets?</a></h3>
 
@@ -1247,9 +1580,9 @@
 <var>leftsubnet</var> to <var>rightsubnet</var> and vice versa. For this
 to work, the two subnets <em>must</em> be distinct.
 <p>
-There are only two solutions to this problem.
+There are several solutions to this problem.
 <ul>
-<li>Usually, you re-number the subnets. Perhaps the Vancouver office becomes
+<li>Usually, you <strong>re-number the subnets</strong>. Perhaps the Vancouver office becomes
 192.168.101.0/24, Calgary 192.168.102.0/24 and so on. FreeS/WAN can happily
 handle this. With, for example <var>leftsubnet=192.168.101.0/24</var> and
 <var>rightsubnet=192.168.102.0/24</var> in a connection description, any machine
@@ -1257,8 +1590,11 @@
 restrictive and use something like <var>leftsubnet=192.168.101.128/25</var> and
 <var>rightsubnet=192.168.102.240/28</var> so only certain machines on each end
 have access to the tunnel, that's fine too.
-<li>Alternately, you can just give up routing directly to machines on the
-subnets. Omit the <var>leftsubnet</var> and <var>rightsubnet</var> parameters
+<li>You could also <strong>split the subnet</strong> into smaller ones, for example
+using <var>192.168.1.0/25</var> in Vancouver and <var>rightsubnet=192.168.0.128/25</var>
+in Calgary. 
+<li>Alternately, you can just <strong>give up routing</strong> directly to machines
+on the subnets. Omit the <var>leftsubnet</var> and <var>rightsubnet</var> parameters
 from your connection descriptions. Your IPSEC tunnels will then run between
 the public interfaces of the two firewalls. Packets will be masqueraded
 both before they are put into tunnels and after they emerge. Your Vancouver
@@ -1306,9 +1642,150 @@
 DiffServ does not interact well with tunneling in general.  Ways of
 improving this are being studied.
 </pre>
+<p>
+Copying the TOS information from the encapsulated packet to the outer
+header reveals the TOS information to an eavesdropper. It is not clear
+whether or how an attacker could use this information, but since we do
+not have to give it to him, our default is not to.
+<p>
 See <a href="manpage.d/ipsec.conf.5.html">ipsec.conf(5)</a> for more
 on the <var>hidetos=</var> parameter.
 
+<h3><a name="deadtunnel">Can I recognise dead tunnels and shut them down?</a></h3>
+
+There is no general mechanism to do this is in the IPSEC protocols.
+<p>
+From time to time, there is discussion on the IETF Working Group
+<a href="mail.htl#ietf">mailing list</a> of adding a &quot;keep-alive&quot;
+mechanism (which some say should be called &quot;make-dead&quot;),
+but it is a fairly complex problem and no consensus has been reached
+on whether or how it should be done.
+<p>
+The protocol does have optional <a href="#ignore">delete-SA</a> messages
+which one side can send when it closes a connection in hopes this will cause the other
+side to do the same. FreeS/WAN does not currently support these. In any
+case, they would not solve the problem since:
+<ul>
+<li>a gateway that crashes or hangs would not send the messages
+<li>the sender is not required to send them
+<li>they are not authenticated, so any receiver that trusts them leaves itself open to a
+<a href="glossary.html#DOS">denial of service</a> attack
+<li>the receiver is not required to do anything about them
+<li>the receiver cannot acknowledge them; the protocol provides no mechanism for that
+<li>since they are not acknowledged, the sender cannot rely on them
+</ul>
+<p>
+However, connections do have limited lifetimes and you can control how many
+attempts your gateway makes to rekey before giving up. For example, you can
+set:
+<pre>
+conn default
+	keyingtries=3
+	keylife=30m
+</pre>
+With these settings old connections will be cleaned up. Within 30 minutes
+of the other end dying, rekeying will be attempted. If it succeeds, the new
+connection replaces the old one. If it fails, no new connection is created.
+Either way, the old connection is taken down when its lifetime expires.
+<p>
+Here is a mailing list message on the topic from FreeS/WAN tech support person
+Claudia Schmeing:
+<pre>
+You ask how to determine whether a tunnel is redundant:
+
+> Can anybody explain the best way to determine this. Esp when a RW has
+> disconnected? I thought 'ipsec auto --status' might be one way.
+
+If a tunnel goes down from one end, Linux FreeS/WAN on the
+other end has no way of knowing this until it attempts to rekey.
+Once it tries to rekey and fails, it will 'know' that the tunnel is 
+down.
+
+Because it doesn't have a way of knowing the state until this point, 
+it will also not be able to tell you the state via ipsec auto --status.
+
+&gt; However, comparing output from a working tunnel with that of one that
+&gt; was closed 
+&gt; did not show clearly show tunnel status.
+
+If your tunnel is down but not 'unrouted' (see man ipsec_auto), you
+should not be able to ping the opposite side of the tunnel. You can
+use this as an indicator of tunnel status.
+
+On a related note, you may be interested to know that as of 1.7, 
+redundant tunnels caused by RW disconnections are likely to be 
+less of a pain. From doc/CHANGES:
+
+    There is a new configuration parameter, uniqueids, to control a new Pluto
+    option:  when a new connection is negotiated with the same ID as an old
+    one, the old one is deleted immediately.  This should help eliminate
+    dangling Road Warrior connections when the same Road Warrior reconnects. 
+    It thus requires that IDs not be shared by hosts (a previously legal but
+    probably useless capability).  NOTE WELL:  the sample ipsec.conf now has
+    uniqueids=yes in its config-setup section.
+
+
+Cheers,
+
+Claudia
+</pre>
+
+<h3><a name="demanddial">Can I build tunnels over a demand-dialed link?</a></h3>
+
+This is possible, but not easy. FreeS/WAN technical lead Henry Spencer wrote:
+<pre>
+&gt; 5. If the ISDN link goes down in between and is reestablished, the SAs
+&gt; are still up but the eroute are deleted and the IPSEC interface shows
+&gt; garbage (with ifconfig)
+&gt; 6. Only restarting IPSEC will bring the VPN back online.
+
+This one is awkward to solve.  If the real interface that the IPsec
+interface is mounted on goes down, it takes most of the IPsec machinery
+down with it, and a restart is the only good way to recover. 
+
+The only really clean fix, right now, is to split the machines in two: 
+
+1. A minimal machine serves as the network router, and only it is aware
+that the link goes up and down. 
+
+2. The IPsec is done on a separate gateway machine, which thinks it has
+a permanent network connection, via the router.
+
+This is clumsy but it does work.  Trying to do both functions within a
+single machine is tricky.  There is a software package (diald) which will
+give the illusion of a permanent connection for demand-dialed modem
+connections; I don't know whether it's usable for ISDN, or whether it can
+be made to cooperate properly with FreeS/WAN. 
+
+Doing a restart each time the interface comes up *does* work, although it
+is a bit painful.  I did that with PPP when I was running on a modem link;
+it wasn't hard to arrange the PPP scripts to bring IPsec up and down at
+the right times.  (I'd meant to investigate diald but never found time.)
+
+In principle you don't need to do a complete restart on reconnect, but you
+do have to rebuild some things, and we have no nice clean way of doing
+only the necessary parts.
+</pre>
+In the same thread, one user commented:
+<pre>
+Subject: Re: linux-ipsec: IPSEC and Dial Up Connections
+   Date: Wed, 22 Nov 2000
+   From: Andy Bradford &lt;andyb@calderasystems.com&gt;
+
+On Wed, 22 Nov 2000 19:47:11 +0100, Philip Reetz wrote:
+
+&gt; Are there any ideas what might be the cause of the problem and any way
+&gt; to work around it.
+&gt; Any help is highly appreciated.
+
+On my laptop, when using ppp there is a ip-up script in /etc/ppp that 
+will be executed each time that the ppp interface is brought up.  
+Likewise there is an ip-down script that is called when it is taken 
+down.  You might consider custimzing those to stop and start FreeS/Wan 
+with each connection.  I believe that ISDN uses the same files, though 
+I could be wrong---there should be something similar though.
+</pre>
+ 
 <a name="PKIcert">
 <h3>Does FreeS/WAN support X.509 or other PKI certificates?</h3>
 
@@ -1357,7 +1834,7 @@
 user authentication in IPSEC. 
 
 
-<a name=noDES>
+<a name=noDES.faq>
 <h3>Does FreeS/WAN support single DES encryption?</h3>
 
 No, single DES is not used either at the <a href="glossary.html#IKE">IKE</a>
@@ -1365,42 +1842,31 @@
 level for actually building them.
 <p>
 Single DES is <a href="politics.html#desnotsecure">insecure</a>.
-
-<a name=DESstandard>
-<h4>But isn't DES support part of the IPSEC standard?</h4>
-
-Yes, but <a href="politics.html#desnotsecure">DES is insecure</a>. As we see it, it is more
+As we see it, it is more
 important to deliver real security than to comply with a standard which
 has been subverted into allowing use of inadequate methods. See this
 <a href="politics.html#weak">discussion</a>.
-
-<a name=DESonly>
-<h4>I have to talk to .... which offers only DES. How do I do this?</h4>
-
-Ask the device vendor for the <a href="glossary.html#3DES">triple DES</a> upgrade.
-These exist for many IPSEC devices. If no cipher stronger than DES is available,
-we recommend you not use that IPSEC implementation.
 <p>
-If a 3DES implementation exists but your vendor cannot sell it to you
-because of export laws, consider complaining to one or more of:
-<ul>
-<li>the vendor
-<li>your own government, especially any branch concerned with citizen's
-privacy and/or protection of communication infrastructure
-<li>the local embassy of the nation which restricts export to you
-</ul>
-<p>
-Consider using FreeS/WAN instead. PCs are cheap and we deliver 3DES now.
-<p>
-As a matter of project policy, we will not help anyone subvert FreeS/WAN
-to provide <a href="politics.html#desnotsecure">insecure DES encryption</a>.
+If you want to interoperate with an IPSEC implementation which offers only DES,
+see our <a href="interop.html#noDES">interoperation</a> document.
 
 
-<h2><a name="spam">Why don't you restrict the mailing list to reduce spam?</a></h2>
+<h2><a name="spam">Why don't you restrict the mailing lists to reduce spam?</a></h2>
 <p>
-As a matter of policy, the list needs to be open to non-subscribers. Project
-management feel strongly that maintaining this openness is more important
-than blocking spam.
+As a matter of policy, some of our <a href="mail.html">mailing lists</a> need
+to be open to non-subscribers. Project management feel strongly that maintaining
+this openness is more important than blocking spam.
+<ul>
+<li>Users should be able to get help or report bugs without subscribing.
+<li>Even a user who is subscribed may not have access to his or her subscribed
+account when he or she needs help, miles from home base in the middle of setting
+up a client's gateway.
+<li>There is arguably a legal requirement for this policy.
+A US resident or citizen could be charged under munitions export laws for
+providing technical assistance to a foreign cryptographic project. Such a
+charge would be more easily defended if the discussion takes place in public,
+on an open list.
+</ul>
 <p>
 This has been discussed several times at some length on the list. See the
 <a href="mail.html#archive">list archives</a>. Bringing the topic up again
@@ -1417,10 +1883,15 @@
 </blockquote>
 Adding this FAQ section is one of the steps he refers to.
 <p>
-You have various options other than just putting up with the spam or
-unsubscribing:
+You have various options other than just putting up with the spam, filtering
+it yourself, or unsubscribing:
+<ul>
+<li>read the main list via one of its <a href="mail.html#archive">archives</a>
+<li>subscribe only to one or both of our lists with restricted posting rules:
 <ul>
-<li>read the list via one of its <a href="mail.html#archive">archives</a>
+<li><a href="mailto:briefs@lists.freeswan.org?body=subscribe">briefs</a>, weekly list summaries
+<li><a href="mailto:announce@lists.freeswan.org?body=subscribe">announce</a>, project-related announcements
+</ul> 
 <li>subscribe to one or more of the <a href="mail.html#additional">other FreeS/WAN-related lists</a>.
 </ul>
 <p>
@@ -1445,7 +1916,8 @@
 <p>
 For information on tracking down spammers, see these
 <a href="http://www.rahul.net/falk/#howtos">HowTos</a>, or
-the <a href="http://www.sputum.com/index2.html">Sputum</a> site.
+the <a href="http://www.sputum.com/index2.html">Sputum</a> site. Sputum have a Linux
+anti-spam screensaver available for download.
 <p>
 Here is a more detailed message from Henry:
 <pre>
diff -bruN freeswan-1.9.orig/doc/src/firewall.html freeswan-1.9/doc/src/firewall.html
--- freeswan-1.9.orig/doc/src/firewall.html	Wed Mar 14 19:12:35 2001
+++ freeswan-1.9/doc/src/firewall.html	Wed May  2 16:56:27 2001
@@ -156,14 +156,15 @@
     <li>protocol 51 if you use AH packet-level authentication</li>
   </ul>
 <p>
-  Your gateway and the other IPSEC gateways it communicates with must be able
-  to exchange these packets for IPSEC to work. Firewall rules must allow UDP
-  500 and at least one of AH or ESP on the interface that communicates with
-  the other gateway.
+Your gateway and the other IPSEC gateways it communicates with must be able
+to exchange these packets for IPSEC to work. Firewall rules must allow UDP
+500 and at least one of AH or ESP on the interface that communicates with
+the other gateway.
 
-  <h3><a name="through">IPSEC <em>through</a></em> the gateway</h3>
+<h3><a name="through">IPSEC <em>through</a></em> the gateway</h3>
 
-  <p>The preceeding paragraph deals with packets <em>addressed to or sent from
+<p>
+The preceeding paragraph deals with packets <em>addressed to or sent from
   your gateway</em>. It is a separate policy decision whether to permit such
   packets to pass <em>through</em> the gateway so that client machines can
   build end-to-end IPSEC tunnels of their own. This may not be practical if
@@ -171,13 +172,20 @@
   may conflict with some corporate security policies. Other than that, it is
   likely a good idea.</p>
 
-  <h3><a name="unknowngate">Filtering packets from unknown gateways</a></h3>
+<h3><a name="ipsec_only">Preventing non-IPSEC traffic</a></h3>
+
+You can of course also filter <em>everything but</em> UDP port 500 and
+ESP or AH to restrict traffic to IPSEC only, either for anyone communicating
+with your host or just for specific partners.
+
+<h3><a name="unknowngate">Filtering packets from unknown gateways</a></h3>
 
-  <p>It is possible to use firewall rules to restrict UDP 500, ESP and AH
-  packets so that these packets are accepted only from known gateways. This is
-  not strictly necessary since FreeS/WAN will discard packets from unknown
-  gateways. You might, however, want to do it for any of a number of reasons.
-  For example:</p>
+<p>
+It is possible to use firewall rules to restrict UDP 500, ESP and AH
+packets so that these packets are accepted only from known gateways. This is
+not strictly necessary since FreeS/WAN will discard packets from unknown
+gateways. You might, however, want to do it for any of a number of reasons.
+For example:</p>
   <ul>
     <li>Arguably, "belt and suspenders" is the sensible approach to security.
       If you can block a potential attack in two ways, use both. The only
@@ -364,7 +372,13 @@
 Here you have a choice of techniques depending on whether you want
 to make your client subnet visible to clients on the other end:
 <ul>
-  <li>If you want to make them visible,
+<li>If you want the single gateway to behave like the two shown above, with
+your clients hidden behind the NAT, then omit the <var>leftsubnet=</var>
+parameter. It then defaults to the gateway address. Clients on the other
+end then talk via the tunnel only to your gateway. The gateway takes packets
+emerging from the tunnel, applies normal masquerading, and forwards them to
+clients.
+<li>If you want to make your client machines visible,
 then give the client subnet addresses as the
 <var>leftsubnet=</var> parameter in the connection description
 and
@@ -382,11 +396,6 @@
 although of course the encapsulating packets use gateway addresses in their
 headers. Clients behind the right security gateway see a route via
 that gateway to the left subnet.</li>
-<li>If you want your clients hidden, then omit the <var>leftsubnet=</var>
-parameter. It then defaults to the gateway address. Clients on the other
-end then talk via the tunnel only to your gateway. The gateway takes packets
-emerging from the tunnel, applies normal masquerading, and forwards them to
-clients.
 </ul>
 
 <h3><a name="nat_bad">NAT between gateways is problematic</a></h3>
@@ -650,7 +659,7 @@
 # or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 # for more details.
 #
-# RCSID $Id: firewall.html,v 1.10.2.3 2001/03/15 00:12:35 henry Exp $
+# RCSID $Id: firewall.html,v 1.16 2001/05/02 20:56:27 sandy Exp $
 
 # check interface version
 case "$PLUTO_VERSION" in
diff -bruN freeswan-1.9.orig/doc/src/glossary.html freeswan-1.9/doc/src/glossary.html
--- freeswan-1.9.orig/doc/src/glossary.html	Sun Mar 11 23:13:16 2001
+++ freeswan-1.9/doc/src/glossary.html	Sun Jun  3 22:41:06 2001
@@ -173,7 +173,7 @@
         FreeS/WAN</a> would be useful undertaking, and considerable freely
         available code exists to start from. One complication is that our code
         is built for a 64-bit block cipher and AES uses a 128-bit block.
-        Volunteers via the <a href="#list">mailing list</a> would be
+        Volunteers via the <a href="#list">mailing lists</a> would be
         welcome.</p>
         <p>For more information, see the <a
         href="http://csrc.nist.gov/encryption/aes/aes_home.htm"> NIST AES home
@@ -628,7 +628,7 @@
             64K bytes and a fragment carries information on where it starts
             within that 64K and how long it is. The "ping of death" delivers
             fragments that say, for example, that they start at 60K and are
-            20K long. Attempting to re-assemble thse without checking for
+            20K long. Attempting to re-assemble these without checking for
             overflow can be fatal.</li>
         </ul>
         <p>The two example attacks discussed were both quite effective when
@@ -1062,9 +1062,9 @@
         interface. It then gets all the replies, does some table lookups and
         more header rewriting, and delivers the replies to the appropriate
         client machines.</p>
-        <p>To use masquerade with Linux FreeS/WAN, you must set
-        leftfirewall=yes and/or rightfirewall=yes in the connection
-        description in /etc/ipsec.conf.</p>
+        <p>
+        For information on using masquerade with Linux FreeS/WAN, see our
+        <a href="firewall.html#NAT">firewall document</a> and the <a href="faq.html#masq.faq">FAQ</a> and.</p>
       </dd>
     <dt><a name="IPng">IPng</a></dt>
       <dd>"IP the Next Generation", see <a href="#ipv6.gloss">IPv6</a>.</dd>
@@ -1175,18 +1175,9 @@
       </dd>
     <dt><a name="M">M</a></dt>
     <dt><a name="list">Mailing list</a></dt>
-      <dd>The <a href="#FreeSWAN">Linux FreeS/WAN</a> project has an open
-        public email list for bug reports and software development
-        discussions. The list address is <b>linux-ipsec@clinet.fi</b>. To
-        subscribe, send mail to <a
-        href="mailto:majordomo@clinet.fi">majordomo@clinet.fi</a> with a
-        one-line message body "subscribe linux-ipsec".For more information,
-        send majordomo the one-line message "help".
-        <p>NOTE: <strong>US citizens or residents are asked not to post code
-        to the list, not even one-line bug fixes.</strong> The project cannot
-        accept code which might entangle it in US export restrictions.</p>
-        <p>For more detail, see our document on this and other <a
-        href="mail.html">mailing lists</a>.</p>
+      <dd>The <a href="#FreeSWAN">Linux FreeS/WAN</a> project has several
+        public email lists for bug reports and software development
+        discussions. See our document on <a href="mail.html">mailing lists</a>.</p>
       </dd>
     <dt><a name="middle">Man-in-the-middle attack</a></dt>
       <dd>An <a href="#active">active attack</a> in which the attacker
@@ -1422,7 +1413,10 @@
         communications, without a pre-shared secret and without a common <a
         href="#PKI">PKI</a> or previous exchange of public keys. This is one
         of the goals of the Linux FreeS/WAN project, discussed in our <a
-        href="#goals">introduction</a> section.</dd>
+        href="intro.html#goals">introduction</a> section.
+    <p>
+    Setting up for opportunistic encryption is described in our
+    <a href="config.html#oppex">configuration</a> document.</dd>
     <dt><a name="P">P</a></dt>
     <dt><a name="P1363"><a href="http://grouper.ieee.org/groups/1363">P1363
     standard</a></dt>
diff -bruN freeswan-1.9.orig/doc/src/index.html freeswan-1.9/doc/src/index.html
--- freeswan-1.9.orig/doc/src/index.html	Sun Mar 11 23:13:17 2001
+++ freeswan-1.9/doc/src/index.html	Wed May 30 11:42:36 2001
@@ -2,6 +2,17 @@
 <HTML>
 <HEAD>
 <TITLE>FreeS/WAN HTML document index</TITLE>
+<meta name="keywords" content="Linux, IPSEC, VPN, security, encryption, crytography, FreeS/WAN, FreeSWAN">
+
+<!--
+
+Written by Sandy Harris for the Linux FreeS/WAN project
+Freely distributable under the GNU General Public License
+
+More information at www.freeswan.org
+Feedback to users@lists.freeswan.org
+
+-->
 </HEAD>
 <BODY>
 <H1>FreeS/WAN documentation</H1>
diff -bruN freeswan-1.9.orig/doc/src/install.html freeswan-1.9/doc/src/install.html
--- freeswan-1.9.orig/doc/src/install.html	Sun Mar 11 23:13:17 2001
+++ freeswan-1.9/doc/src/install.html	Sun Jun  3 22:41:06 2001
@@ -67,21 +67,28 @@
 
 <h3><a name="choosek">Choosing a kernel</a></h3>
 
-<h4><a name="2.2">2.2.x for most users</a></h4>
+<h4><a name="2.2">2.2.19 for many users</a></h4>
 
 <p>
-Most users should run the most stable available series of
-Linux production <a href="glossary.html#kernel">kernels</a>. At time of writing
-(February 2001), we recommend the 2.2 series for most users. The latest version is
-2.2.18.</p>
+Many users can continue to run kernels from the 2.2 series of
+Linux production <a href="glossary.html#kernel">kernels</a>.
+<p>
+At time of writing (June 2001), the latest version is 2.2.19. If you
+are going to use a 2.2 kernel, we <strong>strongly recommend</strong>
+upgrading to 2.2.19 since:
+<ul>
+<li>It has a number of small security fixes not found in earlier kernels.
+<li>There have been changes in some kernel file formats that make it
+difficult to compile a current FreeS/WAN with earlier kernels. See the
+<a href="mail.html">mailing list archives</a> for details if needed.
+</ul>
 
 <h4><a name="2.4">2.4.x is possible</a></h4>
 
-The new 2.4 series of kernels were first released in January 2001 and are currently
-(mid-February) at 2.4.2. FreeS/WAN does work on these kernels, but for production
-use we suggest waiting a while yet.
+The new 2.4 series of kernels began in January 2001 and are currently
+(early June) at 2.4.5. FreeS/WAN is known to work on 2.4.5.
 <p>
-On the other hand, 2.4 has new firewalling code called
+2.4 has new firewalling code called
 <a href="http://netfilter.kernelnotes.org/unreliable-guides/index.html">netfilter</a>.
 This may provide good reasons to move to 2.4, especially on for gateway machines.
 
@@ -108,7 +115,7 @@
 in the version number (2.0, 2.2, 2.4) and development kernels have an odd
 digit there (2.1, 2.3, 2.5).
 <p>
-At time of writing (February 2001, shortly after the release of 2.4), no more 2.3
+At time of writing, no more 2.3
 kernels are being produced and the 2.5 series has not been started yet, so just
 now development kernels are not an issue. No doubt a 2.5 series will be started
 in the next few months.
@@ -452,7 +459,7 @@
 Of course any status information at this point should be uninteresting
 since you have not yet configured connections.</p>
 
-<h2>Links to other sections</h2>
+<h2>Where to go from here</h2>
 
 <p>See the following section for information on <a href="config.html">configuring
 connections</a>.</p>
diff -bruN freeswan-1.9.orig/doc/src/interop.html freeswan-1.9/doc/src/interop.html
--- freeswan-1.9.orig/doc/src/interop.html	Wed Mar 14 19:12:35 2001
+++ freeswan-1.9/doc/src/interop.html	Sun Jun  3 22:41:06 2001
@@ -49,40 +49,41 @@
 are available for both those formats. See this list of 
 <a href="web.html#patch">patches and add-ons</a>.
 
-  <h2><a name="interop.problem">Interoperability problems</a></h2>
+<h2><a name="interop.problem">Interoperability problems</a></h2>
 
-  <p>The IPSEC RFCs are complex and include a number of optional features.
+<p>
+The IPSEC RFCs are complex and include a number of optional features.
   There is considerable opportunity for even two correct, standard-conforming,
   implementations to disagree on details in a way that blocks interoperation.
   Of course, misinterpretations of the standards and implementation or
   configuration errors on either end can also foul things up.</p>
 
   <p>That said, FreeS/WAN interoperates successfully with many other
-  implementations. There is a <a href="interop.html">list</a> in another
-  section.</p>
+  implementations. There is a <a href="#mail.interop">list</a> below.</p>
 
 <p>
 Known areas where problems may appear are:</p>
   <ul>
+    <li><strong>FreeS/WAN does not implement single DES</strong> because <a
+      href="politics.html#desnotsecure">DES is insecure</a>. Suggestions on what to do if
+      the device you want to talk to has only DES are <a href="#noDES">below</a>.</li>
+    <li><strong>FreeS/WAN does not implement Diffie-Hellman group 1</strong> because it
+      it is not entirely clear that this is secure.</li>
     <li>The RFCs define two modes for IKE negotiations -- main mode and
       aggressive mode. Aggressive mode is slightly faster, but reveals more
       information to an eavesdropper. Specifically, it lets an eavesdropper
       know what identities are in use. <strong>FreeS/WAN does not implement
       aggressive mode</strong>, so any negotiation another implementation
-      tries that way will fail. In principle this should not be a problem
-      since main mode support is required in all implementations and aggressive
-      mode is optional.
+      tries that way will fail.
       <p>
-      In practice, it is sometimes a problem. Some implementations default to
+      In principle this should not be a problem
+      since main mode support is required in all implementations and aggressive
+      mode is optional.       In practice, it is sometimes a problem.
+      Some implementations default to
       aggressive mode unless you configure them for main mode.</p>
-    </li>
-    <li><strong>FreeS/WAN does not implement single DES</strong> because <a
-      href="politics.html#desnotsecure">DES is insecure</a>. Suggestions on what to do if
-      the device you want to talk to has only DES are in our <a
-      href="FAQ.html#noDES">FAQ</a> document.</li>
-    <li><strong>FreeS/WAN does not implement Diffie-Hellman group 1</strong> because it
-      it is not entirely clear that this is secure.
-    <li>For automatic keying, <strong>the FreeS/WAN default is to provide
+
+    <li>
+      For automatic keying, <strong>the FreeS/WAN default is to provide
       <a href="glossary.html#PFS">perfect forward secrecy</a></strong>. We see no reason not
       to; this is more secure and costs little. Some other implementations,
       however, turn PFS off by default.
@@ -90,6 +91,18 @@
       You can turn PFS off in FreeS/WAN with the <var>pfs=no</var> setting in
       <a href="manpage.d/ipsec.conf.5.html">ipsec.conf(5)</a>, but if possible
       we suggest you enable it on the other end instead. That is more secure.</li>
+    <li>
+      The IKE protocol allows several types of optional message. Two things happen
+      which are allowed by the RFCs:
+      <ul>
+      <li>Some implementations send various optional messages.
+      <li>FreeS/WAN ignores them.
+      </ul>
+      However, problems may arise if the other end relies on some expected effect
+      of these messages. There are two FAQ questions dealing with this, one on the
+      <a href="faq.html#ignore">log message</a> FreeS/WAN gives when ignoring
+      optional payloads and one on the <a href="faq.html#deadtunnel">delete SA</a>
+      payload.
   </ul>
 
 <p>
@@ -105,10 +118,10 @@
 This is possible for most implementations.</p>
 
 
-<h3><a name="noDES">Systems that want to use DES</a></h3>
+<h3><a name="noDES">Systems that want to use single DES</a></h3>
 
 <p>
-Linux FreeS/WAN does not support DES transforms. Neither Pluto's IKE
+Linux FreeS/WAN does not support single DES transforms. Neither Pluto's IKE
 connections nor KLIPS' IPSEC connections can use DES. Since
 <a href="politics.html#desnotsecure">DES is insecure</a> we do not,
 and will not at any future time, provide it.</p>
@@ -117,31 +130,35 @@
 DES is, unfortunately, a mandatory part of the <a href="glossary.html#IPSEC">IPSEC</a>
 standard. Despite that, we will not implement DES. We believe it is more
 important to provide security than to comply with a standard which has been
-subverted into allowing weak algorithms. See our <a href="politics.html">history
+<a href="politics.html#weak">subverted</a> into allowing weak algorithms. See our
+<a href="politics.html">history
 and politics</a> section for discussion.</p>
 
-  <p>Some implementations may offer DES as the default. In such cases we urge
-  you to change them to <a href="glossary.html#3DES">Triple DES</a>. If this is not
-  possible, for example because <a href="politics.html#exlaw">export laws</a> prevent your
-  vendor from offerring you adequate crytography, we urge you to complain
-  vigorously to</p>
+<p>
+Some implementations may offer DES as the default. In such cases we urge
+you to change them to <a href="glossary.html#3DES">Triple DES</a>. If this is not
+possible, for example because <a href="politics.html#exlaw">export laws</a> prevent your
+vendor from offerring you adequate crytography, we urge you to complain
+vigorously to one or more of:</p>
   <ul>
-    <li>your government</li>
+    <li>your government, especially any department concerned with protecting citizens' 
+      privacy or your nation's communication infrastructure</li>
     <li>the vendor</li>
-    <li>the embassy of the nation whose laws are problematic for you.</li>
+    <li>the embassy of the nation whose laws are problematic for you</li>
   </ul>
 
 <p>
-In the meanwhile, use FreeS/WAN to get strong crypto until the laws are
-fixed.</p>
+Consider using FreeS/WAN instead. PCs are cheap and we deliver 3DES now.
 
-  <p>
+<p>
 FreeS/WAN does have <a href="glossary.html#DES">DES</a> code in it as a sort of
 historical accident, since we need it to implement our default (currently,
 our only) block cipher, <a href="glossary.html#3DES">Triple DES</a>. However, since <a
 href="politics.html#desnotsecure">DES is insecure</a>, we do not provide any interface to
-that code and, as a matter of policy, will provide no help to anyone who may
-wish to use it.</p>
+that code.</p>
+<p>
+As a matter of project policy, we will not help anyone subvert FreeS/WAN
+to provide <a href="politics.html#desnotsecure">insecure DES encryption</a>.
 
 
 <h2><a name="otherpub">Interop HowTo documents</a></h2>
@@ -183,6 +200,8 @@
   <a href="http://el06-24-29-255-187.ce.mediaone.net/carl/linux/ipsec/swan-w2k/swanw2k-b.html">FreeS/WAN and Windows 2000</a>
    <li>Ryan's <a href="http://www-ec.njit.edu/~rxt1077/Howto.txt">HowTo</a> for getting PGPnet to
    connect with FreeS/WAN using x509 certs through a Linksys router, with IPSec passthru enabled.
+ 
+
   </ul>
 <p>
 See also our list of available <a href="web.html#patch">patches and add-ons</a>.
@@ -333,7 +352,8 @@
 but it gets there :-)
 </pre>
 
-  <p>A later message from Ian:</p>
+<p>
+A later message from Ian:</p>
 <pre>
 This configuration is provided as-is and with no assistance or guarantee
 that it works whatsover. In particular your attention is drawn to the versions
@@ -415,6 +435,19 @@
 
 <h3><a name="bay">Nortel (Bay Networks) Contivity switch</a></h3>
 
+There is one known issue in FreeS/WAN-to-Contivity interoperation.
+Recent versions of FreeS/WAN no longer support DH group 1 for key
+exchange. Older versions of Contivity software support nothing else.
+Group 2 was added in more recent releases. So:
+<ul>
+<li>older FreeS/WANs, such as 1.5, will work with any Contivity software.
+Key exchange will be done using DH Group 1. This may not be secure.
+<li>current FreeS/WANs will work only with recent Contivity releases
+supporting DH Group 2. Contivity 3.5 is one such release.
+</ul>
+We recommend using the latest Contivity release.
+<p>
+Some messages from the mailing list:
 <pre>
 Subject: Contivity Extranet Switch
    Date: Fri, 11 Jun 1999
@@ -832,6 +865,20 @@
   vendor's site or browsed at a VPN mailing list <a
   href="http://kubarb.phsx.ukans.edu/~tbird/vpn.html">site</a>.</p>
 
+<h3><a name="redcreek">Redcreek Ravlin</a></h3>
+
+We have reports of successful interoperation at an interop
+<a href="http://www.opus1.com/vpn/atl99display.html">conference</a>, but
+there is also a mailing list 
+<a href="http://www.sandelman.ottawa.on.ca/linux-ipsec/html/2000/11/msg00510.html">thread</a>
+discussing difficulties some users have encountered.
+
+<h3><a name="sentinel">SSH Sentinel</a></h3>
+
+The vendor's 
+<a href="http://www.ipsec.com/products/sentinel/documents.html">web site</a>
+has configuration examples for use with FreeS/WAN.
+
 <h3><a name="Fsecure">F-Secure VPN for Windows</a></h3>
   <pre>   Subject: linux-ipsec: Identification through other than IP number
    Date: Tue, 13 Apr 1999
@@ -1510,7 +1557,8 @@
 of both domains or consider setting up WINS service(s).
 </pre>
 We suspect that in some cases it may be more complex than that. See the
-discussion of Linux services and Windows 2000 <a href="#lin2k">below</a>.
+discussion of <a href="#lin2k">Linux services and Windows 2000</a> below
+and the <a href="#otherpub">Interop HowTo</a> documents listed above.
 
 <h3><a name="win2k">Windows 2000</a></h3>
 
@@ -1594,15 +1642,10 @@
 
   <h4><a name="interop.win2k">FreeS/WAN-to-Win2000 interop</a></h4>
 
-<p>As for IPSEC interoperation between Windows 2000 and FreeS/WAN,
-there are some web sites:</p>
-<ul>
-    <li>The Norwegian company <a
-      href="http://security.nta.no/freeswan-w2k.html">Telenor</a></li>
-    <li><a href="http://jixen.tripod.com/#Win2000-Fwan">Jean-Francois
-      Nadeau</a></li>
-    <li><a href="http://el06-24-29-255-187.ce.mediaone.net/carl/linux/ipsec/swan-w2k/swanw2k-b.html">Carl's guide</a>
-</ul>
+<p>
+As for IPSEC interoperation between Windows 2000 and FreeS/WAN,
+there are several web sites listed under <a href="#otherpub">Interop HowTo</a> documents
+above.</p>
 
   <p>Here is a discussion from the mailing list:</p>
   <pre>From: "Jean-Francois Nadeau" &lt;jna@microflex.ca&gt;
diff -bruN freeswan-1.9.orig/doc/src/intro.html freeswan-1.9/doc/src/intro.html
--- freeswan-1.9.orig/doc/src/intro.html	Wed Mar 14 19:12:35 2001
+++ freeswan-1.9/doc/src/intro.html	Sun Jun  3 22:41:07 2001
@@ -184,7 +184,7 @@
   <li>If Network Address Translation (NAT) is applied between the two IPSEC
     Gateways, this breaks IPSEC. IPSEC authenticates packets on an end-to-end
     basis, to ensure they are not altered en route. NAT rewrites packets as
-    they go by.</li>
+    they go by. See our <a href="firewall.html#NAT">firewalls</a> document for details.</li>
 </ul>
 
 <p>
@@ -201,7 +201,7 @@
 preset information about the other</em>.  We hope this will go some distance
 toward creating a secure Internet, an environment where message privacy is the
 default. See our <a href="politics.html">history and politics of cryptography</a>
-section for discussion</p>
+section for discussion.</p>
 <p>
 Both systems pick up the authentication information they need from the
 <a href="glossary.html#DNS.gloss">DNS</a> (domain name service), the service
@@ -214,8 +214,8 @@
 accept unencrypted communication is a policy decision the administrator can
 make.</p>
 <p>
-A draft document giving most of the <a href="opportunism.txt">details</a>
-of how we plan to implement this is available.</p>
+A draft document giving most of the details of how we plan to implement
+this has been posted to the mailing list. See <a href=#applied>links</a> below.</p>
 <p>
 Only one current product we know of implements a form of opportunistic
 encryption. <a href="web.html#ssmail">Secure sendmail</a> will automatically encrypt
@@ -377,8 +377,11 @@
   <li><a href="ftp://ftp.net.lut.ac.uk/freeswan">the UK</a></li>
   <li><a href="http://storm.alert.sk/comp/mirrors/freeswan/">Slovak
     Republic</a></li>
+  <li><a href="http://the.wiretapped.net/security/vpn-tunnelling/freeswan/">Australia</a></li>
   <li><a href="http://freeswan.technolust.cx/">technolust</a></li>
   <li>Ivan Moore's <a href="http://snowcrash.tdyc.com/freeswan/">site</a></li>
+  <li>the <a href="http://www.cryptoarchive.net/">Crypto Archive</a> on the
+  <a href="http://www.securityportal.com/">Security Portal</a> site
 </ul>
 
 <h4><a name="munitions">The &quot;munitions&quot; archive of Linux crypto software</a></h4>
@@ -395,14 +398,18 @@
 Any of those will have a list of other &quot;munitions&quot; mirrors.
 
 <h3><a name="archives">Archives of the project mailing list</a></h3>
+
+Until quite recently, there was only one FreeS/WAN mailing list, and archives
+of it were:
 <ul>
   <li><a href="http://www.sandelman.ottawa.on.ca/linux-ipsec">Canada</a></li>
   <li><a href="http://www.nexial.com">Holland</a></li>
 </ul>
-
-<p>
 The two archives use completely different search engines. You might want to
 try both.</p>
+<p>
+More recently we have expanded to five lists, each with its own archive.
+See <a href="mail.html">details</a> elsewhere in the documentation.
 
 <p><a href="mail.html">More information</a> on this and other mailing lists.</p>
 
@@ -425,7 +432,7 @@
   <li><a href="http://www.trustix.net/">Trustix Secure Linux</a> (Norway)
 </ul>
 <p>
-For distributions which do not include FreeS/WAN and are not Redhat 6.x (which we
+For distributions which do not include FreeS/WAN and are not Redhat (which we
 develop and test on), there is additional information in our
 <a href="compatibility.html#otherdist">compatibility</a> section.</p>
 <p>
@@ -475,6 +482,8 @@
   FreeS/WAN</li>
   <li><a href="http://www.merilus.com">Merilus</a> use FreeS/WAN in their Gateway Guardian firewall
     product and in their <a href="http://www.merilus.com/firecard/index.shtml">Firecard</a> product, a Linux firewall on a PCI card.
+  <li><a href="http://www.kyzo.com/">Kyzo</a> have a &quot;pizza box&quot; product line with various types of
+    server, all running from flash. One of them is an IPSEC/PPTP VPN server.
 </ul>
 
 <p>We would appreciate hearing of other products using FreeS/WAN.</p>
@@ -601,7 +610,7 @@
      <li>kernel programmer Richard Guy Briggs on
     <a href="http://www.sandelman.ottawa.on.ca/linux-ipsec/html/2001/02/msg00435.html">redesign of KLIPS</a>
      <li>technical lead Henry Spencer on
-     <a href="http://www.sandelman.ottawa.on.ca/linux-ipsec/html/2001/02/msg00381.html">opportunistic encryption</a>
+     <a href="http://www.sandelman.ottawa.on.ca/linux-ipsec/html/2001/05/msg00084.html">opportunistic encryption</a>
   </ul>
    Both documents are works in progress and may be revised. Check the mailing list for more recent versions.
     <li>Bart Trojanowski's web page has a draft design for
diff -bruN freeswan-1.9.orig/doc/src/ipsec.html freeswan-1.9/doc/src/ipsec.html
--- freeswan-1.9.orig/doc/src/ipsec.html	Mon Feb 26 19:59:17 2001
+++ freeswan-1.9/doc/src/ipsec.html	Sun Jun  3 22:41:07 2001
@@ -243,7 +243,8 @@
 
   <h3><a name="authonly">Using authentication without encryption</a></h3>
 
-  <p>Where appropriate, IPSEC can provide authentication without encryption.
+<p>
+Where appropriate, IPSEC can provide authentication without encryption.
   One might do this, for example:</p>
   <ul>
     <li>where the data is public but one wants to be sure of getting the right
@@ -256,7 +257,14 @@
       harder.</li>
   </ul>
 <p>
-  Authentication has lower overheads than encryption.
+Authentication has lower overheads than encryption.
+<p>
+The protocols provide four ways to build such connections, using either an
+AH-only connection or ESP using null encryption, and in either manually or
+automatically keyed mode. FreeS/WAN supports only one of these, manually keyed
+AH-only connections, and <strong>we do not recommend using that</strong>. Our
+reasons are discussed under <a href="#traffic.resist">Resisting traffic analysis</a>
+a few sections further along.
 
   <h3><a name="encnoauth">Encryption without authentication is dangerous</a></h3>
 
@@ -276,7 +284,8 @@
     <li>AH for authentication alone</li>
   </ul>
 
-  <p>Other variants are allowed by the standard, but not much used:</p>
+<p>
+Other variants are allowed by the standard, but not much used:</p>
   <dl>
     <dt>ESP encryption without authentication</dt>
       <dd><strong>Bellovin has demonstrated fatal flaws in this. Do not
@@ -296,15 +305,14 @@
         might use ESP as well.</dd>
     <dt>ESP authentication without encryption</dt>
       <dd>The standard allows this, calling it "null encryption". FreeS/WAN
-        does not normally support it, but it can be enabled with a kernel
-        configuration option. We recommend that you use AH instead if
+        does not support it. We recommend that you use AH instead if
         authentication is all you require. AH authenticates parts of the IP
-        header, which ESP-null does not do. Also, if you do not enable
-        ESP-null on your FreeS/WAN machine, then you run no risk of a
-        configuration error using this when it should be encrypting.</dd>
+        header, which ESP-null does not do.</dd>
   </dl>
-
-  <p>There are fairly frequent suggestions that AH be dropped entirely from
+Some of these variants cannot be used with FreeS/WAN because we do not support
+ESP-null and do not support automatic keying of AH-only connections. 
+<p>
+There are fairly frequent suggestions that AH be dropped entirely from
   the IPSEC specifications since ESP and null encryption can handle that
   situation. It is not clear whether this will occur. My guess is that it is
   unlikely.</p>
@@ -340,14 +348,13 @@
 derive useful intelligence from encrypted traffic without breaking the
 encryption. For example, an eavesdropper might deduce something interesting
 merely by knowing that your CEO was exchanging email with a particular
-venture capital firm. Or that all the CEO's mail this week went to a
-firm of bankruptcy trustees and a half dozen executive recruiting
-agencies.
+venture capital firm, or that the CEO was talking to a firm of bankruptcy
+trustees and a half dozen executive recruiting agencies.
 <p>
 Except in the simplest cases, traffic analysis is hard to do well. It
 requires both considerable resources and considerable analytic skill.
 However, intelligence agencies of various nations have been doing it
-for centuries and most of them are likely quite good at it by now.
+for centuries and many of them are likely quite good at it by now.
 Various commercial organisations, especially those working on
 &quot;targeted marketing&quot; may also be quite good at analysing
 certain types of traffic.
@@ -860,14 +867,13 @@
   <p>The authentication algorithms are the same ones used in the IPSEC <a
   href="#AH">authentication header</a>.</p>
 
-  <p>We do not implement single DES since <a href="politics.html#desnotsecure">DES is
-  insecure</a>. Instead we provide <a href="glossary.html#3DES">triple DES or 3DES</a>.
-  This is currently the only encryption algorithm supported.</p>
-
-  <p>We do implement null encryption, but it is disabled by default. You can
-  enable it in the IPSEC part of kernel configuration if required. We would
-  suggest, however, that if you need only authentication, you should use AH
-  rather than ESP with null encryption.</p>
+  <p>
+We do not implement single DES since <a href="politics.html#desnotsecure">DES is
+insecure</a>. Instead we provide <a href="glossary.html#3DES">triple DES or 3DES</a>.
+This is currently the only encryption algorithm supported.</p>
+
+<p>
+We do not implement null encryption since it is obviously insecure.</p>
 
   <h2><a name="modes">IPSEC modes</a></h2>
 
diff -bruN freeswan-1.9.orig/doc/src/mail.html freeswan-1.9/doc/src/mail.html
--- freeswan-1.9.orig/doc/src/mail.html	Wed Mar 14 19:12:35 2001
+++ freeswan-1.9/doc/src/mail.html	Sun Jun  3 22:41:07 2001
@@ -17,7 +17,7 @@
 <dd>
 <ul>
    <li>The general list for discussing use of the software
-   <li>The place for seeking <strong>help with problems</strong>.
+   <li>The place for seeking <strong>help with problems</strong> (but please check the <a href="faq.html">FAQ</a> first).
    <li>Anyone can post.
 </ul>
 </dd>
@@ -35,7 +35,9 @@
 <ul>
    <li><strong>Design discussions</strong>, for people working on FreeS/WAN development or others with an interest
         in design and security issues.
-   <li>Only subscribers can post.
+   <li>It would be a good idea to read the existing design papers (see this <a href="intro.html#applied">list</a>) before
+         posting.
+   <li>Anyone can post.
 </ul>
 </dd>
 <dt><a href="mailto:announce-request@lists.freeswan.org?body=subscribe">announce</a></dt>
@@ -44,8 +46,9 @@
    <li>A <strong>low-traffic</strong> list.
    <li><strong>Announcements</strong> about FreeS/WAN and related software.
    <li>All posts here are also sent to the users list. You need not subscribe to both.
-   <li>Only authorised people can post.
-</ul>
+   <li>Only the FreeS/WAN team can post.
+   <li>If you have something you feel should go on this list, send it to <var>announce-admin@lists.freeswan.org</var>.
+     Unless it is obvious, please include a short note explaining why we should post it.</ul>
 </dd>
 <dt><a href="mailto:briefs-request@lists.freeswan.org?body=subscribe">briefs</a></dt>
 <dd>
@@ -53,7 +56,7 @@
    <li>A <strong>low-traffic</strong> list.
    <li><strong>Weekly summaries</strong> of activity on the users list.
    <li>All posts here are also sent to the users list. You need not subscribe to both.
-   <li>Only authorised people can post.
+   <li>Only the FreeS/WAN team can post.
 </ul>
 </dd>
 </dl>
@@ -64,6 +67,10 @@
 <li>send mail to <var>listname</var>-request@lists.freeswan.org
 with a one-line message body "subscribe"
 </ul>
+<p>
+Archives of these lists are available via the
+<a href="http://www.freeswan.org/mail.html">web interface</a>.
+
 
 <h4><a name="policy.list">List policies</a></h4>
 
@@ -91,7 +98,13 @@
     <li><a href="http://www.nexial.com">Holland</a></li>
   </ul>
 
-  <p>Note that these use different search engines. Try both.</p>
+<p>
+Note that these use different search engines. Try both.</p>
+
+<p>
+Archives of the new lists are available via the
+<a href="http://www.freeswan.org/mail.html">web interface</a>.
+
 
 <h3><a name="additional">Other FreeS/WAN related lists</a></h3>
 <p>
diff -bruN freeswan-1.9.orig/doc/src/politics.html freeswan-1.9/doc/src/politics.html
--- freeswan-1.9.orig/doc/src/politics.html	Sun Mar 11 23:13:18 2001
+++ freeswan-1.9/doc/src/politics.html	Wed May 30 11:42:36 2001
@@ -64,10 +64,10 @@
 University, several old Ultra hands included, built one of the world's first
 actual general-purpose digital computers.
 <li>Ultra made codebreaking a large-scale enterprise, producing intelligence on
-an industrial scale. This was not a &quot;black chamber&quot;, not some hidden room
+an industrial scale. This was not a &quot;black chamber&quot;, not a hidden room
 in some obscure government building with a small crew of code-breakers. The whole
-operation -- from intercept operators all over the world grabbing copies of enemy
-communications, through large-scale code-breaking and analysis of the decrypted
+operation -- from wholesale interception of enemy communications by stations
+around the world, through large-scale code-breaking and analysis of the decrypted
 material (with an enormous set of files for cross-referencing), to delivery of
 intelligence to field commanders -- was huge, and very carefully managed.
 </ul>
@@ -78,7 +78,7 @@
 <h4><a name="postwar">Postwar and Cold War</a></h4>
 
 The wartime innovations were enthusiastically adopted by post-war and Cold War
-signals intelligence agencies. Presumably most nations now have some agency capable
+signals intelligence agencies. Presumably many nations now have some agency capable
 of sophisticated attacks on communications security, and quite a few engage in such
 activity on a large scale.
 <p>
@@ -100,7 +100,7 @@
 on cell phones, or intercepting electronic mail, or tapping into the huge
 volumes of data on new media such as fiber optics or satellite links. None
 of these targets existed in 1950. All of them can be attacked today, and almost
-certainly are being attacked on a large scale.
+certainly are being attacked.
 <p>
 The Ultra story was not made public until the 1970s. Much of the recent history
 of codes and code-breaking has not been made public, and some of it may never be.
@@ -136,19 +136,22 @@
 becoming ubiquitous, cryptography is now important to almost everyone. Among
 the developments since the 1970s:
 <ul>
-<li>the US gov't established the <a href="glossary.html#DES">DES</a>
+<li>The US gov't established the Data Encryption Standard, <a href="glossary.html#DES">DES</a>
 standard, a <a href="glossary.html#block">block cipher</a> for
-cryptographic protection of unclassfied documents
-<li><a href="glossary.html#public">public key</a> cryptography invented by Diffie and Hellman
-<li>academic conferences such as <a href="http://www-cse.ucsd.edu/users/mihir/crypto2k.html">Crypto</a>,
-<a href="http://www.esat.kuleuven.ac.be/cosic/eurocrypt2000/">Eurocrypt</a>, ...
-<li>companies offerring cryptographic products: <a href="glossary.html#RSAco">RSA</a>,
+cryptographic protection of unclassfied documents. It has also been widely used in
+industry.
+<li><a href="glossary.html#public">Public key</a> cryptography was invented by Diffie and Hellman.
+<li>Academic conferences such as <a href="http://www-cse.ucsd.edu/users/mihir/crypto2k.html">Crypto</a>
+and <a href="http://www.esat.kuleuven.ac.be/cosic/eurocrypt2000/">Eurocrypt</a> began.
+<li>Several companies began offerring cryptographic products: <a href="glossary.html#RSAco">RSA</a>,
 <a href="glossary.html#PGPI">PGP</a>, the many vendors with <a href="glossary.html#PKI">PKI</a> products,
 ...
-<li>crypto in other products: operating systems, word processors, ...
-<li>network protocols based on crypto:  <a href="glossary.html#SSH">SSH</a>,
+<li>Cryptography appeared in other products: operating systems, word processors, ...
+<li>Network protocols based on crypto were developed:  <a href="glossary.html#SSH">SSH</a>,
 <a href="glossary.html#SSL">SSL</a>,  <a href="glossary.html#IPSEC">IPSEC</a>, ...
-<li>widespread use of cryptography to secure bank cards, terminals, ... 
+<li>Crytography came into widespread use to secure bank cards, terminals, ...
+<li>The US government replaced <a href="glossary.html#DES">DES</a> with the much stronger
+Advanced Encryption Standard, <a href="glossary.html#AES">AES</a>
 </ul>
 <p>
 This has led to a complex ongoing battle between various mainly government groups wanting to
@@ -218,7 +221,8 @@
     <li>Echelon, a monitor-the-world project of the US, UK, NZ, Australian and
       Canadian <a href="glossary.html#SIGINT">signals intelligence</a> agencies. See this
       <a href="http://sg.yahoo.com/government/intelligence/echelon_network/">collection</a> of links and
-      this <a href="http://www.zdnet.com/zdnn/stories/news/0,4586,2640682,00.html">story</a> on the French Parliament's reaction.</li>
+      this <a href="http://www.zdnet.com/zdnn/stories/news/0,4586,2640682,00.html">story</a>
+      on the French Parliament's reaction.</li>
     <li>Others governments may well have their own Echelon-like projects. To quote
        the Dutch Minister of Defense, as reported in a German
       <a href="http://www.heise.de/tp/english/inhalt/te/4729/1.html">magazine</a>:
@@ -228,13 +232,18 @@
     investigative authorities and intelligence services of many countries with
      governments of different political signature.
     </blockquote>
-    Even if they have nothing on the scale of Echelon, most or all intelligence agencies and
+    Even if they have nothing on the scale of Echelon, most intelligence agencies and
     police forces certainly have some interception capability.
+   <li><a href="glossary.html#NSA">NSA</a> tapping of submarine communication cables, described
+     in <a href="http://www.zdnet.com/zdnn/stories/news/0,4586,2764372,00.html">this article</a>
     <li>A proposal for international co-operation on 
       <a href="http://www.heise.de/tp/english/special/enfo/4306/1.html">Internet surveillance</a>.</li>
 
     <li>Alleged <a href="http://cryptome.org/nsa-sabotage.htm">sabotage</a> of security
       products by the <a href="glossary.html#NSA">NSA</a> (the US signals intelligence agency).</li>
+   <li>The German armed forces and some government departments will stop using American software for fear of NSA
+      &quot;back doors&quot;, according to this <a href="http://www.theregister.co.uk/content/4/17679.html">news story</a>. 
+ 
     <li>The British Regulation of Investigatory Powers bill. See
       this <a href="http://www.fipr.org/rip/index.html">web page.</a> and
       perhaps this <a href="http://ars.userfriendly.org/cartoons/?id=20000806&amp;mode=classic">cartoon</a>.</li>
@@ -269,6 +278,8 @@
 <ul>
 <li>industrial espionage, as for example in this
 <a href="http://www.zdnet.com/zdnn/stories/news/0,4586,2626931,00.html">news story</a></li>
+<li>attacks by organised criminals, as in this 
+<a href="http://www.sans.org/newlook/alerts/NTE-bank.htm">large-scale attack</a>
 <li>collection of personal data by various companies.
 <ul>
 <li>for example, consider the various corporate winners of Privacy International's
@@ -665,17 +676,18 @@
 
 <p>
 Various governments have made persistent attempts to encourage or mandate
-"escrowed encrytion", also called "key recovery", or GAK for "government
-access to keys". The idea is that cryptographic keys be held by some third
+&quot;escrowed encrytion&quot;, also called &quot;key recovery&quot;, or GAK for &quot;government
+access to keys&quot;. The idea is that cryptographic keys be held by some third
 party and turned over to law enforcement or security agencies under some
 conditions.</p>
 <pre>
-Mary had cryptography
-Her keys were in escrow
-And everything that Mary said
-The feds were sure to know
+  Mary had cryptography
+  Her keys were in escrow
+  And everything that Mary said
+  The feds were sure to know
 </pre>
-
+(If anyone knows the origin of that ditty, let
+<a href="mailto:sandy@storm.ca">let me know</a> so I can credit the author.)
 <p>
 There is an excellent paper available on
 <a href="http://www.cdt.org/crypto/risks98/">Risks of Escrowed Encryption</a>,
@@ -700,16 +712,20 @@
 
 <p>
 Various governments, and some vendors, have also made persistent attempts
-to convince people that weak systems are sufficient for some data, that
-strong cryptography should be reserved for cases where the extra overheads
-are justified. This is nonsense.</p>
+to convince people that:
+<ul>
+<li>weak systems are sufficient for some data
+<li>strong cryptography should be reserved for cases where the extra overheads
+are justified
+</ul>
+<strong>This is nonsense</strong>.</p>
 
 <p>
 Weak systems touted include:</p>
 
 <ul>
   <li>the ludicrously weak (deliberately crippled) 40-bit ciphers that until
-    recently were all various <a href="#exlaw">export laws</a> allowed.</li>
+    recently were all various <a href="#exlaw">export laws</a> allowed</li>
     <li>56-bit single DES, discussed <a href="#desnotsecure">below</a></li>
   <li>64-bit symmetric ciphers and 512-bit RSA, the maximums for unrestricted
     export under various current laws</li>
@@ -744,10 +760,13 @@
       href="glossary.html#hybrid">hybrid</a> systems in which the bulk of the work is done
       by a symmetric cipher. The effect of increasing the cost of the public
       key operations is typically negligible because the public key operations
-      use only a tiny fraction of total resources. For example, if public key
+      use only a tiny fraction of total resources.
+      <p>
+      For example, suppose public key
       operations use use 1% of the time in a hybrid system and you triple the
-      cost of public key operations, the overall effect is a 2% rise in system
-      cost.</li>
+      cost of public key operations. The cost of symmetric cipher operations
+      is unchanged at 99% of the original total cost, so the overall effect is a
+      jump from 99 + 1 = 100 to 99 + 3 = 102, a 2% rise in system cost.</li>
 </ul>
 
 <p>
diff -bruN freeswan-1.9.orig/doc/src/trouble.html freeswan-1.9/doc/src/trouble.html
--- freeswan-1.9.orig/doc/src/trouble.html	Wed Mar 14 19:12:36 2001
+++ freeswan-1.9/doc/src/trouble.html	Wed May 30 11:42:36 2001
@@ -41,9 +41,9 @@
 
   <h3><a name="pages">man pages provided</a></h3>
   <dl>
-    <dt>ipsec.conf(5)</dt>
+    <dt><a href="manpage.d/ipsec.conf.5.html">ipsec.conf(5)</a></dt>
       <dd>Manual page for IPSEC configuration file.</dd>
-    <dt>ipsec(8)</dt>
+    <dt><a href="manpage.d/ipsec.8.html">ipsec(8)</a></dt>
       <dd>Primary man page for ipsec utilities.</dd>
   </dl>
 
@@ -69,9 +69,11 @@
     <dt>ipsec barf</dt>
       <dd>Copious debugging info.</dd>
   </dl>
-  <h2><a name="pluto.problems">Pluto problem hints</a></h2>
 
-  <p>From a message posted to the mailing list Jan 14 2000 by Pluto developer
+<h2><a name="pluto.problems">Pluto problem hints</a></h2>
+
+<p>
+From a message posted to the mailing list Jan 14 2000 by Pluto developer
   Hugh Redelmeier:</p>
   <pre>
 Until ipsec auto and whack/pluto get fixed:
@@ -94,6 +96,36 @@
 </pre>
 Various error messages from Pluto are discussed in the <a href="faq.html#error">FAQ</a>
 and the <a href="manpage.d/ipsec_pluto.8.html">ipsec_pluto(8)</a> man page.
+
+<h3><a name="gdb.pluto">Using GDB on Pluto</a></h3>
+
+You may need to use the GNU degugger, gdb(1), on Pluto. This should be
+necessary only in unusal cases, for example if you encounter a problem
+which the Pluto developer cannot readily reproduce or if you are
+modifying Pluto.
+<p>
+Here are the Pluto developer's suggestions for doing this:
+<pre>
+Can you get a core dump and use gdb to find out what Pluto was doing
+when it died?
+
+To get a core dump, you will have to set dumpdir to point to a
+suitable directory (see ipsec.conf(5)).
+
+To get gdb to tell you interesting stuff:
+        $ script
+        $ cd dump-directory-you-chose
+        $ gdb /usr/local/lib/ipsec/pluto core
+        (gdb) where
+        (gdb) quit
+        $ exit
+
+The resulting output will have been captured by the script command in
+a file called "typescript".  Send it to the list.
+
+Do not delete the core file.  I may need to ask you to print out some
+more relevant stuff.
+</pre>
 
 <h2><a name="ifconfig">ifconfig reports for KLIPS debugging</a></h2>
 
diff -bruN freeswan-1.9.orig/doc/src/web.html freeswan-1.9/doc/src/web.html
--- freeswan-1.9.orig/doc/src/web.html	Wed Mar 14 19:12:36 2001
+++ freeswan-1.9/doc/src/web.html	Mon Mar 26 13:23:59 2001
@@ -24,12 +24,25 @@
       using FreeS/WAN with PGPnet</li>
   <li>patches for <a href="http://www.strongsec.com/freeswan/">X.509
     certificate support</a>, also available from a <a href="http://www.twi.ch/~sna/strongsec/freeswan/">mirror site</a></li>
+  <li>a <a href="http://tzukanov.narod.ru/">series</a> of patches that
+  <ul>
+  <li>provide GOST, a Russian gov't. standard cipher, in MMX assembler
+  <li>add GOST to OpenSSL
+  <li>add GOST to the International kernel patch
+  <li>let FreeS/WAN use International kernel patch ciphers
   </ul>
+  <li><a href="http://www.ipv6.iabg.de/downloadframe/index.html">IPv6 support</a> 
+</ul>
 <p>
 Before using these, check the <a href="mail.html">mailing list</a> for news of newer
 versions and to see whether they have been incorporated into more recent
 versions of FreeS/WAN.</p>
 <p>
+<strong>Note:</strong> At one point the way PGP generates RSA keys and the way
+FreeS/WAN checks them for validity before using them were slightly different, so
+quite a few PGP-generated keys would be rejected by FreeS/WAN, confusing users
+no end. This is fixed in 1.9.
+<p>
 A set of PKIX patches were recently announced on the mailing list:</p>
 <pre>
 Subject: a different PKIX patch.
@@ -72,6 +85,8 @@
     <li><a href="ftp://ftp.heise.de/pub/ct/listings/9916-180.tgz">patches</a>
       to add <a href="glossary.html#blowfish">Blowfish</a>, <a href="glossary.html#IDEA">IDEA</a> and <a
       href="glossary.html#CAST128">CAST-128</a> to FreeS/WAN</li>
+  <li><a href="http://www.cendio.se/~bellman/aggressive-pluto.snap.tar.gz">patches</a> for aggressive
+      mode support 
 </ul>
 <p>
 These patches are for older versions of FreeS/WAN and
@@ -270,7 +285,7 @@
 
 <p>
 Vendors using FreeS/WAN in turnkey firewall or VPN products are listed in
-  our <a href="turnkey">introduction</a>.</p>
+  our <a href="intro.html#turnkey">introduction</a>.</p>
 
   <p>Other vendors have Linux IPSEC products which, as far as we know, do not
   use FreeS/WAN</p>
diff -bruN freeswan-1.9.orig/doc/toc.html freeswan-1.9/doc/toc.html
--- freeswan-1.9.orig/doc/toc.html	Tue Mar 27 23:16:50 2001
+++ freeswan-1.9/doc/toc.html	Mon Jun  4 01:15:54 2001
@@ -78,7 +78,7 @@
 </UL>
 <LI><A HREF="install.html#testinstall">Testing to see if install 
 succeeded</A></LI>
-<LI><A HREF="install.html#2_6">Links to other sections</A></LI>
+<LI><A HREF="install.html#2_6">Where to go from here</A></LI>
 </UL>
 <B><A HREF="config.html#setup">Configuration</A></B>
 <UL>
@@ -121,7 +121,7 @@
 <LI><A HREF="config.html#testsetup">Sanity checking</A></LI>
 <LI><A HREF="intro.html#test">Starting a connection</A></LI>
 <LI><A HREF="config.html#pingtest">Ping tests</A></LI>
-<LI><A HREF="faq.html#tcpdump">Testing with tcpdump</A></LI>
+<LI><A HREF="config.html#tcpdump">Testing with tcpdump</A></LI>
 </UL>
 <LI><A HREF="config.html#links.conf">What next?</A></LI>
 <LI><A HREF="config.html#otherconf">Other configuration possibilities</A>
@@ -135,7 +135,7 @@
 <LI><A HREF="config.html#multitunnel">Multiple tunnels between the same 
 two gateways</A></LI>
 <LI><A HREF="config.html#biggate">Many tunnels from a single gateway</A></LI>
-<LI><A HREF="glossary.html#extruded">Extruded Subnets</A></LI>
+<LI><A HREF="config.html#extruded">Extruded Subnets</A></LI>
 <LI><A HREF="config.html#roadvirt">Road Warrior with virtual IP address</A>
 </LI>
 <LI><A HREF="config.html#dynamic">Dynamic Network Interfaces</A></LI>
@@ -159,16 +159,17 @@
 </LI>
 <UL>
 <LI><A HREF="firewall.html#through">IPSEC through the gateway</A></LI>
+<LI><A HREF="firewall.html#ipsec_only">Preventing non-IPSEC traffic</A></LI>
 <LI><A HREF="firewall.html#unknowngate">Filtering packets from unknown 
 gateways</A></LI>
 </UL>
 <LI><A HREF="firewall.html#otherfilter">Other packet filters</A></LI>
 <UL>
-<LI><A HREF="glossary.html#ICMP">ICMP filtering</A></LI>
+<LI><A HREF="firewall.html#ICMP">ICMP filtering</A></LI>
 <LI><A HREF="firewall.html#traceroute">UDP packets for traceroute</A></LI>
 <LI><A HREF="firewall.html#l2tp">UDP for L2TP</A></LI>
 </UL>
-<LI><A HREF="firewall.html#NAT">IPSEC and NAT</A></LI>
+<LI><A HREF="glossary.html#NAT">IPSEC and NAT</A></LI>
 <UL>
 <LI><A HREF="firewall.html#nat_ok">NAT on or behind the IPSEC gateway 
 works</A></LI>
@@ -191,7 +192,7 @@
 <LI><A HREF="firewall.html#examplefw">Ipchains firewall configuration 
 at boot</A></LI>
 <UL>
-<LI><A HREF="firewall.html#Ranch">Scripts based on Ranch's work</A></LI>
+<LI><A HREF="biblio.html#Ranch">Scripts based on Ranch's work</A></LI>
 <LI><A HREF="firewall.html#seawall">The Seattle firewall</A></LI>
 <LI><A HREF="firewall.html#rcf">The RCF scripts</A></LI>
 </UL>
@@ -206,6 +207,9 @@
 <LI><A HREF="trouble.html#statusinfo">Status information</A></LI>
 </UL>
 <LI><A HREF="trouble.html#pluto.problems">Pluto problem hints</A></LI>
+<UL>
+<LI><A HREF="trouble.html#gdb.pluto">Using GDB on Pluto</A></LI>
+</UL>
 <LI><A HREF="trouble.html#ifconfig">ifconfig reports for KLIPS debugging</A>
 </LI>
 <LI><A HREF="trouble.html#testgates">Testing between security gateways</A>
@@ -229,7 +233,7 @@
 <LI><A HREF="roadmap.html#top">Top directory</A></LI>
 <LI><A HREF="roadmap.html#doc">Documentation</A></LI>
 <LI><A HREF="ipsec.html#klips">KLIPS: kernel IP security</A></LI>
-<LI><A HREF="roadmap.html#pluto">Pluto key and connection management 
+<LI><A HREF="glossary.html#pluto">Pluto key and connection management 
 daemon</A></LI>
 <LI><A HREF="roadmap.html#utils">Utils</A></LI>
 <LI><A HREF="roadmap.html#lib">Libraries</A></LI>
@@ -258,7 +262,7 @@
 <LI><A HREF="install.html#2.2">2.2 and 2.4 Kernels</A></LI>
 </UL>
 <LI><A HREF="compat.html#otherdist">Intel Linux distributions other 
-than Redhat 5.x and 6.x</A></LI>
+than Redhat</A></LI>
 <UL>
 <LI><A HREF="compat.html#rh7">Redhat 7.0</A></LI>
 <LI><A HREF="compat.html#suse">SuSE Linux</A></LI>
@@ -290,7 +294,7 @@
 interoperability</A></LI>
 <LI><A HREF="interop.html#interop.problem">Interoperability problems</A></LI>
 <UL>
-<LI><A HREF="faq.html#noDES">Systems that want to use DES</A></LI>
+<LI><A HREF="interop.html#noDES">Systems that want to use single DES</A></LI>
 </UL>
 <LI><A HREF="interop.html#otherpub">Interop HowTo documents</A></LI>
 <LI><A HREF="interop.html#mail.interop">Interoperation with specific 
@@ -306,6 +310,8 @@
 <LI><A HREF="interop.html#Raptor">Raptor Firewall</A></LI>
 <LI><A HREF="interop.html#gauntlet">Gauntlet firewall GVPN</A></LI>
 <LI><A HREF="interop.html#checkpoint">Checkpoint Firewall-1</A></LI>
+<LI><A HREF="interop.html#redcreek">Redcreek Ravlin</A></LI>
+<LI><A HREF="interop.html#sentinel">SSH Sentinel</A></LI>
 <LI><A HREF="interop.html#Fsecure">F-Secure VPN for Windows</A></LI>
 <LI><A HREF="interop.html#watchguard">Watchguard</A></LI>
 <LI><A HREF="interop.html#Xedia">Xedia Access Point/QVPN</A></LI>
@@ -391,7 +397,7 @@
 <LI><A HREF="ipsec.html#primitives">Cryptographic components</A></LI>
 <UL>
 <LI><A HREF="ipsec.html#block.cipher">Block ciphers</A></LI>
-<LI><A HREF="glossary.html#hash">Hash functions</A></LI>
+<LI><A HREF="ipsec.html#hash">Hash functions</A></LI>
 <LI><A HREF="ipsec.html#DH.keying">Diffie-Hellman key agreement</A></LI>
 <LI><A HREF="ipsec.html#RSA.auth">RSA authentication</A></LI>
 </UL>
@@ -404,13 +410,13 @@
 </UL>
 <LI><A HREF="ipsec.html#modes">IPSEC modes</A></LI>
 <UL>
-<LI><A HREF="glossary.html#tunnel">Tunnel mode</A></LI>
-<LI><A HREF="glossary.html#transport">Transport mode</A></LI>
+<LI><A HREF="ipsec.html#tunnel">Tunnel mode</A></LI>
+<LI><A HREF="ipsec.html#transport">Transport mode</A></LI>
 </UL>
 <LI><A HREF="ipsec.html#parts">FreeS/WAN parts</A></LI>
 <UL>
 <LI><A HREF="ipsec.html#KLIPS">KLIPS: Kernel IPSEC Support</A></LI>
-<LI><A HREF="roadmap.html#Pluto">The Pluto daemon</A></LI>
+<LI><A HREF="glossary.html#Pluto">The Pluto daemon</A></LI>
 <LI><A HREF="ipsec.html#command">The ipsec(8) command</A></LI>
 <LI><A HREF="ipsec.html#ipsec.conf">Linux FreeS/WAN configuration file</A>
 </LI>
@@ -459,7 +465,7 @@
 <LI><A HREF="web.html#RFCs1">RFCs and other reference documents</A></LI>
 <LI><A HREF="web.html#analysis">Analysis and critiques of IPSEC 
 protocols</A></LI>
-<LI><A HREF="glossary.html#IP">Background information on IP</A></LI>
+<LI><A HREF="web.html#IP">Background information on IP</A></LI>
 </UL>
 <LI><A HREF="web.html#implement">IPSEC Implementations</A></LI>
 <UL>
@@ -541,6 +547,8 @@
 to each other?</A></LI>
 <LI><A HREF="faq.html#versions">Does FreeS/WAN run on my version of 
 Linux?</A></LI>
+<LI><A HREF="faq.html#versions">Does FreeS/WAN run on the latest kernel 
+version?</A></LI>
 <LI><A HREF="faq.html#versions">Can I modify FreeS/WAN to ...?</A></LI>
 <LI><A HREF="faq.html#versions">Can I contribute to the project?</A></LI>
 <LI><A HREF="faq.html#versions">Is there detailed design documentation?</A>
@@ -549,6 +557,7 @@
 <LI><A HREF="faq.html#versions">Compilation problems</A></LI>
 <UL>
 <LI><A HREF="faq.html#versions">gmp.h: No such file or directory</A></LI>
+<LI><A HREF="faq.html#versions">... virtual memory exhausted</A></LI>
 </UL>
 <LI><A HREF="faq.html#versions">Life's little mysteries</A></LI>
 <UL>
@@ -562,6 +571,8 @@
 <LI><A HREF="faq.html#versions">Dropped connections</A></LI>
 <LI><A HREF="faq.html#versions">TCPdump on the gateway shows strange 
 things</A></LI>
+<LI><A HREF="faq.html#versions">Traceroute does not show anything 
+between the gateways</A></LI>
 </UL>
 <LI><A HREF="faq.html#versions">Testing in stages</A></LI>
 <UL>
@@ -581,10 +592,16 @@
 <LI><A HREF="faq.html#versions">Interpreting error messages</A></LI>
 <UL>
 <LI><A HREF="faq.html#versions">SIOCADDRT:Network is unreachable</A></LI>
+<LI><A HREF="faq.html#versions">ipsec_setup: Fatal error, kernel 
+appears to lack KLIPS</A></LI>
 <LI><A HREF="faq.html#versions">Connection names in Pluto error messages</A>
 </LI>
 <LI><A HREF="faq.html#versions">Pluto: ... can't orient connection</A></LI>
 <LI><A HREF="faq.html#versions">Pluto: ... no connection is known</A></LI>
+<LI><A HREF="faq.html#versions">Pluto: ... no suitable connection ...</A>
+</LI>
+<LI><A HREF="faq.html#versions">Pluto: ... no connection has been 
+authorized</A></LI>
 <LI><A HREF="faq.html#versions">Pluto: ... OAKLEY_DES_CBC is not 
 supported.</A></LI>
 <LI><A HREF="faq.html#versions"> Pluto: ... no acceptable transform</A></LI>
@@ -593,6 +610,9 @@
 </LI>
 <LI><A HREF="faq.html#versions">... trouble writing to /dev/ipsec ... 
 SA already in use</A></LI>
+<LI><A HREF="faq.html#versions">... ignoring ... payload</A></LI>
+<LI><A HREF="faq.html#versions">ipsec_setup: ... interfaces ... and ... 
+share address ...</A></LI>
 </UL>
 <LI><A HREF="faq.html#versions">Can I ...</A></LI>
 <UL>
@@ -606,15 +626,19 @@
 on my net?</A></LI>
 <LI><A HREF="faq.html#versions">Can I use Quality of Service routing 
 with FreeS/WAN?</A></LI>
+<LI><A HREF="faq.html#versions">Can I recognise dead tunnels and shut 
+them down?</A></LI>
+<LI><A HREF="faq.html#versions">Can I build tunnels over a 
+demand-dialed link?</A></LI>
 <LI><A HREF="faq.html#PKIcert">Does FreeS/WAN support X.509 or other 
 PKI certificates?</A></LI>
 <LI><A HREF="faq.html#PKIcert">Does FreeS/WAN support Radius or other 
 user authentication?</A></LI>
-<LI><A HREF="faq.html#noDES">Does FreeS/WAN support single DES 
+<LI><A HREF="faq.html#noDES.faq">Does FreeS/WAN support single DES 
 encryption?</A></LI>
 </UL>
-<LI><A HREF="faq.html#DESonly">Why don't you restrict the mailing list 
-to reduce spam?</A></LI>
+<LI><A HREF="faq.html#noDES.faq">Why don't you restrict the mailing 
+lists to reduce spam?</A></LI>
 </UL>
 </BODY>
 </HTML>
diff -bruN freeswan-1.9.orig/doc/trouble.html freeswan-1.9/doc/trouble.html
--- freeswan-1.9.orig/doc/trouble.html	Tue Mar 27 23:16:51 2001
+++ freeswan-1.9/doc/trouble.html	Mon Jun  4 01:15:56 2001
@@ -38,9 +38,9 @@
 <H2><A name="info">Information available on your system</A></H2>
 <H3><A name="pages">man pages provided</A></H3>
 <DL>
-<DT>ipsec.conf(5)</DT>
+<DT><A href="manpage.d/ipsec.conf.5.html">ipsec.conf(5)</A></DT>
 <DD>Manual page for IPSEC configuration file.</DD>
-<DT>ipsec(8)</DT>
+<DT><A href="manpage.d/ipsec.8.html">ipsec(8)</A></DT>
 <DD>Primary man page for ipsec utilities.</DD>
 </DL>
 <P>Other man pages are on</P>
@@ -64,7 +64,7 @@
 <DD>Copious debugging info.</DD>
 </DL>
 <H2><A name="pluto.problems">Pluto problem hints</A></H2>
-<P>From a message posted to the mailing list Jan 14 2000 by Pluto 
+<P> From a message posted to the mailing list Jan 14 2000 by Pluto 
 developer  Hugh Redelmeier:</P>
 <PRE>
 Until ipsec auto and whack/pluto get fixed:
@@ -88,6 +88,33 @@
  Various error messages from Pluto are discussed in the <A href="faq.html#error">
 FAQ</A> and the <A href="manpage.d/ipsec_pluto.8.html">ipsec_pluto(8)</A>
  man page. 
+<H3><A name="gdb.pluto">Using GDB on Pluto</A></H3>
+ You may need to use the GNU degugger, gdb(1), on Pluto. This should be 
+necessary only in unusal cases, for example if you encounter a problem 
+which the Pluto developer cannot readily reproduce or if you are 
+modifying Pluto. 
+<P> Here are the Pluto developer's suggestions for doing this: </P>
+<PRE>
+Can you get a core dump and use gdb to find out what Pluto was doing
+when it died?
+
+To get a core dump, you will have to set dumpdir to point to a
+suitable directory (see ipsec.conf(5)).
+
+To get gdb to tell you interesting stuff:
+        $ script
+        $ cd dump-directory-you-chose
+        $ gdb /usr/local/lib/ipsec/pluto core
+        (gdb) where
+        (gdb) quit
+        $ exit
+
+The resulting output will have been captured by the script command in
+a file called &quot;typescript&quot;.  Send it to the list.
+
+Do not delete the core file.  I may need to ask you to print out some
+more relevant stuff.
+</PRE>
 <H2><A name="ifconfig">ifconfig reports for KLIPS debugging</A></H2>
 <P>From a mail message from our KLIPS developer:</P>
 <PRE>
diff -bruN freeswan-1.9.orig/doc/web.html freeswan-1.9/doc/web.html
--- freeswan-1.9.orig/doc/web.html	Tue Mar 27 23:16:52 2001
+++ freeswan-1.9/doc/web.html	Mon Jun  4 01:15:56 2001
@@ -27,10 +27,24 @@
 <LI>patches for <A href="http://www.strongsec.com/freeswan/">X.509 
  certificate support</A>, also available from a <A href="http://www.twi.ch/~sna/strongsec/freeswan/">
 mirror site</A></LI>
+<LI>a <A href="http://tzukanov.narod.ru/">series</A> of patches that 
+<UL>
+<LI>provide GOST, a Russian gov't. standard cipher, in MMX assembler </LI>
+<LI>add GOST to OpenSSL </LI>
+<LI>add GOST to the International kernel patch </LI>
+<LI>let FreeS/WAN use International kernel patch ciphers </LI>
+</UL>
+</LI>
+<LI><A href="http://www.ipv6.iabg.de/downloadframe/index.html">IPv6 
+support</A></LI>
 </UL>
 <P> Before using these, check the <A href="mail.html">mailing list</A>
  for news of newer versions and to see whether they have been 
 incorporated into more recent versions of FreeS/WAN.</P>
+<P><STRONG> Note:</STRONG> At one point the way PGP generates RSA keys 
+and the way FreeS/WAN checks them for validity before using them were 
+slightly different, so quite a few PGP-generated keys would be rejected 
+by FreeS/WAN, confusing users no end. This is fixed in 1.9. </P>
 <P> A set of PKIX patches were recently announced on the mailing list:</P>
 <PRE>
 Subject: a different PKIX patch.
@@ -70,6 +84,8 @@
 <LI><A href="ftp://ftp.heise.de/pub/ct/listings/9916-180.tgz">patches</A>
  to add <A href="glossary.html#blowfish">Blowfish</A>, <A href="glossary.html#IDEA">
 IDEA</A> and <A href="glossary.html#CAST128">CAST-128</A> to FreeS/WAN</LI>
+<LI><A href="http://www.cendio.se/~bellman/aggressive-pluto.snap.tar.gz">
+patches</A> for aggressive  mode support </LI>
 </UL>
 <P> These patches are for older versions of FreeS/WAN and will likely 
 not work with the current version.  Older versions of FreeS/WAN may be 
@@ -240,7 +256,7 @@
 <H2><A name="implement">IPSEC Implementations</A></H2>
 <H3><A name="linuxprod">Linux products</A></H3>
 <P> Vendors using FreeS/WAN in turnkey firewall or VPN products are 
-listed in  our <A href="turnkey">introduction</A>.</P>
+listed in  our <A href="intro.html#turnkey">introduction</A>.</P>
 <P>Other vendors have Linux IPSEC products which, as far as we know, do 
 not  use FreeS/WAN</P>
 <UL>
diff -bruN freeswan-1.9.orig/ipsec.conf.def freeswan-1.9/ipsec.conf.def
--- freeswan-1.9.orig/ipsec.conf.def	Wed Dec 31 19:00:00 1969
+++ freeswan-1.9/ipsec.conf.def	Wed May 16 10:57:20 2001
@@ -0,0 +1,26 @@
+# /etc/ipsec.conf - FreeS/WAN IPSEC configuration file
+
+# More elaborate and more varied sample configurations can be found
+# in doc/examples.
+
+# basic configuration
+config setup
+	# THIS SETTING MUST BE CORRECT or almost nothing will work;
+	# %defaultroute is okay for most simple cases.
+	interfaces=%defaultroute
+	# Debug-logging controls:  "none" for (almost) none, "all" for lots.
+	klipsdebug=none
+	plutodebug=none
+	# Use auto= parameters in conn descriptions to control startup actions.
+	plutoload=%search
+	plutostart=%search
+
+# defaults for subsequent connection descriptions
+conn %default
+	# How persistent to be in (re)keying negotiations (0 means very).
+	keyingtries=3
+	# Authentication by RSA signature keys
+	authby=rsasig
+	# keylife of 8h is too long for rekeying drops.
+	keylife=1h
+
diff -bruN freeswan-1.9.orig/klips/doc/DONE freeswan-1.9/klips/doc/DONE
--- freeswan-1.9.orig/klips/doc/DONE	Mon Nov  6 00:09:00 2000
+++ freeswan-1.9/klips/doc/DONE	Mon Jun  4 12:54:57 2001
@@ -1,8 +1,12 @@
 *
-* RCSID $Id: DONE,v 1.20 2000/11/06 05:09:00 rgb Exp $
+* RCSID $Id: DONE,v 1.22 2001/06/01 07:25:19 rgb Exp $
 *
 
 Bugs as of 0.90:
+	auto AH+ESP transport mode oops?
+	ipcomp: fix i[56]86 ASM code 2.4 makefile issues
+	kill single-letter options from klips utils manpages.
+	add --label to klips utils manpages
 	ah tunnel -- 3 esp packets kills the sg
 	single spi ungroup fails
 	elucidate the meaning of 'tdb' in all error message references
@@ -180,6 +184,9 @@
 	Oops if IPCOMP not config in KLIPS but negotiated by pluto.
 	Passthrough packets must be sent with frag in mind.
 
+1.9
+	Add magic saids for pass, drop, reject, trap, hold
+
 Features for 2.0:
 	Investigate PMTU (rfc2401-4.4.2, 6.1.2)
 	Mark incoming packets as from ipsec0 for accounting and validation
@@ -200,6 +207,12 @@
 
 *
 * $Log: DONE,v $
+* Revision 1.22  2001/06/01 07:25:19  rgb
+* Clean up miscellaneous stuff...
+*
+* Revision 1.21  2001/02/26 20:11:12  rgb
+* Post 1.9 candidate, magic SAs and email purge updates.
+*
 * Revision 1.20  2000/11/06 05:09:00  rgb
 * A few bugfixes...
 *
diff -bruN freeswan-1.9.orig/klips/doc/TODO freeswan-1.9/klips/doc/TODO
--- freeswan-1.9.orig/klips/doc/TODO	Mon Jan 29 17:29:46 2001
+++ freeswan-1.9/klips/doc/TODO	Mon Jun  4 12:54:57 2001
@@ -1,11 +1,23 @@
 *
-* RCSID $Id: TODO,v 1.65 2001/01/29 22:29:46 rgb Exp $
+* RCSID $Id: TODO,v 1.70 2001/06/01 07:25:19 rgb Exp $
 *
 
 fordhr:	enforce 4k msg limit.
 
 Bugs:
-	IPCOMP frag-in-clear
+	fix tncfg output after attached physical I/F disappears.
+	detach, but don't down ipsec virtual device if attached physical
+		device disappears
+	fix pfkey_update:new tdb should add to, not replace original
+	implement self-documenting kernel code:
+		http://kernelbook.sourceforge.net/#kdocs
+	replace IKE bypass machinery with SPD entries.
+	add hold machinery to store the last packet sent to the hold eroute
+		and re-inject it once the hold is deleted. (eroute entry or
+		separate table?)
+	implement eroute reject IMCP "communication administratively prohibited"
+	fix lifetime_byte_c len/ilen assignment
+	IPCOMP frag-in-clear?
 	pick-next-less-specific-eroute for intermediate tunnel lookup
 		for IKE passthrough.
 	sparc64:klips/net/ipsec/ipsec_tunnel.c:2106/2912:
@@ -106,6 +118,8 @@
 			expire (written, needs testing)
 Most	Expire SA's on soft/hard time/seq/qty and signal user (pfkey) (written, needs testing)
 GG	Port to IPv6
+	satot() conversion for /proc spi display
+	xlen, skb->len review for bogus packets, skb->len must be larger than ip->totlen
 
 2.0:
 	Port to ipchains/netfilter (with ifdefs to virtual device paradigm)
@@ -137,6 +151,21 @@
 
 *
 * $Log: TODO,v $
+* Revision 1.70  2001/06/01 07:25:19  rgb
+* Clean up miscellaneous stuff...
+*
+* Revision 1.69  2001/05/19 02:30:00  rgb
+* Added a couple of klips utils doc bugs.
+*
+* Revision 1.68  2001/04/19 19:03:37  rgb
+* Added note to update in update rather than replace.
+*
+* Revision 1.67  2001/03/16 07:30:20  rgb
+* Add 2.4 ipcomp asm note.
+*
+* Revision 1.66  2001/02/26 20:11:12  rgb
+* Post 1.9 candidate, magic SAs and email purge updates.
+*
 * Revision 1.65  2001/01/29 22:29:46  rgb
 * Add dhr suggestion.
 *
diff -bruN freeswan-1.9.orig/klips/doc/klips2-design-api-trips.txt freeswan-1.9/klips/doc/klips2-design-api-trips.txt
--- freeswan-1.9.orig/klips/doc/klips2-design-api-trips.txt	Wed Dec 31 19:00:00 1969
+++ freeswan-1.9/klips/doc/klips2-design-api-trips.txt	Mon Jun  4 12:54:57 2001
@@ -0,0 +1,1031 @@
+#  -*- mode: Outline; fill-column: 78; fill-prefix: "	" -*-
+#
+#  klips2-design-api-trips.txt
+#	Richard Guy Briggs <rgb@conscoop.ottawa.on.ca>
+#
+#  RCSID $Id: klips2-design-api-trips.txt,v 1.8 2001/05/30 08:00:14 rgb Exp $
+#
+
+# This document outlines various trips that are made through the
+# various APIs for different scenarios.  Please see klips2-design.txt
+# for an overview.
+
+# Several scenario titles are listed.  Under each scenario title is
+# listed point form text to describe what action is happenning and/or
+# the reason for the following calls.  Following the descriptive text
+# is a origin and destination entity interface description.  Within
+# each interface description is a list of specific arguments used or
+# that need to be added to accomplish the action.
+
+Opportunistic encryption:
+	- put a trap in place from KMd
+		KMd -> iptables(8) system(3) call (Policy)
+		KMd -> ip6tables(8) system(3) call (Policy)
+			in:
+				char[] -I
+				char[] -s SADDR/SMASK
+				char[] -d DADDR/DMASK
+				char[] --protocol PROTO
+				char[] --sport SPORT
+				char[] --dport DPORT
+				char[] --uid-owner UID
+				char[] --seclev seclevstr
+				char[] -J TRAP
+			out:
+				unsigned char exit_code
+
+		iptables(8) -> seclev match iptables(8) library
+		ip6tables(8) -> seclev match ip6tables(8) library
+			in:
+				char[] --seclev seclevstr
+			out:
+				struct seclev
+
+		iptables(8) -> NetFilter
+		ip6tables(8) -> NetFilter
+		I/F is already defined in NetFilter.  In addition, it will
+		need structures to pass the following:
+			in:
+				struct seclev
+				target TRAP
+		
+	- packet comes
+		NetFilter -> seclev match NetFilter kernel module
+			in:
+				struct sk_buff *skb
+				struct seclev
+			out:
+				boolean
+
+		NetFilter -> sa match NetFilter kernel module
+			in:
+				struct sk_buff *skb
+				struct ip_said SA[,...]
+			out:
+				boolean
+
+	- packet matches TRAP
+		NetFilter -> TRAP target NetFilter kernel module
+			in:
+				struct sk_buff *skb
+			out:
+				unsigned int = NF_STOLEN
+
+	- send up an ACQUIRE
+		TRAP target NetFilter kernel module -> KMds (PF_KEYv2 ACQUIRE)
+			see RFC2367, PF_KEYv2 ACQUIRE
+
+	- create HOLD target with skb info and store the first packet
+		TRAP target NetFilter kernel module -> NetFilter
+			in:
+				struct sk_buff *skb
+			out:
+				boolean
+
+	- next packet comes in while KMd is negotiating SAs.
+		NetFilter -> seclev match NetFilter kernel module
+			in:
+				struct sk_buff *skb
+				struct seclev
+			out:
+				boolean
+
+		NetFilter -> sa match NetFilter kernel module
+			in:
+				struct sk_buff *skb
+				struct ip_said SA[,...]
+			out:
+				boolean
+
+	- packet matches HOLD so discard previous skb (packet) and store this one
+		NetFilter -> HOLD target NetFilter kernel module
+			in:
+				struct sk_buff *skb
+			out:
+				unsigned int = NF_STOLEN
+				
+	- put the new SAs in place once the negotiations have succeeded
+		KMd -> SADB (PF_KEYv2 ADD/UPDATE)
+			see RFC2367, PF_KEYv2 ADD/UPDATE message for each SA
+
+	- add ENCRYPT target with specific SAs to use
+		KMd -> iptables(8) system(3) call (Policy)
+		KMd -> ip6tables(8) system(3) call (Policy)
+			in:
+				char[] -I
+				char[] -s SADDR/SMASK
+				char[] -d DADDR/DMASK
+				char[] --protocol PROTO
+				char[] --sport SPORT
+				char[] --dport DPORT
+				char[] --uid-owner UID
+				char[] --seclev seclev
+				char[] -J ENCRYPT
+				char[] --salist SAList
+			out:
+				unsigned char exit_code
+
+		iptables(8) -> seclev match iptables(8) library
+		ip6tables(8) -> seclev match ip6tables(8) library
+			in:
+				char[] --seclev seclevstr
+			out:
+				struct seclev
+
+		iptables(8) -> ENCRYPT target iptables(8) library
+		ip6tables(8) -> ENCRYPT target ip6tables(8) library
+			in:
+				char[] --salist SAList
+			out:
+				struct ip_said SA[, ...]
+
+		iptables(8) -> NetFilter
+		ip6tables(8) -> NetFilter
+		I/F is already defined in NetFilter.  In addition, it will
+		need structures to pass the following:
+			in:
+				struct seclev
+				target ENCRYPT
+				struct ip_said SA[, ...]
+		
+	- add ACCEPT target for once the packet is processed
+		KMd -> iptables(8) system(3) call (Policy)
+		KMd -> ip6tables(8) system(3) call (Policy)
+			in:
+				char[] -I
+				char[] -s SADDR/SMASK (local SG)
+				char[] -d DADDR/DMASK (remote SG)
+				char[] --proto ESP
+				char[] --salist SAList
+				char[] --espspi SPI
+				char[] -J ACCEPT
+			out:
+				unsigned char exit_code
+
+		iptables(8) -> seclev match iptables(8) library
+		ip6tables(8) -> seclev match ip6tables(8) library
+			in:
+				char[] --seclev seclevstr
+			out:
+				struct seclev
+
+		iptables(8) -> sa match iptables(8) library
+		ip6tables(8) -> sa match ip6tables(8) library
+			in:
+				char[] --salist SAList
+			out:
+				struct ip_said SA[, ...]
+
+		iptables(8) -> NetFilter
+		ip6tables(8) -> NetFilter
+		I/F is already defined in NetFilter.  In addition, it will
+		need structures to pass the following:
+			in:
+				struct seclev
+				struct ip_said SA[, ...]
+
+	- replace HOLD target with ENCRYPT target, releasing skb
+		HOLD target NetFilter kernel module -> NetFilter
+				(I don't know the best way to show this
+				on the diagram, since the skb is
+				stored with the eroute and not the HOLD
+				target module)
+			in:
+				struct sk_buff *skb
+
+	- send released packet through newly created ENCRYPT target and SAs
+		NetFilter -> ENCRYPT target NetFilter kernel module
+			in:
+				struct sk_buff *skb
+				struct ip_said SA[, ...]
+			out:
+				unsigned int = NF_STOLEN
+
+	- fetch SAs specified in NetFilter table entry with ENCRYPT args
+		ENCRYPT target NetFilter kernel module -> SADB (SAID)
+			in:
+				struct ip_said SA
+			out:
+				struct tdb *tdbp
+
+	- send skb (packet) back into NF_IP_POST_ROUTE
+		ENCRYPT target NetFilter kernel module -> NetFilter
+			in:
+				struct sk_buff *skb
+				struct ip_said SA[,...]
+		
+	- expire SA if a limit is reached
+		SADB -> KMd (PF_KEYv2 EXPIRE)
+			see RFC2367, PF_KEYv2 EXPIRE
+				
+Outgoing w/existing connection specifying SAs
+	- put the new SAs in place once negotiations have succeeded
+		KMd -> SADB (PF_KEYv2 ADD/UPDATE)
+			see RFC2367, PF_KEYv2 ADD/UPDATE message for each SA
+
+	- put in a rule to match packets for that set of SAs
+		KMd -> iptables(8) system(3) call (Policy)
+		KMd -> ip6tables(8) system(3) call (Policy)
+			in:
+				char[] -I
+				char[] -s SADDR/SMASK
+				char[] -d DADDR/DMASK
+				char[] --protocol PROTO
+				char[] --sport SPORT
+				char[] --dport DPORT
+				char[] --uid-owner UID
+				char[] --seclev seclev
+				char[] -J ENCRYPT
+				char[] --salist SAList
+			out:
+				unsigned char exit_code
+
+		iptables(8) -> seclev match iptables(8) library
+		ip6tables(8) -> seclev match ip6tables(8) library
+			in:
+				char[] --seclev seclevstr
+			out:
+				struct seclev
+
+		iptables(8) -> ENCRYPT target iptables(8) library
+		ip6tables(8) -> ENCRYPT target ip6tables(8) library
+			in:
+				char[] --salist SAList
+			out:
+				struct ip_said SA[, ...]
+
+		iptables(8) -> NetFilter
+		ip6tables(8) -> NetFilter
+		I/F is already defined in NetFilter.  In addition, it will
+		need structures to pass the following:
+			in:
+				struct seclev
+				target ENCRYPT
+				struct ip_said SA[, ...]
+		
+	- add ACCEPT for once the packet is processed
+		KMd -> iptables(8) system(3) call (Policy)
+		KMd -> ip6tables(8) system(3) call (Policy)
+			in:
+				char[] -I
+				char[] -s SADDR/SMASK (local SG)
+				char[] -d DADDR/DMASK (remote SG)
+				char[] --proto ESP
+				char[] --salist SAList
+				char[] --espspi SPI
+				char[] -J ACCEPT
+			out:
+				unsigned char exit_code
+
+		iptables(8) -> seclev match iptables(8) library
+		ip6tables(8) -> seclev match ip6tables(8) library
+			in:
+				char[] --seclev seclevstr
+			out:
+				struct seclev
+
+		iptables(8) -> sa match iptables(8) library
+		ip6tables(8) -> sa match ip6tables(8) library
+			in:
+				char[] --salist SAList
+			out:
+				struct ip_said SA[, ...]
+
+		iptables(8) -> NetFilter
+		I/F is already defined in NetFilter.  In addition, it will
+		need structures to pass the following:
+			in:
+				struct seclev
+				struct ip_said SA[, ...]
+				target ACCEPT
+
+	- outgoing packet is tested on selectors
+		NetFilter -> seclev match NetFilter kernel module
+			in:
+				struct sk_buff *skb
+				struct seclev
+			out:
+				boolean
+
+		NetFilter -> sa match NetFilter kernel module
+			in:
+				struct sk_buff *skb
+				struct ip_said SA[,...]
+			out:
+				boolean
+
+	- matching packet is sent to ENCRYPT target with SAList
+		NetFilter -> ENCRYPT target NetFilter kernel module
+			in:
+				struct sk_buff *skb
+				struct ip_said SA[, ...]
+			out:
+				unsigned int = NF_STOLEN
+
+	- fetch SAs specified in NetFilter table entry with ENCRYPT args
+		ENCRYPT target NetFilter kernel module -> SADB (SAID)
+			in:
+				struct ip_said SA
+			out:
+				struct tdb *tdbp
+
+	- send skb (packet) back into NF_IP_POST_ROUTE
+		ENCRYPT target NetFilter kernel module -> NetFilter
+			in:
+				struct sk_buff *skb
+				struct ip_said SA[,...]
+		
+	- outgoing processed packet is tested on selectors and ACCEPTed
+		NetFilter -> seclev match NetFilter kernel module
+			in:
+				struct sk_buff *skb
+				struct seclev
+			out:
+				boolean
+
+		NetFilter -> sa match NetFilter kernel module
+			in:
+				struct sk_buff *skb
+				struct ip_said SA[,...]
+			out:
+				boolean
+
+	- expire SA if a limit is reached
+		SADB -> KMd (PF_KEYv2 EXPIRE)
+			see RFC2367, PF_KEYv2 EXPIRE
+				
+Outgoing w/existing connection routing through IPSec device
+	- put the new SAs in place once negotiations have succeeded
+		KMd -> SADB (PF_KEYv2 ADD/UPDATE)
+			see RFC2367, PF_KEYv2 ADD/UPDATE message for each SA
+
+	- put in a rule to match packets for that set of SAs
+		KMd -> iptables(8) system(3) call (Policy)
+		KMd -> ip6tables(8) system(3) call (Policy)
+			in:
+				char[] -I
+				char[] -s SADDR/SMASK
+				char[] -d DADDR/DMASK
+				char[] --protocol PROTO
+				char[] --sport SPORT
+				char[] --dport DPORT
+				char[] --uid-owner UID
+				char[] --seclev seclev
+				char[] --out-interface IPSECdev
+				char[] -J ENCRYPT
+				char[] --salist SAList
+			out:
+				unsigned char exit_code
+
+		iptables(8) -> seclev match iptables(8) library
+		ip6tables(8) -> seclev match ip6tables(8) library
+			in:
+				char[] --seclev seclevstr
+			out:
+				struct seclev
+
+		iptables(8) -> ENCRYPT target iptables(8) library
+		ip6tables(8) -> ENCRYPT target ip6tables(8) library
+			in:
+				char[] --salist SAList
+			out:
+				struct ip_said SA[, ...]
+
+		iptables(8) -> NetFilter
+		ip6tables(8) -> NetFilter
+		I/F is already defined in NetFilter.  In addition, it will
+		need structures to pass the following:
+			in:
+				struct seclev
+				target ENCRYPT
+				struct ip_said SA[, ...]
+		
+		KMd -> Routing Table (Routing)
+			see route(8) or iproute2(8), currently done by
+				     system(3) calls to _updown.
+			in:
+				char[] IPSECdev
+			out:
+				unsigned char exit_code
+
+	- add ACCEPT for once the packet is processed
+		KMd -> iptables(8) system(3) call (Policy)
+		KMd -> ip6tables(8) system(3) call (Policy)
+			in:
+				char[] -I
+				char[] -s SADDR/SMASK (local SG)
+				char[] -d DADDR/DMASK (remote SG)
+				char[] --proto ESP
+				char[] --espspi SPI
+				char[] --salist SAList
+				char[] -J ACCEPT
+			out:
+				unsigned char exit_code
+
+		iptables(8) -> seclev match iptables(8) library
+		ip6tables(8) -> seclev match ip6tables(8) library
+			in:
+				char[] --seclev seclevstr
+			out:
+				struct seclev
+
+		iptables(8) -> sa match iptables(8) library
+		ip6tables(8) -> sa match ip6tables(8) library
+			in:
+				char[] --salist SAList
+			out:
+				struct ip_said SA[, ...]
+
+		iptables(8) -> NetFilter
+		ip6tables(8) -> NetFilter
+		I/F is already defined in NetFilter.  In addition, it will
+		need structures to pass the following:
+			in:
+				struct seclev
+				struct ip_said SA[, ...]
+
+	- outgoing packet is tested on match modules
+		NetFilter -> seclev match NetFilter kernel module
+			in:
+				struct sk_buff *skb
+				struct seclev
+			out:
+				boolean
+
+		NetFilter -> sa match NetFilter kernel module
+			in:
+				struct sk_buff *skb
+				struct ip_said SA[,...]
+			out:
+				boolean
+
+	- outgoing packet matches IPSECdev and is sent to ENCRYPT target with SAList
+		NetFilter -> ENCRYPT target NetFilter kernel module
+			in:
+				struct sk_buff *skb
+				struct ip_said SA[, ...]
+			out:
+				unsigned int = NF_STOLEN
+
+	- fetch SAs specified in NetFilter table entry with ENCRYPT args
+		ENCRYPT target NetFilter kernel module -> SADB (SAID)
+			in:
+				struct ip_said SA
+			out:
+				struct tdb *tdbp
+
+	- send skb (packet) back into NF_IP_POST_ROUTE
+		ENCRYPT target NetFilter kernel module -> NetFilter
+			in:
+				struct sk_buff *skb
+				struct ip_said SA[,...]
+		
+	- processed packet is tested on match modules and ACCEPTed
+		NetFilter -> seclev match NetFilter kernel module
+			in:
+				struct sk_buff *skb
+				struct seclev
+			out:
+				boolean
+
+		NetFilter -> sa match NetFilter kernel module
+			in:
+				struct sk_buff *skb
+				struct ip_said SA[,...]
+			out:
+				boolean
+
+	- expire SA if a limit is reached
+		SADB -> KMd (PF_KEYv2 EXPIRE)
+			see RFC2367, PF_KEYv2 EXPIRE
+				
+Incoming w/existing connection specifying SAs
+	- put in the new SAs in place once the negotiations have succeeded
+		KMd -> SADB (PF_KEYv2 ADD/UPDATE)
+			see RFC2367, PF_KEYv2 ADD/UPDATE message for each SA
+
+	- put in a blocking entry to prevent unprotected packets entering
+		KMd -> iptables(8) system(3) call (Policy)
+		KMd -> ip6tables(8) system(3) call (Policy)
+			in:
+				char[] -I
+				char[] -s SADDR/SMASK
+				char[] -d DADDR/DMASK
+				char[] --protocol PROTO
+				char[] --sport SPORT
+				char[] --dport DPORT
+				char[] --uid-owner UID
+				char[] --seclev seclev
+				char[] -J DROP (or PEEK)
+			out:
+				unsigned char exit_code
+
+		iptables(8) -> seclev match iptables(8) library
+		ip6tables(8) -> seclev match ip6tables(8) library
+			in:
+				char[] --seclev seclevstr
+			out:
+				struct seclev
+
+		iptables(8) -> NetFilter
+		ip6tables(8) -> NetFilter
+		I/F is already defined in NetFilter.  In addition, it will
+		need structures to pass the following:
+			in:
+				struct seclev
+				target DROP (or PEEK)
+		
+	- allow properly processed packets in
+		KMd -> iptables(8) system(3) call (Policy)
+		KMd -> ip6tables(8) system(3) call (Policy)
+			in:
+				char[] -I
+				char[] -s SADDR/SMASK
+				char[] -d DADDR/DMASK
+				char[] --protocol PROTO
+				char[] --sport SPORT
+				char[] --dport DPORT
+				char[] --uid-owner UID
+				char[] --seclev seclev
+				char[] --salist SAList
+				char[] -J ACCEPT
+			out:
+				unsigned char exit_code
+
+		iptables(8) -> seclev match iptables(8) library
+		ip6tables(8) -> seclev match ip6tables(8) library
+			in:
+				char[] --seclev seclevstr
+			out:
+				struct seclev
+
+		iptables(8) -> sa match iptables(8) library
+		ip6tables(8) -> sa match ip6tables(8) library
+			in:
+				char[] --salist SAList
+			out:
+				struct ip_said SA[, ...]
+
+		iptables(8) -> NetFilter
+		ip6tables(8) -> NetFilter
+		I/F is already defined in NetFilter.  In addition, it will
+		need structures to pass the following:
+			in:
+				struct seclev
+				struct ip_said SA[, ...]
+
+	- allow unprocessed packets from IPSec peer in
+		KMd -> iptables(8) system(3) call (Policy)
+		KMd -> ip6tables(8) system(3) call (Policy)
+			in:
+				char[] -I
+				char[] -s SADDR/SMASK (remote SG)
+				char[] -d DADDR/DMASK (local SG)
+				char[] --proto ESP
+				char[] --espspi SPI
+				char[] -J ACCEPT
+			out:
+				unsigned char exit_code
+
+		iptables(8) -> seclev match iptables(8) library
+		ip6tables(8) -> seclev match ip6tables(8) library
+			in:
+				char[] --seclev seclevstr
+			out:
+				struct seclev
+
+		iptables(8) -> NetFilter
+		ip6tables(8) -> NetFilter
+		I/F is already defined in NetFilter.  In addition, it will
+		need structures to pass the following:
+			in:
+				struct seclev
+
+	- incoming packet is tested on match modules
+		NetFilter -> seclev match NetFilter kernel module
+			in:
+				struct sk_buff *skb
+				struct seclev
+			out:
+				boolean
+
+		NetFilter -> sa match NetFilter kernel module
+			in:
+				struct sk_buff *skb
+				struct ip_said SA[,...]
+			out:
+				boolean
+
+	- packet arrives via transport layer demux to DECRYPT
+		Transport Layer De-mux -> IPSec DECRYPT kernel module
+			in:
+				struct sk_buff *skb
+
+	- fetch SAs specified by packet in skb
+		IPSec DECRYPT kernel module -> SADB (SAID)
+			in:
+				struct ip_said SA
+			out:
+				struct tdb *tdbp
+
+	- send skb (packet) back into NF_IP_PRE_ROUTE
+		IPSec DECRYPT kernel module -> NetFilter
+			in:
+				struct sk_buff *skb
+				struct ip_said SA[,...]
+		
+	- processed packet is tested on match modules and ACCEPTED
+		NetFilter -> seclev match NetFilter kernel module
+			in:
+				struct sk_buff *skb
+				struct seclev
+			out:
+				boolean
+
+		NetFilter -> sa match NetFilter kernel module
+			in:
+				struct sk_buff *skb
+				struct ip_said SA[,...]
+			out:
+				boolean
+
+	- expire SA if a limit is reached
+		SADB -> KMd (PF_KEYv2 EXPIRE)
+			see RFC2367, PF_KEYv2 EXPIRE
+				
+Incoming w/existing connection specifying IPSec device
+	- put in the new SAs in place once the negotiations have succeeded
+		KMd -> SADB (PF_KEYv2 ADD/UPDATE)
+			see RFC2367, PF_KEYv2 ADD/UPDATE message for each SA
+
+	- put in a blocking entry to prevent unprotected packets entering
+		KMd -> iptables(8) system(3) call (Policy)
+		KMd -> ip6tables(8) system(3) call (Policy)
+			in:
+				char[] -I
+				char[] -s SADDR/SMASK
+				char[] -d DADDR/DMASK
+				char[] --protocol PROTO
+				char[] --sport SPORT
+				char[] --dport DPORT
+				char[] --uid-owner UID
+				char[] --seclev seclev
+				char[] -J DROP (or PEEK)
+			out:
+				unsigned char exit_code
+
+		iptables(8) -> seclev match iptables(8) library
+		ip6tables(8) -> seclev match ip6tables(8) library
+			in:
+				char[] --seclev seclevstr
+			out:
+				struct seclev
+
+		iptables(8) -> NetFilter
+		ip6tables(8) -> NetFilter
+		I/F is already defined in NetFilter.  In addition, it will
+		need structures to pass the following:
+			in:
+				struct seclev
+				target DROP (or PEEK)
+		
+	- allow properly processed packets in
+		KMd -> iptables(8) system(3) call (Policy)
+		KMd -> ip6tables(8) system(3) call (Policy)
+			in:
+				char[] -I
+				char[] -s SADDR/SMASK
+				char[] -d DADDR/DMASK
+				char[] --protocol PROTO
+				char[] --sport SPORT
+				char[] --dport DPORT
+				char[] --uid-owner UID
+				char[] --in-interface IPSECdev
+				char[] --seclev seclev
+				char[] --salist SAList
+				       (can we set an --in-interface IPSECdev
+					from this so we can just test
+					in-interface?  This may need two
+					entries, including a target SETDEV)
+				char[] -J ACCEPT
+			out:
+				unsigned char exit_code
+
+		iptables(8) -> seclev match iptables(8) library
+		ip6tables(8) -> seclev match ip6tables(8) library
+			in:
+				char[] --seclev seclevstr
+			out:
+				struct seclev
+
+		iptables(8) -> sa match iptables(8) library
+		ip6tables(8) -> sa match ip6tables(8) library
+			in:
+				char[] --salist SAList
+			out:
+				struct ip_said SA[, ...]
+
+		iptables(8) -> NetFilter
+		ip6tables(8) -> NetFilter
+		I/F is already defined in NetFilter.  In addition, it will
+		need structures to pass the following:
+			in:
+				struct seclev
+				struct ip_said SA[, ...]
+
+	- allow unprocessed packets from IPSec peer in
+		KMd -> iptables(8) system(3) call (Policy)
+		KMd -> ip6tables(8) system(3) call (Policy)
+			in:
+				char[] -I
+				char[] -s SADDR/SMASK (remote SG)
+				char[] -d DADDR/DMASK (local SG)
+				char[] --proto ESP
+				char[] --espspi SPI
+				char[] -J ACCEPT
+			out:
+				unsigned char exit_code
+
+		iptables(8) -> seclev match iptables(8) library
+		ip6tables(8) -> seclev match ip6tables(8) library
+			in:
+				char[] --seclev seclevstr
+			out:
+				struct seclev
+
+		iptables(8) -> NetFilter
+		ip6tables(8) -> NetFilter
+		I/F is already defined in NetFilter.  In addition, it will
+		need structures to pass the following:
+			in:
+				struct seclev
+
+	- incoming packet is tested on match modules
+		NetFilter -> seclev match NetFilter kernel module
+			in:
+				struct sk_buff *skb
+				struct seclev
+			out:
+				boolean
+
+		NetFilter -> sa match NetFilter kernel module
+			in:
+				struct sk_buff *skb
+				struct ip_said SA[,...]
+			out:
+				boolean
+
+	- packet arrives via transport layer demux to DECRYPT
+		Transport Layer De-mux -> IPSec DECRYPT kernel module
+			in:
+				struct sk_buff *skb
+
+	- fetch SAs specified by packet in skb
+		IPSec DECRYPT kernel module -> SADB (SAID)
+			in:
+				struct ip_said SA
+			out:
+				struct tdb *tdbp
+
+	- send skb (packet) back into NF_IP_PRE_ROUTE
+		IPSec DECRYPT kernel module -> NetFilter
+			in:
+				struct sk_buff *skb
+				struct ip_said SA[,...]
+		
+	- processed packet is tested on match modules and ACCEPTED
+		NetFilter -> seclev match NetFilter kernel module
+			in:
+				struct sk_buff *skb
+				struct seclev
+			out:
+				boolean
+
+		NetFilter -> sa match NetFilter kernel module
+			in:
+				struct sk_buff *skb
+				struct ip_said SA[,...]
+			out:
+				boolean
+
+	- expire SA if a limit is reached
+		SADB -> KMd (PF_KEYv2 EXPIRE)
+			see RFC2367, PF_KEYv2 EXPIRE
+				
+Incoming no connection
+	 - set target for PEEKing at (or TRAPing) incoming packets with no connection
+		KMd -> iptables(8) system(3) call (Policy)
+		KMd -> ip6tables(8) system(3) call (Policy)
+			in:
+				char[] -I
+				char[] -s SADDR/SMASK
+				char[] -d DADDR/DMASK
+				char[] --protocol PROTO
+				char[] --sport SPORT
+				char[] --dport DPORT
+				char[] --uid-owner UID
+				char[] --seclev seclev
+				char[] -J PEEK (or TRAP)
+			out:
+				unsigned char exit_code
+
+		iptables(8) -> seclev match iptables(8) library
+		ip6tables(8) -> seclev match ip6tables(8) library
+			in:
+				char[] --seclev seclevstr
+			out:
+				struct seclev
+
+		iptables(8) -> NetFilter
+		ip6tables(8) -> NetFilter
+		I/F is already defined in NetFilter.  In addition, it will
+		need structures to pass the following:
+			in:
+				struct seclev
+				target PEEK (or TRAP)
+
+	- packet comes in and gets tested by match modules
+		NetFilter -> seclev match NetFilter kernel module
+			in:
+				struct sk_buff *skb
+				struct seclev
+			out:
+				boolean
+
+		NetFilter -> sa match NetFilter kernel module
+			in:
+				struct sk_buff *skb
+				struct ip_said SA[,...]
+			out:
+				boolean
+
+	- packet matches and gets sent to PEEK target
+		NetFilter -> PEEK (or TRAP) target NetFilter kernel module
+			in:
+				struct sk_buff *skb
+			out:
+				unsigned int = NF_ACCEPT (or NF_STOLEN)
+
+	- send up an ACQUIRE
+		PEEK (or TRAP) target NetFilter kernel module -> KMds (PF_KEYv2 ACQUIRE)
+			see RFC2367, PF_KEYv2 ACQUIRE
+
+	- create ACCEPT (or HOLD) target with skb info to prevent KMd overload
+		PEEK (or HOLD) target NetFilter kernel module -> NetFilter
+			in:
+				struct sk_buff *skb
+			out:
+				boolean
+
+	- next packet comes in while KMd is negotiating SAs.
+		NetFilter -> seclev match NetFilter kernel module
+			in:
+				struct sk_buff *skb
+				struct seclev
+			out:
+				boolean
+
+		NetFilter -> sa match NetFilter kernel module
+			in:
+				struct sk_buff *skb
+				struct ip_said SA[,...]
+			out:
+				boolean
+
+	- put the new SAs in place once the negotiations have succeeded
+		KMd -> SADB (PF_KEYv2 ADD/UPDATE)
+			see RFC2367, PF_KEYv2 ADD/UPDATE message for each SA
+
+	- put in a blocking entry to prevent unprotected packets entering
+		KMd -> iptables(8) system(3) call (Policy)
+		KMd -> ip6tables(8) system(3) call (Policy)
+			in:
+				char[] -I
+				char[] -s SADDR/SMASK
+				char[] -d DADDR/DMASK
+				char[] --protocol PROTO
+				char[] --sport SPORT
+				char[] --dport DPORT
+				char[] --uid-owner UID
+				char[] --seclev seclev
+				char[] -J DROP (or PEEK)
+			out:
+				unsigned char exit_code
+
+		iptables(8) -> seclev match iptables(8) library
+		ip6tables(8) -> seclev match ip6tables(8) library
+			in:
+				char[] --seclev seclevstr
+			out:
+				struct seclev
+
+		iptables(8) -> NetFilter
+		ip6tables(8) -> NetFilter
+		I/F is already defined in NetFilter.  In addition, it will
+		need structures to pass the following:
+			in:
+				struct seclev
+				(target PEEK)
+		
+	- allow properly processed packets in
+		KMd -> iptables(8) system(3) call (Policy)
+		KMd -> ip6tables(8) system(3) call (Policy)
+			in:
+				char[] -I
+				char[] -s SADDR/SMASK
+				char[] -d DADDR/DMASK
+				char[] --protocol PROTO
+				char[] --sport SPORT
+				char[] --dport DPORT
+				char[] --uid-owner UID
+				char[] --seclev seclev
+				char[] --salist SAList
+				char[] -J ACCEPT
+			out:
+				unsigned char exit_code
+
+		iptables(8) -> seclev match iptables(8) library
+		ip6tables(8) -> seclev match ip6tables(8) library
+			in:
+				char[] --seclev seclevstr
+			out:
+				struct seclev
+
+		iptables(8) -> sa match iptables(8) library
+		ip6tables(8) -> sa match ip6tables(8) library
+			in:
+				char[] --salist SAList
+			out:
+				struct ip_said SA[, ...]
+
+		iptables(8) -> NetFilter
+		ip6tables(8) -> NetFilter
+		I/F is already defined in NetFilter.  In addition, it will
+		need structures to pass the following:
+			in:
+				struct seclev
+				struct ip_said SA[, ...]
+		
+	- incoming packet is tested on match modules
+		NetFilter -> seclev match NetFilter kernel module
+			in:
+				struct sk_buff *skb
+				struct seclev
+			out:
+				boolean
+
+		NetFilter -> sa match NetFilter kernel module
+			in:
+				struct sk_buff *skb
+				struct ip_said SA[,...]
+			out:
+				boolean
+
+	- packet arrives via transport layer demux to DECRYPT
+		Transport Layer De-mux -> IPSec DECRYPT kernel module
+			in:
+				struct sk_buff *skb
+
+	- fetch SAs specified by packet in skb
+		IPSec DECRYPT kernel module -> SADB (SAID)
+			in:
+				struct ip_said SA
+			out:
+				struct tdb *tdbp
+
+	- send skb (packet) back into NF_IP_PRE_ROUTE
+		IPSec DECRYPT kernel module -> NetFilter
+			in:
+				struct sk_buff *skb
+				struct ip_said SA[,...]
+		
+	- processed packet is tested on match modules and ACCEPTed
+		NetFilter -> seclev match NetFilter kernel module
+			in:
+				struct sk_buff *skb
+				struct seclev
+			out:
+				boolean
+
+		NetFilter -> sa match NetFilter kernel module
+			in:
+				struct sk_buff *skb
+				struct ip_said SA[,...]
+			out:
+				boolean
+
+	- expire SA if a limit is reached
+		SADB -> KMd (PF_KEYv2 EXPIRE)
+			see RFC2367, PF_KEYv2 EXPIRE
+
+TODO:
+	api trips:
+		Packet w/no route?  how to get to kmd?  default route to IPSECdev which calls TRAP?
+		Nested tunnels, IKE recursion api trip
+		how to know when to stop decapsulating nested tunnels?
+		DHR's routing problem
+		mutli-layer routing environments that both touch and denker need.
+	nail down function calls and/or globals for each I/F, c-like function syntax
+	better api block comments
+	interface, function, args, block comment
+
diff -bruN freeswan-1.9.orig/klips/doc/klips2-design-api.txt freeswan-1.9/klips/doc/klips2-design-api.txt
--- freeswan-1.9.orig/klips/doc/klips2-design-api.txt	Wed Dec 31 19:00:00 1969
+++ freeswan-1.9/klips/doc/klips2-design-api.txt	Mon Jun  4 12:54:57 2001
@@ -0,0 +1,2375 @@
+#  -*- mode: Outline -*-
+# 
+#  klips2-design-api.txt
+#	Richard Guy Briggs <rgb@conscoop.ottawa.on.ca>
+#
+#  RCSID $Id: klips2-design-api.txt,v 1.17 2001/06/01 07:25:53 rgb Exp $
+#
+
+* Outline Commands cheat sheet (C-c C-s to see this)
+        C-c C-t         Hide EVERYTHING in buffer
+        C-c C-a         Show EVERYTHING in buffer
+
+        C-c C-d         Hide THIS item and subitems (subtree)
+        C-c C-s         Show THIS item and subitems (subtree)
+
+        C-c C-c         Hide ONE item
+        C-c C-e         Show ONE item
+
+* Introduction
+	This document describes all the APIs used in this design.
+	Please see klips2-design.txt for an overview.
+
+** Interface:
+	interface description, listing origin and destination
+	entities, separated by an ">->" with diagram label, if it
+	exists within double quotes ``"''
+
+** Label:
+	diagram label
+
+** Name:
+	the name of the function used and a very brief description
+
+** Synopsis:
+	function form, argument position, type and return type
+
+** Arguments:
+	description of each argument
+
+** Description:
+	description of interface and function
+
+** Implementation notes:
+	caveats and side effects
+
+** Return value:
+	function return values
+
+** Example:
+	usage example
+
+** See also:
+	related documentation or further explanation
+
+
+
+* Interfaces
+
+** KMd >-> iptables(8) "Policy"
+** KMd >-> ip6tables(8) "Policy"
+
+	Interface:
+
+		KMd >-> iptables(8)
+		KMd >-> ip6tables(8)
+
+	Label:
+
+		"Policy"
+
+	Name:
+
+		system(3) call to iptables(8) - execute a shell
+		command to do IP packet filter administration to set
+		ipsec policy
+
+	Synopsis:
+
+		#include <stdlib.h>
+
+		int system(const char * "iptables \
+			--table ipsec \
+			--new-table chain ");
+		int system(const char * "iptables \
+			--table ipsec \
+			--policy chain target");
+		int system(const char * "iptables \
+			--table ipsec \
+			--{append,delete,insert,replace} chain \
+			--protocol protocol \
+			--source src \
+			--destination dst \
+			--jump target \
+			--in-interface IPSECdev \
+			--out-interface IPSECdev \
+			--source-port SPORT \
+			--destination-port DPORT \
+			--uid-owner UID \
+			--gid-owner GID \
+			--pid-owner PID \
+			--sid-owner SID \
+			--espspi SPI \
+			--seclev seclevstr \
+			--salist SAList \
+		");
+
+	Arguments:
+
+		--table ipsec
+			specify ipsec SPDB NetFilter kernel table
+
+		--new-chain chain
+			create new chain in ipsec SPDB
+
+		--policy chain target
+			set default target for specified chain
+
+		--{append,delete,insert,replace} chain
+			manipulate a rule in the specified chain
+
+		--protocol protocol
+			protocol for the matching rule
+
+		--source src
+			source address for the matching rule
+
+		--destination dst
+			destination address for the matching rule
+
+		--in-interface IPSECdev
+			incoming ipsec device for the matching rule
+
+		--out-interface IPSECdev
+			outgoing ipsec device for the matching rule
+
+		--source-port SPORT
+			source port for the matching rule (tcp or udp)
+
+		--destination-port DPORT
+			destination port for the matching rule (tcp or udp)
+
+		--uid-owner UID
+			user ID for the matching rule
+
+		--espspi SPI
+			Encapsulation Security Payload Security Parameters
+			Index for the matching rule
+
+		--seclev seclevstr
+			security or sensitivity level or label for the
+			matching rule
+
+		--salist SAList
+			Security Association IDentifier list for the matching
+			rule
+
+		--jump target
+			target for a matching packet
+
+	Description:
+
+		This is the SPDB (or as yet undefined PF_POLICY)
+		interface from the key management daemons to the
+		kernel via netfilter.
+
+		The default chains of in and out are created when the
+		table is created.  Additional chains can be created as
+		needed with the iptables --new-chain command and can
+		be listed as targets to match entries.
+
+		The default policy of each chain can be changed from
+		the initialised value of DROP (TRAP?) with the
+		iptables --policy command.  The default policy of each
+		chain is one of the standard NetFilter targets of
+		ACCEPT, DROP, REJECT.  IPSec adds the targets TRAP,
+		HOLD (internal), PEEK and IPSEC.  Only the IPSEC
+		target takes any arguments, which consists of a list
+		of SAs to be used for processing.
+
+		Rules are appended, inserted, deleted or replaced to
+		set the IPSec policy.
+
+		Packets can be matched on IP transport protocol,
+		source or destination address, incoming or outgoing
+		ipsec device, source or destination port for tcp or
+		udp, user ID, Encapsulation Security Payload or
+		Authentication Header Security Parameters Index,
+		security or sensitivity level or label, Security
+		Association IDentifier list.  A target must be
+		specified for each matching rule using the iptables
+		--jump option.
+
+	Implementation notes:
+
+		If the in and out chains don't yet exist, they must be
+		created with the iptables --new-chain command.  (These
+		will most likely be created by loading the module and
+		so this paragraph may disappear.)  
+
+		An alternative may be to have the KMd link directly
+		with iptables.o rather than invoking system(3) to call
+		iptables(8).
+
+		It looks like it may be possible to call the libipt
+		functions directly, which will be a big help in
+		speeding things up since text conversion and parsing
+		won't have to be done.  This will change most of the
+		char fields to binary fields and change the calling
+		function and return codes.
+
+	Return value:
+
+		system(3) returns:
+		The value returned is 127 if the execve() call for
+		/bin/sh fails, -1 if there was another error.
+
+		iptables(8) returns:
+		Various error messages are printed to standard error.
+		The exit code is 0 for correct functioning.  Errors
+		which appear to be caused by invalid or abused command
+		line parameters cause an exit code of 2, and other
+		errors cause an exit code of 1.
+
+	Example:
+
+		#include <stdlib.h>
+		int return;
+
+		...
+
+		if((return = system("iptables \
+			--table ipsec \
+			--insert out \
+			--source this-subnet.example.com \
+			--destination that-subnet.example.com \
+			--jump IPSEC \
+			--use-salist esp.12345678@that-sg.example.com \
+			"))){
+			fprintf(stderr, "error $d calling iptables\n");
+			exit 1;
+		}
+
+	See also:
+
+		system(3), iptables(8)
+
+
+
+** iptables(8) >-> seclev match iptables(8) library
+** ip6tables(8) >-> seclev match ip6tables(8) library
+
+	Interface:
+
+		iptables(8) >-> seclev match iptables(8) library
+		ip6tables(8) >-> seclev match ip6tables(8) library
+
+	Label:
+
+	Name:
+
+		(*seclev_parse) - parse, convert and check security level options
+
+	Synopsis:
+
+		static int
+		seclev_parse(
+			int c,
+			char **argv,
+			int invert,
+			unsigned int *flags,
+			const struct ipt_entry *entry,
+			unsigned int *nfcache,
+			struct ipt_entry_match **match
+		)
+
+	Arguments:
+
+		c
+			argument count
+
+		argv
+			text arguments to be parsed by this match
+
+		invert
+			invert this match?
+
+		flags
+			bitmap to indicate which arguments have been processed
+
+		entry
+			pointer to table entry associated with match
+
+		nfcache
+			bitmap of skb parts examined by this match
+
+		match
+			match data
+
+	Description:
+
+		This function parses, converts and checks iptables(8)
+		and ip6tables(8) command line security level text
+		arguments for use by the seclev match NetFilter kernel
+		module.
+
+		Input is expected to be in the form of "--seclev
+		seclevstr" where seclevstr is the security (or
+		sensitivity) level (or label) associated with the
+		packet.
+
+	Implementation notes:
+
+		I don't actually what form security level data takes,
+		but that can be sorted out later.
+
+	Return value:
+
+		1 if an option was eaten, 0 if not.
+
+	Example:
+
+		static int
+		seclev_parse(
+			int c,
+			char **argv,
+			int invert,
+			unsigned int *flags,
+			const struct ipt_entry *entry,
+			unsigned int *nfcache,
+			struct ipt_entry_match **match
+		) {
+			struct ipt_seclev_info *info = (struct ipt_seclev_info*)(*match)->data;
+
+			/* parse option arguments */
+			...
+			return 1;
+		}
+
+		struct iptables_match seclev_match_lib = {
+			NULL,
+			"seclev",
+			NETFILTER_VERSION,
+			IPT_ALIGN(sizeof(struct ipt_seclev_info)),
+			IPT_ALIGN(sizeof(struct ipt_seclev_info)),
+			&seclev_help,
+			&seclev_init,
+			&seclev_parse,
+			&seclev_final_check,
+			&seclev_print,
+			&seclev_save,
+			seclev_opts
+		};
+
+		void
+		_init(void)
+		{
+			register_match(&seclev_match_lib);
+		}
+
+	See also:
+
+
+
+** iptables(8) >-> salist match iptables(8) library
+** ip6tables(8) >-> salist match ip6tables(8) library
+
+	Interface:
+
+		iptables(8) >-> salist match iptables(8) library
+		ip6tables(8) >-> salist match ip6tables(8) library
+
+	Label:
+
+	Name:
+
+		(*salist_parse) - parse, convert and check security
+		association list options
+
+	Synopsis:
+
+		static int
+		salist_parse(
+			int c,
+			char **argv,
+			int invert,
+			unsigned int *flags,
+			const struct ipt_entry *entry,
+			unsigned int *nfcache,
+			struct ipt_entry_match **match
+		)
+
+	Arguments:
+
+		c
+			argument count
+
+		argv
+			text arguments to be parsed by this match
+
+		invert
+			invert this match?
+
+		flags
+			bitmap to indicate which arguments have been processed
+
+		entry
+			pointer to table entry associated with match
+
+		nfcache
+			bitmap of skb parts examined by this match
+
+		match
+			match data
+
+	Description:
+
+		This function parses, converts and checks iptables(8)
+		and ip6tables(8) command line security association
+		list level text arguments for use by the salist match
+		NetFilter kernel module.
+
+		Input is expected to be in the form of "--salist
+		SAList" where SAList is the security association list
+		associated with the packet.
+
+	Implementation notes:
+
+		There is still some disagreement about the form of the
+		salist.
+
+	Return value:
+
+		1 if an option was eaten, 0 if not.
+
+	Example:
+
+		static int
+		salist_parse(
+			int c,
+			char **argv,
+			int invert,
+			unsigned int *flags,
+			const struct ipt_entry *entry,
+			unsigned int *nfcache,
+			struct ipt_entry_match **match
+		) {
+			struct ipt_salist_info *info = (struct ipt_salist_info*)(*match)->data;
+
+			/* parse option arguments */
+			...
+			return 1;
+		}
+
+		struct iptables_match salist_match_lib = {
+			NULL,
+			"salist",
+			NETFILTER_VERSION,
+			IPT_ALIGN(sizeof(struct ipt_salist_info)),
+			IPT_ALIGN(sizeof(struct ipt_salist_info)),
+			&salist_help,
+			&salist_init,
+			&salist_parse,
+			&salist_final_check,
+			&salist_print,
+			&salist_save,
+			salist_opts
+		};
+
+		void
+		_init(void)
+		{
+			register_match(&salist_match_lib);
+		}
+
+	See also:
+
+		http://netfilter.samba.org/unreliable-guides/netfilter-hacking-HOWTO/netfilter-hacking-HOWTO.linuxdoc-4.html
+
+
+
+** iptables(8) >-> TRAP target iptables(8) library
+** ip6tables(8) >-> TRAP target ip6tables(8) library	
+
+	Interface:
+
+		iptables(8) >-> TRAP target iptables(8) library
+		ip6tables(8) >-> TRAP target ip6tables(8) library
+
+	Label:
+
+	Name:
+
+		(*trap_parse) - parse, convert and check TRAP options
+
+	Synopsis:
+
+		static int trap_parse(
+			int c,
+			char **argv,
+			int invert,
+			unsigned int *flags,
+			const struct ipt_entry *entry,
+			struct ipt_entry_target **target
+		)
+
+	Arguments:
+
+		c
+			argument count
+
+		argv
+			text arguments to be parsed by this target
+
+		invert
+			invert flag (doesn't make sense for targets)
+
+		flags
+			bitmap to indicate which arguments have been processed
+
+		entry
+			pointer to table entry associated with target
+
+		target
+			target data
+
+	Description:
+
+		This function parses, converts and checks iptables(8)
+		and ip6tables(8) command line TRAP text
+		arguments for use by the TRAP target NetFilter kernel
+		module.
+
+		Input is expected to be in the form of "--salist
+		SAList" where SAList is the security association list
+		to be applied to packets sent to the TRAP target.
+
+	Implementation notes:
+
+		There is still some disagreement about the form of the
+		salist.
+
+	Return value:
+
+		1 if an option was eaten, 0 if not.
+
+	Example:
+
+		static int
+		trap_parse(
+			int c,
+			char **argv,
+			int invert,
+			unsigned int *flags,
+			const struct ipt_entry *entry,
+			struct ipt_entry_target **target
+		) {
+			struct ipt_trap_target_info *info = (struct ipt_trap_target_info*)(*target)->data;
+
+			/* parse option arguments */
+			...
+			return 1;
+		}
+
+		struct iptables_target trap_target_lib = {
+			NULL,
+			"TRAP",
+			NETFILTER_VERSION,
+			IPT_ALIGN(sizeof(struct ipt_trap_target_info)),
+			IPT_ALIGN(sizeof(struct ipt_trap_target_info)),
+			&trap_help,
+			&trap_init,
+			&trap_parse,
+			&trap_final_check,
+			&trap_print,
+			&trap_save,
+			trap_opts
+		};
+
+		void
+		_init(void)
+		{
+			register_target(&trap_target_lib);
+		}
+
+	See also:
+
+		http://netfilter.samba.org/unreliable-guides/netfilter-hacking-HOWTO/netfilter-hacking-HOWTO.linuxdoc-4.html
+
+
+
+** iptables(8) >-> HOLD target iptables(8) library
+** ip6tables(8) >-> HOLD target ip6tables(8) library	
+
+	Interface:
+
+		iptables(8) >-> HOLD target iptables(8) library
+		ip6tables(8) >-> HOLD target ip6tables(8) library
+
+	Label:
+
+	Name:
+
+	Synopsis:
+
+		static int hold_parse(
+			int c,
+			char **argv,
+			int invert,
+			unsigned int *flags,
+			const struct ipt_entry *entry,
+			struct ipt_entry_target **target
+		)
+
+	Arguments:
+
+		c
+			argument count
+
+		argv
+			text arguments to be parsed by this target
+
+		invert
+			invert flag (doesn't make sense for targets)
+
+		flags
+			bitmap to indicate which arguments have been processed
+
+		entry
+			pointer to table entry associated with target
+
+		target
+		target data
+
+	Description:
+
+		This function parses, converts and checks iptables(8)
+		and ip6tables(8) command line HOLD text
+		arguments for use by the HOLD target NetFilter kernel
+		module.
+
+		Input is expected to be in the form of "--salist
+		SAList" where SAList is the security association list
+		to be applied to packets sent to the HOLD target.
+
+	Implementation notes:
+
+		There is still some disagreement about the form of the
+		salist.
+
+	Return value:
+
+		1 if an option was eaten, 0 if not.
+
+	Example:
+
+		static int
+		hold_parse(
+			int c,
+			char **argv,
+			int invert,
+			unsigned int *flags,
+			const struct ipt_entry *entry,
+			struct ipt_entry_target **target
+		) {
+			struct ipt_hold_target_info *info = (struct ipt_hold_target_info*)(*target)->data;
+
+			/* parse option arguments */
+			...
+			return 1;
+		}
+
+		struct iptables_target hold_target_lib = {
+			NULL,
+			"HOLD",
+			NETFILTER_VERSION,
+			IPT_ALIGN(sizeof(struct ipt_hold_target_info)),
+			IPT_ALIGN(sizeof(struct ipt_hold_target_info)),
+			&hold_help,
+			&hold_init,
+			&hold_parse,
+			&hold_final_check,
+			&hold_print,
+			&hold_save,
+			hold_opts
+		};
+
+		void
+		_init(void)
+		{
+			register_target(&hold_target_lib);
+		}
+
+	See also:
+
+		http://netfilter.samba.org/unreliable-guides/netfilter-hacking-HOWTO/netfilter-hacking-HOWTO.linuxdoc-4.html
+
+
+
+** iptables(8) >-> PEEK target iptables(8) library
+** ip6tables(8) >-> PEEK target ip6tables(8) library	
+
+	Interface:
+
+		iptables(8) >-> PEEK target iptables(8) library
+		ip6tables(8) >-> PEEK target ip6tables(8) library
+
+	Label:
+
+	Name:
+
+	Synopsis:
+
+		static int peek_parse(
+			int c,
+			char **argv,
+			int invert,
+			unsigned int *flags,
+			const struct ipt_entry *entry,
+			struct ipt_entry_target **target
+		)
+
+	Arguments:
+
+		c
+			argument count
+
+		argv
+			text arguments to be parsed by this target
+
+		invert
+			invert flag (doesn't make sense for targets)
+
+		flags
+			bitmap to indicate which arguments have been processed
+
+		entry
+			pointer to table entry associated with target
+
+		target
+			target data
+
+	Description:
+
+		This function parses, converts and checks iptables(8)
+		and ip6tables(8) command line PEEK text
+		arguments for use by the PEEK target NetFilter kernel
+		module.
+
+		Input is expected to be in the form of "--salist
+		SAList" where SAList is the security association list
+		to be applied to packets sent to the PEEK target.
+
+	Implementation notes:
+
+		There is still some disagreement about the form of the
+		salist.
+
+	Return value:
+
+		1 if an option was eaten, 0 if not.
+
+	Example:
+
+		static int
+		peek_parse(
+			int c,
+			char **argv,
+			int invert,
+			unsigned int *flags,
+			const struct ipt_entry *entry,
+			struct ipt_entry_target **target
+		) {
+			struct ipt_peek_target_info *info = (struct ipt_peek_target_info*)(*target)->data;
+
+			/* parse option arguments */
+			...
+			return 1;
+		}
+
+		struct iptables_target peek_target_lib = {
+			NULL,
+			"PEEK",
+			NETFILTER_VERSION,
+			IPT_ALIGN(sizeof(struct ipt_peek_target_info)),
+			IPT_ALIGN(sizeof(struct ipt_peek_target_info)),
+			&peek_help,
+			&peek_init,
+			&peek_parse,
+			&peek_final_check,
+			&peek_print,
+			&peek_save,
+			peek_opts
+		};
+
+		void
+		_init(void)
+		{
+			register_target(&peek_target_lib);
+		}
+
+	See also:
+
+		http://netfilter.samba.org/unreliable-guides/netfilter-hacking-HOWTO/netfilter-hacking-HOWTO.linuxdoc-4.html
+
+
+
+** iptables(8) >-> IPSEC target iptables(8) library
+** ip6tables(8) >-> IPSEC target ip6tables(8) library	
+
+	Interface:
+
+		iptables(8) >-> IPSEC target iptables(8) library
+		ip6tables(8) >-> IPSEC target ip6tables(8) library
+
+	Label:
+
+	Name:
+
+	Synopsis:
+
+		static int ipsec_parse(
+			int c,
+			char **argv,
+			int invert,
+			unsigned int *flags,
+			const struct ipt_entry *entry,
+			struct ipt_entry_target **target
+		)
+
+	Arguments:
+
+		c
+			argument count
+
+		argv
+			text arguments to be parsed by this target
+
+		invert
+			invert flag (doesn't make sense for targets)
+
+		flags
+			bitmap to indicate which arguments have been processed
+
+		entry
+			pointer to table entry associated with target
+
+		target
+			target data
+
+	Description:
+
+		This function parses, converts and checks iptables(8)
+		and ip6tables(8) command line IPSEC text
+		arguments for use by the IPSEC target NetFilter kernel
+		module.
+
+		Input is expected to be in the form of "--salist
+		SAList" where SAList is the security association list
+		to be applied to packets sent to the IPSEC target.
+
+	Implementation notes:
+
+		There is still some disagreement about the form of the
+		salist.
+
+	Return value:
+
+		1 if an option was eaten, 0 if not.
+
+	Example:
+
+		static int
+		ipsec_parse(
+			int c,
+			char **argv,
+			int invert,
+			unsigned int *flags,
+			const struct ipt_entry *entry,
+			struct ipt_entry_target **target
+		) {
+			struct ipt_ipsec_target_info *info = (struct ipt_ipsec_target_info*)(*target)->data;
+
+			/* parse option arguments */
+			...
+			return 1;
+		}
+
+		struct iptables_target ipsec_target_lib = {
+			NULL,
+			"IPSEC",
+			NETFILTER_VERSION,
+			IPT_ALIGN(sizeof(struct ipt_ipsec_target_info)),
+			IPT_ALIGN(sizeof(struct ipt_ipsec_target_info)),
+			&ipsec_help,
+			&ipsec_init,
+			&ipsec_parse,
+			&ipsec_final_check,
+			&ipsec_print,
+			&ipsec_save,
+			ipsec_opts
+		};
+
+		void
+		_init(void)
+		{
+			register_target(&ipsec_target_lib);
+		}
+
+	See also:
+
+		http://netfilter.samba.org/unreliable-guides/netfilter-hacking-HOWTO/netfilter-hacking-HOWTO.linuxdoc-4.html
+
+
+
+** iptables(8) >-> NetFilter
+** ip6tables(8) >-> NetFilter
+
+	Interface:
+
+		iptables(8) >-> NetFilter
+		ip6tables(8) >-> NetFilter
+
+	Label:
+
+	Name:
+
+	Synopsis:
+
+	Arguments:
+
+		match->data = struct ipt_seclev_info
+		match->data = struct ipt_salist_info
+		target->data = struct ipt_trap_target_info
+		target->data = struct ipt_peek_target_info
+		target->data = struct ipt_ipsec_target_info
+
+	Description:
+
+		This I/F is already defined in NetFilter.  We don't
+		call it directly.  In addition, it will need
+		structures to pass the arguments above.  This
+		interface provides a mechanism for iptables to update
+		the kernel netfilter tables.
+
+	Implementation notes:
+
+	Return value:
+
+	Example:
+
+	See also:
+
+
+** NetFilter >-> seclev match NetFilter kernel module
+
+	Interface:
+
+		NetFilter >-> seclev match NetFilter kernel module
+
+	Label:
+
+	Name:
+
+		(*seclev_match) - does the packet match Security
+		Level?
+
+	Synopsis:
+
+		static int
+		seclev_match(
+			const struct sk_buff *skb,
+			const struct net_device *in,
+			const struct net_device *out,
+			const void *matchinfo,
+			int offset,
+			const void *hdr,
+			u_int16_t datalen,
+			int *hotdrop
+		)
+
+	Arguments:
+
+		skb
+			skb to test for match
+
+		in
+			incoming network interface
+
+		out
+			outgoing network interface
+
+		matchinfo
+			match information
+
+		offset
+			packet offset
+
+		hdr
+			transport layer header pointer
+
+		datalen
+			length of skb
+
+		hotdrop
+			flag to immediately drop packet
+
+	Description:
+
+		This function checks if the skb supplied matches
+		the security level specified in matchinfo.
+
+	Implementation notes:
+
+	Return value:
+
+		It returns true (1) for	match, false (0) for no match.
+
+	Example:
+
+		static int
+		seclev_match(
+			const struct sk_buff *skb,
+			const struct net_device *in,
+			const struct net_device *out,
+			const void *matchinfo,
+			int offset,
+			const void *hdr,
+			u_int16_t datalen,
+			int *hotdrop
+		) {
+			struct ipt_seclev_info *info = (struct ipt_seclev_info*)matchinfo;
+
+			if(/* test skb for match to matchinfo data */) {
+				return 1;
+			}
+			return 0;
+		}
+
+		static struct ipt_match seclev_match_mod = {
+			{ NULL, NULL },
+			"seclev",
+			&seclev_match,
+			&seclev_checkentry,
+			NULL,
+			THIS_MODULE
+		};
+
+		static int __init
+		init(void)
+		{
+			return ipt_register_match(&seclev_match_mod);
+		}
+
+		static void __exit
+		fini(void)
+		{
+			ipt_unregister_match(&seclev_match_mod);
+		}
+
+	See also:
+
+		http://netfilter.samba.org/unreliable-guides/netfilter-hacking-HOWTO/netfilter-hacking-HOWTO.linuxdoc-4.html
+
+
+
+** NetFilter >-> salist match NetFilter kernel module
+
+	Interface:
+
+		NetFilter >-> salist match NetFilter kernel module
+
+	Label:
+
+	Name:
+
+		(*salist_match) - does the packet match the Security
+		Association List?
+
+	Synopsis:
+
+		static int salist_match(
+			const struct sk_buff *skb,
+			const struct net_device *in,
+			const struct net_device *out,
+			const void *matchinfo,
+			int offset,
+			const void *hdr,
+			u_int16_t datalen,
+			int *hotdrop
+		)
+
+	Arguments:
+
+		skb
+			skb to test for match
+
+		in
+			incoming network interface
+
+		out
+			outgoing network interface
+
+		matchinfo
+			match information
+
+		offset
+			packet offset
+
+		hdr
+			transport layer header pointer
+
+		datalen
+			length of skb
+
+		hotdrop
+			flag to immediately drop packet
+
+	Description:
+
+		This function checks if the skb supplied matches
+		the Security Association list specified in matchinfo.
+
+	Implementation notes:
+
+	Return value:
+
+		It returns true (1) for	match, false (0) for no match.
+
+	Example:
+
+		static int
+		salist_match(
+			const struct sk_buff *skb,
+			const struct net_device *in,
+			const struct net_device *out,
+			const void *matchinfo,
+			int offset,
+			const void *hdr,
+			u_int16_t datalen,
+			int *hotdrop
+		) {
+			struct ipt_salist_info *info = (struct ipt_salist_info*)matchinfo;
+
+			if(/* test skb for match to matchinfo data */) {
+				return 1;
+			}
+			return 0;
+		}
+
+		static struct ipt_match salist_match_mod = {
+			{ NULL, NULL },
+			"salist",
+			&salist_match,
+			&salist_checkentry,
+			NULL,
+			THIS_MODULE
+		};
+
+		static int __init
+		init(void)
+		{
+			return ipt_register_match(&salist_match_mod);
+		}
+
+		static void __exit
+		fini(void)
+		{
+			ipt_unregister_match(&salist_match_mod);
+		}
+
+	See also:
+
+		http://netfilter.samba.org/unreliable-guides/netfilter-hacking-HOWTO/netfilter-hacking-HOWTO.linuxdoc-4.html
+
+
+
+** NetFilter >-> TRAP target NetFilter kernel module
+
+	Interface:
+
+		NetFilter >-> TRAP target NetFilter kernel module
+
+	Label:
+
+		TRAP
+
+	Name:
+
+		(*trap_target) - TRAP outgoing packets to initiate
+		opportunism
+
+	Synopsis:
+
+		static unsigned int
+		trap_target(
+			struct sk_buff **pskb,
+			unsigned int hooknum,
+			const struct net_device *in,
+			const struct net_device *out,
+			const void *targinfo,
+			void *userinfo
+		)
+
+	Arguments:
+
+		pskb
+			skb to be processed by target
+
+        	hooknum
+			which hook from which it was called
+
+		in
+			network device it came from
+
+		out
+			network device to which it is headed
+
+		targinfo
+			data used by target for processing
+
+		userinfo
+			optional user data passed in from mainline
+			hook
+
+	Description:
+
+		This is a NetFilter target.  It TRAPs packets to notify the
+		key management daemons to acquire a new set of
+		Security Associations and to set up a HOLD to save it
+		until the acquire has succeeded.
+
+	Implementation notes:
+
+	Return value:
+
+		It returns NF_STOLEN.
+
+	Example:
+
+		File net/ipv4/netfilter/ipt_TRAP.c:
+		#include <linux/netfilter_ipv4/ip_tables.h>
+
+		static unsigned int
+		trap_target(struct sk_buff **pskb,
+			unsigned int hooknum,
+			const struct net_device *in,
+			const struct net_device *out,
+			const void *targinfo,
+			void *userinfo)
+		{
+			/* send up a PF_KEYv2 ACQUIRE */
+			...
+			/* create HOLD and save packet */
+			...
+			return NF_STOLEN;
+		}
+
+		static struct ipt_target trap_target_mod = {
+			{ NULL, NULL },
+			"TRAP",
+			trap_target,
+			trap_checkentry,
+			NULL,
+			THIS_MODULE
+		};
+
+		static int __init init(void)
+		{
+			if (ipt_register_target(&trap_target_mod))
+				return -EINVAL;
+			return 0;
+		}
+
+		static void __exit fini(void)
+		{
+			ipt_unregister_target(&trap_target_mod);
+		}
+
+	See also:
+
+		http://netfilter.samba.org/unreliable-guides/netfilter-hacking-HOWTO/netfilter-hacking-HOWTO.linuxdoc-4.html
+
+
+
+** TRAP target NetFilter kernel module >-> KMds "PF_KEYv2 ACQUIRE"
+
+	Interface:
+
+		TRAP target NetFilter kernel module >-> KMds "PF_KEYv2 ACQUIRE"
+
+	Label:
+
+		see RFC2367, PF_KEYv2 ACQUIRE
+
+	Name:
+
+		see RFC2367, PF_KEYv2 ACQUIRE
+
+	Synopsis:
+
+		see RFC2367, PF_KEYv2 ACQUIRE
+
+	Arguments:
+
+		see RFC2367, PF_KEYv2 ACQUIRE
+
+	Description:
+
+		This interface is used to make requests from the
+		kernel to key management daemons for a set of Security
+		Associations to cover the specified traffic named to a
+		remote host.
+
+	Implementation notes:
+
+	Return value:
+
+		see RFC2367, PF_KEYv2 ACQUIRE
+
+	Example:
+
+	See also:
+
+
+** TRAP target NetFilter kernel module >-> NetFilter
+
+	Interface:
+
+		TRAP target NetFilter kernel module >-> NetFilter
+
+	Label:
+
+	Name:
+
+	Synopsis:
+
+	Arguments:
+
+	in:
+		struct sk_buff *skb
+	out:
+		boolean
+
+	Description:
+
+		This interface is used by the NetFilter TRAP target
+		kernel module to set up a HOLD to save outgoing
+		packets until the acquire has succeeded, limiting the
+		demand on the PF_KEYv2 ACQUIRE interface.
+
+	Implementation notes:
+
+		At present, this looks really ugly.  The table can
+		only be modified from userspace by reading the entire
+		table and then replacing the entire table atomically.
+
+	Return value:
+
+	Example:
+
+	See also:
+
+
+** NetFilter >-> HOLD target NetFilter kernel module
+
+	Interface:
+
+		NetFilter >-> HOLD target NetFilter kernel module
+
+	Label:
+
+	Name:
+
+		(*hold_target) - HOLD packets to prevent key
+		management daemon flooding
+
+	Synopsis:
+
+		static unsigned int 
+		hold_target(
+			struct sk_buff **pskb,
+			unsigned int hooknum,
+			const struct net_device *in,
+			const struct net_device *out,
+			const void *targinfo,
+			void *userinfo
+		)
+
+	Arguments:
+
+		pskb
+			skb to be processed by target
+
+        	hooknum
+			which hook from which it was called
+
+		in
+			network device it came from
+
+		out
+			network device to which it is headed
+
+		targinfo
+			data used by target for processing
+
+		userinfo
+			optional user data passed in from mainline
+			hook
+
+	Description:
+
+		This is a NetFilter target.  It discards the 
+		previous held packet and holds onto the
+		last packet packet pending replacement by an SPDB
+		change that deletes this HOLD and releases the packet.
+
+	Implementation notes:
+
+		There sound like there will be problems with this
+		because of the atomic complete replacement of the
+		table at which point any data stored with the target
+		will be lost.
+
+	Return value:
+
+		It returns NF_STOLEN.
+
+	Example:
+
+		File net/ipv4/netfilter/ipt_HOLD.c:
+		#include <linux/netfilter_ipv4/ip_tables.h>
+
+		static unsigned int
+		hold_target(struct sk_buff **pskb,
+			unsigned int hooknum,
+			const struct net_device *in,
+			const struct net_device *out,
+			const void *targinfo,
+			void *userinfo)
+		{
+			/* send up a PF_KEYv2 ACQUIRE */
+			...
+			/* create HOLD and save packet */
+			...
+			return NF_STOLEN;
+		}
+
+		static struct ipt_target hold_target_mod = {
+			{ NULL, NULL },
+			"HOLD",
+			hold_target,
+			hold_checkentry,
+			NULL,
+			THIS_MODULE
+		};
+
+		static int __init init(void)
+		{
+			if (ipt_register_target(&hold_target_mod))
+				return -EINVAL;
+			return 0;
+		}
+
+		static void __exit fini(void)
+		{
+			ipt_unregister_target(&hold_target_mod);
+		}
+
+	See also:
+
+		http://netfilter.samba.org/unreliable-guides/netfilter-hacking-HOWTO/netfilter-hacking-HOWTO.linuxdoc-4.html
+
+
+
+** KMd >-> SADB "PF_KEYv2 ADD/UPDATE"
+
+	Interface:
+
+		KMd >-> SADB "PF_KEYv2 ADD/UPDATE"
+
+	Label:
+
+		see RFC2367, PF_KEYv2 ADD/UPDATE
+
+	Name:
+
+		see RFC2367, PF_KEYv2 ADD/UPDATE
+
+	Synopsis:
+
+		see RFC2367, PF_KEYv2 ADD/UPDATE
+
+	Arguments:
+
+		see RFC2367, PF_KEYv2 ADD/UPDATE
+
+	Description:
+
+		This interface is used by key management daemons to
+		set incoming or outgoing Security Associations in the
+		kernel to/from a remote host.
+
+	Implementation notes:
+
+	Return value:
+
+		see RFC2367, PF_KEYv2 ADD/UPDATE
+
+	Example:
+
+	See also:
+
+
+
+** HOLD target NetFilter kernel module >-> NetFilter
+
+	Interface:
+
+		HOLD target NetFilter kernel module >-> NetFilter
+
+	Label:
+
+	Name:
+
+	Synopsis:
+
+	Arguments:
+
+	in:
+		struct sk_buff *skb
+
+	Description:
+
+		This interface provides a method for previously held
+		packets to be released and sent on their way once the
+		HOLD SPDB entry has been replaced or deleted, usually
+		pointing to newly created Security Associations that
+		were aquired to cover that packet stream.  (I don't
+		know the best way to show this on the diagram, since
+		the skb is stored with the eroute and not the HOLD
+		target module)
+
+	Implementation notes:
+
+	Return value:
+
+	Example:
+
+	See also:
+
+
+
+** NetFilter >-> IPSEC target NetFilter kernel module
+
+	Interface:
+
+		NetFilter >-> IPSEC target NetFilter kernel module
+
+	Label:
+
+	Name:
+
+		(*ipsec_target) - process outgoing packet with
+		specified Security Associations
+
+	Synopsis:
+
+		static unsigned int
+		ipsec_target(
+			struct sk_buff **pskb,
+			unsigned int hooknum,
+			const struct net_device *in,
+			const struct net_device *out,
+			const void *targinfo,
+			void *userinfo
+		)
+
+	Arguments:
+
+		pskb
+			skb to be processed by target
+
+        	hooknum
+			which hook from which it was called
+
+		in
+			network device it came from
+
+		out
+			network device to which it is headed
+
+		targinfo
+			data used by target for processing
+
+		userinfo
+			optional user data passed in from mainline
+			hook
+
+	Description:
+
+		This is a NetFilter target.  It looks up the Security
+		Associations listed as an argument, in the Security
+		Association DataBase, and applies them in sequence to
+		the outgoing packet.
+
+	Implementation notes:
+
+	Return value:
+
+	       It returns NF_STOLEN.
+
+	Example:
+
+		File net/ipv4/netfilter/ipt_IPSEC.c:
+		#include <linux/netfilter_ipv4/ip_tables.h>
+
+		static unsigned int
+		ipsec_target(struct sk_buff **pskb,
+			unsigned int hooknum,
+			const struct net_device *in,
+			const struct net_device *out,
+			const void *targinfo,
+			void *userinfo)
+		{
+			/* send up a PF_KEYv2 ACQUIRE */
+			...
+			/* create HOLD and save packet */
+			...
+			return NF_STOLEN;
+		}
+
+		static struct ipt_target ipsec_target_mod = {
+			{ NULL, NULL },
+			"IPSEC",
+			ipsec_target,
+			ipsec_checkentry,
+			NULL,
+			THIS_MODULE
+		};
+
+		static int __init init(void)
+		{
+			if (ipt_register_target(&ipsec_target_mod))
+				return -EINVAL;
+			return 0;
+		}
+
+		static void __exit fini(void)
+		{
+			ipt_unregister_target(&ipsec_target_mod);
+		}
+
+	See also:
+
+		http://netfilter.samba.org/unreliable-guides/netfilter-hacking-HOWTO/netfilter-hacking-HOWTO.linuxdoc-4.html
+
+
+
+** IPSEC target NetFilter kernel module >-> SADB "SAID"
+
+	Interface:
+
+		IPSEC target NetFilter kernel module >-> SADB
+
+	Label: 
+
+		SAID
+
+	Name:
+
+		ipsec_getsa - get an SA from the SADB by SAID
+
+	Synopsis: 
+
+		#include <ipsec_sadb.h>
+
+		struct ipsec_sa *
+		ipsec_getsa(
+			struct ipsec_said asaid
+		);
+
+	Arguments:
+
+		asaid
+			Security Association IDentifier to try to
+			match in SADB
+
+
+	Description:
+
+		Retrieve a Security Association from the system
+		Security Association DataBase that matches the
+		supplied Security Association IDentifier.
+
+		The Security Association IDentifier must be supplied
+		as a completely filled struct ipsec_said.  ipsec_getsa() attempts
+		to exactly match the SAID structure of an SA
+		entry in the global SADB hash table ipsec_sadb with
+		the SAID argument.  If this succeeds, 
+		a pointer to the matching SA is returned.
+
+	Implementation notes:
+
+		The reference count of the matching SA is atomically
+		incremented by ipsec_getsa() and must be atomically
+		decremented when the caller of ipsec_getsa() has
+		finished with the SA.
+
+		The global SADB hash table struct
+		ipsec_sa*ipsec_sadb[] is locked by ipsec_getsa()
+		during lookup.
+
+	Return values:
+
+		A pointer to a valid Security Association is returned
+		if a match was found, otherwise NULL is returned.
+
+	Example:
+
+		struct ipsec_sa *sa;
+		struct ipsec_said said;
+		...
+		sa = ipsec_getsa(said);
+		...
+		if(atomic_dec_and_test(sa->refcount)) {
+			ipsec_sa_free(sa);
+		}
+
+	See also:
+
+
+
+** IPSEC target NetFilter kernel module >-> NetFilter
+
+	Interface:
+
+		IPSEC target NetFilter kernel module >-> NetFilter
+
+	Label:
+
+	Name:
+
+		nf_reinject - re-inject a packet at one of the
+		netfilter hooks
+
+	Synopsis:
+
+		void
+		nf_reinject(
+			struct sk_buff *skb,
+			struct nf_info *info,
+			unsigned int verdict
+		)
+
+	Arguments:
+
+		skb
+			packet to be re-injected
+
+		info
+
+		verdict
+			verdict to be returned to netfilter hook
+
+	Description:
+
+		This interface is to re-inject packets to
+		NF_IP_LOCAL_OUT after the packet has been processed.
+
+	Implementation notes:
+
+	Return value:
+
+		none (void)
+
+	Example:
+
+		skb->salist = struct salist
+
+	See also:
+
+		http://netfilter.samba.org/unreliable-guides/netfilter-hacking-HOWTO/netfilter-hacking-HOWTO.linuxdoc-4.html
+
+
+
+** SADB >-> KMd "PF_KEYv2 EXPIRE"
+
+	Interface:
+
+		SADB >-> KMd "PF_KEYv2 EXPIRE"
+
+	Label:
+
+		see RFC2367, PF_KEYv2 EXPIRE
+
+	Name:
+
+		see RFC2367, PF_KEYv2 EXPIRE
+
+	Synopsis:
+
+		see RFC2367, PF_KEYv2 EXPIRE
+
+	Arguments:
+
+		see RFC2367, PF_KEYv2 EXPIRE
+
+	Description:
+
+		This interface is used by the kernel to notify key
+		management daemons that a security association has
+		either soft or hard expired and to negotiate a
+		replacement.
+
+	Implementation notes:
+
+	Return value:
+
+		see RFC2367, PF_KEYv2 EXPIRE
+
+	Example:
+
+	See also:
+
+
+** Routing Table >-> IPSEC target NetFilter kernel module "IPSECdev"
+
+	Interface:
+
+		Routing Table >-> IPSEC target NetFilter kernel module
+
+	Label:
+
+		 "IPSECdev"
+
+	Name:
+
+	Synopsis:
+
+	Arguments:
+
+	Description:
+
+		This interface provides a way of routing packets
+		through a specific IPSec virtual tunnel.  This is
+		standard linux network routing.
+
+	Implementation notes:
+
+	Return value:
+
+	Example:
+
+	See also:
+
+
+
+** KMd >-> Routing Table "Routing"
+
+	Interface:
+
+		KMd >-> Routing Table
+
+	Label:
+
+		"Routing"
+
+	Name:
+
+		system(3) call to route(8) - execute a shell
+		command to do IP packet routing administration to set
+		ipsec policy
+
+	Synopsis:
+
+		#include <stdlib.h>
+
+		int
+		system(
+			const char * "route \
+			{add,del} -{host,net} \
+			{<host>,<net>[/mask]} \
+			gw <gateway> \
+			dev <device> \
+		");
+
+	Arguments:
+
+		add
+			add an entry to the routing table
+
+		del
+			delete an entry from the routing table
+
+		-host
+			add or delete a host
+
+		-net
+			add or delete a network
+
+		<host>
+			host FQDN or IPv4 or IPv6 address
+
+		<net>[/mask]
+			network FQDN or IPv4 or IPv6 address with netmask
+
+		gw <gateway>
+			nexthop gateway address
+
+		dev <device>
+
+		char[] IPSECdev
+		unsigned char exit_code
+
+	Description:
+
+		This is an interface from the key management daemon to
+		explicitly route traffic through an IPSEC virtual
+		device which is defined by a pair of IPSEC tunnel
+		endpoints and a set of Security Associations.
+
+	Implementation notes:
+
+		currently done by system(3) calls to _updown.
+
+	Return value:
+
+	Example:
+
+	See also:
+
+		system(3), route(8), iproute2(8)
+
+
+
+** Transport Layer De-mux >-> IPSec DECRYPT kernel module
+
+	Interface:
+
+		Transport Layer De-mux >-> IPSec DECRYPT kernel module
+
+	Label:
+
+	Name:
+
+		ipsec_rcv - process an incoming IPSec packet
+	Synopsis:
+		
+		#include <ipsec_rcv.h>
+
+		int
+		ipsec_rcv(
+			struct sk_buff *skb,
+			unsigned short xlen
+		)
+
+	Arguments:
+
+		skb
+			skb to be processed
+
+		xlen
+			length of skb buffer
+
+	Description:
+
+		This interface is to call the IPSEC ESP transport
+		layer protocol handler to process (decrypt) an
+		incoming packet.
+
+		The packet is freed, being re-injected into the
+		NF_IP_PRE_ROUTING hook.
+
+	Implementation notes:
+
+	Return value:
+
+	       ipsec_rcv() returns zero (0).
+
+	Example:
+
+	See also:
+
+
+** IPSec DECRYPT kernel module >-> SADB "SAID"
+
+	Interface:
+
+		IPSec DECRYPT kernel module >-> SADB
+
+	Label:
+
+		see "SAID"
+
+	Name:
+
+		ipsec_getsa - get an SA from the SADB by SAID
+
+	Synopsis:
+
+		#include <ipsec_sadb.h>
+
+		struct ipsec_sa *
+		ipsec_getsa(
+			struct ipsec_said asaid
+		)
+
+	Arguments:
+
+		asaid
+			Security Association IDentifier to try to
+			match in SADB
+
+	Description:
+
+	Implementation notes:
+
+	Return value:
+
+	Example:
+
+	See also:
+
+		IPSEC target NetFilter kernel module >-> SADB "SAID"
+
+
+** IPSec DECRYPT kernel module >-> NetFilter
+
+	Interface:
+
+		IPSec DECRYPT kernel module >-> NetFilter
+
+	Label:
+
+	Name:
+
+		nf_reinject - re-inject a packet at one of the
+		netfilter hooks
+
+	Synopsis:
+
+		void
+		nf_reinject(
+			struct sk_buff *skb,
+			struct nf_info *info,
+			unsigned int verdict
+		)
+
+	Arguments:
+
+			skb
+				packet to be re-injected
+
+			info
+
+			verdict
+				verdict to be returned to netfilter hook
+
+	Description:
+
+		This interface is to re-inject the processed packet
+		back into the input stream at NF_IP_PRE_ROUTE to check
+		policy with processed (decrypted) connection
+		information.
+
+	Implementation notes:
+
+	Return value:
+
+		none (void)
+
+	Example:
+
+		skb->salist = struct salist
+
+	See also:
+
+
+** NetFilter >-> PEEK target NetFilter kernel module
+
+	Interface:
+
+		NetFilter >-> PEEK target NetFilter kernel module
+
+	Label:
+
+	Name:
+
+		(*peek_target) - PEEK at packets to initiate opportunism
+
+	Synopsis:
+
+		static unsigned int
+		peek_target(
+			struct sk_buff **pskb,
+			unsigned int hooknum,
+			const struct net_device *in,
+			const struct net_device *out,
+			const void *targinfo,
+			void *userinfo
+		)
+
+	Arguments:
+
+		pskb
+			skb to be processed by target
+
+        	hooknum
+			which hook from which it was called
+
+		in
+			network device it came from
+
+		out
+			network device to which it is headed
+
+		targinfo
+			data used by target for processing
+
+		userinfo
+			optional user data passed in from mainline
+			hook
+
+	Description:
+
+		This interface is used by the kernel netfilter table
+		as a target for packets to be PEEKed at to notify the
+		key management daemons to acquire a new set of
+		Security Associations and to set up an ACCEPT to allow
+		packets in and avoid overloading the KMds.
+
+	Implementation notes:
+
+	Return value:
+
+		It returns NF_ACCEPT.
+
+	Example:
+
+		File net/ipv4/netfilter/ipt_PEEK.c:
+		#include <linux/netfilter_ipv4/ip_tables.h>
+
+		static unsigned int
+		peek_target(struct sk_buff **pskb,
+			unsigned int hooknum,
+			const struct net_device *in,
+			const struct net_device *out,
+			const void *targinfo,
+			void *userinfo)
+		{
+			/* send up a PF_KEYv2 ACQUIRE */
+			...
+			/* create HOLD and save packet */
+			...
+			return NF_STOLEN;
+		}
+
+		static struct ipt_target peek_target_mod =
+		{ { NULL, NULL }, "PEEK", peek_target, peek_checkentry, NULL,
+			THIS_MODULE };
+
+		static int __init init(void)
+		{
+			if (ipt_register_target(&peek_target_mod))
+				return -EINVAL;
+			return 0;
+		}
+
+		static void __exit fini(void)
+		{
+			ipt_unregister_target(&peek_target_mod);
+		}
+
+	See also:
+
+		http://netfilter.samba.org/unreliable-guides/netfilter-hacking-HOWTO/netfilter-hacking-HOWTO.linuxdoc-4.html
+
+
+
+** PEEK target NetFilter kernel module >-> KMds "PF_KEYv2 ACQUIRE"
+
+	Interface:
+
+		PEEK target NetFilter kernel module >-> KMds
+
+	Label:
+
+		"PF_KEYv2 ACQUIRE"
+
+	Name:
+
+		see RFC2367, PF_KEYv2 ACQUIRE
+
+	Synopsis:
+
+		see RFC2367, PF_KEYv2 ACQUIRE
+
+	Arguments:
+
+		see RFC2367, PF_KEYv2 ACQUIRE
+
+	Description:
+
+		This interface is used to make requests from the
+		kernel to key management daemons for a set of Security
+		Associations to cover the specified traffic named to a
+		remote host.
+
+	Implementation notes:
+
+	Return value:
+
+		see RFC2367, PF_KEYv2 ACQUIRE
+
+	Example:
+
+	See also:
+
+		see RFC2367, PF_KEYv2 ACQUIRE
+
+
+
+** PEEK target NetFilter kernel module >-> NetFilter
+
+	Interface:
+
+		PEEK target NetFilter kernel module >-> NetFilter
+
+	Label:
+
+	Name:
+
+	Synopsis:
+
+	Arguments:
+
+	in:
+		struct sk_buff *skb
+	out:
+		boolean
+
+	Description:
+
+		This interface is to provide a way to install an
+		ACCEPT target to avoid overloading the KMds while they
+		are negotiating.
+
+	Implementation notes:
+
+	Return value:
+
+	Example:
+
+	See also:
+
+
+
+
+** New I/F section template
+
+	Interface:
+
+	Label:
+
+	Name:
+
+	Synopsis:
+
+	Arguments:
+
+	Description:
+
+	Implementation notes:
+
+	Return value:
+
+	Example:
+
+	See also:
+
+
+
+
+* Definitions and Data structures used
+
+SAList := <SAID>[,<SAID>[,<SAID>[,<SAID>]]]
+
+<SAID> := <proto><PF><spi>@<dstaddr>
+
+<proto> := ah | esp | comp | tun
+
+<PF> := . | : (indicates IPv4 or IPv6 respectively)
+
+<spi> := <8-digit hexadecimal string>
+
+<dstaddr> := <any valid FQDN or IP address of the appropriate family>
+
+
+const struct ipt_entry is already defined in netfilter.
+
+struct ipt_entry_match is already defined in netfilter.
+
+struct ipsec_seclev remains to be defined.
+
+struct ipt_seclev_info {
+	struct ipsec_seclev;		/* Security Level data */
+	u_int8_t  invert;	/* Invert match */
+};
+
+struct ipsec_salist {
+	struct ipsec_said said1;
+	struct ipsec_said said2;
+	struct ipsec_said said3;
+	struct ipsec_said said4;
+}
+
+struct ipt_salist_info {
+	struct ipsec_salist salist;	/* Security Association List data */
+	u_int8_t  invert;	/* Invert match */
+};
+
+struct ipt_ipsec_target_info {
+	struct ipsec_said said1;
+	struct ipsec_said said2;
+	struct ipsec_said said3;
+	struct ipsec_said said4;
+};
+
+struct ipsec_said{		/* 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
+	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 */
+};
+
+typedef struct {
+	union {
+		struct sockaddr_in v4;
+		struct sockaddr_in6 v6;
+	} u;
+} ip_address;
+
+struct ipsec_sa {
+	/* copy most from struct tdb */
+};
+
+struct ipsecinfo {
+	struct ipt_entry_target t;
+	struct ipt_ipsec_target_info salist;
+};
+
+struct trapinfo {
+	struct ipt_entry_target t;
+};
+
+struct peekinfo {
+	struct ipt_entry_target t;
+};
+
+struct holdinfo {
+	struct ipt_entry_target t;
+};
+
+* Version:
+
+	$Id: klips2-design-api.txt,v 1.17 2001/06/01 07:25:53 rgb Exp $
diff -bruN freeswan-1.9.orig/klips/doc/klips2-design-legend.txt freeswan-1.9/klips/doc/klips2-design-legend.txt
--- freeswan-1.9.orig/klips/doc/klips2-design-legend.txt	Wed Dec 31 19:00:00 1969
+++ freeswan-1.9/klips/doc/klips2-design-legend.txt	Mon Jun  4 12:54:57 2001
@@ -0,0 +1,46 @@
+#  -*- mode: Outline; fill-column: 78; fill-prefix: "	" -*-
+#
+#  klips2-design-legend.txt
+#	Richard Guy Briggs <rgb@conscoop.ottawa.on.ca>
+#
+#  RCSID $Id: klips2-design-legend.txt,v 1.7 2001/05/29 18:52:12 rgb Exp $
+#
+
+# This document is a legend of labels and acronyms on the diagram.  It
+# also acts as a very brief glossary to the rest of the klips2-design
+# documents.  Please see klips2-design.txt for an overview.
+
+# The first column contains the acronym or label used.  It is followed
+# by the acronym written out in full or a very brief description.
+
+
+KMd-1...n	Key Management Daemons 1 to n
+Routing		Routing Table kernel interface
+Policy		SPDB KMd interface
+seclev		Match Packet Security Level (not yet implemented in Linux)
+SADDR		Match Packet Source Address
+DADDR		Match Packet Destination Address
+SMASK		Match Packet Source Address Network Mask
+DMASK		Match Packet Destination Address Network Mask
+SPORT		Match Packet Transport Layer Source Port Number
+DPORT		Match Packet Transport Layer Destination Port Number
+UID		Match Packet User IDentifier
+SA		Security Association
+SAList		Security Association List
+SAID		Security Association IDentifier
+TDB		Tunnel Descriptor Block
+ESP		Encapsulating Security Payload
+IPSECdev	IPSEC virtual tunnel device
+SADB		Security Association DataBase
+SPDB		Security Policy DataBase
+SPI		Security Parameters Index
+get/set_sockopt	get or set socket options
+DROP		Target DROP Packet
+ACCEPT		Target ACCEPT Packet
+REJECT		Target REJECT Packet
+TRAP		Target TRAP Packet
+HOLD		Target HOLD Packet
+PEEK		Target PEEK Packet
+IPSEC		Target IPSEC Packet
+__..__..	PF_KEYv2 communication path
+___.___.	User/Kernel Space demarcation
diff -bruN freeswan-1.9.orig/klips/doc/klips2-design.dia freeswan-1.9/klips/doc/klips2-design.dia
--- freeswan-1.9.orig/klips/doc/klips2-design.dia	Wed Dec 31 19:00:00 1969
+++ freeswan-1.9/klips/doc/klips2-design.dia	Mon Jun  4 12:54:57 2001
@@ -0,0 +1,4316 @@
+<?xml version="1.0"?>
+<diagram xmlns:dia="http://www.lysator.liu.se/~alla/dia/">
+  <diagramdata>
+    <attribute name="background">
+      <color val="#ffffff"/>
+    </attribute>
+    <attribute name="paper">
+      <composite type="paper">
+        <attribute name="name">
+          <string>#A4#</string>
+        </attribute>
+        <attribute name="tmargin">
+          <real val="2.8222"/>
+        </attribute>
+        <attribute name="bmargin">
+          <real val="2.8222"/>
+        </attribute>
+        <attribute name="lmargin">
+          <real val="2.8222"/>
+        </attribute>
+        <attribute name="rmargin">
+          <real val="2.8222"/>
+        </attribute>
+        <attribute name="is_portrait">
+          <boolean val="false"/>
+        </attribute>
+        <attribute name="scaling">
+          <real val="0.629413"/>
+        </attribute>
+        <attribute name="fitto">
+          <boolean val="true"/>
+        </attribute>
+        <attribute name="fitwidth">
+          <int val="2"/>
+        </attribute>
+        <attribute name="fitheight">
+          <int val="2"/>
+        </attribute>
+      </composite>
+    </attribute>
+  </diagramdata>
+  <layer name="Background" visible="true">
+    <object type="Standard - Box" version="0" id="O0">
+      <attribute name="obj_pos">
+        <point val="7,11"/>
+      </attribute>
+      <attribute name="obj_bb">
+        <rectangle val="6.95,10.95;11.05,13.05"/>
+      </attribute>
+      <attribute name="elem_corner">
+        <point val="7,11"/>
+      </attribute>
+      <attribute name="elem_width">
+        <real val="4"/>
+      </attribute>
+      <attribute name="elem_height">
+        <real val="2"/>
+      </attribute>
+      <attribute name="show_background">
+        <boolean val="true"/>
+      </attribute>
+    </object>
+    <object type="Standard - Box" version="0" id="O1">
+      <attribute name="obj_pos">
+        <point val="-5,2"/>
+      </attribute>
+      <attribute name="obj_bb">
+        <rectangle val="-5.05,1.95;5.05,14.05"/>
+      </attribute>
+      <attribute name="elem_corner">
+        <point val="-5,2"/>
+      </attribute>
+      <attribute name="elem_width">
+        <real val="10"/>
+      </attribute>
+      <attribute name="elem_height">
+        <real val="12"/>
+      </attribute>
+      <attribute name="show_background">
+        <boolean val="true"/>
+      </attribute>
+    </object>
+    <object type="Standard - Box" version="0" id="O2">
+      <attribute name="obj_pos">
+        <point val="-5,-13"/>
+      </attribute>
+      <attribute name="obj_bb">
+        <rectangle val="-5.05,-13.05;5.05,-3.95"/>
+      </attribute>
+      <attribute name="elem_corner">
+        <point val="-5,-13"/>
+      </attribute>
+      <attribute name="elem_width">
+        <real val="10"/>
+      </attribute>
+      <attribute name="elem_height">
+        <real val="9"/>
+      </attribute>
+      <attribute name="show_background">
+        <boolean val="true"/>
+      </attribute>
+    </object>
+    <object type="Standard - Box" version="0" id="O3">
+      <attribute name="obj_pos">
+        <point val="-2.05,-11"/>
+      </attribute>
+      <attribute name="obj_bb">
+        <rectangle val="-2.1,-11.05;-1.85,-10.95"/>
+      </attribute>
+      <attribute name="elem_corner">
+        <point val="-2.05,-11"/>
+      </attribute>
+      <attribute name="elem_width">
+        <real val="0.15"/>
+      </attribute>
+      <attribute name="elem_height">
+        <real val="8.88178e-16"/>
+      </attribute>
+      <attribute name="show_background">
+        <boolean val="true"/>
+      </attribute>
+    </object>
+    <object type="Standard - Box" version="0" id="O4">
+      <attribute name="obj_pos">
+        <point val="-5,-11"/>
+      </attribute>
+      <attribute name="obj_bb">
+        <rectangle val="-5.05,-11.05;-0.95,-9.95"/>
+      </attribute>
+      <attribute name="elem_corner">
+        <point val="-5,-11"/>
+      </attribute>
+      <attribute name="elem_width">
+        <real val="4"/>
+      </attribute>
+      <attribute name="elem_height">
+        <real val="1"/>
+      </attribute>
+      <attribute name="show_background">
+        <boolean val="true"/>
+      </attribute>
+    </object>
+    <object type="Standard - Box" version="0" id="O5">
+      <attribute name="obj_pos">
+        <point val="-5,-10"/>
+      </attribute>
+      <attribute name="obj_bb">
+        <rectangle val="-5.05,-10.05;-0.95,-8.95"/>
+      </attribute>
+      <attribute name="elem_corner">
+        <point val="-5,-10"/>
+      </attribute>
+      <attribute name="elem_width">
+        <real val="4"/>
+      </attribute>
+      <attribute name="elem_height">
+        <real val="1"/>
+      </attribute>
+      <attribute name="show_background">
+        <boolean val="true"/>
+      </attribute>
+    </object>
+    <object type="Standard - Box" version="0" id="O6">
+      <attribute name="obj_pos">
+        <point val="-5,-9"/>
+      </attribute>
+      <attribute name="obj_bb">
+        <rectangle val="-5.05,-9.05;-0.95,-7.95"/>
+      </attribute>
+      <attribute name="elem_corner">
+        <point val="-5,-9"/>
+      </attribute>
+      <attribute name="elem_width">
+        <real val="4"/>
+      </attribute>
+      <attribute name="elem_height">
+        <real val="1"/>
+      </attribute>
+      <attribute name="show_background">
+        <boolean val="true"/>
+      </attribute>
+    </object>
+    <object type="Standard - Box" version="0" id="O7">
+      <attribute name="obj_pos">
+        <point val="-5,-8"/>
+      </attribute>
+      <attribute name="obj_bb">
+        <rectangle val="-5.05,-8.05;-0.95,-6.95"/>
+      </attribute>
+      <attribute name="elem_corner">
+        <point val="-5,-8"/>
+      </attribute>
+      <attribute name="elem_width">
+        <real val="4"/>
+      </attribute>
+      <attribute name="elem_height">
+        <real val="1"/>
+      </attribute>
+      <attribute name="show_background">
+        <boolean val="true"/>
+      </attribute>
+    </object>
+    <object type="Standard - Box" version="0" id="O8">
+      <attribute name="obj_pos">
+        <point val="-5,-7"/>
+      </attribute>
+      <attribute name="obj_bb">
+        <rectangle val="-5.05,-7.05;-0.95,-5.95"/>
+      </attribute>
+      <attribute name="elem_corner">
+        <point val="-5,-7"/>
+      </attribute>
+      <attribute name="elem_width">
+        <real val="4"/>
+      </attribute>
+      <attribute name="elem_height">
+        <real val="1"/>
+      </attribute>
+      <attribute name="show_background">
+        <boolean val="true"/>
+      </attribute>
+    </object>
+    <object type="Standard - Box" version="0" id="O9">
+      <attribute name="obj_pos">
+        <point val="-5,-6"/>
+      </attribute>
+      <attribute name="obj_bb">
+        <rectangle val="-5.05,-6.05;-0.95,-4.95"/>
+      </attribute>
+      <attribute name="elem_corner">
+        <point val="-5,-6"/>
+      </attribute>
+      <attribute name="elem_width">
+        <real val="4"/>
+      </attribute>
+      <attribute name="elem_height">
+        <real val="1"/>
+      </attribute>
+      <attribute name="show_background">
+        <boolean val="true"/>
+      </attribute>
+    </object>
+    <object type="Standard - Box" version="0" id="O10">
+      <attribute name="obj_pos">
+        <point val="-5,-5"/>
+      </attribute>
+      <attribute name="obj_bb">
+        <rectangle val="-5.05,-5.05;-0.95,-3.95"/>
+      </attribute>
+      <attribute name="elem_corner">
+        <point val="-5,-5"/>
+      </attribute>
+      <attribute name="elem_width">
+        <real val="4"/>
+      </attribute>
+      <attribute name="elem_height">
+        <real val="1"/>
+      </attribute>
+      <attribute name="show_background">
+        <boolean val="true"/>
+      </attribute>
+    </object>
+    <object type="Standard - Text" version="0" id="O11">
+      <attribute name="obj_pos">
+        <point val="-3,-10"/>
+      </attribute>
+      <attribute name="obj_bb">
+        <rectangle val="-4.615,-10.7434;-1.385,-9.74336"/>
+      </attribute>
+      <attribute name="text">
+        <composite type="text">
+          <attribute name="string">
+            <string>#SADDR#</string>
+          </attribute>
+          <attribute name="font">
+            <font name="Courier"/>
+          </attribute>
+          <attribute name="height">
+            <real val="1"/>
+          </attribute>
+          <attribute name="pos">
+            <point val="-3,-10"/>
+          </attribute>
+          <attribute name="color">
+            <color val="#000000"/>
+          </attribute>
+          <attribute name="alignment">
+            <enum val="1"/>
+          </attribute>
+        </composite>
+      </attribute>
+      <connections>
+        <connection handle="0" to="O4" connection="6"/>
+      </connections>
+    </object>
+    <object type="Standard - Text" version="0" id="O12">
+      <attribute name="obj_pos">
+        <point val="-3,-9"/>
+      </attribute>
+      <attribute name="obj_bb">
+        <rectangle val="-4.615,-9.74336;-1.385,-8.74336"/>
+      </attribute>
+      <attribute name="text">
+        <composite type="text">
+          <attribute name="string">
+            <string>#DADDR#</string>
+          </attribute>
+          <attribute name="font">
+            <font name="Courier"/>
+          </attribute>
+          <attribute name="height">
+            <real val="1"/>
+          </attribute>
+          <attribute name="pos">
+            <point val="-3,-9"/>
+          </attribute>
+          <attribute name="color">
+            <color val="#000000"/>
+          </attribute>
+          <attribute name="alignment">
+            <enum val="1"/>
+          </attribute>
+        </composite>
+      </attribute>
+      <connections>
+        <connection handle="0" to="O5" connection="6"/>
+      </connections>
+    </object>
+    <object type="Standard - Text" version="0" id="O13">
+      <attribute name="obj_pos">
+        <point val="-3,-8"/>
+      </attribute>
+      <attribute name="obj_bb">
+        <rectangle val="-4.615,-8.74336;-1.385,-7.74336"/>
+      </attribute>
+      <attribute name="text">
+        <composite type="text">
+          <attribute name="string">
+            <string>#SMASK#</string>
+          </attribute>
+          <attribute name="font">
+            <font name="Courier"/>
+          </attribute>
+          <attribute name="height">
+            <real val="1"/>
+          </attribute>
+          <attribute name="pos">
+            <point val="-3,-8"/>
+          </attribute>
+          <attribute name="color">
+            <color val="#000000"/>
+          </attribute>
+          <attribute name="alignment">
+            <enum val="1"/>
+          </attribute>
+        </composite>
+      </attribute>
+      <connections>
+        <connection handle="0" to="O6" connection="6"/>
+      </connections>
+    </object>
+    <object type="Standard - Text" version="0" id="O14">
+      <attribute name="obj_pos">
+        <point val="-3,-7"/>
+      </attribute>
+      <attribute name="obj_bb">
+        <rectangle val="-4.615,-7.74336;-1.385,-6.74336"/>
+      </attribute>
+      <attribute name="text">
+        <composite type="text">
+          <attribute name="string">
+            <string>#DMASK#</string>
+          </attribute>
+          <attribute name="font">
+            <font name="Courier"/>
+          </attribute>
+          <attribute name="height">
+            <real val="1"/>
+          </attribute>
+          <attribute name="pos">
+            <point val="-3,-7"/>
+          </attribute>
+          <attribute name="color">
+            <color val="#000000"/>
+          </attribute>
+          <attribute name="alignment">
+            <enum val="1"/>
+          </attribute>
+        </composite>
+      </attribute>
+      <connections>
+        <connection handle="0" to="O7" connection="6"/>
+      </connections>
+    </object>
+    <object type="Standard - Text" version="0" id="O15">
+      <attribute name="obj_pos">
+        <point val="-3,-6"/>
+      </attribute>
+      <attribute name="obj_bb">
+        <rectangle val="-4.615,-6.74336;-1.385,-5.74336"/>
+      </attribute>
+      <attribute name="text">
+        <composite type="text">
+          <attribute name="string">
+            <string>#SPORT#</string>
+          </attribute>
+          <attribute name="font">
+            <font name="Courier"/>
+          </attribute>
+          <attribute name="height">
+            <real val="1"/>
+          </attribute>
+          <attribute name="pos">
+            <point val="-3,-6"/>
+          </attribute>
+          <attribute name="color">
+            <color val="#000000"/>
+          </attribute>
+          <attribute name="alignment">
+            <enum val="1"/>
+          </attribute>
+        </composite>
+      </attribute>
+      <connections>
+        <connection handle="0" to="O8" connection="6"/>
+      </connections>
+    </object>
+    <object type="Standard - Text" version="0" id="O16">
+      <attribute name="obj_pos">
+        <point val="-3,-5"/>
+      </attribute>
+      <attribute name="obj_bb">
+        <rectangle val="-4.615,-5.74336;-1.385,-4.74336"/>
+      </attribute>
+      <attribute name="text">
+        <composite type="text">
+          <attribute name="string">
+            <string>#DPORT#</string>
+          </attribute>
+          <attribute name="font">
+            <font name="Courier"/>
+          </attribute>
+          <attribute name="height">
+            <real val="1"/>
+          </attribute>
+          <attribute name="pos">
+            <point val="-3,-5"/>
+          </attribute>
+          <attribute name="color">
+            <color val="#000000"/>
+          </attribute>
+          <attribute name="alignment">
+            <enum val="1"/>
+          </attribute>
+        </composite>
+      </attribute>
+      <connections>
+        <connection handle="0" to="O9" connection="6"/>
+      </connections>
+    </object>
+    <object type="Standard - Text" version="0" id="O17">
+      <attribute name="obj_pos">
+        <point val="-3,-4"/>
+      </attribute>
+      <attribute name="obj_bb">
+        <rectangle val="-4.009,-4.74336;-1.991,-3.74336"/>
+      </attribute>
+      <attribute name="text">
+        <composite type="text">
+          <attribute name="string">
+            <string>#UID#</string>
+          </attribute>
+          <attribute name="font">
+            <font name="Courier"/>
+          </attribute>
+          <attribute name="height">
+            <real val="1"/>
+          </attribute>
+          <attribute name="pos">
+            <point val="-3,-4"/>
+          </attribute>
+          <attribute name="color">
+            <color val="#000000"/>
+          </attribute>
+          <attribute name="alignment">
+            <enum val="1"/>
+          </attribute>
+        </composite>
+      </attribute>
+      <connections>
+        <connection handle="0" to="O10" connection="6"/>
+      </connections>
+    </object>
+    <object type="Standard - Box" version="0" id="O18">
+      <attribute name="obj_pos">
+        <point val="8,18"/>
+      </attribute>
+      <attribute name="obj_bb">
+        <rectangle val="7.95,17.95;22.05,20.05"/>
+      </attribute>
+      <attribute name="elem_corner">
+        <point val="8,18"/>
+      </attribute>
+      <attribute name="elem_width">
+        <real val="14"/>
+      </attribute>
+      <attribute name="elem_height">
+        <real val="2"/>
+      </attribute>
+      <attribute name="show_background">
+        <boolean val="true"/>
+      </attribute>
+    </object>
+    <object type="Standard - Text" version="0" id="O19">
+      <attribute name="obj_pos">
+        <point val="-20,-26"/>
+      </attribute>
+      <attribute name="obj_bb">
+        <rectangle val="-20,-26.7434;20.802,-25.7434"/>
+      </attribute>
+      <attribute name="text">
+        <composite type="text">
+          <attribute name="string">
+            <string>#Snapshot and Release document location: klips/doc/klips2-design.dia#</string>
+          </attribute>
+          <attribute name="font">
+            <font name="Courier"/>
+          </attribute>
+          <attribute name="height">
+            <real val="1"/>
+          </attribute>
+          <attribute name="pos">
+            <point val="-20,-26"/>
+          </attribute>
+          <attribute name="color">
+            <color val="#000000"/>
+          </attribute>
+          <attribute name="alignment">
+            <enum val="0"/>
+          </attribute>
+        </composite>
+      </attribute>
+    </object>
+    <object type="Standard - Box" version="0" id="O20">
+      <attribute name="obj_pos">
+        <point val="7,8"/>
+      </attribute>
+      <attribute name="obj_bb">
+        <rectangle val="6.95,7.95;11.05,10.05"/>
+      </attribute>
+      <attribute name="elem_corner">
+        <point val="7,8"/>
+      </attribute>
+      <attribute name="elem_width">
+        <real val="4"/>
+      </attribute>
+      <attribute name="elem_height">
+        <real val="2"/>
+      </attribute>
+      <attribute name="show_background">
+        <boolean val="true"/>
+      </attribute>
+    </object>
+    <object type="Standard - Box" version="0" id="O21">
+      <attribute name="obj_pos">
+        <point val="-1.05,-12"/>
+      </attribute>
+      <attribute name="obj_bb">
+        <rectangle val="-1.1,-12.05;-0.85,-11.95"/>
+      </attribute>
+      <attribute name="elem_corner">
+        <point val="-1.05,-12"/>
+      </attribute>
+      <attribute name="elem_width">
+        <real val="0.15"/>
+      </attribute>
+      <attribute name="elem_height">
+        <real val="8.88178e-16"/>
+      </attribute>
+      <attribute name="show_background">
+        <boolean val="true"/>
+      </attribute>
+    </object>
+    <object type="Standard - Text" version="0" id="O22">
+      <attribute name="obj_pos">
+        <point val="0,-12"/>
+      </attribute>
+      <attribute name="obj_bb">
+        <rectangle val="-3.433,-12.7434;3.433,-11.7434"/>
+      </attribute>
+      <attribute name="text">
+        <composite type="text">
+          <attribute name="string">
+            <string>#iptables(8)#</string>
+          </attribute>
+          <attribute name="font">
+            <font name="Courier"/>
+          </attribute>
+          <attribute name="height">
+            <real val="1"/>
+          </attribute>
+          <attribute name="pos">
+            <point val="0,-12"/>
+          </attribute>
+          <attribute name="color">
+            <color val="#000000"/>
+          </attribute>
+          <attribute name="alignment">
+            <enum val="1"/>
+          </attribute>
+        </composite>
+      </attribute>
+    </object>
+    <object type="Standard - Box" version="0" id="O23">
+      <attribute name="obj_pos">
+        <point val="1,-7"/>
+      </attribute>
+      <attribute name="obj_bb">
+        <rectangle val="0.95,-7.05;5.05,-5.95"/>
+      </attribute>
+      <attribute name="elem_corner">
+        <point val="1,-7"/>
+      </attribute>
+      <attribute name="elem_width">
+        <real val="4"/>
+      </attribute>
+      <attribute name="elem_height">
+        <real val="1"/>
+      </attribute>
+      <attribute name="show_background">
+        <boolean val="true"/>
+      </attribute>
+    </object>
+    <object type="Standard - Box" version="0" id="O24">
+      <attribute name="obj_pos">
+        <point val="1,-6"/>
+      </attribute>
+      <attribute name="obj_bb">
+        <rectangle val="0.95,-6.05;5.05,-4.95"/>
+      </attribute>
+      <attribute name="elem_corner">
+        <point val="1,-6"/>
+      </attribute>
+      <attribute name="elem_width">
+        <real val="4"/>
+      </attribute>
+      <attribute name="elem_height">
+        <real val="1"/>
+      </attribute>
+      <attribute name="show_background">
+        <boolean val="true"/>
+      </attribute>
+    </object>
+    <object type="Standard - Box" version="0" id="O25">
+      <attribute name="obj_pos">
+        <point val="1,-5"/>
+      </attribute>
+      <attribute name="obj_bb">
+        <rectangle val="0.95,-5.05;5.05,-3.95"/>
+      </attribute>
+      <attribute name="elem_corner">
+        <point val="1,-5"/>
+      </attribute>
+      <attribute name="elem_width">
+        <real val="4"/>
+      </attribute>
+      <attribute name="elem_height">
+        <real val="1"/>
+      </attribute>
+      <attribute name="show_background">
+        <boolean val="true"/>
+      </attribute>
+    </object>
+    <object type="Standard - Text" version="0" id="O26">
+      <attribute name="obj_pos">
+        <point val="3,-6"/>
+      </attribute>
+      <attribute name="obj_bb">
+        <rectangle val="1.688,-6.74336;4.312,-5.74336"/>
+      </attribute>
+      <attribute name="text">
+        <composite type="text">
+          <attribute name="string">
+            <string>#DROP#</string>
+          </attribute>
+          <attribute name="font">
+            <font name="Courier"/>
+          </attribute>
+          <attribute name="height">
+            <real val="1"/>
+          </attribute>
+          <attribute name="pos">
+            <point val="3,-6"/>
+          </attribute>
+          <attribute name="color">
+            <color val="#000000"/>
+          </attribute>
+          <attribute name="alignment">
+            <enum val="1"/>
+          </attribute>
+        </composite>
+      </attribute>
+      <connections>
+        <connection handle="0" to="O23" connection="6"/>
+      </connections>
+    </object>
+    <object type="Standard - Text" version="0" id="O27">
+      <attribute name="obj_pos">
+        <point val="3,-5"/>
+      </attribute>
+      <attribute name="obj_bb">
+        <rectangle val="1.082,-5.74336;4.918,-4.74336"/>
+      </attribute>
+      <attribute name="text">
+        <composite type="text">
+          <attribute name="string">
+            <string>#ACCEPT#</string>
+          </attribute>
+          <attribute name="font">
+            <font name="Courier"/>
+          </attribute>
+          <attribute name="height">
+            <real val="1"/>
+          </attribute>
+          <attribute name="pos">
+            <point val="3,-5"/>
+          </attribute>
+          <attribute name="color">
+            <color val="#000000"/>
+          </attribute>
+          <attribute name="alignment">
+            <enum val="1"/>
+          </attribute>
+        </composite>
+      </attribute>
+      <connections>
+        <connection handle="0" to="O24" connection="6"/>
+      </connections>
+    </object>
+    <object type="Standard - Text" version="0" id="O28">
+      <attribute name="obj_pos">
+        <point val="3,-4"/>
+      </attribute>
+      <attribute name="obj_bb">
+        <rectangle val="1.082,-4.74336;4.918,-3.74336"/>
+      </attribute>
+      <attribute name="text">
+        <composite type="text">
+          <attribute name="string">
+            <string>#REJECT#</string>
+          </attribute>
+          <attribute name="font">
+            <font name="Courier"/>
+          </attribute>
+          <attribute name="height">
+            <real val="1"/>
+          </attribute>
+          <attribute name="pos">
+            <point val="3,-4"/>
+          </attribute>
+          <attribute name="color">
+            <color val="#000000"/>
+          </attribute>
+          <attribute name="alignment">
+            <enum val="1"/>
+          </attribute>
+        </composite>
+      </attribute>
+      <connections>
+        <connection handle="0" to="O25" connection="6"/>
+      </connections>
+    </object>
+    <object type="Standard - Box" version="0" id="O29">
+      <attribute name="obj_pos">
+        <point val="-2.05,4"/>
+      </attribute>
+      <attribute name="obj_bb">
+        <rectangle val="-2.1,3.95;-1.85,4.05"/>
+      </attribute>
+      <attribute name="elem_corner">
+        <point val="-2.05,4"/>
+      </attribute>
+      <attribute name="elem_width">
+        <real val="0.15"/>
+      </attribute>
+      <attribute name="elem_height">
+        <real val="8.88178e-16"/>
+      </attribute>
+      <attribute name="show_background">
+        <boolean val="true"/>
+      </attribute>
+    </object>
+    <object type="Standard - Text" version="0" id="O30">
+      <attribute name="obj_pos">
+        <point val="0,3"/>
+      </attribute>
+      <attribute name="obj_bb">
+        <rectangle val="-2.827,2.25664;2.827,5.25664"/>
+      </attribute>
+      <attribute name="text">
+        <composite type="text">
+          <attribute name="string">
+            <string>#IPSec
+NetFilter
+Table#</string>
+          </attribute>
+          <attribute name="font">
+            <font name="Courier"/>
+          </attribute>
+          <attribute name="height">
+            <real val="1"/>
+          </attribute>
+          <attribute name="pos">
+            <point val="0,3"/>
+          </attribute>
+          <attribute name="color">
+            <color val="#000000"/>
+          </attribute>
+          <attribute name="alignment">
+            <enum val="1"/>
+          </attribute>
+        </composite>
+      </attribute>
+    </object>
+    <object type="Standard - Box" version="0" id="O31">
+      <attribute name="obj_pos">
+        <point val="-5,7"/>
+      </attribute>
+      <attribute name="obj_bb">
+        <rectangle val="-5.05,6.95;-0.95,8.05"/>
+      </attribute>
+      <attribute name="elem_corner">
+        <point val="-5,7"/>
+      </attribute>
+      <attribute name="elem_width">
+        <real val="4"/>
+      </attribute>
+      <attribute name="elem_height">
+        <real val="1"/>
+      </attribute>
+      <attribute name="show_background">
+        <boolean val="true"/>
+      </attribute>
+    </object>
+    <object type="Standard - Box" version="0" id="O32">
+      <attribute name="obj_pos">
+        <point val="-5,8"/>
+      </attribute>
+      <attribute name="obj_bb">
+        <rectangle val="-5.05,7.95;-0.95,9.05"/>
+      </attribute>
+      <attribute name="elem_corner">
+        <point val="-5,8"/>
+      </attribute>
+      <attribute name="elem_width">
+        <real val="4"/>
+      </attribute>
+      <attribute name="elem_height">
+        <real val="1"/>
+      </attribute>
+      <attribute name="show_background">
+        <boolean val="true"/>
+      </attribute>
+    </object>
+    <object type="Standard - Box" version="0" id="O33">
+      <attribute name="obj_pos">
+        <point val="-5,9"/>
+      </attribute>
+      <attribute name="obj_bb">
+        <rectangle val="-5.05,8.95;-0.95,10.05"/>
+      </attribute>
+      <attribute name="elem_corner">
+        <point val="-5,9"/>
+      </attribute>
+      <attribute name="elem_width">
+        <real val="4"/>
+      </attribute>
+      <attribute name="elem_height">
+        <real val="1"/>
+      </attribute>
+      <attribute name="show_background">
+        <boolean val="true"/>
+      </attribute>
+    </object>
+    <object type="Standard - Box" version="0" id="O34">
+      <attribute name="obj_pos">
+        <point val="-5,10"/>
+      </attribute>
+      <attribute name="obj_bb">
+        <rectangle val="-5.05,9.95;-0.95,11.05"/>
+      </attribute>
+      <attribute name="elem_corner">
+        <point val="-5,10"/>
+      </attribute>
+      <attribute name="elem_width">
+        <real val="4"/>
+      </attribute>
+      <attribute name="elem_height">
+        <real val="1"/>
+      </attribute>
+      <attribute name="show_background">
+        <boolean val="true"/>
+      </attribute>
+    </object>
+    <object type="Standard - Box" version="0" id="O35">
+      <attribute name="obj_pos">
+        <point val="-5,11"/>
+      </attribute>
+      <attribute name="obj_bb">
+        <rectangle val="-5.05,10.95;-0.95,12.05"/>
+      </attribute>
+      <attribute name="elem_corner">
+        <point val="-5,11"/>
+      </attribute>
+      <attribute name="elem_width">
+        <real val="4"/>
+      </attribute>
+      <attribute name="elem_height">
+        <real val="1"/>
+      </attribute>
+      <attribute name="show_background">
+        <boolean val="true"/>
+      </attribute>
+    </object>
+    <object type="Standard - Box" version="0" id="O36">
+      <attribute name="obj_pos">
+        <point val="-5,12"/>
+      </attribute>
+      <attribute name="obj_bb">
+        <rectangle val="-5.05,11.95;-0.95,13.05"/>
+      </attribute>
+      <attribute name="elem_corner">
+        <point val="-5,12"/>
+      </attribute>
+      <attribute name="elem_width">
+        <real val="4"/>
+      </attribute>
+      <attribute name="elem_height">
+        <real val="1"/>
+      </attribute>
+      <attribute name="show_background">
+        <boolean val="true"/>
+      </attribute>
+    </object>
+    <object type="Standard - Box" version="0" id="O37">
+      <attribute name="obj_pos">
+        <point val="-5,13"/>
+      </attribute>
+      <attribute name="obj_bb">
+        <rectangle val="-5.05,12.95;-0.95,14.05"/>
+      </attribute>
+      <attribute name="elem_corner">
+        <point val="-5,13"/>
+      </attribute>
+      <attribute name="elem_width">
+        <real val="4"/>
+      </attribute>
+      <attribute name="elem_height">
+        <real val="1"/>
+      </attribute>
+      <attribute name="show_background">
+        <boolean val="true"/>
+      </attribute>
+    </object>
+    <object type="Standard - Text" version="0" id="O38">
+      <attribute name="obj_pos">
+        <point val="-3,8"/>
+      </attribute>
+      <attribute name="obj_bb">
+        <rectangle val="-4.615,7.25664;-1.385,8.25664"/>
+      </attribute>
+      <attribute name="text">
+        <composite type="text">
+          <attribute name="string">
+            <string>#SADDR#</string>
+          </attribute>
+          <attribute name="font">
+            <font name="Courier"/>
+          </attribute>
+          <attribute name="height">
+            <real val="1"/>
+          </attribute>
+          <attribute name="pos">
+            <point val="-3,8"/>
+          </attribute>
+          <attribute name="color">
+            <color val="#000000"/>
+          </attribute>
+          <attribute name="alignment">
+            <enum val="1"/>
+          </attribute>
+        </composite>
+      </attribute>
+      <connections>
+        <connection handle="0" to="O31" connection="6"/>
+      </connections>
+    </object>
+    <object type="Standard - Text" version="0" id="O39">
+      <attribute name="obj_pos">
+        <point val="-3,9"/>
+      </attribute>
+      <attribute name="obj_bb">
+        <rectangle val="-4.615,8.25664;-1.385,9.25664"/>
+      </attribute>
+      <attribute name="text">
+        <composite type="text">
+          <attribute name="string">
+            <string>#DADDR#</string>
+          </attribute>
+          <attribute name="font">
+            <font name="Courier"/>
+          </attribute>
+          <attribute name="height">
+            <real val="1"/>
+          </attribute>
+          <attribute name="pos">
+            <point val="-3,9"/>
+          </attribute>
+          <attribute name="color">
+            <color val="#000000"/>
+          </attribute>
+          <attribute name="alignment">
+            <enum val="1"/>
+          </attribute>
+        </composite>
+      </attribute>
+      <connections>
+        <connection handle="0" to="O32" connection="6"/>
+      </connections>
+    </object>
+    <object type="Standard - Text" version="0" id="O40">
+      <attribute name="obj_pos">
+        <point val="-3,10"/>
+      </attribute>
+      <attribute name="obj_bb">
+        <rectangle val="-4.615,9.25664;-1.385,10.2566"/>
+      </attribute>
+      <attribute name="text">
+        <composite type="text">
+          <attribute name="string">
+            <string>#SMASK#</string>
+          </attribute>
+          <attribute name="font">
+            <font name="Courier"/>
+          </attribute>
+          <attribute name="height">
+            <real val="1"/>
+          </attribute>
+          <attribute name="pos">
+            <point val="-3,10"/>
+          </attribute>
+          <attribute name="color">
+            <color val="#000000"/>
+          </attribute>
+          <attribute name="alignment">
+            <enum val="1"/>
+          </attribute>
+        </composite>
+      </attribute>
+      <connections>
+        <connection handle="0" to="O33" connection="6"/>
+      </connections>
+    </object>
+    <object type="Standard - Text" version="0" id="O41">
+      <attribute name="obj_pos">
+        <point val="-3,11"/>
+      </attribute>
+      <attribute name="obj_bb">
+        <rectangle val="-4.615,10.2566;-1.385,11.2566"/>
+      </attribute>
+      <attribute name="text">
+        <composite type="text">
+          <attribute name="string">
+            <string>#DMASK#</string>
+          </attribute>
+          <attribute name="font">
+            <font name="Courier"/>
+          </attribute>
+          <attribute name="height">
+            <real val="1"/>
+          </attribute>
+          <attribute name="pos">
+            <point val="-3,11"/>
+          </attribute>
+          <attribute name="color">
+            <color val="#000000"/>
+          </attribute>
+          <attribute name="alignment">
+            <enum val="1"/>
+          </attribute>
+        </composite>
+      </attribute>
+      <connections>
+        <connection handle="0" to="O34" connection="6"/>
+      </connections>
+    </object>
+    <object type="Standard - Text" version="0" id="O42">
+      <attribute name="obj_pos">
+        <point val="-3,12"/>
+      </attribute>
+      <attribute name="obj_bb">
+        <rectangle val="-4.615,11.2566;-1.385,12.2566"/>
+      </attribute>
+      <attribute name="text">
+        <composite type="text">
+          <attribute name="string">
+            <string>#SPORT#</string>
+          </attribute>
+          <attribute name="font">
+            <font name="Courier"/>
+          </attribute>
+          <attribute name="height">
+            <real val="1"/>
+          </attribute>
+          <attribute name="pos">
+            <point val="-3,12"/>
+          </attribute>
+          <attribute name="color">
+            <color val="#000000"/>
+          </attribute>
+          <attribute name="alignment">
+            <enum val="1"/>
+          </attribute>
+        </composite>
+      </attribute>
+      <connections>
+        <connection handle="0" to="O35" connection="6"/>
+      </connections>
+    </object>
+    <object type="Standard - Text" version="0" id="O43">
+      <attribute name="obj_pos">
+        <point val="-3,13"/>
+      </attribute>
+      <attribute name="obj_bb">
+        <rectangle val="-4.615,12.2566;-1.385,13.2566"/>
+      </attribute>
+      <attribute name="text">
+        <composite type="text">
+          <attribute name="string">
+            <string>#DPORT#</string>
+          </attribute>
+          <attribute name="font">
+            <font name="Courier"/>
+          </attribute>
+          <attribute name="height">
+            <real val="1"/>
+          </attribute>
+          <attribute name="pos">
+            <point val="-3,13"/>
+          </attribute>
+          <attribute name="color">
+            <color val="#000000"/>
+          </attribute>
+          <attribute name="alignment">
+            <enum val="1"/>
+          </attribute>
+        </composite>
+      </attribute>
+      <connections>
+        <connection handle="0" to="O36" connection="6"/>
+      </connections>
+    </object>
+    <object type="Standard - Text" version="0" id="O44">
+      <attribute name="obj_pos">
+        <point val="-3,14"/>
+      </attribute>
+      <attribute name="obj_bb">
+        <rectangle val="-4.009,13.2566;-1.991,14.2566"/>
+      </attribute>
+      <attribute name="text">
+        <composite type="text">
+          <attribute name="string">
+            <string>#UID#</string>
+          </attribute>
+          <attribute name="font">
+            <font name="Courier"/>
+          </attribute>
+          <attribute name="height">
+            <real val="1"/>
+          </attribute>
+          <attribute name="pos">
+            <point val="-3,14"/>
+          </attribute>
+          <attribute name="color">
+            <color val="#000000"/>
+          </attribute>
+          <attribute name="alignment">
+            <enum val="1"/>
+          </attribute>
+        </composite>
+      </attribute>
+      <connections>
+        <connection handle="0" to="O37" connection="6"/>
+      </connections>
+    </object>
+    <object type="Standard - Box" version="0" id="O45">
+      <attribute name="obj_pos">
+        <point val="1,11"/>
+      </attribute>
+      <attribute name="obj_bb">
+        <rectangle val="0.95,10.95;5.05,12.05"/>
+      </attribute>
+      <attribute name="elem_corner">
+        <point val="1,11"/>
+      </attribute>
+      <attribute name="elem_width">
+        <real val="4"/>
+      </attribute>
+      <attribute name="elem_height">
+        <real val="1"/>
+      </attribute>
+      <attribute name="show_background">
+        <boolean val="true"/>
+      </attribute>
+    </object>
+    <object type="Standard - Box" version="0" id="O46">
+      <attribute name="obj_pos">
+        <point val="1,12"/>
+      </attribute>
+      <attribute name="obj_bb">
+        <rectangle val="0.95,11.95;5.05,13.05"/>
+      </attribute>
+      <attribute name="elem_corner">
+        <point val="1,12"/>
+      </attribute>
+      <attribute name="elem_width">
+        <real val="4"/>
+      </attribute>
+      <attribute name="elem_height">
+        <real val="1"/>
+      </attribute>
+      <attribute name="show_background">
+        <boolean val="true"/>
+      </attribute>
+    </object>
+    <object type="Standard - Box" version="0" id="O47">
+      <attribute name="obj_pos">
+        <point val="1,13"/>
+      </attribute>
+      <attribute name="obj_bb">
+        <rectangle val="0.95,12.95;5.05,14.05"/>
+      </attribute>
+      <attribute name="elem_corner">
+        <point val="1,13"/>
+      </attribute>
+      <attribute name="elem_width">
+        <real val="4"/>
+      </attribute>
+      <attribute name="elem_height">
+        <real val="1"/>
+      </attribute>
+      <attribute name="show_background">
+        <boolean val="true"/>
+      </attribute>
+    </object>
+    <object type="Standard - Text" version="0" id="O48">
+      <attribute name="obj_pos">
+        <point val="3,12"/>
+      </attribute>
+      <attribute name="obj_bb">
+        <rectangle val="1.688,11.2566;4.312,12.2566"/>
+      </attribute>
+      <attribute name="text">
+        <composite type="text">
+          <attribute name="string">
+            <string>#DROP#</string>
+          </attribute>
+          <attribute name="font">
+            <font name="Courier"/>
+          </attribute>
+          <attribute name="height">
+            <real val="1"/>
+          </attribute>
+          <attribute name="pos">
+            <point val="3,12"/>
+          </attribute>
+          <attribute name="color">
+            <color val="#000000"/>
+          </attribute>
+          <attribute name="alignment">
+            <enum val="1"/>
+          </attribute>
+        </composite>
+      </attribute>
+      <connections>
+        <connection handle="0" to="O45" connection="6"/>
+      </connections>
+    </object>
+    <object type="Standard - Text" version="0" id="O49">
+      <attribute name="obj_pos">
+        <point val="3,13"/>
+      </attribute>
+      <attribute name="obj_bb">
+        <rectangle val="1.082,12.2566;4.918,13.2566"/>
+      </attribute>
+      <attribute name="text">
+        <composite type="text">
+          <attribute name="string">
+            <string>#ACCEPT#</string>
+          </attribute>
+          <attribute name="font">
+            <font name="Courier"/>
+          </attribute>
+          <attribute name="height">
+            <real val="1"/>
+          </attribute>
+          <attribute name="pos">
+            <point val="3,13"/>
+          </attribute>
+          <attribute name="color">
+            <color val="#000000"/>
+          </attribute>
+          <attribute name="alignment">
+            <enum val="1"/>
+          </attribute>
+        </composite>
+      </attribute>
+      <connections>
+        <connection handle="0" to="O46" connection="6"/>
+      </connections>
+    </object>
+    <object type="Standard - Text" version="0" id="O50">
+      <attribute name="obj_pos">
+        <point val="3,14"/>
+      </attribute>
+      <attribute name="obj_bb">
+        <rectangle val="1.082,13.2566;4.918,14.2566"/>
+      </attribute>
+      <attribute name="text">
+        <composite type="text">
+          <attribute name="string">
+            <string>#REJECT#</string>
+          </attribute>
+          <attribute name="font">
+            <font name="Courier"/>
+          </attribute>
+          <attribute name="height">
+            <real val="1"/>
+          </attribute>
+          <attribute name="pos">
+            <point val="3,14"/>
+          </attribute>
+          <attribute name="color">
+            <color val="#000000"/>
+          </attribute>
+          <attribute name="alignment">
+            <enum val="1"/>
+          </attribute>
+        </composite>
+      </attribute>
+      <connections>
+        <connection handle="0" to="O47" connection="6"/>
+      </connections>
+    </object>
+    <object type="Standard - Box" version="0" id="O51">
+      <attribute name="obj_pos">
+        <point val="7,-4"/>
+      </attribute>
+      <attribute name="obj_bb">
+        <rectangle val="6.95,-4.05;11.05,-1.95"/>
+      </attribute>
+      <attribute name="elem_corner">
+        <point val="7,-4"/>
+      </attribute>
+      <attribute name="elem_width">
+        <real val="4"/>
+      </attribute>
+      <attribute name="elem_height">
+        <real val="2"/>
+      </attribute>
+      <attribute name="show_background">
+        <boolean val="true"/>
+      </attribute>
+    </object>
+    <object type="Standard - Text" version="0" id="O52">
+      <attribute name="obj_pos">
+        <point val="9,-3"/>
+      </attribute>
+      <attribute name="obj_bb">
+        <rectangle val="7.385,-3.74336;10.615,-2.74336"/>
+      </attribute>
+      <attribute name="text">
+        <composite type="text">
+          <attribute name="string">
+            <string>#IPSEC#</string>
+          </attribute>
+          <attribute name="font">
+            <font name="Courier"/>
+          </attribute>
+          <attribute name="height">
+            <real val="1"/>
+          </attribute>
+          <attribute name="pos">
+            <point val="9,-3"/>
+          </attribute>
+          <attribute name="color">
+            <color val="#000000"/>
+          </attribute>
+          <attribute name="alignment">
+            <enum val="1"/>
+          </attribute>
+        </composite>
+      </attribute>
+    </object>
+    <object type="Standard - Box" version="0" id="O53">
+      <attribute name="obj_pos">
+        <point val="7,5"/>
+      </attribute>
+      <attribute name="obj_bb">
+        <rectangle val="6.95,4.95;11.05,7.05"/>
+      </attribute>
+      <attribute name="elem_corner">
+        <point val="7,5"/>
+      </attribute>
+      <attribute name="elem_width">
+        <real val="4"/>
+      </attribute>
+      <attribute name="elem_height">
+        <real val="2"/>
+      </attribute>
+      <attribute name="show_background">
+        <boolean val="true"/>
+      </attribute>
+    </object>
+    <object type="Standard - Text" version="0" id="O54">
+      <attribute name="obj_pos">
+        <point val="9,6"/>
+      </attribute>
+      <attribute name="obj_bb">
+        <rectangle val="7.688,5.25664;10.312,6.25664"/>
+      </attribute>
+      <attribute name="text">
+        <composite type="text">
+          <attribute name="string">
+            <string>#TRAP#</string>
+          </attribute>
+          <attribute name="font">
+            <font name="Courier"/>
+          </attribute>
+          <attribute name="height">
+            <real val="1"/>
+          </attribute>
+          <attribute name="pos">
+            <point val="9,6"/>
+          </attribute>
+          <attribute name="color">
+            <color val="#000000"/>
+          </attribute>
+          <attribute name="alignment">
+            <enum val="1"/>
+          </attribute>
+        </composite>
+      </attribute>
+    </object>
+    <object type="Standard - Text" version="0" id="O55">
+      <attribute name="obj_pos">
+        <point val="9,12"/>
+      </attribute>
+      <attribute name="obj_bb">
+        <rectangle val="7.385,11.2566;10.615,12.2566"/>
+      </attribute>
+      <attribute name="text">
+        <composite type="text">
+          <attribute name="string">
+            <string>#IPSEC#</string>
+          </attribute>
+          <attribute name="font">
+            <font name="Courier"/>
+          </attribute>
+          <attribute name="height">
+            <real val="1"/>
+          </attribute>
+          <attribute name="pos">
+            <point val="9,12"/>
+          </attribute>
+          <attribute name="color">
+            <color val="#000000"/>
+          </attribute>
+          <attribute name="alignment">
+            <enum val="1"/>
+          </attribute>
+        </composite>
+      </attribute>
+    </object>
+    <object type="Standard - Text" version="0" id="O56">
+      <attribute name="obj_pos">
+        <point val="9,9"/>
+      </attribute>
+      <attribute name="obj_bb">
+        <rectangle val="7.688,8.25664;10.312,9.25664"/>
+      </attribute>
+      <attribute name="text">
+        <composite type="text">
+          <attribute name="string">
+            <string>#HOLD#</string>
+          </attribute>
+          <attribute name="font">
+            <font name="Courier"/>
+          </attribute>
+          <attribute name="height">
+            <real val="1"/>
+          </attribute>
+          <attribute name="pos">
+            <point val="9,9"/>
+          </attribute>
+          <attribute name="color">
+            <color val="#000000"/>
+          </attribute>
+          <attribute name="alignment">
+            <enum val="1"/>
+          </attribute>
+        </composite>
+      </attribute>
+    </object>
+    <object type="Standard - Box" version="0" id="O57">
+      <attribute name="obj_pos">
+        <point val="-12,2"/>
+      </attribute>
+      <attribute name="obj_bb">
+        <rectangle val="-12.05,1.95;-6.95,4.05"/>
+      </attribute>
+      <attribute name="elem_corner">
+        <point val="-12,2"/>
+      </attribute>
+      <attribute name="elem_width">
+        <real val="5"/>
+      </attribute>
+      <attribute name="elem_height">
+        <real val="2"/>
+      </attribute>
+      <attribute name="show_background">
+        <boolean val="true"/>
+      </attribute>
+    </object>
+    <object type="Standard - Text" version="0" id="O58">
+      <attribute name="obj_pos">
+        <point val="-9,3"/>
+      </attribute>
+      <attribute name="obj_bb">
+        <rectangle val="-10.918,2.25664;-7.082,3.25664"/>
+      </attribute>
+      <attribute name="text">
+        <composite type="text">
+          <attribute name="string">
+            <string>#seclev#</string>
+          </attribute>
+          <attribute name="font">
+            <font name="Courier"/>
+          </attribute>
+          <attribute name="height">
+            <real val="1"/>
+          </attribute>
+          <attribute name="pos">
+            <point val="-9,3"/>
+          </attribute>
+          <attribute name="color">
+            <color val="#000000"/>
+          </attribute>
+          <attribute name="alignment">
+            <enum val="1"/>
+          </attribute>
+        </composite>
+      </attribute>
+    </object>
+    <object type="Standard - Box" version="0" id="O59">
+      <attribute name="obj_pos">
+        <point val="16,3"/>
+      </attribute>
+      <attribute name="obj_bb">
+        <rectangle val="15.95,2.95;20.05,5.05"/>
+      </attribute>
+      <attribute name="elem_corner">
+        <point val="16,3"/>
+      </attribute>
+      <attribute name="elem_width">
+        <real val="4"/>
+      </attribute>
+      <attribute name="elem_height">
+        <real val="2"/>
+      </attribute>
+      <attribute name="show_background">
+        <boolean val="true"/>
+      </attribute>
+    </object>
+    <object type="Standard - Text" version="0" id="O60">
+      <attribute name="obj_pos">
+        <point val="18,4"/>
+      </attribute>
+      <attribute name="obj_bb">
+        <rectangle val="16.688,3.25664;19.312,4.25664"/>
+      </attribute>
+      <attribute name="text">
+        <composite type="text">
+          <attribute name="string">
+            <string>#SADB#</string>
+          </attribute>
+          <attribute name="font">
+            <font name="Courier"/>
+          </attribute>
+          <attribute name="height">
+            <real val="1"/>
+          </attribute>
+          <attribute name="pos">
+            <point val="18,4"/>
+          </attribute>
+          <attribute name="color">
+            <color val="#000000"/>
+          </attribute>
+          <attribute name="alignment">
+            <enum val="1"/>
+          </attribute>
+        </composite>
+      </attribute>
+    </object>
+    <object type="Standard - Box" version="0" id="O61">
+      <attribute name="obj_pos">
+        <point val="-13,11"/>
+      </attribute>
+      <attribute name="obj_bb">
+        <rectangle val="-13.05,10.95;-6.95,14.05"/>
+      </attribute>
+      <attribute name="elem_corner">
+        <point val="-13,11"/>
+      </attribute>
+      <attribute name="elem_width">
+        <real val="6"/>
+      </attribute>
+      <attribute name="elem_height">
+        <real val="3"/>
+      </attribute>
+      <attribute name="show_background">
+        <boolean val="true"/>
+      </attribute>
+    </object>
+    <object type="Standard - Text" version="0" id="O62">
+      <attribute name="obj_pos">
+        <point val="-10,12"/>
+      </attribute>
+      <attribute name="obj_bb">
+        <rectangle val="-12.221,11.2566;-7.779,13.2566"/>
+      </attribute>
+      <attribute name="text">
+        <composite type="text">
+          <attribute name="string">
+            <string>#Routing
+Table#</string>
+          </attribute>
+          <attribute name="font">
+            <font name="Courier"/>
+          </attribute>
+          <attribute name="height">
+            <real val="1"/>
+          </attribute>
+          <attribute name="pos">
+            <point val="-10,12"/>
+          </attribute>
+          <attribute name="color">
+            <color val="#000000"/>
+          </attribute>
+          <attribute name="alignment">
+            <enum val="1"/>
+          </attribute>
+        </composite>
+      </attribute>
+    </object>
+    <object type="Standard - Line" version="0" id="O63">
+      <attribute name="obj_pos">
+        <point val="-20,0"/>
+      </attribute>
+      <attribute name="obj_bb">
+        <rectangle val="-20.1,-0.1;21.1,0.1"/>
+      </attribute>
+      <attribute name="conn_endpoints">
+        <point val="-20,0"/>
+        <point val="21,0"/>
+      </attribute>
+      <attribute name="numcp">
+        <int val="1"/>
+      </attribute>
+      <attribute name="line_width">
+        <real val="0.2"/>
+      </attribute>
+      <attribute name="line_style">
+        <enum val="2"/>
+      </attribute>
+    </object>
+    <object type="Standard - Text" version="0" id="O64">
+      <attribute name="obj_pos">
+        <point val="-17,-1"/>
+      </attribute>
+      <attribute name="obj_bb">
+        <rectangle val="-19.827,-1.74336;-14.173,-0.743363"/>
+      </attribute>
+      <attribute name="text">
+        <composite type="text">
+          <attribute name="string">
+            <string>#UserSpace#</string>
+          </attribute>
+          <attribute name="font">
+            <font name="Courier"/>
+          </attribute>
+          <attribute name="height">
+            <real val="1"/>
+          </attribute>
+          <attribute name="pos">
+            <point val="-17,-1"/>
+          </attribute>
+          <attribute name="color">
+            <color val="#000000"/>
+          </attribute>
+          <attribute name="alignment">
+            <enum val="1"/>
+          </attribute>
+        </composite>
+      </attribute>
+    </object>
+    <object type="Standard - Text" version="0" id="O65">
+      <attribute name="obj_pos">
+        <point val="-17,1"/>
+      </attribute>
+      <attribute name="obj_bb">
+        <rectangle val="-20.433,0.256637;-13.567,1.25664"/>
+      </attribute>
+      <attribute name="text">
+        <composite type="text">
+          <attribute name="string">
+            <string>#KernelSpace#</string>
+          </attribute>
+          <attribute name="font">
+            <font name="Courier"/>
+          </attribute>
+          <attribute name="height">
+            <real val="1"/>
+          </attribute>
+          <attribute name="pos">
+            <point val="-17,1"/>
+          </attribute>
+          <attribute name="color">
+            <color val="#000000"/>
+          </attribute>
+          <attribute name="alignment">
+            <enum val="1"/>
+          </attribute>
+        </composite>
+      </attribute>
+    </object>
+    <object type="Standard - Text" version="0" id="O66">
+      <attribute name="obj_pos">
+        <point val="-3,-1"/>
+      </attribute>
+      <attribute name="obj_bb">
+        <rectangle val="-7.948,-1.74336;1.948,-0.743363"/>
+      </attribute>
+      <attribute name="text">
+        <composite type="text">
+          <attribute name="string">
+            <string>#get/set_sock_opt#</string>
+          </attribute>
+          <attribute name="font">
+            <font name="Courier"/>
+          </attribute>
+          <attribute name="height">
+            <real val="1"/>
+          </attribute>
+          <attribute name="pos">
+            <point val="-3,-1"/>
+          </attribute>
+          <attribute name="color">
+            <color val="#000000"/>
+          </attribute>
+          <attribute name="alignment">
+            <enum val="1"/>
+          </attribute>
+        </composite>
+      </attribute>
+    </object>
+    <object type="Standard - Line" version="0" id="O67">
+      <attribute name="obj_pos">
+        <point val="0,-4"/>
+      </attribute>
+      <attribute name="obj_bb">
+        <rectangle val="-0.85,-4.85;0.85,2.85"/>
+      </attribute>
+      <attribute name="conn_endpoints">
+        <point val="0,-4"/>
+        <point val="0,2"/>
+      </attribute>
+      <attribute name="numcp">
+        <int val="1"/>
+      </attribute>
+      <attribute name="end_arrow">
+        <enum val="3"/>
+      </attribute>
+      <attribute name="end_arrow_length">
+        <real val="0.5"/>
+      </attribute>
+      <attribute name="end_arrow_width">
+        <real val="0.5"/>
+      </attribute>
+      <connections>
+        <connection handle="0" to="O2" connection="6"/>
+        <connection handle="1" to="O1" connection="1"/>
+      </connections>
+    </object>
+    <object type="Standard - Line" version="0" id="O68">
+      <attribute name="obj_pos">
+        <point val="5,5"/>
+      </attribute>
+      <attribute name="obj_bb">
+        <rectangle val="4.15,4.15;7.85,5.85"/>
+      </attribute>
+      <attribute name="conn_endpoints">
+        <point val="5,5"/>
+        <point val="7,5"/>
+      </attribute>
+      <attribute name="numcp">
+        <int val="1"/>
+      </attribute>
+      <attribute name="end_arrow">
+        <enum val="3"/>
+      </attribute>
+      <attribute name="end_arrow_length">
+        <real val="0.5"/>
+      </attribute>
+      <attribute name="end_arrow_width">
+        <real val="0.5"/>
+      </attribute>
+      <connections>
+        <connection handle="1" to="O53" connection="0"/>
+      </connections>
+    </object>
+    <object type="Standard - Line" version="0" id="O69">
+      <attribute name="obj_pos">
+        <point val="5,8"/>
+      </attribute>
+      <attribute name="obj_bb">
+        <rectangle val="4.15,7.15;7.85,8.85"/>
+      </attribute>
+      <attribute name="conn_endpoints">
+        <point val="5,8"/>
+        <point val="7,8"/>
+      </attribute>
+      <attribute name="numcp">
+        <int val="1"/>
+      </attribute>
+      <attribute name="end_arrow">
+        <enum val="3"/>
+      </attribute>
+      <attribute name="end_arrow_length">
+        <real val="0.5"/>
+      </attribute>
+      <attribute name="end_arrow_width">
+        <real val="0.5"/>
+      </attribute>
+      <connections>
+        <connection handle="0" to="O1" connection="4"/>
+        <connection handle="1" to="O20" connection="0"/>
+      </connections>
+    </object>
+    <object type="Standard - Line" version="0" id="O70">
+      <attribute name="obj_pos">
+        <point val="5,11"/>
+      </attribute>
+      <attribute name="obj_bb">
+        <rectangle val="4.15,10.15;7.85,11.85"/>
+      </attribute>
+      <attribute name="conn_endpoints">
+        <point val="5,11"/>
+        <point val="7,11"/>
+      </attribute>
+      <attribute name="numcp">
+        <int val="1"/>
+      </attribute>
+      <attribute name="end_arrow">
+        <enum val="3"/>
+      </attribute>
+      <attribute name="end_arrow_length">
+        <real val="0.5"/>
+      </attribute>
+      <attribute name="end_arrow_width">
+        <real val="0.5"/>
+      </attribute>
+      <connections>
+        <connection handle="0" to="O45" connection="2"/>
+        <connection handle="1" to="O0" connection="0"/>
+      </connections>
+    </object>
+    <object type="Standard - Line" version="0" id="O71">
+      <attribute name="obj_pos">
+        <point val="5,-4"/>
+      </attribute>
+      <attribute name="obj_bb">
+        <rectangle val="4.45,-4.55;7.55,-3.45"/>
+      </attribute>
+      <attribute name="conn_endpoints">
+        <point val="5,-4"/>
+        <point val="7,-4"/>
+      </attribute>
+      <attribute name="numcp">
+        <int val="1"/>
+      </attribute>
+      <attribute name="start_arrow">
+        <enum val="3"/>
+      </attribute>
+      <attribute name="start_arrow_length">
+        <real val="0.5"/>
+      </attribute>
+      <attribute name="start_arrow_width">
+        <real val="0.5"/>
+      </attribute>
+      <attribute name="end_arrow">
+        <enum val="3"/>
+      </attribute>
+      <attribute name="end_arrow_length">
+        <real val="0.5"/>
+      </attribute>
+      <attribute name="end_arrow_width">
+        <real val="0.5"/>
+      </attribute>
+      <connections>
+        <connection handle="0" to="O2" connection="7"/>
+        <connection handle="1" to="O51" connection="0"/>
+      </connections>
+    </object>
+    <object type="Standard - ZigZagLine" version="0" id="O72">
+      <attribute name="obj_pos">
+        <point val="-9,14"/>
+      </attribute>
+      <attribute name="obj_bb">
+        <rectangle val="-9.85,13.15;-2.15,16.85"/>
+      </attribute>
+      <attribute name="orth_points">
+        <point val="-9,14"/>
+        <point val="-9,16"/>
+        <point val="-3,16"/>
+        <point val="-3,14"/>
+      </attribute>
+      <attribute name="orth_orient">
+        <enum val="1"/>
+        <enum val="0"/>
+        <enum val="1"/>
+      </attribute>
+      <attribute name="end_arrow">
+        <enum val="3"/>
+      </attribute>
+      <attribute name="end_arrow_length">
+        <real val="0.5"/>
+      </attribute>
+      <attribute name="end_arrow_width">
+        <real val="0.5"/>
+      </attribute>
+      <connections>
+        <connection handle="1" to="O37" connection="6"/>
+      </connections>
+    </object>
+    <object type="Standard - Box" version="0" id="O73">
+      <attribute name="obj_pos">
+        <point val="-14,-22"/>
+      </attribute>
+      <attribute name="obj_bb">
+        <rectangle val="-14.05,-22.05;-7.95,-19.95"/>
+      </attribute>
+      <attribute name="elem_corner">
+        <point val="-14,-22"/>
+      </attribute>
+      <attribute name="elem_width">
+        <real val="6"/>
+      </attribute>
+      <attribute name="elem_height">
+        <real val="2"/>
+      </attribute>
+      <attribute name="show_background">
+        <boolean val="true"/>
+      </attribute>
+    </object>
+    <object type="Standard - Text" version="0" id="O74">
+      <attribute name="obj_pos">
+        <point val="-11,-21"/>
+      </attribute>
+      <attribute name="obj_bb">
+        <rectangle val="-12.615,-21.7434;-9.385,-20.7434"/>
+      </attribute>
+      <attribute name="text">
+        <composite type="text">
+          <attribute name="string">
+            <string>#KMd-1#</string>
+          </attribute>
+          <attribute name="font">
+            <font name="Courier"/>
+          </attribute>
+          <attribute name="height">
+            <real val="1"/>
+          </attribute>
+          <attribute name="pos">
+            <point val="-11,-21"/>
+          </attribute>
+          <attribute name="color">
+            <color val="#000000"/>
+          </attribute>
+          <attribute name="alignment">
+            <enum val="1"/>
+          </attribute>
+        </composite>
+      </attribute>
+    </object>
+    <object type="Standard - Box" version="0" id="O75">
+      <attribute name="obj_pos">
+        <point val="14,-22"/>
+      </attribute>
+      <attribute name="obj_bb">
+        <rectangle val="13.95,-22.05;20.05,-19.95"/>
+      </attribute>
+      <attribute name="elem_corner">
+        <point val="14,-22"/>
+      </attribute>
+      <attribute name="elem_width">
+        <real val="6"/>
+      </attribute>
+      <attribute name="elem_height">
+        <real val="2"/>
+      </attribute>
+      <attribute name="show_background">
+        <boolean val="true"/>
+      </attribute>
+    </object>
+    <object type="Standard - Text" version="0" id="O76">
+      <attribute name="obj_pos">
+        <point val="17,-21"/>
+      </attribute>
+      <attribute name="obj_bb">
+        <rectangle val="15.385,-21.7434;18.615,-20.7434"/>
+      </attribute>
+      <attribute name="text">
+        <composite type="text">
+          <attribute name="string">
+            <string>#KMd-n#</string>
+          </attribute>
+          <attribute name="font">
+            <font name="Courier"/>
+          </attribute>
+          <attribute name="height">
+            <real val="1"/>
+          </attribute>
+          <attribute name="pos">
+            <point val="17,-21"/>
+          </attribute>
+          <attribute name="color">
+            <color val="#000000"/>
+          </attribute>
+          <attribute name="alignment">
+            <enum val="1"/>
+          </attribute>
+        </composite>
+      </attribute>
+    </object>
+    <object type="Standard - PolyLine" version="0" id="O77">
+      <attribute name="obj_pos">
+        <point val="-13,-19"/>
+      </attribute>
+      <attribute name="obj_bb">
+        <rectangle val="-13.85,-19.85;-12.15,11.85"/>
+      </attribute>
+      <attribute name="poly_points">
+        <point val="-13,-19"/>
+        <point val="-13,11"/>
+      </attribute>
+      <attribute name="end_arrow">
+        <enum val="3"/>
+      </attribute>
+      <attribute name="end_arrow_length">
+        <real val="0.5"/>
+      </attribute>
+      <attribute name="end_arrow_width">
+        <real val="0.5"/>
+      </attribute>
+    </object>
+    <object type="Standard - PolyLine" version="0" id="O78">
+      <attribute name="obj_pos">
+        <point val="15,-20"/>
+      </attribute>
+      <attribute name="obj_bb">
+        <rectangle val="14.95,-20.05;15.05,-18.95"/>
+      </attribute>
+      <attribute name="poly_points">
+        <point val="15,-20"/>
+        <point val="15,-19"/>
+      </attribute>
+    </object>
+    <object type="Standard - PolyLine" version="0" id="O79">
+      <attribute name="obj_pos">
+        <point val="15,-19"/>
+      </attribute>
+      <attribute name="obj_bb">
+        <rectangle val="-13.85,-19.85;15.85,-18.15"/>
+      </attribute>
+      <attribute name="poly_points">
+        <point val="15,-19"/>
+        <point val="-13,-19"/>
+      </attribute>
+      <attribute name="end_arrow">
+        <enum val="3"/>
+      </attribute>
+      <attribute name="end_arrow_length">
+        <real val="0.5"/>
+      </attribute>
+      <attribute name="end_arrow_width">
+        <real val="0.5"/>
+      </attribute>
+    </object>
+    <object type="Standard - PolyLine" version="0" id="O80">
+      <attribute name="obj_pos">
+        <point val="-9,-20"/>
+      </attribute>
+      <attribute name="obj_bb">
+        <rectangle val="-9.05,-20.05;-8.95,-14.95"/>
+      </attribute>
+      <attribute name="poly_points">
+        <point val="-9,-20"/>
+        <point val="-9,-15"/>
+      </attribute>
+      <attribute name="line_style">
+        <enum val="3"/>
+      </attribute>
+    </object>
+    <object type="Standard - PolyLine" version="0" id="O81">
+      <attribute name="obj_pos">
+        <point val="-9,-15"/>
+      </attribute>
+      <attribute name="obj_bb">
+        <rectangle val="-9.85,-15.85;19.85,-14.15"/>
+      </attribute>
+      <attribute name="poly_points">
+        <point val="-9,-15"/>
+        <point val="19,-15"/>
+      </attribute>
+      <attribute name="line_style">
+        <enum val="3"/>
+      </attribute>
+      <attribute name="end_arrow">
+        <enum val="3"/>
+      </attribute>
+      <attribute name="end_arrow_length">
+        <real val="0.5"/>
+      </attribute>
+      <attribute name="end_arrow_width">
+        <real val="0.5"/>
+      </attribute>
+    </object>
+    <object type="Standard - PolyLine" version="0" id="O82">
+      <attribute name="obj_pos">
+        <point val="19,-15"/>
+      </attribute>
+      <attribute name="obj_bb">
+        <rectangle val="18.15,-15.85;19.85,3.85"/>
+      </attribute>
+      <attribute name="poly_points">
+        <point val="19,-15"/>
+        <point val="19,3"/>
+      </attribute>
+      <attribute name="line_style">
+        <enum val="3"/>
+      </attribute>
+      <attribute name="end_arrow">
+        <enum val="3"/>
+      </attribute>
+      <attribute name="end_arrow_length">
+        <real val="0.5"/>
+      </attribute>
+      <attribute name="end_arrow_width">
+        <real val="0.5"/>
+      </attribute>
+    </object>
+    <object type="Standard - PolyLine" version="0" id="O83">
+      <attribute name="obj_pos">
+        <point val="19,-20"/>
+      </attribute>
+      <attribute name="obj_bb">
+        <rectangle val="18.15,-20.85;19.85,-14.15"/>
+      </attribute>
+      <attribute name="poly_points">
+        <point val="19,-20"/>
+        <point val="19,-15"/>
+      </attribute>
+      <attribute name="line_style">
+        <enum val="3"/>
+      </attribute>
+      <attribute name="end_arrow">
+        <enum val="3"/>
+      </attribute>
+      <attribute name="end_arrow_length">
+        <real val="0.5"/>
+      </attribute>
+      <attribute name="end_arrow_width">
+        <real val="0.5"/>
+      </attribute>
+    </object>
+    <object type="Standard - PolyLine" version="0" id="O84">
+      <attribute name="obj_pos">
+        <point val="18,3"/>
+      </attribute>
+      <attribute name="obj_bb">
+        <rectangle val="17.15,-16.85;18.85,3.85"/>
+      </attribute>
+      <attribute name="poly_points">
+        <point val="18,3"/>
+        <point val="18,-16"/>
+      </attribute>
+      <attribute name="line_style">
+        <enum val="3"/>
+      </attribute>
+      <attribute name="end_arrow">
+        <enum val="3"/>
+      </attribute>
+      <attribute name="end_arrow_length">
+        <real val="0.5"/>
+      </attribute>
+      <attribute name="end_arrow_width">
+        <real val="0.5"/>
+      </attribute>
+      <connections>
+        <connection handle="0" to="O59" connection="1"/>
+      </connections>
+    </object>
+    <object type="Standard - PolyLine" version="0" id="O85">
+      <attribute name="obj_pos">
+        <point val="18,-16"/>
+      </attribute>
+      <attribute name="obj_bb">
+        <rectangle val="17.15,-20.85;18.85,-15.15"/>
+      </attribute>
+      <attribute name="poly_points">
+        <point val="18,-16"/>
+        <point val="18,-20"/>
+      </attribute>
+      <attribute name="line_style">
+        <enum val="3"/>
+      </attribute>
+      <attribute name="end_arrow">
+        <enum val="3"/>
+      </attribute>
+      <attribute name="end_arrow_length">
+        <real val="0.5"/>
+      </attribute>
+      <attribute name="end_arrow_width">
+        <real val="0.5"/>
+      </attribute>
+    </object>
+    <object type="Standard - PolyLine" version="0" id="O86">
+      <attribute name="obj_pos">
+        <point val="18,-16"/>
+      </attribute>
+      <attribute name="obj_bb">
+        <rectangle val="-10.05,-16.05;18.05,-15.95"/>
+      </attribute>
+      <attribute name="poly_points">
+        <point val="18,-16"/>
+        <point val="-10,-16"/>
+      </attribute>
+      <attribute name="line_style">
+        <enum val="3"/>
+      </attribute>
+    </object>
+    <object type="Standard - PolyLine" version="0" id="O87">
+      <attribute name="obj_pos">
+        <point val="-10,-16"/>
+      </attribute>
+      <attribute name="obj_bb">
+        <rectangle val="-10.85,-20.85;-9.15,-15.15"/>
+      </attribute>
+      <attribute name="poly_points">
+        <point val="-10,-16"/>
+        <point val="-10,-20"/>
+      </attribute>
+      <attribute name="line_style">
+        <enum val="3"/>
+      </attribute>
+      <attribute name="end_arrow">
+        <enum val="3"/>
+      </attribute>
+      <attribute name="end_arrow_length">
+        <real val="0.5"/>
+      </attribute>
+      <attribute name="end_arrow_width">
+        <real val="0.5"/>
+      </attribute>
+    </object>
+    <object type="Standard - PolyLine" version="0" id="O88">
+      <attribute name="obj_pos">
+        <point val="-13,-20"/>
+      </attribute>
+      <attribute name="obj_bb">
+        <rectangle val="-13.85,-20.85;-12.15,-18.15"/>
+      </attribute>
+      <attribute name="poly_points">
+        <point val="-13,-20"/>
+        <point val="-13,-19"/>
+      </attribute>
+      <attribute name="end_arrow">
+        <enum val="3"/>
+      </attribute>
+      <attribute name="end_arrow_length">
+        <real val="0.5"/>
+      </attribute>
+      <attribute name="end_arrow_width">
+        <real val="0.5"/>
+      </attribute>
+    </object>
+    <object type="Standard - Line" version="0" id="O89">
+      <attribute name="obj_pos">
+        <point val="11,5"/>
+      </attribute>
+      <attribute name="obj_bb">
+        <rectangle val="10.95,4.95;15.05,5.05"/>
+      </attribute>
+      <attribute name="conn_endpoints">
+        <point val="11,5"/>
+        <point val="15,5"/>
+      </attribute>
+      <attribute name="numcp">
+        <int val="1"/>
+      </attribute>
+      <attribute name="line_style">
+        <enum val="3"/>
+      </attribute>
+      <connections>
+        <connection handle="0" to="O53" connection="2"/>
+      </connections>
+    </object>
+    <object type="Standard - Line" version="0" id="O90">
+      <attribute name="obj_pos">
+        <point val="15,2"/>
+      </attribute>
+      <attribute name="obj_bb">
+        <rectangle val="14.15,-17.85;15.85,2.85"/>
+      </attribute>
+      <attribute name="conn_endpoints">
+        <point val="15,2"/>
+        <point val="15,-17"/>
+      </attribute>
+      <attribute name="numcp">
+        <int val="1"/>
+      </attribute>
+      <attribute name="line_style">
+        <enum val="3"/>
+      </attribute>
+      <attribute name="end_arrow">
+        <enum val="3"/>
+      </attribute>
+      <attribute name="end_arrow_length">
+        <real val="0.5"/>
+      </attribute>
+      <attribute name="end_arrow_width">
+        <real val="0.5"/>
+      </attribute>
+    </object>
+    <object type="Standard - Line" version="0" id="O91">
+      <attribute name="obj_pos">
+        <point val="15,-17"/>
+      </attribute>
+      <attribute name="obj_bb">
+        <rectangle val="14.95,-17.05;17.05,-16.95"/>
+      </attribute>
+      <attribute name="conn_endpoints">
+        <point val="15,-17"/>
+        <point val="17,-17"/>
+      </attribute>
+      <attribute name="numcp">
+        <int val="1"/>
+      </attribute>
+      <attribute name="line_style">
+        <enum val="3"/>
+      </attribute>
+    </object>
+    <object type="Standard - Line" version="0" id="O92">
+      <attribute name="obj_pos">
+        <point val="17,-17"/>
+      </attribute>
+      <attribute name="obj_bb">
+        <rectangle val="16.15,-20.85;17.85,-16.15"/>
+      </attribute>
+      <attribute name="conn_endpoints">
+        <point val="17,-17"/>
+        <point val="17,-20"/>
+      </attribute>
+      <attribute name="numcp">
+        <int val="1"/>
+      </attribute>
+      <attribute name="line_style">
+        <enum val="3"/>
+      </attribute>
+      <attribute name="end_arrow">
+        <enum val="3"/>
+      </attribute>
+      <attribute name="end_arrow_length">
+        <real val="0.5"/>
+      </attribute>
+      <attribute name="end_arrow_width">
+        <real val="0.5"/>
+      </attribute>
+      <connections>
+        <connection handle="1" to="O75" connection="6"/>
+      </connections>
+    </object>
+    <object type="Standard - Line" version="0" id="O93">
+      <attribute name="obj_pos">
+        <point val="15,-17"/>
+      </attribute>
+      <attribute name="obj_bb">
+        <rectangle val="-11.05,-17.05;15.05,-16.95"/>
+      </attribute>
+      <attribute name="conn_endpoints">
+        <point val="15,-17"/>
+        <point val="-11,-17"/>
+      </attribute>
+      <attribute name="numcp">
+        <int val="1"/>
+      </attribute>
+      <attribute name="line_style">
+        <enum val="3"/>
+      </attribute>
+    </object>
+    <object type="Standard - Line" version="0" id="O94">
+      <attribute name="obj_pos">
+        <point val="-11,-17"/>
+      </attribute>
+      <attribute name="obj_bb">
+        <rectangle val="-11.85,-20.85;-10.15,-16.15"/>
+      </attribute>
+      <attribute name="conn_endpoints">
+        <point val="-11,-17"/>
+        <point val="-11,-20"/>
+      </attribute>
+      <attribute name="numcp">
+        <int val="1"/>
+      </attribute>
+      <attribute name="line_style">
+        <enum val="3"/>
+      </attribute>
+      <attribute name="end_arrow">
+        <enum val="3"/>
+      </attribute>
+      <attribute name="end_arrow_length">
+        <real val="0.5"/>
+      </attribute>
+      <attribute name="end_arrow_width">
+        <real val="0.5"/>
+      </attribute>
+      <connections>
+        <connection handle="1" to="O73" connection="6"/>
+      </connections>
+    </object>
+    <object type="Standard - Line" version="0" id="O95">
+      <attribute name="obj_pos">
+        <point val="-12,-20"/>
+      </attribute>
+      <attribute name="obj_bb">
+        <rectangle val="-12.05,-20.05;-11.95,-17.95"/>
+      </attribute>
+      <attribute name="conn_endpoints">
+        <point val="-12,-20"/>
+        <point val="-12,-18"/>
+      </attribute>
+      <attribute name="numcp">
+        <int val="1"/>
+      </attribute>
+    </object>
+    <object type="Standard - Line" version="0" id="O96">
+      <attribute name="obj_pos">
+        <point val="-3,-18"/>
+      </attribute>
+      <attribute name="obj_bb">
+        <rectangle val="-3.85,-18.85;-2.15,-12.15"/>
+      </attribute>
+      <attribute name="conn_endpoints">
+        <point val="-3,-18"/>
+        <point val="-3,-13"/>
+      </attribute>
+      <attribute name="numcp">
+        <int val="1"/>
+      </attribute>
+      <attribute name="end_arrow">
+        <enum val="3"/>
+      </attribute>
+      <attribute name="end_arrow_length">
+        <real val="0.5"/>
+      </attribute>
+      <attribute name="end_arrow_width">
+        <real val="0.5"/>
+      </attribute>
+    </object>
+    <object type="Standard - Line" version="0" id="O97">
+      <attribute name="obj_pos">
+        <point val="16,-20"/>
+      </attribute>
+      <attribute name="obj_bb">
+        <rectangle val="15.95,-20.05;16.05,-17.95"/>
+      </attribute>
+      <attribute name="conn_endpoints">
+        <point val="16,-20"/>
+        <point val="16,-18"/>
+      </attribute>
+      <attribute name="numcp">
+        <int val="1"/>
+      </attribute>
+    </object>
+    <object type="Standard - Text" version="0" id="O98">
+      <attribute name="obj_pos">
+        <point val="7,-17"/>
+      </attribute>
+      <attribute name="obj_bb">
+        <rectangle val="4.779,-17.7434;9.221,-16.7434"/>
+      </attribute>
+      <attribute name="text">
+        <composite type="text">
+          <attribute name="string">
+            <string>#ACQUIRE#</string>
+          </attribute>
+          <attribute name="font">
+            <font name="Courier"/>
+          </attribute>
+          <attribute name="height">
+            <real val="1"/>
+          </attribute>
+          <attribute name="pos">
+            <point val="7,-17"/>
+          </attribute>
+          <attribute name="color">
+            <color val="#000000"/>
+          </attribute>
+          <attribute name="alignment">
+            <enum val="1"/>
+          </attribute>
+        </composite>
+      </attribute>
+    </object>
+    <object type="Standard - Text" version="0" id="O99">
+      <attribute name="obj_pos">
+        <point val="7,-16"/>
+      </attribute>
+      <attribute name="obj_bb">
+        <rectangle val="5.082,-16.7434;8.918,-15.7434"/>
+      </attribute>
+      <attribute name="text">
+        <composite type="text">
+          <attribute name="string">
+            <string>#EXPIRE#</string>
+          </attribute>
+          <attribute name="font">
+            <font name="Courier"/>
+          </attribute>
+          <attribute name="height">
+            <real val="1"/>
+          </attribute>
+          <attribute name="pos">
+            <point val="7,-16"/>
+          </attribute>
+          <attribute name="color">
+            <color val="#000000"/>
+          </attribute>
+          <attribute name="alignment">
+            <enum val="1"/>
+          </attribute>
+        </composite>
+      </attribute>
+    </object>
+    <object type="Standard - Text" version="0" id="O100">
+      <attribute name="obj_pos">
+        <point val="7,-15"/>
+      </attribute>
+      <attribute name="obj_bb">
+        <rectangle val="3.87,-15.7434;10.13,-14.7434"/>
+      </attribute>
+      <attribute name="text">
+        <composite type="text">
+          <attribute name="string">
+            <string>#ADD/UPDATE#</string>
+          </attribute>
+          <attribute name="font">
+            <font name="Courier"/>
+          </attribute>
+          <attribute name="height">
+            <real val="1"/>
+          </attribute>
+          <attribute name="pos">
+            <point val="7,-15"/>
+          </attribute>
+          <attribute name="color">
+            <color val="#000000"/>
+          </attribute>
+          <attribute name="alignment">
+            <enum val="1"/>
+          </attribute>
+        </composite>
+      </attribute>
+    </object>
+    <object type="Standard - Text" version="0" id="O101">
+      <attribute name="obj_pos">
+        <point val="15,10"/>
+      </attribute>
+      <attribute name="obj_bb">
+        <rectangle val="13.688,9.25664;16.312,10.2566"/>
+      </attribute>
+      <attribute name="text">
+        <composite type="text">
+          <attribute name="string">
+            <string>#SAID#</string>
+          </attribute>
+          <attribute name="font">
+            <font name="Courier"/>
+          </attribute>
+          <attribute name="height">
+            <real val="1"/>
+          </attribute>
+          <attribute name="pos">
+            <point val="15,10"/>
+          </attribute>
+          <attribute name="color">
+            <color val="#000000"/>
+          </attribute>
+          <attribute name="alignment">
+            <enum val="1"/>
+          </attribute>
+        </composite>
+      </attribute>
+    </object>
+    <object type="Standard - Text" version="0" id="O102">
+      <attribute name="obj_pos">
+        <point val="-6,15"/>
+      </attribute>
+      <attribute name="obj_bb">
+        <rectangle val="-8.524,14.2566;-3.476,15.2566"/>
+      </attribute>
+      <attribute name="text">
+        <composite type="text">
+          <attribute name="string">
+            <string>#IPSECdev#</string>
+          </attribute>
+          <attribute name="font">
+            <font name="Courier"/>
+          </attribute>
+          <attribute name="height">
+            <real val="1"/>
+          </attribute>
+          <attribute name="pos">
+            <point val="-6,15"/>
+          </attribute>
+          <attribute name="color">
+            <color val="#000000"/>
+          </attribute>
+          <attribute name="alignment">
+            <enum val="1"/>
+          </attribute>
+        </composite>
+      </attribute>
+    </object>
+    <object type="Standard - Line" version="0" id="O103">
+      <attribute name="obj_pos">
+        <point val="9,10"/>
+      </attribute>
+      <attribute name="obj_bb">
+        <rectangle val="8.15,9.15;9.85,11.85"/>
+      </attribute>
+      <attribute name="conn_endpoints">
+        <point val="9,10"/>
+        <point val="9,11"/>
+      </attribute>
+      <attribute name="numcp">
+        <int val="1"/>
+      </attribute>
+      <attribute name="end_arrow">
+        <enum val="3"/>
+      </attribute>
+      <attribute name="end_arrow_length">
+        <real val="0.5"/>
+      </attribute>
+      <attribute name="end_arrow_width">
+        <real val="0.5"/>
+      </attribute>
+      <connections>
+        <connection handle="0" to="O20" connection="6"/>
+        <connection handle="1" to="O0" connection="1"/>
+      </connections>
+    </object>
+    <object type="Standard - Text" version="0" id="O104">
+      <attribute name="obj_pos">
+        <point val="-20,-28"/>
+      </attribute>
+      <attribute name="obj_bb">
+        <rectangle val="-20,-28.7434;5.046,-27.7434"/>
+      </attribute>
+      <attribute name="text">
+        <composite type="text">
+          <attribute name="string">
+            <string>#Linux FreeS/WAN KLIPS2 Design w/NetFilter#</string>
+          </attribute>
+          <attribute name="font">
+            <font name="Courier"/>
+          </attribute>
+          <attribute name="height">
+            <real val="1"/>
+          </attribute>
+          <attribute name="pos">
+            <point val="-20,-28"/>
+          </attribute>
+          <attribute name="color">
+            <color val="#000000"/>
+          </attribute>
+          <attribute name="alignment">
+            <enum val="0"/>
+          </attribute>
+        </composite>
+      </attribute>
+    </object>
+    <object type="Standard - Text" version="0" id="O105">
+      <attribute name="obj_pos">
+        <point val="-20,-24"/>
+      </attribute>
+      <attribute name="obj_bb">
+        <rectangle val="-20,-24.7434;20.802,-23.7434"/>
+      </attribute>
+      <attribute name="text">
+        <composite type="text">
+          <attribute name="string">
+            <string>#Version: $Id: klips2-design.dia,v 1.7 2001/05/29 18:52:13 rgb Exp $#</string>
+          </attribute>
+          <attribute name="font">
+            <font name="Courier"/>
+          </attribute>
+          <attribute name="height">
+            <real val="1"/>
+          </attribute>
+          <attribute name="pos">
+            <point val="-20,-24"/>
+          </attribute>
+          <attribute name="color">
+            <color val="#000000"/>
+          </attribute>
+          <attribute name="alignment">
+            <enum val="0"/>
+          </attribute>
+        </composite>
+      </attribute>
+    </object>
+    <object type="Standard - Text" version="0" id="O106">
+      <attribute name="obj_pos">
+        <point val="-20,-27"/>
+      </attribute>
+      <attribute name="obj_bb">
+        <rectangle val="-20,-27.7434;4.44,-26.7434"/>
+      </attribute>
+      <attribute name="text">
+        <composite type="text">
+          <attribute name="string">
+            <string>#Project website: http://www.freeswan.org#</string>
+          </attribute>
+          <attribute name="font">
+            <font name="Courier"/>
+          </attribute>
+          <attribute name="height">
+            <real val="1"/>
+          </attribute>
+          <attribute name="pos">
+            <point val="-20,-27"/>
+          </attribute>
+          <attribute name="color">
+            <color val="#000000"/>
+          </attribute>
+          <attribute name="alignment">
+            <enum val="0"/>
+          </attribute>
+        </composite>
+      </attribute>
+    </object>
+    <object type="Standard - Text" version="0" id="O107">
+      <attribute name="obj_pos">
+        <point val="1,-21"/>
+      </attribute>
+      <attribute name="obj_bb">
+        <rectangle val="-1.221,-21.7434;3.221,-20.7434"/>
+      </attribute>
+      <attribute name="text">
+        <composite type="text">
+          <attribute name="string">
+            <string>#.  .  .#</string>
+          </attribute>
+          <attribute name="font">
+            <font name="Courier"/>
+          </attribute>
+          <attribute name="height">
+            <real val="1"/>
+          </attribute>
+          <attribute name="pos">
+            <point val="1,-21"/>
+          </attribute>
+          <attribute name="color">
+            <color val="#000000"/>
+          </attribute>
+          <attribute name="alignment">
+            <enum val="1"/>
+          </attribute>
+        </composite>
+      </attribute>
+    </object>
+    <object type="Standard - Line" version="0" id="O108">
+      <attribute name="obj_pos">
+        <point val="-7,2"/>
+      </attribute>
+      <attribute name="obj_bb">
+        <rectangle val="-7.55,1.45;-4.45,2.55"/>
+      </attribute>
+      <attribute name="conn_endpoints">
+        <point val="-7,2"/>
+        <point val="-5,2"/>
+      </attribute>
+      <attribute name="numcp">
+        <int val="1"/>
+      </attribute>
+      <attribute name="start_arrow">
+        <enum val="3"/>
+      </attribute>
+      <attribute name="start_arrow_length">
+        <real val="0.5"/>
+      </attribute>
+      <attribute name="start_arrow_width">
+        <real val="0.5"/>
+      </attribute>
+      <attribute name="end_arrow">
+        <enum val="3"/>
+      </attribute>
+      <attribute name="end_arrow_length">
+        <real val="0.5"/>
+      </attribute>
+      <attribute name="end_arrow_width">
+        <real val="0.5"/>
+      </attribute>
+      <connections>
+        <connection handle="0" to="O57" connection="2"/>
+        <connection handle="1" to="O1" connection="0"/>
+      </connections>
+    </object>
+    <object type="Standard - Text" version="0" id="O109">
+      <attribute name="obj_pos">
+        <point val="-20,-25"/>
+      </attribute>
+      <attribute name="obj_bb">
+        <rectangle val="-20,-25.7434;3.834,-24.7434"/>
+      </attribute>
+      <attribute name="text">
+        <composite type="text">
+          <attribute name="string">
+            <string>#Accompanies klips/doc/klips2-design.txt#</string>
+          </attribute>
+          <attribute name="font">
+            <font name="Courier"/>
+          </attribute>
+          <attribute name="height">
+            <real val="1"/>
+          </attribute>
+          <attribute name="pos">
+            <point val="-20,-25"/>
+          </attribute>
+          <attribute name="color">
+            <color val="#000000"/>
+          </attribute>
+          <attribute name="alignment">
+            <enum val="0"/>
+          </attribute>
+        </composite>
+      </attribute>
+    </object>
+    <object type="Standard - Box" version="0" id="O110">
+      <attribute name="obj_pos">
+        <point val="-12,-13"/>
+      </attribute>
+      <attribute name="obj_bb">
+        <rectangle val="-12.05,-13.05;-6.95,-10.95"/>
+      </attribute>
+      <attribute name="elem_corner">
+        <point val="-12,-13"/>
+      </attribute>
+      <attribute name="elem_width">
+        <real val="5"/>
+      </attribute>
+      <attribute name="elem_height">
+        <real val="2"/>
+      </attribute>
+      <attribute name="show_background">
+        <boolean val="true"/>
+      </attribute>
+    </object>
+    <object type="Standard - Text" version="0" id="O111">
+      <attribute name="obj_pos">
+        <point val="-9,-12"/>
+      </attribute>
+      <attribute name="obj_bb">
+        <rectangle val="-10.918,-12.7434;-7.082,-11.7434"/>
+      </attribute>
+      <attribute name="text">
+        <composite type="text">
+          <attribute name="string">
+            <string>#seclev#</string>
+          </attribute>
+          <attribute name="font">
+            <font name="Courier"/>
+          </attribute>
+          <attribute name="height">
+            <real val="1"/>
+          </attribute>
+          <attribute name="pos">
+            <point val="-9,-12"/>
+          </attribute>
+          <attribute name="color">
+            <color val="#000000"/>
+          </attribute>
+          <attribute name="alignment">
+            <enum val="1"/>
+          </attribute>
+        </composite>
+      </attribute>
+    </object>
+    <object type="Standard - PolyLine" version="0" id="O112">
+      <attribute name="obj_pos">
+        <point val="-5,-13"/>
+      </attribute>
+      <attribute name="obj_bb">
+        <rectangle val="-7.55,-13.55;-4.45,-12.45"/>
+      </attribute>
+      <attribute name="poly_points">
+        <point val="-5,-13"/>
+        <point val="-7,-13"/>
+      </attribute>
+      <attribute name="start_arrow">
+        <enum val="3"/>
+      </attribute>
+      <attribute name="start_arrow_length">
+        <real val="0.5"/>
+      </attribute>
+      <attribute name="start_arrow_width">
+        <real val="0.5"/>
+      </attribute>
+      <attribute name="end_arrow">
+        <enum val="3"/>
+      </attribute>
+      <attribute name="end_arrow_length">
+        <real val="0.5"/>
+      </attribute>
+      <attribute name="end_arrow_width">
+        <real val="0.5"/>
+      </attribute>
+      <connections>
+        <connection handle="0" to="O2" connection="0"/>
+        <connection handle="1" to="O110" connection="2"/>
+      </connections>
+    </object>
+    <object type="Standard - Text" version="0" id="O113">
+      <attribute name="obj_pos">
+        <point val="-23,-23"/>
+      </attribute>
+      <attribute name="obj_bb">
+        <rectangle val="-23,-23.7434;-23,-22.7434"/>
+      </attribute>
+      <attribute name="text">
+        <composite type="text">
+          <attribute name="string">
+            <string>##</string>
+          </attribute>
+          <attribute name="font">
+            <font name="Courier"/>
+          </attribute>
+          <attribute name="height">
+            <real val="1"/>
+          </attribute>
+          <attribute name="pos">
+            <point val="-23,-23"/>
+          </attribute>
+          <attribute name="color">
+            <color val="#000000"/>
+          </attribute>
+          <attribute name="alignment">
+            <enum val="1"/>
+          </attribute>
+        </composite>
+      </attribute>
+    </object>
+    <object type="Standard - Text" version="0" id="O114">
+      <attribute name="obj_pos">
+        <point val="-21,-23"/>
+      </attribute>
+      <attribute name="obj_bb">
+        <rectangle val="-21,-23.7434;-21,-22.7434"/>
+      </attribute>
+      <attribute name="text">
+        <composite type="text">
+          <attribute name="string">
+            <string>##</string>
+          </attribute>
+          <attribute name="font">
+            <font name="Courier"/>
+          </attribute>
+          <attribute name="height">
+            <real val="1"/>
+          </attribute>
+          <attribute name="pos">
+            <point val="-21,-23"/>
+          </attribute>
+          <attribute name="color">
+            <color val="#000000"/>
+          </attribute>
+          <attribute name="alignment">
+            <enum val="1"/>
+          </attribute>
+        </composite>
+      </attribute>
+    </object>
+    <object type="Standard - Text" version="0" id="O115">
+      <attribute name="obj_pos">
+        <point val="7,-19"/>
+      </attribute>
+      <attribute name="obj_bb">
+        <rectangle val="4.779,-19.7434;9.221,-18.7434"/>
+      </attribute>
+      <attribute name="text">
+        <composite type="text">
+          <attribute name="string">
+            <string>#Routing#</string>
+          </attribute>
+          <attribute name="font">
+            <font name="Courier"/>
+          </attribute>
+          <attribute name="height">
+            <real val="1"/>
+          </attribute>
+          <attribute name="pos">
+            <point val="7,-19"/>
+          </attribute>
+          <attribute name="color">
+            <color val="#000000"/>
+          </attribute>
+          <attribute name="alignment">
+            <enum val="1"/>
+          </attribute>
+        </composite>
+      </attribute>
+    </object>
+    <object type="Standard - Text" version="0" id="O116">
+      <attribute name="obj_pos">
+        <point val="6.5,-18"/>
+      </attribute>
+      <attribute name="obj_bb">
+        <rectangle val="4.582,-18.7434;8.418,-17.7434"/>
+      </attribute>
+      <attribute name="text">
+        <composite type="text">
+          <attribute name="string">
+            <string>#Policy#</string>
+          </attribute>
+          <attribute name="font">
+            <font name="Courier"/>
+          </attribute>
+          <attribute name="height">
+            <real val="1"/>
+          </attribute>
+          <attribute name="pos">
+            <point val="6.5,-18"/>
+          </attribute>
+          <attribute name="color">
+            <color val="#000000"/>
+          </attribute>
+          <attribute name="alignment">
+            <enum val="1"/>
+          </attribute>
+        </composite>
+      </attribute>
+      <connections>
+        <connection handle="0" to="O121" connection="0"/>
+      </connections>
+    </object>
+    <object type="Standard - Text" version="0" id="O117">
+      <attribute name="obj_pos">
+        <point val="-26,-20"/>
+      </attribute>
+      <attribute name="obj_bb">
+        <rectangle val="-26,-20.7434;-26,-19.7434"/>
+      </attribute>
+      <attribute name="text">
+        <composite type="text">
+          <attribute name="string">
+            <string>##</string>
+          </attribute>
+          <attribute name="font">
+            <font name="Courier"/>
+          </attribute>
+          <attribute name="height">
+            <real val="1"/>
+          </attribute>
+          <attribute name="pos">
+            <point val="-26,-20"/>
+          </attribute>
+          <attribute name="color">
+            <color val="#000000"/>
+          </attribute>
+          <attribute name="alignment">
+            <enum val="1"/>
+          </attribute>
+        </composite>
+      </attribute>
+    </object>
+    <object type="Standard - Text" version="0" id="O118">
+      <attribute name="obj_pos">
+        <point val="-26,-20"/>
+      </attribute>
+      <attribute name="obj_bb">
+        <rectangle val="-26,-20.7434;-26,-19.7434"/>
+      </attribute>
+      <attribute name="text">
+        <composite type="text">
+          <attribute name="string">
+            <string>##</string>
+          </attribute>
+          <attribute name="font">
+            <font name="Courier"/>
+          </attribute>
+          <attribute name="height">
+            <real val="1"/>
+          </attribute>
+          <attribute name="pos">
+            <point val="-26,-20"/>
+          </attribute>
+          <attribute name="color">
+            <color val="#000000"/>
+          </attribute>
+          <attribute name="alignment">
+            <enum val="1"/>
+          </attribute>
+        </composite>
+      </attribute>
+    </object>
+    <object type="Standard - Text" version="0" id="O119">
+      <attribute name="obj_pos">
+        <point val="-26,-20"/>
+      </attribute>
+      <attribute name="obj_bb">
+        <rectangle val="-26,-20.7434;-26,-19.7434"/>
+      </attribute>
+      <attribute name="text">
+        <composite type="text">
+          <attribute name="string">
+            <string>##</string>
+          </attribute>
+          <attribute name="font">
+            <font name="Courier"/>
+          </attribute>
+          <attribute name="height">
+            <real val="1"/>
+          </attribute>
+          <attribute name="pos">
+            <point val="-26,-20"/>
+          </attribute>
+          <attribute name="color">
+            <color val="#000000"/>
+          </attribute>
+          <attribute name="alignment">
+            <enum val="1"/>
+          </attribute>
+        </composite>
+      </attribute>
+    </object>
+    <object type="Standard - Text" version="0" id="O120">
+      <attribute name="obj_pos">
+        <point val="-26,-20"/>
+      </attribute>
+      <attribute name="obj_bb">
+        <rectangle val="-26,-20.7434;-26,-19.7434"/>
+      </attribute>
+      <attribute name="text">
+        <composite type="text">
+          <attribute name="string">
+            <string>##</string>
+          </attribute>
+          <attribute name="font">
+            <font name="Courier"/>
+          </attribute>
+          <attribute name="height">
+            <real val="1"/>
+          </attribute>
+          <attribute name="pos">
+            <point val="-26,-20"/>
+          </attribute>
+          <attribute name="color">
+            <color val="#000000"/>
+          </attribute>
+          <attribute name="alignment">
+            <enum val="1"/>
+          </attribute>
+        </composite>
+      </attribute>
+    </object>
+    <object type="Standard - Line" version="0" id="O121">
+      <attribute name="obj_pos">
+        <point val="16,-18"/>
+      </attribute>
+      <attribute name="obj_bb">
+        <rectangle val="-3.85,-18.85;16.85,-17.15"/>
+      </attribute>
+      <attribute name="conn_endpoints">
+        <point val="16,-18"/>
+        <point val="-3,-18"/>
+      </attribute>
+      <attribute name="numcp">
+        <int val="1"/>
+      </attribute>
+      <attribute name="end_arrow">
+        <enum val="3"/>
+      </attribute>
+      <attribute name="end_arrow_length">
+        <real val="0.5"/>
+      </attribute>
+      <attribute name="end_arrow_width">
+        <real val="0.5"/>
+      </attribute>
+    </object>
+    <object type="Standard - Line" version="0" id="O122">
+      <attribute name="obj_pos">
+        <point val="-12,-18"/>
+      </attribute>
+      <attribute name="obj_bb">
+        <rectangle val="-12.85,-18.85;-2.15,-17.15"/>
+      </attribute>
+      <attribute name="conn_endpoints">
+        <point val="-12,-18"/>
+        <point val="-3,-18"/>
+      </attribute>
+      <attribute name="numcp">
+        <int val="1"/>
+      </attribute>
+      <attribute name="end_arrow">
+        <enum val="3"/>
+      </attribute>
+      <attribute name="end_arrow_length">
+        <real val="0.5"/>
+      </attribute>
+      <attribute name="end_arrow_width">
+        <real val="0.5"/>
+      </attribute>
+    </object>
+    <object type="Standard - Line" version="0" id="O123">
+      <attribute name="obj_pos">
+        <point val="7,7"/>
+      </attribute>
+      <attribute name="obj_bb">
+        <rectangle val="4.15,6.15;7.85,7.85"/>
+      </attribute>
+      <attribute name="conn_endpoints">
+        <point val="7,7"/>
+        <point val="5,7"/>
+      </attribute>
+      <attribute name="numcp">
+        <int val="1"/>
+      </attribute>
+      <attribute name="end_arrow">
+        <enum val="3"/>
+      </attribute>
+      <attribute name="end_arrow_length">
+        <real val="0.5"/>
+      </attribute>
+      <attribute name="end_arrow_width">
+        <real val="0.5"/>
+      </attribute>
+      <connections>
+        <connection handle="0" to="O53" connection="5"/>
+      </connections>
+    </object>
+    <object type="Standard - Box" version="0" id="O124">
+      <attribute name="obj_pos">
+        <point val="15,13"/>
+      </attribute>
+      <attribute name="obj_bb">
+        <rectangle val="14.95,12.95;21.05,15.05"/>
+      </attribute>
+      <attribute name="elem_corner">
+        <point val="15,13"/>
+      </attribute>
+      <attribute name="elem_width">
+        <real val="6"/>
+      </attribute>
+      <attribute name="elem_height">
+        <real val="2"/>
+      </attribute>
+      <attribute name="show_background">
+        <boolean val="true"/>
+      </attribute>
+    </object>
+    <object type="Standard - Text" version="0" id="O125">
+      <attribute name="obj_pos">
+        <point val="18,14"/>
+      </attribute>
+      <attribute name="obj_bb">
+        <rectangle val="15.173,13.2566;20.827,14.2566"/>
+      </attribute>
+      <attribute name="text">
+        <composite type="text">
+          <attribute name="string">
+            <string>#ipsec_rcv#</string>
+          </attribute>
+          <attribute name="font">
+            <font name="Courier"/>
+          </attribute>
+          <attribute name="height">
+            <real val="1"/>
+          </attribute>
+          <attribute name="pos">
+            <point val="18,14"/>
+          </attribute>
+          <attribute name="color">
+            <color val="#000000"/>
+          </attribute>
+          <attribute name="alignment">
+            <enum val="1"/>
+          </attribute>
+        </composite>
+      </attribute>
+    </object>
+    <object type="Standard - ZigZagLine" version="0" id="O126">
+      <attribute name="obj_pos">
+        <point val="18,11"/>
+      </attribute>
+      <attribute name="obj_bb">
+        <rectangle val="17.15,4.15;18.85,11.85"/>
+      </attribute>
+      <attribute name="orth_points">
+        <point val="18,11"/>
+        <point val="18,9"/>
+        <point val="18,9"/>
+        <point val="18,5"/>
+      </attribute>
+      <attribute name="orth_orient">
+        <enum val="1"/>
+        <enum val="0"/>
+        <enum val="1"/>
+      </attribute>
+      <attribute name="end_arrow">
+        <enum val="3"/>
+      </attribute>
+      <attribute name="end_arrow_length">
+        <real val="0.5"/>
+      </attribute>
+      <attribute name="end_arrow_width">
+        <real val="0.5"/>
+      </attribute>
+      <connections>
+        <connection handle="1" to="O59" connection="6"/>
+      </connections>
+    </object>
+    <object type="Standard - ZigZagLine" version="0" id="O127">
+      <attribute name="obj_pos">
+        <point val="7,13"/>
+      </attribute>
+      <attribute name="obj_bb">
+        <rectangle val="1.15,12.15;7.85,15.85"/>
+      </attribute>
+      <attribute name="orth_points">
+        <point val="7,13"/>
+        <point val="7,15"/>
+        <point val="2,15"/>
+        <point val="2,14"/>
+      </attribute>
+      <attribute name="orth_orient">
+        <enum val="1"/>
+        <enum val="0"/>
+        <enum val="1"/>
+      </attribute>
+      <attribute name="end_arrow">
+        <enum val="3"/>
+      </attribute>
+      <attribute name="end_arrow_length">
+        <real val="0.5"/>
+      </attribute>
+      <attribute name="end_arrow_width">
+        <real val="0.5"/>
+      </attribute>
+      <connections>
+        <connection handle="0" to="O0" connection="5"/>
+      </connections>
+    </object>
+    <object type="Standard - Text" version="0" id="O128">
+      <attribute name="obj_pos">
+        <point val="15,19"/>
+      </attribute>
+      <attribute name="obj_bb">
+        <rectangle val="8.234,18.2566;21.766,19.2566"/>
+      </attribute>
+      <attribute name="text">
+        <composite type="text">
+          <attribute name="string">
+            <string>#Transport Layer De-mux#</string>
+          </attribute>
+          <attribute name="font">
+            <font name="Courier"/>
+          </attribute>
+          <attribute name="height">
+            <real val="1"/>
+          </attribute>
+          <attribute name="pos">
+            <point val="15,19"/>
+          </attribute>
+          <attribute name="color">
+            <color val="#000000"/>
+          </attribute>
+          <attribute name="alignment">
+            <enum val="1"/>
+          </attribute>
+        </composite>
+      </attribute>
+    </object>
+    <object type="Standard - Line" version="0" id="O129">
+      <attribute name="obj_pos">
+        <point val="19,18"/>
+      </attribute>
+      <attribute name="obj_bb">
+        <rectangle val="18.15,14.15;19.85,18.85"/>
+      </attribute>
+      <attribute name="conn_endpoints">
+        <point val="19,18"/>
+        <point val="19,15"/>
+      </attribute>
+      <attribute name="numcp">
+        <int val="1"/>
+      </attribute>
+      <attribute name="end_arrow">
+        <enum val="3"/>
+      </attribute>
+      <attribute name="end_arrow_length">
+        <real val="0.5"/>
+      </attribute>
+      <attribute name="end_arrow_width">
+        <real val="0.5"/>
+      </attribute>
+    </object>
+    <object type="Standard - Box" version="0" id="O130">
+      <attribute name="obj_pos">
+        <point val="7,2"/>
+      </attribute>
+      <attribute name="obj_bb">
+        <rectangle val="6.95,1.95;11.05,4.05"/>
+      </attribute>
+      <attribute name="elem_corner">
+        <point val="7,2"/>
+      </attribute>
+      <attribute name="elem_width">
+        <real val="4"/>
+      </attribute>
+      <attribute name="elem_height">
+        <real val="2"/>
+      </attribute>
+      <attribute name="show_background">
+        <boolean val="true"/>
+      </attribute>
+    </object>
+    <object type="Standard - Text" version="0" id="O131">
+      <attribute name="obj_pos">
+        <point val="9,3"/>
+      </attribute>
+      <attribute name="obj_bb">
+        <rectangle val="7.688,2.25664;10.312,3.25664"/>
+      </attribute>
+      <attribute name="text">
+        <composite type="text">
+          <attribute name="string">
+            <string>#PEEK#</string>
+          </attribute>
+          <attribute name="font">
+            <font name="Courier"/>
+          </attribute>
+          <attribute name="height">
+            <real val="1"/>
+          </attribute>
+          <attribute name="pos">
+            <point val="9,3"/>
+          </attribute>
+          <attribute name="color">
+            <color val="#000000"/>
+          </attribute>
+          <attribute name="alignment">
+            <enum val="1"/>
+          </attribute>
+        </composite>
+      </attribute>
+    </object>
+    <object type="Standard - Line" version="0" id="O132">
+      <attribute name="obj_pos">
+        <point val="5,2"/>
+      </attribute>
+      <attribute name="obj_bb">
+        <rectangle val="4.15,1.15;7.85,2.85"/>
+      </attribute>
+      <attribute name="conn_endpoints">
+        <point val="5,2"/>
+        <point val="7,2"/>
+      </attribute>
+      <attribute name="numcp">
+        <int val="1"/>
+      </attribute>
+      <attribute name="end_arrow">
+        <enum val="3"/>
+      </attribute>
+      <attribute name="end_arrow_length">
+        <real val="0.5"/>
+      </attribute>
+      <attribute name="end_arrow_width">
+        <real val="0.5"/>
+      </attribute>
+      <connections>
+        <connection handle="0" to="O1" connection="2"/>
+        <connection handle="1" to="O130" connection="0"/>
+      </connections>
+    </object>
+    <object type="Standard - Line" version="0" id="O133">
+      <attribute name="obj_pos">
+        <point val="11,2"/>
+      </attribute>
+      <attribute name="obj_bb">
+        <rectangle val="10.15,1.15;15.85,2.85"/>
+      </attribute>
+      <attribute name="conn_endpoints">
+        <point val="11,2"/>
+        <point val="15,2"/>
+      </attribute>
+      <attribute name="numcp">
+        <int val="1"/>
+      </attribute>
+      <attribute name="line_style">
+        <enum val="3"/>
+      </attribute>
+      <attribute name="end_arrow">
+        <enum val="3"/>
+      </attribute>
+      <attribute name="end_arrow_length">
+        <real val="0.5"/>
+      </attribute>
+      <attribute name="end_arrow_width">
+        <real val="0.5"/>
+      </attribute>
+      <connections>
+        <connection handle="0" to="O130" connection="2"/>
+      </connections>
+    </object>
+    <object type="Standard - PolyLine" version="0" id="O134">
+      <attribute name="obj_pos">
+        <point val="15,5"/>
+      </attribute>
+      <attribute name="obj_bb">
+        <rectangle val="14.15,1.15;15.85,5.85"/>
+      </attribute>
+      <attribute name="poly_points">
+        <point val="15,5"/>
+        <point val="15,2"/>
+      </attribute>
+      <attribute name="line_style">
+        <enum val="3"/>
+      </attribute>
+      <attribute name="end_arrow">
+        <enum val="3"/>
+      </attribute>
+      <attribute name="end_arrow_length">
+        <real val="0.5"/>
+      </attribute>
+      <attribute name="end_arrow_width">
+        <real val="0.5"/>
+      </attribute>
+    </object>
+    <object type="Standard - ZigZagLine" version="0" id="O135">
+      <attribute name="obj_pos">
+        <point val="15,15"/>
+      </attribute>
+      <attribute name="obj_bb">
+        <rectangle val="0.15,13.15;15.85,16.85"/>
+      </attribute>
+      <attribute name="orth_points">
+        <point val="15,15"/>
+        <point val="15,16"/>
+        <point val="1,16"/>
+        <point val="1,14"/>
+      </attribute>
+      <attribute name="orth_orient">
+        <enum val="1"/>
+        <enum val="0"/>
+        <enum val="1"/>
+      </attribute>
+      <attribute name="end_arrow">
+        <enum val="3"/>
+      </attribute>
+      <attribute name="end_arrow_length">
+        <real val="0.5"/>
+      </attribute>
+      <attribute name="end_arrow_width">
+        <real val="0.5"/>
+      </attribute>
+      <connections>
+        <connection handle="0" to="O124" connection="5"/>
+        <connection handle="1" to="O47" connection="5"/>
+      </connections>
+    </object>
+    <object type="Standard - ZigZagLine" version="0" id="O136">
+      <attribute name="obj_pos">
+        <point val="18,11"/>
+      </attribute>
+      <attribute name="obj_bb">
+        <rectangle val="17.15,10.15;18.85,13.85"/>
+      </attribute>
+      <attribute name="orth_points">
+        <point val="18,11"/>
+        <point val="18,12.1539"/>
+        <point val="18,12.1539"/>
+        <point val="18,13"/>
+      </attribute>
+      <attribute name="orth_orient">
+        <enum val="1"/>
+        <enum val="0"/>
+        <enum val="1"/>
+      </attribute>
+      <attribute name="end_arrow">
+        <enum val="3"/>
+      </attribute>
+      <attribute name="end_arrow_length">
+        <real val="0.5"/>
+      </attribute>
+      <attribute name="end_arrow_width">
+        <real val="0.5"/>
+      </attribute>
+      <connections>
+        <connection handle="1" to="O124" connection="1"/>
+      </connections>
+    </object>
+    <object type="Standard - Line" version="0" id="O137">
+      <attribute name="obj_pos">
+        <point val="7,4"/>
+      </attribute>
+      <attribute name="obj_bb">
+        <rectangle val="4.15,3.15;7.85,4.85"/>
+      </attribute>
+      <attribute name="conn_endpoints">
+        <point val="7,4"/>
+        <point val="5,4"/>
+      </attribute>
+      <attribute name="numcp">
+        <int val="1"/>
+      </attribute>
+      <attribute name="end_arrow">
+        <enum val="3"/>
+      </attribute>
+      <attribute name="end_arrow_length">
+        <real val="0.5"/>
+      </attribute>
+      <attribute name="end_arrow_width">
+        <real val="0.5"/>
+      </attribute>
+      <connections>
+        <connection handle="0" to="O130" connection="5"/>
+      </connections>
+    </object>
+    <object type="Standard - Box" version="0" id="O138">
+      <attribute name="obj_pos">
+        <point val="-12,-9"/>
+      </attribute>
+      <attribute name="obj_bb">
+        <rectangle val="-12.05,-9.05;-6.95,-6.95"/>
+      </attribute>
+      <attribute name="elem_corner">
+        <point val="-12,-9"/>
+      </attribute>
+      <attribute name="elem_width">
+        <real val="5"/>
+      </attribute>
+      <attribute name="elem_height">
+        <real val="2"/>
+      </attribute>
+      <attribute name="show_background">
+        <boolean val="true"/>
+      </attribute>
+    </object>
+    <object type="Standard - Text" version="0" id="O139">
+      <attribute name="obj_pos">
+        <point val="-9,-8"/>
+      </attribute>
+      <attribute name="obj_bb">
+        <rectangle val="-10.918,-8.74336;-7.082,-7.74336"/>
+      </attribute>
+      <attribute name="text">
+        <composite type="text">
+          <attribute name="string">
+            <string>#salist#</string>
+          </attribute>
+          <attribute name="font">
+            <font name="Courier"/>
+          </attribute>
+          <attribute name="height">
+            <real val="1"/>
+          </attribute>
+          <attribute name="pos">
+            <point val="-9,-8"/>
+          </attribute>
+          <attribute name="color">
+            <color val="#000000"/>
+          </attribute>
+          <attribute name="alignment">
+            <enum val="1"/>
+          </attribute>
+        </composite>
+      </attribute>
+    </object>
+    <object type="Standard - PolyLine" version="0" id="O140">
+      <attribute name="obj_pos">
+        <point val="-5,-9"/>
+      </attribute>
+      <attribute name="obj_bb">
+        <rectangle val="-7.55,-9.55;-4.45,-8.45"/>
+      </attribute>
+      <attribute name="poly_points">
+        <point val="-5,-9"/>
+        <point val="-7,-9"/>
+      </attribute>
+      <attribute name="start_arrow">
+        <enum val="3"/>
+      </attribute>
+      <attribute name="start_arrow_length">
+        <real val="0.5"/>
+      </attribute>
+      <attribute name="start_arrow_width">
+        <real val="0.5"/>
+      </attribute>
+      <attribute name="end_arrow">
+        <enum val="3"/>
+      </attribute>
+      <attribute name="end_arrow_length">
+        <real val="0.5"/>
+      </attribute>
+      <attribute name="end_arrow_width">
+        <real val="0.5"/>
+      </attribute>
+      <connections>
+        <connection handle="0" to="O5" connection="5"/>
+        <connection handle="1" to="O138" connection="2"/>
+      </connections>
+    </object>
+    <object type="Standard - Box" version="0" id="O141">
+      <attribute name="obj_pos">
+        <point val="-12,6"/>
+      </attribute>
+      <attribute name="obj_bb">
+        <rectangle val="-12.05,5.95;-6.95,8.05"/>
+      </attribute>
+      <attribute name="elem_corner">
+        <point val="-12,6"/>
+      </attribute>
+      <attribute name="elem_width">
+        <real val="5"/>
+      </attribute>
+      <attribute name="elem_height">
+        <real val="2"/>
+      </attribute>
+      <attribute name="show_background">
+        <boolean val="true"/>
+      </attribute>
+    </object>
+    <object type="Standard - Text" version="0" id="O142">
+      <attribute name="obj_pos">
+        <point val="-9,7"/>
+      </attribute>
+      <attribute name="obj_bb">
+        <rectangle val="-10.918,6.25664;-7.082,7.25664"/>
+      </attribute>
+      <attribute name="text">
+        <composite type="text">
+          <attribute name="string">
+            <string>#salist#</string>
+          </attribute>
+          <attribute name="font">
+            <font name="Courier"/>
+          </attribute>
+          <attribute name="height">
+            <real val="1"/>
+          </attribute>
+          <attribute name="pos">
+            <point val="-9,7"/>
+          </attribute>
+          <attribute name="color">
+            <color val="#000000"/>
+          </attribute>
+          <attribute name="alignment">
+            <enum val="1"/>
+          </attribute>
+        </composite>
+      </attribute>
+    </object>
+    <object type="Standard - PolyLine" version="0" id="O143">
+      <attribute name="obj_pos">
+        <point val="-5,6"/>
+      </attribute>
+      <attribute name="obj_bb">
+        <rectangle val="-7.55,5.45;-4.45,6.55"/>
+      </attribute>
+      <attribute name="poly_points">
+        <point val="-5,6"/>
+        <point val="-7,6"/>
+      </attribute>
+      <attribute name="start_arrow">
+        <enum val="3"/>
+      </attribute>
+      <attribute name="start_arrow_length">
+        <real val="0.5"/>
+      </attribute>
+      <attribute name="start_arrow_width">
+        <real val="0.5"/>
+      </attribute>
+      <attribute name="end_arrow">
+        <enum val="3"/>
+      </attribute>
+      <attribute name="end_arrow_length">
+        <real val="0.5"/>
+      </attribute>
+      <attribute name="end_arrow_width">
+        <real val="0.5"/>
+      </attribute>
+      <connections>
+        <connection handle="1" to="O141" connection="2"/>
+      </connections>
+    </object>
+    <object type="Standard - Box" version="0" id="O144">
+      <attribute name="obj_pos">
+        <point val="-20,18"/>
+      </attribute>
+      <attribute name="obj_bb">
+        <rectangle val="-20.05,17.95;-9.95,20.05"/>
+      </attribute>
+      <attribute name="elem_corner">
+        <point val="-20,18"/>
+      </attribute>
+      <attribute name="elem_width">
+        <real val="10"/>
+      </attribute>
+      <attribute name="elem_height">
+        <real val="2"/>
+      </attribute>
+      <attribute name="show_background">
+        <boolean val="true"/>
+      </attribute>
+    </object>
+    <object type="Standard - Box" version="0" id="O145">
+      <attribute name="obj_pos">
+        <point val="-20,15"/>
+      </attribute>
+      <attribute name="obj_bb">
+        <rectangle val="-20.05,14.95;-9.95,17.05"/>
+      </attribute>
+      <attribute name="elem_corner">
+        <point val="-20,15"/>
+      </attribute>
+      <attribute name="elem_width">
+        <real val="10"/>
+      </attribute>
+      <attribute name="elem_height">
+        <real val="2"/>
+      </attribute>
+      <attribute name="show_background">
+        <boolean val="true"/>
+      </attribute>
+    </object>
+    <object type="Standard - Text" version="0" id="O146">
+      <attribute name="obj_pos">
+        <point val="-15,16"/>
+      </attribute>
+      <attribute name="obj_bb">
+        <rectangle val="-19.948,15.2566;-10.052,16.2566"/>
+      </attribute>
+      <attribute name="text">
+        <composite type="text">
+          <attribute name="string">
+            <string>#NF_IP_POST_ROUTE#</string>
+          </attribute>
+          <attribute name="font">
+            <font name="Courier"/>
+          </attribute>
+          <attribute name="height">
+            <real val="1"/>
+          </attribute>
+          <attribute name="pos">
+            <point val="-15,16"/>
+          </attribute>
+          <attribute name="color">
+            <color val="#000000"/>
+          </attribute>
+          <attribute name="alignment">
+            <enum val="1"/>
+          </attribute>
+        </composite>
+      </attribute>
+    </object>
+    <object type="Standard - Text" version="0" id="O147">
+      <attribute name="obj_pos">
+        <point val="-15,19"/>
+      </attribute>
+      <attribute name="obj_bb">
+        <rectangle val="-19.645,18.2566;-10.355,19.2566"/>
+      </attribute>
+      <attribute name="text">
+        <composite type="text">
+          <attribute name="string">
+            <string>#NF_IP_PRE_ROUTE#</string>
+          </attribute>
+          <attribute name="font">
+            <font name="Courier"/>
+          </attribute>
+          <attribute name="height">
+            <real val="1"/>
+          </attribute>
+          <attribute name="pos">
+            <point val="-15,19"/>
+          </attribute>
+          <attribute name="color">
+            <color val="#000000"/>
+          </attribute>
+          <attribute name="alignment">
+            <enum val="1"/>
+          </attribute>
+        </composite>
+      </attribute>
+    </object>
+    <object type="Standard - ZigZagLine" version="0" id="O148">
+      <attribute name="obj_pos">
+        <point val="-10,17"/>
+      </attribute>
+      <attribute name="obj_bb">
+        <rectangle val="-10.85,13.15;-1.15,17.85"/>
+      </attribute>
+      <attribute name="orth_points">
+        <point val="-10,17"/>
+        <point val="-10,17"/>
+        <point val="-2,17"/>
+        <point val="-2,14"/>
+      </attribute>
+      <attribute name="orth_orient">
+        <enum val="1"/>
+        <enum val="0"/>
+        <enum val="1"/>
+      </attribute>
+      <attribute name="end_arrow">
+        <enum val="3"/>
+      </attribute>
+      <attribute name="end_arrow_length">
+        <real val="0.5"/>
+      </attribute>
+      <attribute name="end_arrow_width">
+        <real val="0.5"/>
+      </attribute>
+      <connections>
+        <connection handle="0" to="O145" connection="7"/>
+      </connections>
+    </object>
+    <object type="Standard - ZigZagLine" version="0" id="O149">
+      <attribute name="obj_pos">
+        <point val="-10,18"/>
+      </attribute>
+      <attribute name="obj_bb">
+        <rectangle val="-10.85,13.15;-0.15,18.85"/>
+      </attribute>
+      <attribute name="orth_points">
+        <point val="-10,18"/>
+        <point val="-10,18"/>
+        <point val="-1,18"/>
+        <point val="-1,14"/>
+      </attribute>
+      <attribute name="orth_orient">
+        <enum val="1"/>
+        <enum val="0"/>
+        <enum val="1"/>
+      </attribute>
+      <attribute name="end_arrow">
+        <enum val="3"/>
+      </attribute>
+      <attribute name="end_arrow_length">
+        <real val="0.5"/>
+      </attribute>
+      <attribute name="end_arrow_width">
+        <real val="0.5"/>
+      </attribute>
+      <connections>
+        <connection handle="0" to="O144" connection="2"/>
+        <connection handle="1" to="O37" connection="7"/>
+      </connections>
+    </object>
+    <object type="Standard - Box" version="0" id="O150">
+      <attribute name="obj_pos">
+        <point val="7,-7"/>
+      </attribute>
+      <attribute name="obj_bb">
+        <rectangle val="6.95,-7.05;11.05,-4.95"/>
+      </attribute>
+      <attribute name="elem_corner">
+        <point val="7,-7"/>
+      </attribute>
+      <attribute name="elem_width">
+        <real val="4"/>
+      </attribute>
+      <attribute name="elem_height">
+        <real val="2"/>
+      </attribute>
+      <attribute name="show_background">
+        <boolean val="true"/>
+      </attribute>
+    </object>
+    <object type="Standard - Box" version="0" id="O151">
+      <attribute name="obj_pos">
+        <point val="7,-10"/>
+      </attribute>
+      <attribute name="obj_bb">
+        <rectangle val="6.95,-10.05;11.05,-7.95"/>
+      </attribute>
+      <attribute name="elem_corner">
+        <point val="7,-10"/>
+      </attribute>
+      <attribute name="elem_width">
+        <real val="4"/>
+      </attribute>
+      <attribute name="elem_height">
+        <real val="2"/>
+      </attribute>
+      <attribute name="show_background">
+        <boolean val="true"/>
+      </attribute>
+    </object>
+    <object type="Standard - Text" version="0" id="O152">
+      <attribute name="obj_pos">
+        <point val="9,-9"/>
+      </attribute>
+      <attribute name="obj_bb">
+        <rectangle val="7.688,-9.74336;10.312,-8.74336"/>
+      </attribute>
+      <attribute name="text">
+        <composite type="text">
+          <attribute name="string">
+            <string>#TRAP#</string>
+          </attribute>
+          <attribute name="font">
+            <font name="Courier"/>
+          </attribute>
+          <attribute name="height">
+            <real val="1"/>
+          </attribute>
+          <attribute name="pos">
+            <point val="9,-9"/>
+          </attribute>
+          <attribute name="color">
+            <color val="#000000"/>
+          </attribute>
+          <attribute name="alignment">
+            <enum val="1"/>
+          </attribute>
+        </composite>
+      </attribute>
+    </object>
+    <object type="Standard - Text" version="0" id="O153">
+      <attribute name="obj_pos">
+        <point val="9,-6"/>
+      </attribute>
+      <attribute name="obj_bb">
+        <rectangle val="7.688,-6.74336;10.312,-5.74336"/>
+      </attribute>
+      <attribute name="text">
+        <composite type="text">
+          <attribute name="string">
+            <string>#HOLD#</string>
+          </attribute>
+          <attribute name="font">
+            <font name="Courier"/>
+          </attribute>
+          <attribute name="height">
+            <real val="1"/>
+          </attribute>
+          <attribute name="pos">
+            <point val="9,-6"/>
+          </attribute>
+          <attribute name="color">
+            <color val="#000000"/>
+          </attribute>
+          <attribute name="alignment">
+            <enum val="1"/>
+          </attribute>
+        </composite>
+      </attribute>
+    </object>
+    <object type="Standard - Line" version="0" id="O154">
+      <attribute name="obj_pos">
+        <point val="5,-10"/>
+      </attribute>
+      <attribute name="obj_bb">
+        <rectangle val="4.45,-10.55;7.55,-9.45"/>
+      </attribute>
+      <attribute name="conn_endpoints">
+        <point val="5,-10"/>
+        <point val="7,-10"/>
+      </attribute>
+      <attribute name="numcp">
+        <int val="1"/>
+      </attribute>
+      <attribute name="line_width">
+        <real val="0.1"/>
+      </attribute>
+      <attribute name="start_arrow">
+        <enum val="3"/>
+      </attribute>
+      <attribute name="start_arrow_length">
+        <real val="0.5"/>
+      </attribute>
+      <attribute name="start_arrow_width">
+        <real val="0.5"/>
+      </attribute>
+      <attribute name="end_arrow">
+        <enum val="3"/>
+      </attribute>
+      <attribute name="end_arrow_length">
+        <real val="0.5"/>
+      </attribute>
+      <attribute name="end_arrow_width">
+        <real val="0.5"/>
+      </attribute>
+      <connections>
+        <connection handle="1" to="O151" connection="0"/>
+      </connections>
+    </object>
+    <object type="Standard - Line" version="0" id="O155">
+      <attribute name="obj_pos">
+        <point val="5,-7"/>
+      </attribute>
+      <attribute name="obj_bb">
+        <rectangle val="4.45,-7.55;7.55,-6.45"/>
+      </attribute>
+      <attribute name="conn_endpoints">
+        <point val="5,-7"/>
+        <point val="7,-7"/>
+      </attribute>
+      <attribute name="numcp">
+        <int val="1"/>
+      </attribute>
+      <attribute name="line_width">
+        <real val="0.1"/>
+      </attribute>
+      <attribute name="start_arrow">
+        <enum val="3"/>
+      </attribute>
+      <attribute name="start_arrow_length">
+        <real val="0.5"/>
+      </attribute>
+      <attribute name="start_arrow_width">
+        <real val="0.5"/>
+      </attribute>
+      <attribute name="end_arrow">
+        <enum val="3"/>
+      </attribute>
+      <attribute name="end_arrow_length">
+        <real val="0.5"/>
+      </attribute>
+      <attribute name="end_arrow_width">
+        <real val="0.5"/>
+      </attribute>
+      <connections>
+        <connection handle="0" to="O23" connection="2"/>
+        <connection handle="1" to="O150" connection="0"/>
+      </connections>
+    </object>
+    <object type="Standard - Box" version="0" id="O156">
+      <attribute name="obj_pos">
+        <point val="7,-13"/>
+      </attribute>
+      <attribute name="obj_bb">
+        <rectangle val="6.95,-13.05;11.05,-10.95"/>
+      </attribute>
+      <attribute name="elem_corner">
+        <point val="7,-13"/>
+      </attribute>
+      <attribute name="elem_width">
+        <real val="4"/>
+      </attribute>
+      <attribute name="elem_height">
+        <real val="2"/>
+      </attribute>
+      <attribute name="show_background">
+        <boolean val="true"/>
+      </attribute>
+    </object>
+    <object type="Standard - Text" version="0" id="O157">
+      <attribute name="obj_pos">
+        <point val="9,-12"/>
+      </attribute>
+      <attribute name="obj_bb">
+        <rectangle val="7.688,-12.7434;10.312,-11.7434"/>
+      </attribute>
+      <attribute name="text">
+        <composite type="text">
+          <attribute name="string">
+            <string>#PEEK#</string>
+          </attribute>
+          <attribute name="font">
+            <font name="Courier"/>
+          </attribute>
+          <attribute name="height">
+            <real val="1"/>
+          </attribute>
+          <attribute name="pos">
+            <point val="9,-12"/>
+          </attribute>
+          <attribute name="color">
+            <color val="#000000"/>
+          </attribute>
+          <attribute name="alignment">
+            <enum val="1"/>
+          </attribute>
+        </composite>
+      </attribute>
+    </object>
+    <object type="Standard - Line" version="0" id="O158">
+      <attribute name="obj_pos">
+        <point val="5,-13"/>
+      </attribute>
+      <attribute name="obj_bb">
+        <rectangle val="4.45,-13.55;7.55,-12.45"/>
+      </attribute>
+      <attribute name="conn_endpoints">
+        <point val="5,-13"/>
+        <point val="7,-13"/>
+      </attribute>
+      <attribute name="numcp">
+        <int val="1"/>
+      </attribute>
+      <attribute name="line_width">
+        <real val="0.1"/>
+      </attribute>
+      <attribute name="start_arrow">
+        <enum val="3"/>
+      </attribute>
+      <attribute name="start_arrow_length">
+        <real val="0.5"/>
+      </attribute>
+      <attribute name="start_arrow_width">
+        <real val="0.5"/>
+      </attribute>
+      <attribute name="end_arrow">
+        <enum val="3"/>
+      </attribute>
+      <attribute name="end_arrow_length">
+        <real val="0.5"/>
+      </attribute>
+      <attribute name="end_arrow_width">
+        <real val="0.5"/>
+      </attribute>
+      <connections>
+        <connection handle="0" to="O2" connection="2"/>
+        <connection handle="1" to="O156" connection="0"/>
+      </connections>
+    </object>
+    <object type="Standard - ZigZagLine" version="0" id="O159">
+      <attribute name="obj_pos">
+        <point val="17,11"/>
+      </attribute>
+      <attribute name="obj_bb">
+        <rectangle val="16.15,4.15;17.85,11.85"/>
+      </attribute>
+      <attribute name="orth_points">
+        <point val="17,11"/>
+        <point val="17,9"/>
+        <point val="17,9"/>
+        <point val="17,5"/>
+      </attribute>
+      <attribute name="orth_orient">
+        <enum val="1"/>
+        <enum val="0"/>
+        <enum val="1"/>
+      </attribute>
+      <attribute name="end_arrow">
+        <enum val="3"/>
+      </attribute>
+      <attribute name="end_arrow_length">
+        <real val="0.5"/>
+      </attribute>
+      <attribute name="end_arrow_width">
+        <real val="0.5"/>
+      </attribute>
+    </object>
+    <object type="Standard - Line" version="0" id="O160">
+      <attribute name="obj_pos">
+        <point val="17,11"/>
+      </attribute>
+      <attribute name="obj_bb">
+        <rectangle val="10.15,10.15;17.85,11.85"/>
+      </attribute>
+      <attribute name="conn_endpoints">
+        <point val="17,11"/>
+        <point val="11,11"/>
+      </attribute>
+      <attribute name="numcp">
+        <int val="1"/>
+      </attribute>
+      <attribute name="end_arrow">
+        <enum val="3"/>
+      </attribute>
+      <attribute name="end_arrow_length">
+        <real val="0.5"/>
+      </attribute>
+      <attribute name="end_arrow_width">
+        <real val="0.5"/>
+      </attribute>
+      <connections>
+        <connection handle="1" to="O0" connection="2"/>
+      </connections>
+    </object>
+  </layer>
+</diagram>
diff -bruN freeswan-1.9.orig/klips/doc/klips2-design.txt freeswan-1.9/klips/doc/klips2-design.txt
--- freeswan-1.9.orig/klips/doc/klips2-design.txt	Wed Dec 31 19:00:00 1969
+++ freeswan-1.9/klips/doc/klips2-design.txt	Mon Jun  4 12:54:57 2001
@@ -0,0 +1,383 @@
+#  -*- mode: Outline; fill-column: 78; fill-prefix: "	" -*-
+#
+#  klips2-design.txt
+#	Richard Guy Briggs <rgb@conscoop.ottawa.on.ca>
+#
+#  RCSID $Id: klips2-design.txt,v 1.16 2001/06/01 07:26:15 rgb Exp $
+#
+
+* Outline Commands cheat sheet (C-c C-s to see this)
+        C-c C-t         Hide EVERYTHING in buffer
+        C-c C-a         Show EVERYTHING in buffer
+
+        C-c C-d         Hide THIS item and subitems (subtree)
+        C-c C-s         Show THIS item and subitems (subtree)
+
+        C-c C-c         Hide ONE item
+        C-c C-e         Show ONE item
+
+* Introduction
+
+Linux FreeS/WAN IPSec -- KLIPS2 DESIGN
+======================================
+
+# This document outlines the proposed design for KLIPS2, the second
+# generation Linux FreeS/WAN IPSec kernel implementation.  It is
+# accompanied by the following:
+#
+# klips2-design.dia		dia(1) diagram
+# klips2-design-legend.txt	diagram legend
+# klips2-design-api.txt		API descriptions
+# klips2-design-api-trips.txt	scenarios that force trips through the
+#				various APIs to verify all needed resources
+#				are available
+
+# This document is devided up into Introduction, Goals, Feature requests,
+# Packet path overview, NetFilter overview, IPSec path description, and
+# Other issues.
+#
+# This document was originally written 2.5 weeks after OLS2000, inspired
+# from a meeting with Rusty and Marc Boucher in Montreal in November 1999
+# and two meetings at OLS2000.
+#
+# Please comment to the linux-ipsec, netfilter-devel or netdev lists.
+#
+# Current kernel version reference is 2.4.4 with iptables 1.2
+
+* Goals:
+
+	To get rid of the current IPSec virtual interfaces that associate with
+	a specific physical network interfaces and replace them with IPSec
+	virtual interfaces that specify a local gateway address as a source
+	address, a remote gateway address as a destination address and
+	specific tunnel policy or SAs.
+
+	To use existing packet matching engines rather than re-invent.
+
+	To support more of the required selectors, especially source and
+	destination ports, and possibly userid.  Security labels are not of
+	obvious value, but the selectors will be easy to add in the future if
+	they are implemented in the Linux kernel.
+
+	To get access to *all* packets incoming and outgoing to enforce policy
+	in both directions.
+
+	To better support opportunistic encryption.
+
+	To take advantage of the parallellism of SMP and H/W encryption.
+
+	To make encryption and authentication modular.
+
+The idea is to redesign KLIPS (kernel parts of FreeS/WAN) to avoid all the
+'stoopid routing tricks' (TM) to which we have had to resort since the project
+started by disassociating any IPSec devices from physical devices and to add a
+proper SPDB to do proper incoming IPSec policy checks.  We are hoping to use
+existing pattern-matching tools rather than invent our own.  NetFilter appears
+to have all the pattern matching capabilities with the exception of security
+labels which Linux doesn't appear to have anyways, but may be limited in other
+ways.
+
+There is also a significant interest in enabling FreeS/WAN to communicate with
+routing daemons and be able to do load sharing and failover:
+
+	http://www.quintillion.com/fdis/moat/ipsec+routing/
+
+
+
+* Feature requests:
+
+Code=Level/Status/Priority
+Level:
+	S = strategic
+	M = middle
+	T = tactical
+	U = unset
+Status:
+	U = unstarted
+	C = coded
+	T = tested
+	D = deleted
+Priority:
+	H = high
+	M = medium
+	L = low
+	U = unset
+	D = deprecated
+
+Code	Feature		Implementation
+====	=======		==============
+S/U/U	changeable gw wild-side addresses on-the-fly
+			- road warriors with RSA keys and hooks from DHCP
+			  to move to a new set of SAs upon expiry of previous
+			  DHCP lease.  Notify peers.  Negociate new tunnels.
+			  Handle delayed or denied renewal see: conn up, down,
+			  wanted.
+M/U/U	address inertia for remote gw's with changeable wild-side addresses
+	so local gw reboots will initiate reconnect to remotes.
+			- this requires a disk cache.
+T/U/U	mini-database of road warriors that persists across reboots.
+			- this requires a disk cache.
+M/U/U	connection up, down, wanted
+			- 
+S/U/U	routing below tunnel layer to support mobility and multi-homing
+			-
+M/U/U	tunnel identified by subnets served?
+			-
+M/U/U	why do equalizing schedulers not play well with tunnels?
+			-
+M/U/U	decouple SA retrieval from DADDR (don't care how it arrived)
+			- protocol redesign
+T/U/U	SPIs unique, independant of protocol and DADDR
+			- 
+S/U/U	routing above tunnel layer
+			-
+S/U/U	granularity smaller than host
+			- SPORT, DPORT, UID, SecLev
+M/U/U	/dev/ipsecNNN devices that could be chown(1)ed and chmod(1)ed.
+
+M/U/U	process to process tunnels
+
+T/U/U	netfilter,pf_key,ioctl,/dev/ipsecNNN ways to manipulate tunnel perms.
+
+S/U/U	KLIPS as a loadable module (isn't it already?)
+
+S/U/U	stats: {number,time_of_last} packets {out,good_in,error_in}
+
+S/U/U	integrate IPSec and firewall policy into Security Policy.
+	(What APIs and user-level tools?)
+
+S/U/U	full inbound policy checking
+S/U/U	secure ciphers and hashes
+T/U/U	kernel implementation (should be faster)
+S/U/U	plays well with routing daemons
+S/U/U	free of export restrictions
+T/U/U	standard crypto api to add newer ciphers and hashes
+S/U/U	opportunistic
+T/U/U	SADB hash table will be locked for additions/deletions
+T/U/U	use a refcount on each SA to increase locking granularity
+
+
+
+* Packet path overview:
+
+The basic path through the kernel as it concerns IPSec for the three
+types of packets is as follows:
+
+IN:
+	NIC
+	basic sanity checks
+	NF_IP_PRE_ROUTING hook
+	route-in
+	ip-options processing
+	defragmentation
+	NF_IP_LOCAL_IN hook
+	transport layer demux
+	application
+
+FORWARD:
+	NIC
+	basic sanity checks
+	NF_IP_PRE_ROUTING hook
+	routing-in
+	ip-options processing
+	ttl decrement and check
+	NF_IP_FORWARD hook
+	fragmentation
+	NF_IP_POST_ROUTING hook
+	fragmentation
+	output()
+	NIC
+
+OUT:
+	application
+	transport layer mux
+	NF_IP_LOCAL_OUT hook
+	route-out
+	NF_IP_POST_ROUTING hook
+	fragmentation
+	output()
+	NIC
+
+
+
+* NetFilter overview:
+
+The basic architecture of NetFilter is:
+
+       --->[1]--->(ROUTE)--->[3]--->[4]--->     where:
+                     |            ^             [1] NF_IP_PRE_ROUTING
+                     |            |             [2] NF_IP_LOCAL_IN
+                     |         (ROUTE)          [3] NF_IP_FORWARD
+                     v            |             [4] NF_IP_POST_ROUTING
+                    [2]          [5]            [5] NF_IP_LOCAL_OUT
+                     |            ^             
+                     |            |             
+                     v            |             
+
+Destination NAT (port forwarding) gets applied in NF_IP_PRE_ROUTING and
+NF_IP_LOCAL_OUT at priority NF_IP_PRIORITY_DNAT = -100, and Source NAT
+(masquerading) gets applied in NF_IP_POST_ROUTING at priority
+NF_IP_PRIORITY_SNAT = 100, .  Filtering is applied in NF_IP_LOCAL_IN,
+NF_IP_FORWARD and NF_IP_LOCAL_OUT at priority NF_IP_PRIORITY_FILTER = 0.
+
+
+Hook processing order would generally be:
+<PRE>
+PRE	IN	FWD	OUT	POST	PRIORITY MACRO         PRI
+=======.=======.=======.=======.=======.=================== = ====
+-500?  .       .       .       .       .NF_IP_PRI_IPSEC_IN  = -500 (?)
+-200   .       .       .-200   .       .NF_IP_PRI_CONNTRACK = -200
+-175? . . . . . . . . . . . . . . . . .	NF_IP_PRI_IPSEC_IN  = -175 (?)
+-150   .       .       .-150   .       .NF_IP_PRI_MANGLE    = -150
+-100   .       .       .-100   .       .NF_IP_PRI_NAT_DST   = -100
+. . . . . .0. . . .0. .	. .0. . . . . . NF_IP_PRI_FILTER    =    0
+       .       .       .       . 100   .NF_IP_PRI_NAT_SRC   =  100
+       .       .       .       . 500   .NF_IP_PRI_IPSEC_OUT =  500
+=======.=======.=======.=======.=======.=================== = ====
+</PRE>
+
+Not all modules are present at each hook.  I am uncertain still if IPSEC_IN
+should be before or after CONNTRACK.  Any comments?
+
+
+
+* IPSec path description:
+
+Treat incoming IPSec encapsulation as a transport layer protocol and
+decapsulate it at the transport layer demultiplexer since it appears as a
+transport layer protocol from the bottom of the Internet Protocol network
+stack.  For outgoing, we treat IPSec as a network layer protocol since that is
+what IPSec appears to be from the top of the IP stack.
+
+An incoming packet starts off with a sanity check.  It then goes through all
+the NF_IP_PRE_ROUTING hooks starting with the SPDB checking.  It would have
+several possible targets: DROP; REJECT; ACCEPT; PEEK.  DROP, REJECT, ACCEPT
+are standard NetFilter targets.  It would DROP if it should have been
+encrypted.  REJECT is a special case of DROP where an ICMP is returned.  It
+would ACCEPT if it was an encrypted IPSec packet bound for this machine and no
+other policy was expected first, it had already been decrypted from expected
+SAs indicated by nfmarks or virtual IPSec device or there was policy to allow
+it through.  PEEK would let the KMd have a look at the packet to see if it
+needed to start thinking about opportunistic and then pass it on.  Since it is
+a fresh ESP or AH packet, it will not have any nfmarks or virtual IPSec device
+association and unless that outer IP header should have been processed by
+another SG in between, no policy will have been required, letting it through.
+
+The rest of the NF_IP_PRE_ROUTING hooks may cause it to be DNATed and
+defragmented.  It then goes through routing which thinks it is a local packet,
+deals with any outer header IP options, then defragmentation and
+NF_IP_LOCAL_IN filter (allow ESP,AH) before getting to ipsec_rcv() where the
+outer bundle is authenticated and decrypted and nfmarked or associated with a
+virtual IPSec device to indicate what decapsulation happenned before being
+passed back to netif_rx().  The next IP header is now visible.  The packet now
+gets re-injected at the beginning.  It goes through the incoming sanity check
+again, getting checked at NF_IP_PRE_ROUTING for policy using previously set
+nfmark or virtual IPSec device from decryption.  It may again be DNATed and
+defragmented.  Routing looks at the now-visible next IP header and routes it
+locally or via the forward hook.
+
+If it is a local packet, IP options and defragmentation are processed.
+NF_IP_LOCAL_IN then gets to check filtering policy for other transport layer
+protocols.  If it is the endpoint for nested bundles, it is sent back to
+netif_rx(), having exposed the next IP header.
+
+If it is not a local packet, routing has selected a route, potentially through
+an existing virtual IPSec device, one per connection, not per physical I/F.
+IP options and TTL are processed before being filtered at NF_IP_FORWARD,
+fragmented, then sent to NF_IP_POST_ROUTING.
+
+If it is a locally generated packet, it would go through normal filtering at
+NF_IP_LOCAL_OUT, then go through routing, then be sent to NF_IP_POST_ROUTING.
+
+At NF_IP_POST_ROUTING, the ipsec table would make a decision about the fate of
+the packet.  It would have several possible targets: ACCEPT; IPSEC SAList;
+DROP; REJECT; TRAP; HOLD.  ACCEPT would allow the packet through with no
+processing.  IPSEC would return NF_STOLEN, stealing the packet and applying
+the policy specified by its parameter of an SA list.  If the SA(s) do(es)n't
+exist(s) or if the TRAP target was specified, it would send up an ACQUIRE to
+all listening key management daemons via PF_KEYv2 and put in a HOLD that would
+keep only the last packet that matched for that HOLD, waiting for the
+appropriate SA(s).  If or once the SA(s) is/are available, it then IPSec
+processes the packet, then re-injects the packet at NF_IP_LOCAL_OUT (since the
+packet now appears to originate from this host) and sets nfmark or associates
+it with a virtual IPSec device to indicate what processing happenned.  The
+packet would then be routed and sent back to NF_IP_POST_ROUTING.  If the IPSec
+remote security gateway is not different upon policy lookup, the ipsec table
+would ACCEPT it.  DROP would drop the packet if previous attempts to do
+opportunistic encryption failed and the default policy was to block non-IPSec
+packets.  REJECT would be almost the same as DROP, except that it returns
+ICMPs.  ACCEPT, DROP, REJECT are standard NetFilter targets.
+
+A packet routed through an optional IPSec virtual I/F simply gets assigned a
+specific source address, and has the nfmark/SA list preloaded.
+
+
+
+* Other issues:
+
+The way that nfmark is used is rather vague.  It is presently only 32 bits.
+Ideally, I would like to be able to indicate exactly which SAs were processed
+on the way in, which would most easily be represented by as many as 4 SAs (AH,
+ESP, IPCOMP, IPIP), each having an 8 bit protocol field (absolute minimum of
+2-bits), 32-bit destination address field (for IPv4, IPv6 would be 128) and a
+32-bit SPI.  This is a potential maximum of 672 bits.  A way of mapping 672
+bits on to the 32 bits available would be required to use this.  A lookup
+table could be used to map nfmarks to SAIDs, not the SAs themselves, since the
+SAs could disappear at any time the SADB is not locked.  It should be
+able to represent a bundle of SAs where one SA could be used in more than one
+bundle.  There could also be more than one right answer for the incoming SPDB.
+I have an idea how to accomplish this by changing/extending nfmark by
+converting it to a list of nfmark structures that contain a pointer to the
+next item on the list, a cookie for the specific netfilter function that owns
+the data and a pointer to a data structure.
+
+nfmark may not be the right tool for this.  Another possible solution is to
+add a member to the struct sk_buff to point to this information.  This has the
+benefit of not depending on anyone else, but the drawback of needing to patch
+a header file *and recompiling the entire kernel*.  There is also the
+possibility of using the NetFilter Connection Tracking facility.
+
+The SADB would be managed via the PF_KEYv2 socket I/F.
+
+The SPDB would be managed via a combination of PF_KEYv2 socket I/F extensions
+and iptables.  A separate NetFilter table called 'ipsec' (as opposed to
+'filter', 'nat' or 'mangle') would have the first hook at NF_IP_PRE_ROUTING
+and the last hook at NF_IP_POST_ROUTING.  iptables(8) currently uses
+get/set_sockopt(2) system calles, but there is discussion of having it
+converted to use the AF_NETLINK socket family.  Having it use a PF_POLICY
+interface that was interoperable with multiple platforms would be a big win.
+
+For matches, we have source/destination address/mask/port, userid (owner) and
+security label.  source/destination address/mask/port and userid are already
+supplied by iptables.  We only need to supply security label, if we even think
+we need it.
+
+
+For targets, how do we do this?  SPDB with policies, or name specific SAs, SA
+chains or SA lists or even virtual IPSec devices.  Currently, we name specific
+SAs which are chained exclusively together.
+ 
+We could have a target iptables library and kernel module that has a target of
+IPSEC which:
+	1. names a specific SA/chain which are unsharable
+	2. lists SAs to apply which are sharable
+	3. names a specific virtual IPSec device which implies a list of SAs
+	4. spec's req'd policy, ie.: cipher, hash, shared?, remote gw
+		(pfs should not be and option)
+ 
+I am favouring option number 2.  Option number 3 would map to number 2 in the
+SPDB.
+ 
+SAs would still be stored in a SADB hash table.  The prev and next fields of
+struct ipsec_sa would be removed if SAs were no longer chained, but were
+listed in lists, either from a direct list, virtual IPSec device or from an
+SPDB.
+
+
+We could use one table for ipsec matching or maybe use one table for each of
+ipsec_in and ipsec_out.  It would have to use a table separate from filter,
+nat or mangle since we need an input NF_IP_PREROUTE priority of less than -200
+(CONNTRACK) and an output NF_IP_POST_ROUTING priority of more than 200
+(CONNTRACK?).  I suggest NF_IP_PRIORITY_IPSEC_IN = -500 and
+NF_IP_PRIORITY_IPSEC_OUT = 500.
+
diff -bruN freeswan-1.9.orig/klips/doc/modes.html freeswan-1.9/klips/doc/modes.html
--- freeswan-1.9.orig/klips/doc/modes.html	Tue Apr  6 00:54:23 1999
+++ freeswan-1.9/klips/doc/modes.html	Mon Jun  4 12:54:57 2001
@@ -1,6 +1,6 @@
 <!-- 
-    RCSID $Id: modes.html,v 1.8 1999/04/06 04:54:23 rgb Exp $
---!>
+    RCSID $Id: modes.html,v 1.9 2001/04/19 18:54:53 rgb Exp $
+-->
 
 <HTML>
   <HEAD>
@@ -925,8 +925,11 @@
 
 <!--
     $Log: modes.html,v $
+    Revision 1.9  2001/04/19 18:54:53  rgb
+    Fixed HTML comment terminator.
+
     Revision 1.8  1999/04/06 04:54:23  rgb
     Fix/Add RCSID Id: and Log: bits to make PHMDs happy.  This includes
     patch shell fixes.
 
---!>
+-->
diff -bruN freeswan-1.9.orig/klips/net/ipsec/Config.in freeswan-1.9/klips/net/ipsec/Config.in
--- freeswan-1.9.orig/klips/net/ipsec/Config.in	Fri Sep 15 07:37:00 2000
+++ freeswan-1.9/klips/net/ipsec/Config.in	Mon Jun  4 11:34:31 2001
@@ -27,6 +27,7 @@
 bool '   IPSEC: Encapsulating Security Payload' CONFIG_IPSEC_ESP
 if [ "$CONFIG_IPSEC_ESP" = "y" ]; then
   bool '      3DES encryption algorithm' CONFIG_IPSEC_ENC_3DES
+  bool '      DES encryption algorithm' CONFIG_IPSEC_ENC_DES
 fi
 
 bool '   IPSEC: IP Compression' CONFIG_IPSEC_IPCOMP
diff -bruN freeswan-1.9.orig/klips/net/ipsec/Makefile freeswan-1.9/klips/net/ipsec/Makefile
--- freeswan-1.9.orig/klips/net/ipsec/Makefile	Mon Jan 29 17:19:06 2001
+++ freeswan-1.9/klips/net/ipsec/Makefile	Tue Jun 12 15:56:33 2001
@@ -54,6 +54,7 @@
 EXTRA_CFLAGS += -Wbad-function-cast 
 
 obj-$(CONFIG_IPSEC_ENC_3DES) += libdes/libdes.a
+obj-$(CONFIG_IPSEC_ENC_DES) += libdes/libdes.a
 obj-$(CONFIG_IPSEC_AUTH_HMAC_MD5) += ipsec_md5c.o
 obj-$(CONFIG_IPSEC_AUTH_HMAC_SHA1) += ipsec_sha1.o
 obj-$(CONFIG_IPSEC_IPCOMP) += ipcomp.o zlib/zlib.a
diff -bruN freeswan-1.9.orig/klips/net/ipsec/defconfig freeswan-1.9/klips/net/ipsec/defconfig
--- freeswan-1.9.orig/klips/net/ipsec/defconfig	Thu Nov 30 12:26:56 2000
+++ freeswan-1.9/klips/net/ipsec/defconfig	Mon Jun  4 11:34:31 2001
@@ -43,6 +43,7 @@
 
 # Encryption algorithm(s):
 CONFIG_IPSEC_ENC_3DES=y
+CONFIG_IPSEC_ENC_DES=y
 
 # IP Compression: new, probably still has minor bugs.
 CONFIG_IPSEC_IPCOMP=y
diff -bruN freeswan-1.9.orig/klips/net/ipsec/ipcomp.c freeswan-1.9/klips/net/ipsec/ipcomp.c
--- freeswan-1.9.orig/klips/net/ipsec/ipcomp.c	Mon Jan 29 17:19:22 2001
+++ freeswan-1.9/klips/net/ipsec/ipcomp.c	Mon Jun  4 11:34:31 2001
@@ -14,7 +14,7 @@
  * for more details.
  */
 
-char ipcomp_c_version[] = "RCSID $Id: ipcomp.c,v 1.20 2001/01/29 22:19:22 rgb Exp $";
+char ipcomp_c_version[] = "RCSID $Id: ipcomp.c,v 1.22 2001/05/05 03:31:41 rgb Exp $";
 
 /* SSS */
 
@@ -136,7 +136,7 @@
 	}
 	
 	/* Don't compress packets already fragmented */
-	if (ntohs(iph->frag_off) & ~0x4000) {
+	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");
@@ -707,7 +707,9 @@
 		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;
diff -bruN freeswan-1.9.orig/klips/net/ipsec/ipsec_encap.h freeswan-1.9/klips/net/ipsec/ipsec_encap.h
--- freeswan-1.9.orig/klips/net/ipsec/ipsec_encap.h	Fri Sep  8 15:12:56 2000
+++ freeswan-1.9/klips/net/ipsec/ipsec_encap.h	Mon Jun  4 12:54:13 2001
@@ -13,18 +13,27 @@
  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  * for more details.
  *
- * RCSID $Id: ipsec_encap.h,v 1.11 2000/09/08 19:12:56 rgb Exp $
+ * RCSID $Id: ipsec_encap.h,v 1.12 2001/05/27 06:12:10 rgb Exp $
  */
 
 #define SENT_IP4	0x0008		/* data is two struct in_addr */
+			/* (2 * sizeof(struct in_addr)) */
+			/* sizeof(struct sockaddr_encap)
+			   - offsetof(struct sockaddr_encap, Sen.Sip4.Src) */
 
 #define SEN_HDRLEN	(2*sizeof(__u8)+sizeof(__u16))
+			/* offsetof(struct sockaddr_encap, Sen.Sip4.Src) */
 
 #define SEN_IP4_SRCOFF	(0)
 #define SEN_IP4_DSTOFF (sizeof (struct in_addr))
+			/* offsetof(struct sockaddr_encap, Sen.Sip4.Dst)
+			   - offsetof(struct sockaddr_encap, Sen.Sip4.Src) */
 #define SEN_IP4_OPTOFF	(2 * sizeof (struct in_addr))
+			/* sizeof(struct sockaddr_encap)
+			   - offsetof(struct sockaddr_encap, Sen.Sip4.Src) */
 
 #define SEN_IP4_LEN	(SENT_HDRLEN + SENT_IP4_OPTOFF)
+			/* sizeof(struct sockaddr_encap) */
 
 #ifdef CONFIG_IPSEC_DEBUG
 #define DB_ER_PROCFS	0x0001
@@ -79,11 +88,13 @@
  * radix tree entry and a SAID (a destination_address/SPI/protocol triple).
  */
 
-struct
-eroute
+struct eroute
 {
 	struct rjtentry er_rjt;
 	struct sa_id er_said;
+	uint32_t er_pid;
+	uint32_t er_count;
+	uint64_t er_lasttime;
 	struct sockaddr_encap er_eaddr;
 	struct sockaddr_encap er_emask;
 };
@@ -106,6 +117,10 @@
 
 /*
  * $Log: ipsec_encap.h,v $
+ * 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.
  *
diff -bruN freeswan-1.9.orig/klips/net/ipsec/ipsec_esp.h freeswan-1.9/klips/net/ipsec/ipsec_esp.h
--- freeswan-1.9.orig/klips/net/ipsec/ipsec_esp.h	Fri Sep  8 15:12:56 2000
+++ freeswan-1.9/klips/net/ipsec/ipsec_esp.h	Tue Jun 12 15:21:15 2001
@@ -40,6 +40,27 @@
 #define DB_ES_OH	0x0400
 #define DB_ES_REPLAY	0x0800
 
+struct espdesold_xdata
+{
+       int     edx_ivlen;              /* 4 or 8 */
+       union
+       {
+               __u8    Iv[8];          /* that's enough space */
+               __u32   Ivl[2];
+               __u64   Ivq;
+       }Iu;
+#define edx_iv Iu.Iv
+#define edx_ivl Iu.Ivl
+#define edx_ivq Iu.Ivq
+       union
+       {
+               __u8 Rk[8];
+               __u32 Eks[16][2];
+       }Xu;
+#define edx_rk Xu.Rk
+#define edx_eks        Xu.Eks
+};
+
 struct espblkrply_edata
 {
 	__u16	eme_klen;		/* encryption key length */
@@ -64,6 +85,19 @@
 };
 
 #ifdef __KERNEL__
+struct espdesmd5_xdata
+{
+       __u8    edmx_flags;             /* same as before */
+       __u8    edmx_ooowin;            /* out-of-order window size */
+       __u16   edmx_ivlen;             /* IV length */
+       __u32   edmx_bitmap;            /* this&next should be 4 bytes each */
+       __u32   edmx_lastseq;           /* in host order */
+       __u32   edmx_eks[16][2];        /* the key schedule */
+       __u32   edmx_iv[2];             /* constant IV */
+       MD5_CTX edmx_ictx;              /* derived from HMAC_key */
+       MD5_CTX edmx_octx;              /* ditto */
+};
+
 struct esp3desmd5_xdata
 {
 	__u8	edmx_flags;		/* same as before */
@@ -89,6 +123,19 @@
 	MD5_CTX edmx_octx;		/* ditto */
 };
 
+struct espdessha1_xdata
+{
+       __u8    edmx_flags;             /* same as before */
+       __u8    edmx_ooowin;            /* out-of-order window size */
+       __u16   edmx_ivlen;             /* IV length */
+       __u32   edmx_bitmap;            /* this&next should be 4 bytes each */
+       __u32   edmx_lastseq;           /* in host order */
+       __u32   edmx_eks[16][2];        /* the key schedule */
+       __u32   edmx_iv[2];             /* constant IV */
+       SHA1_CTX edmx_ictx;             /* derived from HMAC_key */
+       SHA1_CTX edmx_octx;             /* ditto */
+};
+
 struct esp3dessha1_xdata
 {
 	__u8	edmx_flags;		/* same as before */
@@ -114,6 +161,17 @@
 	SHA1_CTX edmx_octx;		/* ditto */
 };
 
+struct espdes_xdata
+{
+       __u8    edmx_flags;             /* same as before */
+       __u8    edmx_ooowin;            /* out-of-order window size */
+       __u16   edmx_ivlen;             /* IV length */
+       __u32   edmx_bitmap;            /* this&next should be 4 bytes each */
+       __u32   edmx_lastseq;           /* in host order */
+       __u32   edmx_eks[16][2];        /* the key schedule */
+       __u32   edmx_iv[2];             /* constant IV */
+};
+
 struct esp3des_xdata
 {
 	__u8	edmx_flags;		/* same as before */
@@ -165,9 +223,6 @@
  * $Log: ipsec_esp.h,v $
  * 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.
diff -bruN freeswan-1.9.orig/klips/net/ipsec/ipsec_init.c freeswan-1.9/klips/net/ipsec/ipsec_init.c
--- freeswan-1.9.orig/klips/net/ipsec/ipsec_init.c	Mon Feb 26 19:50:59 2001
+++ freeswan-1.9/klips/net/ipsec/ipsec_init.c	Mon Jun  4 12:54:13 2001
@@ -14,7 +14,7 @@
  * for more details.
  */
 
-char ipsec_init_c_version[] = "RCSID $Id: ipsec_init.c,v 1.63.2.1 2001/02/27 00:50:59 henry Exp $";
+char ipsec_init_c_version[] = "RCSID $Id: ipsec_init.c,v 1.68 2001/05/29 05:14:36 rgb Exp $";
 
 #include <linux/config.h>
 #include <linux/version.h>
@@ -100,9 +100,12 @@
 #endif /* CONFIG_IPSEC_DEBUG */
 
 	KLIPS_PRINT(debug_tunnel & DB_TN_PROCFS,
-		    "klips_debug:ipsec_eroute_get_info: buffer=0x%p,"
-		    " *start=0x%x, offset=%d, length=%d\n",
-		    buffer, (u_int)*start, (int)offset, length);
+		    "klips_debug:ipsec_eroute_get_info: "
+		    "buffer=0x%p, *start=0x%x, offset=%d, length=%d\n",
+		    buffer,
+		    (u_int)*start,
+		    (int)offset,
+		    length);
 
 	spin_lock_bh(&eroute_lock);
 
@@ -140,16 +143,19 @@
 	size_t sa_len;
 
 	KLIPS_PRINT(debug_tunnel & DB_TN_PROCFS,
-		    "klips_debug:ipsec_spi_get_info: buffer=0x%p,"
-		    "*start=0x%x, offset=%d, length=%d\n",
-		    buffer, (u_int)*start, (int)offset, length);
+		    "klips_debug:ipsec_spi_get_info: "
+		    "buffer=0x%p, *start=0x%x, offset=%d, length=%d\n",
+		    buffer,
+		    (u_int)*start,
+		    (int)offset,
+		    length);
 	
 	spin_lock_bh(&tdb_lock);
 	
 	for (i = 0; i < TDB_HASHMOD; i++) {
 		for (tdbp = tdbh[i]; tdbp; tdbp = tdbp->tdb_hnext) {
 			sa_len = satoa(tdbp->tdb_said, 0, sa, SATOA_BUF);
-			len += sprintf(buffer + len, "%s ", sa);
+			len += sprintf(buffer + len, "%s ", sa_len ? sa : " (error)");
 			len += sprintf(buffer + len, "%s%s%s", TDB_XFORM_NAME(tdbp));
 			len += sprintf(buffer + len, ": dir=%s",
 				       (tdbp->tdb_flags & EMT_INBOUND) ?
@@ -381,9 +387,12 @@
 	size_t sa_len;
 
 	KLIPS_PRINT(debug_tunnel & DB_TN_PROCFS,
-		    "klips_debug:ipsec_spigrp_get_info: buffer=0x%p,"
-		    " *start=0x%x, offset=%d, length=%d\n",
-		    buffer, (u_int)*start, (int)offset, length);
+		    "klips_debug:ipsec_spigrp_get_info: "
+		    "buffer=0x%p, *start=0x%x, offset=%d, length=%d\n",
+		    buffer,
+		    (u_int)*start,
+		    (int)offset,
+		    length);
 
 	spin_lock_bh(&tdb_lock);
 	
@@ -396,7 +405,7 @@
 				while(tdbp2) {
 					sa_len = satoa(tdbp2->tdb_said, 0, sa, SATOA_BUF);
 					len += sprintf(buffer + len, "%s ",
-						       sa);
+						       sa_len ? sa : " (error)");
 					tdbp2 = tdbp2->tdb_onext;
 				}
 				len += sprintf(buffer + len, "\n");
@@ -440,9 +449,12 @@
 	struct ipsecpriv *priv;
 
 	KLIPS_PRINT(debug_tunnel & DB_TN_PROCFS,
-		    "klips_debug:ipsec_tncfg_get_info: buffer=0x%p,"
-		    "*start=0x%x, offset=%d, length=%d\n",
-		    buffer, (u_int)*start, (int)offset, length);
+		    "klips_debug:ipsec_tncfg_get_info: "
+		    "buffer=0x%p, *start=0x%x, offset=%d, length=%d\n",
+		    buffer,
+		    (u_int)*start,
+		    (int)offset,
+		    length);
 
 	for(i = 0; i < IPSEC_NUM_IF; i++) {
 		sprintf(name, "ipsec%d", i);
@@ -455,8 +467,10 @@
 				privdev = (struct device *)(priv->dev);
 				len += sprintf(buffer + len, " -> %s",
 					       privdev ? privdev->name : "NULL");
-				len += sprintf(buffer + len, " mtu=%d -> %d",
-					       /* priv */ dev->mtu, privdev ? privdev->mtu : 0);
+				len += sprintf(buffer + len, " mtu=%d(%d) -> %d",
+					       dev->mtu,
+					       priv->mtu,
+					       privdev ? privdev->mtu : 0);
 			} else {
 				KLIPS_PRINT(debug_tunnel & DB_TN_PROCFS,
 					    "klips_debug:ipsec_tncfg_get_info: device '%s' has no private data space!\n",
@@ -497,7 +511,10 @@
 	KLIPS_PRINT(debug_tunnel & DB_TN_PROCFS,
 		    "klips_debug:ipsec_version_get_info: "
 		    "buffer=0x%p, *start=0x%x, offset=%d, length=%d\n",
-		    buffer, (u_int)*start, (int)offset, length);
+		    buffer,
+		    (u_int)*start,
+		    (int)offset,
+		    length);
 
 	len += sprintf(buffer + len, "FreeS/WAN version: %s\n", freeswan_version);
 #if 0
@@ -541,9 +558,12 @@
 	off_t begin = 0;
 
 	KLIPS_PRINT(debug_tunnel & DB_TN_PROCFS,
-		    "klips_debug:ipsec_klipsdebug_get_info: buffer=0x%p,"
-		    "*start=0x%x, offset=%d, length=%d\n",
-		    buffer, (u_int)*start, (int)offset, length);
+		    "klips_debug:ipsec_klipsdebug_get_info: "
+		    "buffer=0x%p, *start=0x%x, offset=%d, length=%d\n",
+		    buffer,
+		    (u_int)*start,
+		    (int)offset,
+		    length);
 
 	len += sprintf(buffer + len, "debug_tunnel=%08x.\n", debug_tunnel);
 	len += sprintf(buffer + len, "debug_netlink=%08x.\n", debug_netlink);
@@ -655,22 +675,22 @@
 #ifdef CONFIG_PROC_FS
 #  ifndef PROC_FS_2325
 #    ifdef PROC_FS_21
-	proc_register(proc_net, &ipsec_eroute);
-	proc_register(proc_net, &ipsec_spi);
-	proc_register(proc_net, &ipsec_spigrp);
-	proc_register(proc_net, &ipsec_tncfg);
-	proc_register(proc_net, &ipsec_version);
+	error |= proc_register(proc_net, &ipsec_eroute);
+	error |= proc_register(proc_net, &ipsec_spi);
+	error |= proc_register(proc_net, &ipsec_spigrp);
+	error |= proc_register(proc_net, &ipsec_tncfg);
+	error |= proc_register(proc_net, &ipsec_version);
 #      ifdef CONFIG_IPSEC_DEBUG
-	proc_register(proc_net, &ipsec_klipsdebug);
+	error |= proc_register(proc_net, &ipsec_klipsdebug);
 #      endif /* CONFIG_IPSEC_DEBUG */
 #    else /* PROC_FS_21 */
-	proc_register_dynamic(&proc_net, &ipsec_eroute);
-	proc_register_dynamic(&proc_net, &ipsec_spi);
-	proc_register_dynamic(&proc_net, &ipsec_spigrp);
-	proc_register_dynamic(&proc_net, &ipsec_tncfg);
-	proc_register_dynamic(&proc_net, &ipsec_version);
+	error |= proc_register_dynamic(&proc_net, &ipsec_eroute);
+	error |= proc_register_dynamic(&proc_net, &ipsec_spi);
+	error |= proc_register_dynamic(&proc_net, &ipsec_spigrp);
+	error |= proc_register_dynamic(&proc_net, &ipsec_tncfg);
+	error |= proc_register_dynamic(&proc_net, &ipsec_version);
 #      ifdef CONFIG_IPSEC_DEBUG
-	proc_register_dynamic(&proc_net, &ipsec_klipsdebug);
+	error |= proc_register_dynamic(&proc_net, &ipsec_klipsdebug);
 #      endif /* CONFIG_IPSEC_DEBUG */
 #    endif /* PROC_FS_21 */
 #  else /* !PROC_FS_2325 */
@@ -685,7 +705,8 @@
 #  endif /* !PROC_FS_2325 */
 #endif          /* CONFIG_PROC_FS */
 
-	printk("IPsec: KLIPS startup, FreeS/WAN version: %s\n",
+	printk("klips_debug:ipsec_init: "
+	       "KLIPS startup, FreeS/WAN IPSec version: %s\n",
 	       freeswan_version);
 
 #ifndef SPINLOCK
@@ -698,7 +719,7 @@
 
 	error |= pfkey_init();
 
-	register_netdevice_notifier(&ipsec_dev_notifier);
+	error |= register_netdevice_notifier(&ipsec_dev_notifier);
 
 #ifdef CONFIG_IPSEC_ESP
 	inet_add_protocol(&esp_protocol);
@@ -733,53 +754,66 @@
         ipsec_sysctl_unregister();
 #endif                                                                          
 	KLIPS_PRINT(debug_netlink, /* debug_tunnel & DB_TN_INIT, */
-		    "klips_debug:ipsec_cleanup: calling ipsec_tunnel_cleanup_devices.\n");
+		    "klips_debug:ipsec_cleanup: "
+		    "calling ipsec_tunnel_cleanup_devices.\n");
 	error |= ipsec_tunnel_cleanup_devices();
 
 #if 0
 #ifdef CONFIG_IPSEC_IPCOMP
   if (inet_del_protocol(&comp_protocol) < 0)
-    printk(KERN_INFO "klips_debug:ipsec_cleanup:comp close: can't remove protocol\n");
+		printk(KERN_INFO "klips_debug:ipsec_cleanup: "
+		       "comp close: can't remove protocol\n");
 #endif
 #endif
 #ifdef CONFIG_IPSEC_AH
-	if ( inet_del_protocol(&ah_protocol) < 0 )
-		printk(KERN_INFO "klips_debug:ipsec_cleanup:ah close: can't remove protocol\n");
+	if (inet_del_protocol(&ah_protocol) < 0)
+		printk(KERN_INFO "klips_debug:ipsec_cleanup: "
+		       "ah close: can't remove protocol\n");
 #endif /* CONFIG_IPSEC_AH */
 #ifdef CONFIG_IPSEC_ESP
-	if ( inet_del_protocol(&esp_protocol) < 0 )
-		printk(KERN_INFO "klips_debug:ipsec_cleanup:esp close: can't remove protocol\n");
+	if (inet_del_protocol(&esp_protocol) < 0)
+		printk(KERN_INFO "klips_debug:ipsec_cleanup: "
+		       "esp close: can't remove protocol\n");
 #endif /* CONFIG_IPSEC_ESP */
 
-	unregister_netdevice_notifier(&ipsec_dev_notifier);
+	error |= unregister_netdevice_notifier(&ipsec_dev_notifier);
 
 	KLIPS_PRINT(debug_netlink, /* debug_tunnel & DB_TN_INIT, */
-		    "klips_debug:ipsec_cleanup: calling ipsec_tdbcleanup.\n");
+		    "klips_debug:ipsec_cleanup: "
+		    "calling ipsec_tdbcleanup.\n");
 	error |= ipsec_tdbcleanup(0);
 	KLIPS_PRINT(debug_netlink, /* debug_tunnel & DB_TN_INIT, */
-		    "klips_debug:ipsec_cleanup: calling ipsec_radijcleanup.\n");
+		    "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");
+		    "klips_debug:ipsec_cleanup: "
+		    "calling pfkey_cleanup.\n");
 	error |= pfkey_cleanup();
 
 #ifdef CONFIG_PROC_FS
 #  ifndef PROC_FS_2325
 #    ifdef CONFIG_IPSEC_DEBUG
 	if (proc_net_unregister(ipsec_klipsdebug.low_ino) != 0)
-		printk("klips_debug:ipsec_cleanup: cannot unregister /proc/net/ipsec_klipsdebug\n");
+		printk("klips_debug:ipsec_cleanup: "
+		       "cannot unregister /proc/net/ipsec_klipsdebug\n");
 #    endif /* CONFIG_IPSEC_DEBUG */
 	if (proc_net_unregister(ipsec_version.low_ino) != 0)
-		printk("klips_debug:ipsec_cleanup: cannot unregister /proc/net/ipsec_version\n");
+		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");
+		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");
+		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");
+		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");
+		printk("klips_debug:ipsec_cleanup: "
+		       "cannot unregister /proc/net/ipsec_tncfg\n");
 #  else /* !PROC_FS_2325 */
 #    ifdef CONFIG_IPSEC_DEBUG
 	proc_net_remove ("ipsec_klipsdebug");
@@ -812,11 +846,13 @@
 	int error = 0;
 
 	KLIPS_PRINT(debug_netlink, /* debug_tunnel & DB_TN_INIT, */
-		    "klips_debug:cleanup_module: calling ipsec_cleanup.\n");
+		    "klips_debug:cleanup_module: "
+		    "calling ipsec_cleanup.\n");
 
 	error |= ipsec_cleanup();
 
-	KLIPS_PRINT(1, "klips_debug:cleanup_module: ipsec module unloaded.\n");
+	KLIPS_PRINT(1, "klips_debug:cleanup_module: "
+		    "ipsec module unloaded.\n");
 
 	return error;
 }
@@ -824,8 +860,21 @@
 
 /*
  * $Log: ipsec_init.c,v $
- * Revision 1.63.2.1  2001/02/27 00:50:59  henry
- * message improvements
+ * 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.
diff -bruN freeswan-1.9.orig/klips/net/ipsec/ipsec_netlink.c freeswan-1.9/klips/net/ipsec/ipsec_netlink.c
--- freeswan-1.9.orig/klips/net/ipsec/ipsec_netlink.c	Sun Nov  5 23:32:08 2000
+++ freeswan-1.9/klips/net/ipsec/ipsec_netlink.c	Mon Jun  4 11:34:31 2001
@@ -14,7 +14,7 @@
  * for more details.
  */
 
-char ipsec_netlink_c_version[] = "RCSID $Id: ipsec_netlink.c,v 1.47 2000/11/06 04:32:08 rgb Exp $";
+char ipsec_netlink_c_version[] = "RCSID $Id: ipsec_netlink.c,v 1.48 2001/02/27 22:24:54 rgb Exp $";
 
 #include <linux/config.h>
 #include <linux/version.h>
@@ -93,23 +93,31 @@
 #ifdef CONFIG_IPSEC_DEBUG
 	struct eroute *eret;
 	char sa[SATOA_BUF];
+	size_t sa_len;
 
 
-	satoa(em->em_said, 0, sa, SATOA_BUF);
+	sa_len = satoa(em->em_said, 0, sa, SATOA_BUF);
 
 	if(debug_netlink) {
-		printk("klips_debug:ipsec_callback: skb=0x%p skblen=%ld em_magic=%d em_type=%d\n",
-		       skb, (unsigned long int)skb->len, em->em_magic, em->em_type);
+		printk("klips_debug:ipsec_callback: "
+		       "skb=0x%p skblen=%ld em_magic=%d em_type=%d\n",
+		       skb,
+		       (unsigned long int)skb->len,
+		       em->em_magic,
+		       em->em_type);
 		switch(em->em_type) {
 		case EMT_SETDEBUG:
-			printk("klips_debug:ipsec_callback: set ipsec_debug level\n");
+			printk("klips_debug:ipsec_callback: "
+			       "set ipsec_debug level\n");
 			break;
 		case EMT_DELEROUTE:
 		case EMT_CLREROUTE:
 		case EMT_CLRSPIS:
 			break;
 		default:
-			printk("klips_debug:ipsec_callback: called for SA:%s\n", sa);
+			printk("klips_debug:ipsec_callback: "
+			       "called for SA:%s\n",
+			       sa_len ? sa : " (error)");
 		}
 	}
 #endif /* CONFIG_IPSEC_DEBUG */
@@ -120,7 +128,8 @@
 
 	/*	em = (struct encap_msghdr *)dat; */
 	if (em->em_magic != EM_MAGIC) {
-		printk("klips_debug:ipsec_callback: bad magic=%d failed, should be %d\n",
+		printk("klips_debug:ipsec_callback: "
+		       "bad magic=%d failed, should be %d\n",
 		       em->em_magic,
 		       EM_MAGIC);
 		SENDERR(EINVAL);
@@ -157,7 +166,8 @@
 			debug_pfkey   &= em->em_db_ky;
 		}
 #else /* CONFIG_IPSEC_DEBUG */
-		printk("klips_debug:ipsec_callback: debugging not enabled\n");
+		printk("klips_debug:ipsec_callback: "
+		       "debugging not enabled\n");
 		SENDERR(EINVAL);
 #endif /* CONFIG_IPSEC_DEBUG */
 		break;
@@ -205,22 +215,26 @@
 				tdbp->tdb_flags |= EMT_INBOUND;
 			}
 			KLIPS_PRINT(debug_netlink & DB_NL_TDBCB,
-				    "klips_debug:ipsec_callback: existing Tunnel Descriptor Block not found (this\n"
-				    "klips_debug:                is good) for SA: %s, %s-bound, allocating.\n",
-				    sa, (tdbp->tdb_flags & EMT_INBOUND) ? "in" : "out");
+				    "klips_debug:ipsec_callback: "
+				    "existing Tunnel Descriptor Block not found (this is good) for SA: %s, %s-bound, allocating.\n",
+				    sa_len ? sa : " (error)",
+				    (tdbp->tdb_flags & EMT_INBOUND) ? "in" : "out");
 
 /* XXX  		tdbp->tdb_rcvif = &(enc_softc[em->em_if].enc_if);*/
 			tdbp->tdb_rcvif = NULL;
 		} else {
 			KLIPS_PRINT(debug_netlink & DB_NL_TDBCB,
-				    "klips_debug:ipsec_callback: EMT_SETSPI found an old Tunnel Descriptor Block\n"
-				    "klips_debug:                for SA: %s, delete it first.\n", sa);
+				    "klips_debug:ipsec_callback: "
+				    "EMT_SETSPI found an old Tunnel Descriptor Block for SA: %s, delete it first.\n",
+				    sa_len ? sa : " (error)");
 			SENDERR(EEXIST);
 		}
 		
 		if ((error = tdb_init(tdbp, em))) {
 			KLIPS_PRINT(debug_netlink & DB_NL_TDBCB,
-				    "klips_debug:ipsec_callback: EMT_SETSPI not successful for SA: %s, deleting.\n", sa);
+				    "klips_debug:ipsec_callback: "
+				    "EMT_SETSPI not successful for SA: %s, deleting.\n",
+				    sa_len ? sa : " (error)");
 			ipsec_tdbwipe(tdbp);
 			
 			SENDERR(-error);
@@ -234,7 +248,9 @@
 
 		puttdb(tdbp);
 		KLIPS_PRINT(debug_netlink & DB_NL_TDBCB,
-			    "klips_debug:ipsec_callback: EMT_SETSPI successful for SA: %s\n", sa);
+			    "klips_debug:ipsec_callback: "
+			    "EMT_SETSPI successful for SA: %s\n",
+			    sa_len ? sa : " (error)");
 		break;
 		
 	case EMT_DELSPI:
@@ -247,8 +263,8 @@
 		if (tdbp == NULL) {
 			KLIPS_PRINT(debug_netlink & DB_NL_TDBCB,
 				    "klips_debug:ipsec_callback: "
-				    "EMT_DELSPI Tunnel Descriptor Block not found for SA:\n"
-				    "klips_debug:                %s, could not delete.\n", sa);
+				    "EMT_DELSPI Tunnel Descriptor Block not found for SA%s, could not delete.\n",
+				    sa_len ? sa : " (error)");
 			spin_unlock_bh(&tdb_lock);
 			SENDERR(ENXIO);  /* XXX -- wrong error message... */
 		} else {
@@ -264,7 +280,8 @@
 	case EMT_GRPSPIS:
 		nspis = (len - EMT_GRPSPIS_FLEN) / sizeof(em->em_rel[0]);
 		if ((nspis * (sizeof(em->em_rel[0]))) != (len - EMT_GRPSPIS_FLEN)) {
-			printk("klips_debug:ipsec_callback: EMT_GRPSPI message size incorrect, expected nspis(%d)*%d, got %d.\n",
+			printk("klips_debug:ipsec_callback: "
+			       "EMT_GRPSPI message size incorrect, expected nspis(%d)*%d, got %d.\n",
 			       nspis,
 			       sizeof(em->em_rel[0]),
 			       (len - EMT_GRPSPIS_FLEN));
@@ -276,21 +293,23 @@
 
 		for (i = 0; i < nspis; i++) {
 			KLIPS_PRINT(debug_netlink,
-				    "klips_debug:ipsec_callback: EMT_GRPSPI for SA(%d)\n"
-				    "klips_debug:                %s,\n", i, sa);
+				    "klips_debug:ipsec_callback: "
+				    "EMT_GRPSPI for SA(%d) %s,\n",
+				    i,
+				    sa_len ? sa : " (error)");
 			if ((tdbp = gettdb(&(em->em_rel[i].emr_said))) == NULL) {
 				KLIPS_PRINT(debug_netlink,
 					    "klips_debug:ipsec_callback: "
-					    "EMT_GRPSPI Tunnel Descriptor Block not found for SA:\n"
-					    "klips_debug:                %s, could not group.\n", sa);
+					    "EMT_GRPSPI Tunnel Descriptor Block not found for SA%s, could not group.\n",
+					    sa_len ? sa : " (error)");
 				spin_unlock_bh(&tdb_lock);
 				SENDERR(ENXIO);
 			} else {
 				if(tdbp->tdb_inext || tdbp->tdb_onext) {
 					KLIPS_PRINT(debug_netlink,
 						    "klips_debug:ipsec_callback: "
-						    "EMT_GRPSPI Tunnel Descriptor Block already grouped\n"
-						    "klips_debug:                for SA: %s, can't regroup.\n", sa);
+						    "EMT_GRPSPI Tunnel Descriptor Block already grouped for SA: %s, can't regroup.\n",
+						    sa_len ? sa : " (error)");
 					spin_unlock_bh(&tdb_lock);
 					SENDERR(EBUSY);
 				}
@@ -327,8 +346,8 @@
 		if ((tdbp = gettdb(&(em->em_rel[0].emr_said))) == NULL) {
 			KLIPS_PRINT(debug_netlink,
 				    "klips_debug:ipsec_callback: "
-				    "EMT_UGRPSPI Tunnel Descriptor Block not found for SA:\n"
-				    "klips_debug:                %s, could not ungroup.\n", sa);
+				    "EMT_UGRPSPI Tunnel Descriptor Block not found for SA%s, could not ungroup.\n",
+				    sa_len ? sa : " (error)");
 			spin_unlock_bh(&tdb_lock);
 			SENDERR(ENXIO);
 		}
@@ -348,14 +367,16 @@
 		
 	case EMT_CLRSPIS:
 		KLIPS_PRINT(debug_netlink,
-			    "klips_debug:ipsec_callback: spi clear called.\n");
+			    "klips_debug:ipsec_callback: "
+			    "spi clear called.\n");
 		if (em->em_if >= 5)	/* XXX -- why 5? */
 			SENDERR(ENODEV);
 		ipsec_tdbcleanup(0);
 		break;
 	default:
 		KLIPS_PRINT(debug_netlink,
-			    "klips_debug:ipsec_callback: unknown message type\n");
+			    "klips_debug:ipsec_callback: "
+			    "unknown message type\n");
 		SENDERR(EINVAL);
 	}
  errlab:
@@ -370,6 +391,10 @@
 
 /*
  * $Log: ipsec_netlink.c,v $
+ * Revision 1.48  2001/02/27 22:24:54  rgb
+ * Re-formatting debug output (line-splitting, joining, 1arg/line).
+ * Check for satoa() return codes.
+ *
  * Revision 1.47  2000/11/06 04:32:08  rgb
  * Ditched spin_lock_irqsave in favour of spin_lock_bh.
  *
diff -bruN freeswan-1.9.orig/klips/net/ipsec/ipsec_radij.c freeswan-1.9/klips/net/ipsec/ipsec_radij.c
--- freeswan-1.9.orig/klips/net/ipsec/ipsec_radij.c	Sun Nov  5 23:32:08 2000
+++ freeswan-1.9/klips/net/ipsec/ipsec_radij.c	Mon Jun  4 12:54:13 2001
@@ -13,7 +13,7 @@
  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  * for more details.
  *
- * RCSID $Id: ipsec_radij.c,v 1.41 2000/11/06 04:32:08 rgb Exp $
+ * RCSID $Id: ipsec_radij.c,v 1.45 2001/05/27 06:12:11 rgb Exp $
  */
 
 #include <linux/config.h>
@@ -54,7 +54,7 @@
 int debug_radij = 0;
 #endif /* CONFIG_IPSEC_DEBUG */
 
-struct radij_node_head *rnh = 0;
+struct radij_node_head *rnh = NULL;
 #ifdef SPINLOCK
 spinlock_t eroute_lock = SPIN_LOCK_UNLOCKED;
 #else /* SPINLOCK */
@@ -68,7 +68,7 @@
 
 	rj_init();
 	
-	if (rj_inithead((void **)&rnh, 16) == 0) /* 16 is bit offset of sen_type */
+	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;
 }
@@ -90,7 +90,7 @@
 int
 ipsec_cleareroutes(void)
 {
-	int error;
+	int error = 0;
 
 	spin_lock_bh(&eroute_lock);
 
@@ -105,15 +105,18 @@
 ipsec_breakroute(struct sockaddr_encap *eaddr, struct sockaddr_encap *emask)
 {
 	struct radij_node *rn;
-	int error;
+	int error = 0;
 #ifdef CONFIG_IPSEC_DEBUG
 	char buf1[64], buf2[64];
 	
 	if (debug_eroute) {
 		subnettoa(eaddr->sen_ip_src, emask->sen_ip_src, 0, buf1, sizeof(buf1));
 		subnettoa(eaddr->sen_ip_dst, emask->sen_ip_dst, 0, buf2, sizeof(buf2));
-		printk("klips_debug:ipsec_breakroute: attempting to delete eroute for %s->%s\n",
-			       buf1, buf2);
+		KLIPS_PRINT(debug_eroute, 
+			    "klips_debug:ipsec_breakroute: "
+			    "attempting to delete eroute for %s->%s\n",
+			    buf1,
+			    buf2);
 	}
 #endif /* CONFIG_IPSEC_DEBUG */
 
@@ -121,7 +124,8 @@
 
 	if ((error = rj_delete(eaddr, emask, rnh, &rn)) != 0) {
 		spin_unlock_bh(&eroute_lock);
-		KLIPS_PRINT(debug_eroute, "klips_debug:ipsec_breakroute: "
+		KLIPS_PRINT(debug_eroute, 
+			    "klips_debug:ipsec_breakroute: "
 			    "node not found, eroute delete failed.\n");
 		return error;
 	}
@@ -138,10 +142,10 @@
 }
 
 int
-ipsec_makeroute(struct sockaddr_encap *eaddr, struct sockaddr_encap *emask, struct sa_id said)
+ipsec_makeroute(struct sockaddr_encap *eaddr, struct sockaddr_encap *emask, struct sa_id said, uint32_t pid)
 {
 	struct eroute *retrt;
-	int error;
+	int error = 0;
 	char sa[SATOA_BUF];
 	size_t sa_len;
 #ifdef CONFIG_IPSEC_DEBUG
@@ -151,14 +155,20 @@
 		subnettoa(eaddr->sen_ip_src, emask->sen_ip_src, 0, buf1, sizeof(buf1));
 		subnettoa(eaddr->sen_ip_dst, emask->sen_ip_dst, 0, buf2, sizeof(buf2));
 		sa_len = satoa(said, 0, sa, SATOA_BUF);
-		printk("klips_debug:ipsec_makeroute: attempting to insert eroute for %s->%s, SA: %s\n",
-		       buf1, buf2, sa);
+		KLIPS_PRINT(debug_eroute, 
+			    "klips_debug:ipsec_makeroute: "
+			    "attempting to insert eroute for %s->%s, SA: %s, PID:%d\n",
+			    buf1,
+			    buf2,
+			    sa_len ? sa : " (error)",
+			    pid);
 	}
 #endif /* CONFIG_IPSEC_DEBUG */
 
 	retrt = (struct eroute *)kmalloc(sizeof (struct eroute), GFP_ATOMIC);
 	if (retrt == NULL) {
-		printk("klips_error:ipsec_makeroute: not able to allocate kernel memory");
+		printk("klips_error:ipsec_makeroute: "
+		       "not able to allocate kernel memory");
 		return ENOMEM;
 	}
 	memset((caddr_t)retrt, 0, sizeof (struct eroute));
@@ -166,6 +176,9 @@
 	retrt->er_eaddr = *eaddr;
 	retrt->er_emask = *emask;
 	retrt->er_said = said;
+	retrt->er_pid = pid;
+	retrt->er_count = 0;
+	retrt->er_lasttime = jiffies/HZ;
 	rd_key((&(retrt->er_rjt))) = &(retrt->er_eaddr);
 	
 	spin_lock_bh(&eroute_lock);
@@ -177,12 +190,40 @@
 	
 	if(error) {
 		sa_len = satoa(said, 0, sa, SATOA_BUF);
-		printk("klips_debug:ipsec_makeroute: rj_addroute not able to insert eroute for SA:%s\n", sa);
+		KLIPS_PRINT(debug_eroute, 
+			    "klips_debug:ipsec_makeroute: "
+			    "rj_addroute not able to insert eroute for SA:%s\n",
+			    sa_len ? sa : " (error)");
 		kfree(retrt); /* XXX -- should we? */
 		return error;
 	}
+
+	if (debug_eroute && 0) {
+/*
+		subnettoa(eaddr->sen_ip_src, emask->sen_ip_src, 0, buf1, sizeof(buf1));
+		subnettoa(eaddr->sen_ip_dst, emask->sen_ip_dst, 0, buf2, sizeof(buf2));
+*/
+		subnettoa(rd_key((&(retrt->er_rjt)))->sen_ip_src, rd_mask((&(retrt->er_rjt)))->sen_ip_src, 0, buf1, sizeof(buf1));
+		subnettoa(rd_key((&(retrt->er_rjt)))->sen_ip_dst, rd_mask((&(retrt->er_rjt)))->sen_ip_dst, 0, buf2, sizeof(buf2));
+		sa_len = satoa(retrt->er_said, 0, sa, SATOA_BUF);
+		
 	KLIPS_PRINT(debug_eroute,
-		    "klips_debug:ipsec_makeroute: succeeded, I think...\n");
+			    "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)");
+	}
+
+	KLIPS_PRINT(debug_eroute,
+		    "klips_debug:ipsec_makeroute: "
+		    "succeeded, I think...\n");
 	return 0;
 }
 
@@ -196,11 +237,22 @@
 	if (debug_radij & DB_RJ_FINDROUTE) {
 		addrtoa(eaddr->sen_ip_src, 0, buf1, sizeof(buf1));
 		addrtoa(eaddr->sen_ip_dst, 0, buf2, sizeof(buf2));
-		printk("klips_debug:ipsec_findroute: %s->%s\n",
-		       buf1, buf2);
+		KLIPS_PRINT(debug_eroute,
+			    "klips_debug:ipsec_findroute: "
+			    "%s->%s\n",
+			    buf1,
+			    buf2);
 	}
 #endif /* CONFIG_IPSEC_DEBUG */
 	rn = rj_match((caddr_t)eaddr, rnh);
+	if(rn) {
+		KLIPS_PRINT(debug_eroute,
+			    "klips_debug:ipsec_findroute: "
+			    "found, points to proto=%d, spi=%x, dst=%x.\n",
+			    ((struct eroute*)rn)->er_said.proto,
+			    ntohl(((struct eroute*)rn)->er_said.spi),
+			    ntohl(((struct eroute*)rn)->er_said.dst.s_addr));
+	}
 	return (struct eroute *)rn;
 }
 		
@@ -217,8 +269,10 @@
 	struct sockaddr_encap *key, *mask;
 	
 	KLIPS_PRINT(debug_radij,
-		    "klips_debug:ipsec_rj_walker_procprint: rn=%p, w0=%p\n",
-		    rn, w0);
+		    "klips_debug:ipsec_rj_walker_procprint: "
+		    "rn=%p, w0=%p\n",
+		    rn,
+		    w0);
 	if (rn == NULL)	{
 		return 120;
 	}
@@ -238,8 +292,24 @@
 	subnettoa(key->sen_ip_dst, mask->sen_ip_dst, 0, buf2, sizeof(buf2));
 	sa_len = satoa(ro->er_said, 0, sa, SATOA_BUF);
 	w->len += sprintf(w->buffer + w->len,
+/*
+			  "%05d "
+*/
+			  "%-10d "
+/*
+			  "%6d "
+*/
 			  "%-18s -> %-18s => %s\n",
-			  buf1, buf2, sa);
+/*
+			  ro->er_pid,
+*/
+			  ro->er_count,
+/*
+			  jiffies / HZ - ro->er_lasttime,
+*/
+			  buf1,
+			  buf2,
+			  sa_len ? sa : " (error)");
 	
 	w->pos = w->begin + w->len;
 	if(w->pos < w->offset) {
@@ -258,7 +328,7 @@
 {
 	struct rjtentry *rd = (struct rjtentry *)rn;
 	struct radij_node *rn2;
-	int error;
+	int error = 0;
 	struct sockaddr_encap *key, *mask;
 #ifdef CONFIG_IPSEC_DEBUG
 	char buf1[64] = { 0 }, buf2[64] = { 0 };
@@ -272,14 +342,17 @@
 	mask = rd_mask(rd);
 	
 	if(!key || !mask) {
-		return -1;
+		return -ENODATA;
 	}
 #ifdef CONFIG_IPSEC_DEBUG
 	if(debug_radij)	{
 		subnettoa(key->sen_ip_src, mask->sen_ip_src, 0, buf1, sizeof(buf1));
 		subnettoa(key->sen_ip_dst, mask->sen_ip_dst, 0, buf2, sizeof(buf2));
-		printk("klips_debug:ipsec_rj_walker_delete: deleting: %s -> %s\n",
-		       buf1, buf2);
+		KLIPS_PRINT(debug_radij, 
+			    "klips_debug:ipsec_rj_walker_delete: "
+			    "deleting: %s -> %s\n",
+			    buf1,
+			    buf2);
 	}
 #endif /* CONFIG_IPSEC_DEBUG */
 
@@ -291,8 +364,8 @@
 	}
 
 	if(rn2 != rn) {
-		printk("klips_debug:ipsec_rj_walker_delete: tried to delete a different node?!?"
-		       "This should never happen!\n");
+		printk("klips_debug:ipsec_rj_walker_delete: "
+		       "tried to delete a different node?!?  This should never happen!\n");
 	}
 	memset((caddr_t)rn, 0, sizeof (struct eroute));
 	kfree(rn);
@@ -302,6 +375,21 @@
 
 /*
  * $Log: ipsec_radij.c,v $
+ * 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.
  *
diff -bruN freeswan-1.9.orig/klips/net/ipsec/ipsec_radij.h freeswan-1.9/klips/net/ipsec/ipsec_radij.h
--- freeswan-1.9.orig/klips/net/ipsec/ipsec_radij.h	Fri Sep  8 15:12:56 2000
+++ freeswan-1.9/klips/net/ipsec/ipsec_radij.h	Mon Jun  4 12:54:13 2001
@@ -13,7 +13,7 @@
  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  * for more details.
  *
- * RCSID $Id: ipsec_radij.h,v 1.11 2000/09/08 19:12:56 rgb Exp $
+ * RCSID $Id: ipsec_radij.h,v 1.12 2001/05/27 06:12:11 rgb Exp $
  */
 
 #include <freeswan.h>
@@ -34,14 +34,8 @@
 	off_t pos;
 };
 
-#if 0
-struct eroute * ipsec_makeroute(struct sockaddr_encap *ea, struct sockaddr_encap *em, struct sa_id);
-#endif
-int ipsec_makeroute(struct sockaddr_encap *ea, struct sockaddr_encap *em, struct sa_id);
-
-#if 0
-struct eroute * ipsec_breakroute(struct sockaddr_encap *ea, struct sockaddr_encap *em);
-#endif
+int ipsec_makeroute(struct sockaddr_encap *ea, struct sockaddr_encap *em, struct sa_id, uint32_t pid);
+
 int ipsec_breakroute(struct sockaddr_encap *ea, struct sockaddr_encap *em);
 
 int ipsec_radijinit(void);
@@ -68,6 +62,10 @@
 
 /*
  * $Log: ipsec_radij.h,v $
+ * 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.
  *
diff -bruN freeswan-1.9.orig/klips/net/ipsec/ipsec_rcv.c freeswan-1.9/klips/net/ipsec/ipsec_rcv.c
--- freeswan-1.9.orig/klips/net/ipsec/ipsec_rcv.c	Mon Feb 19 17:28:30 2001
+++ freeswan-1.9/klips/net/ipsec/ipsec_rcv.c	Tue Jun 12 16:25:46 2001
@@ -14,7 +14,7 @@
  * for more details.
  */
 
-char ipsec_rcv_c_version[] = "RCSID $Id: ipsec_rcv.c,v 1.75 2001/02/19 22:28:30 rgb Exp $";
+char ipsec_rcv_c_version[] = "RCSID $Id: ipsec_rcv.c,v 1.85 2001/05/30 08:14:02 rgb Exp $";
 
 #include <linux/config.h>
 #include <linux/version.h>
@@ -77,6 +77,7 @@
 int sysctl_ipsec_inbound_policy_check = 1;
 
 #ifdef CONFIG_IPSEC_ESP
+extern void des_cbc_encrypt(caddr_t, caddr_t, int, caddr_t, caddr_t, int);
 extern void des_ede3_cbc_encrypt(caddr_t, caddr_t, int, caddr_t, caddr_t, caddr_t, caddr_t, int);
 #endif /* !CONFIG_IPSEC_ESP */
 #if defined(CONFIG_IPSEC_ESP) || defined(CONFIG_IPSEC_AH)
@@ -252,6 +253,14 @@
 		goto rcvleave;
 	}
 		
+#ifdef IPH_is_SKB_PULLED
+	/* In Linux 2.4.4, the IP header has been skb_pull()ed before the
+	   packet is passed to us. So we'll skb_push() to get back to it. */
+	if (skb->data == skb->h.raw) {
+		skb_push(skb, skb->h.raw - skb->nh.raw);
+	}
+#endif /* IPH_is_SKB_PULLED */
+	
 	ipp = (struct iphdr *)skb->data;
 	iphlen = ipp->ihl << 2;
 	/* dev->hard_header_len is unreliable and should not be used */
@@ -267,20 +276,26 @@
 		/* include any mac header while copying.. */
 		if(skb_headroom(skb) < hard_header_len) {
 			printk(KERN_WARNING "klips_error:ipsec_rcv: "
-			       "tried to skb_push hhlen=%d, %d available.  "
-			       "This should never happen, please report.\n",
-			       hard_header_len, skb_headroom(skb));
+			       "tried to skb_push hhlen=%d, %d available.  This should never happen, please report.\n",
+			       hard_header_len,
+			       skb_headroom(skb));
 			goto rcvleave;
 		}
 		skb_push(skb, hard_header_len);
-		if ((skb = skb_cow(skb, skb_headroom(skb))) == NULL) {
+		if
+#ifdef SKB_COW_NEW
+               (skb_cow(skb, skb_headroom(skb)) != 0)
+#else /* SKB_COW_NEW */
+               ((skb = skb_cow(skb, skb_headroom(skb))) == NULL)
+#endif /* SKB_COW_NEW */
+		{
 			goto rcvleave;
 		}
 		if(skb->len < hard_header_len) {
 			printk(KERN_WARNING "klips_error:ipsec_rcv: "
-			       "tried to skb_pull hhlen=%d, %d available.  "
-			       "This should never happen, please report.\n",
-			       hard_header_len, skb->len);
+			       "tried to skb_pull hhlen=%d, %d available.  This should never happen, please report.\n",
+			       hard_header_len,
+			       skb->len);
 			goto rcvleave;
 		}
 		skb_pull(skb, hard_header_len);
@@ -289,7 +304,8 @@
 #endif /* NET_21 */
 		
 	KLIPS_PRINT(debug_rcv, 
-		    "klips_debug:ipsec_rcv: <<< Info -- ");
+		    "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 ",
@@ -297,9 +313,8 @@
 	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",
+		    "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");
 
@@ -333,24 +348,25 @@
 				}
 				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");
+					    "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);
+					    "klips_error:ipsec_rcv: "
+					    "device %s does not exist\n",
+					    name);
 			}
 			prv = ipsecdev ? (struct ipsecpriv *)(ipsecdev->priv) : NULL;
 			prvdev = prv ? (struct device *)(prv->dev) : NULL;
 			
 #if 0
 			KLIPS_PRINT(debug_rcv && prvdev, 
-				    "klips_debug:ipsec_rcv: physical device"
-				    " for device %s is %s\n",
-				    name, prvdev->name);
+				    "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)) {
@@ -368,20 +384,16 @@
 		}
 	} else {
 		KLIPS_PRINT(debug_rcv, 
-			    "klips_debug:ipsec_rcv: device supplied"
-			    " with skb is NULL\n");
+			    "klips_debug:ipsec_rcv: "
+			    "device supplied with skb is NULL\n");
 	}
 			
 	if(!stats) {
 		ipsecdev = NULL;
 	}
 	KLIPS_PRINT((debug_rcv && !stats),
-		    "klips_error:ipsec_rcv: packet received from physical "
-		    "I/F (%s) not connected to ipsec I/F.  Cannot record "
-		    "stats.\n"
-		    "klips_error          May not have SA for decoding.  "
-		    "Is IPSEC traffic expected on this I/F?  "
-		    "Check routing.\n",
+		    "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);
@@ -415,9 +427,9 @@
 		/* XXX this will need to be 8 for IPv6 */
 		if ((proto == IPPROTO_ESP) && ((len - iphlen) % 4)) {
 			printk("klips_error:ipsec_rcv: "
-			       "got packet with content length = %d from %s "
-			       "-- should be on 4 octet boundary, packet dropped\n",
-			       len - iphlen, ipaddr_txt);
+			       "got packet with content length = %d from %s -- should be on 4 octet boundary, packet dropped\n",
+			       len - iphlen,
+			       ipaddr_txt);
 			if(stats) {
 				stats->rx_errors++;
 			}
@@ -467,11 +479,9 @@
 			next_header = ahp->ah_nh;
 			if (ahhlen != sizeof(struct ah)) {
 				KLIPS_PRINT(debug_rcv & DB_RX_INAU,
-					    "klips_debug:ipsec_rcv: bad "
-					    "authenticator length %d, expected "
-					    "%d from %s\n",
-					    ahhlen - ((caddr_t)(ahp->ah_data) -
-						      (caddr_t)ahp),
+					    "klips_debug:ipsec_rcv: "
+					    "bad authenticator length %d, expected %d from %s\n",
+					    ahhlen - ((caddr_t)(ahp->ah_data) - (caddr_t)ahp),
 					    AHHMAC_HASHLEN,
 					    ipaddr_txt);
 				if(stats) {
@@ -484,26 +494,34 @@
 #endif /* CONFIG_IPSEC_AH */
 		
 		/*
-		 * The spinlock is to prevent any other process from
-		 * accessing or deleting the structure while we are
-		 * using and updating it.
+		  The spinlock is to prevent any other process from
+		  accessing or deleting the TDB hash table or any of the
+		  TDBs while we are using and updating them.
+		  
+		  This is not optimal, but was relatively straightforward
+		  at the time.  A better way to do it has been planned for
+		  more than a year, to lock the hash table and put reference
+		  counts on each TDB instead.  This is not likely to happen
+		  in KLIPS1 unless a volunteer contributes it, but will be
+		  designed into KLIPS2.
 		 */
+		if(tdbprev == NULL) {
 		spin_lock(&tdb_lock);
+		}
 		
 #ifdef CONFIG_IPSEC_IPCOMP
 		if (proto == IPPROTO_COMP) {
 			unsigned int flags = 0;
 			if (tdbp == NULL) {
+				spin_unlock(&tdb_lock);
 				KLIPS_PRINT(debug_rcv,
 					    "klips_debug:ipsec_rcv: "
-					    "Incoming packet with outer IPCOMP "
-					    "header SA:%s: not yet supported "
-					    "by KLIPS, dropped\n", sa);
+					    "Incoming packet with outer IPCOMP header SA:%s: not yet supported by KLIPS, dropped\n",
+					    sa_len ? sa : " (error)");
 				if(stats) {
 					stats->rx_dropped++;
 				}
 
-				spin_unlock(&tdb_lock);
 				goto rcvleave;
 			}
 
@@ -516,27 +534,24 @@
 				   && ((ntohl(tdbp->tdb_said.spi) & 0x0000ffff)
 				       != ntohl(said.spi))))) {
 				char sa2[SATOA_BUF];
+				size_t sa_len2 = 0;
 
 				if(tdbp) {
-					sa_len = satoa(tdbp->tdb_said, 0, sa2, SATOA_BUF);
+					sa_len2 = satoa(tdbp->tdb_said, 0, sa2, SATOA_BUF);
 				}
 				KLIPS_PRINT(debug_rcv,
 					    "klips_debug:ipsec_rcv: "
-					    "Incoming packet with SA(IPCA):%s "
-					    "does not match policy SA(IPCA):%s "
-					    "cpi=%04x cpi->spi=%08x spi=%08x, spi->cpi=%04x for "
-					    "SA grouping, dropped.\n",
-					    sa,
-					    tdbp ? sa2 : "NULL",
+					    "Incoming packet with SA(IPCA):%s does not match policy SA(IPCA):%s cpi=%04x cpi->spi=%08x spi=%08x, spi->cpi=%04x for SA grouping, dropped.\n",
+					    sa_len ? sa : " (error)",
+					    tdbp ? (sa_len2 ? sa2 : " (error)") : "NULL",
 					    ntohs(compp->ipcomp_cpi),
 					    (__u32)ntohl(said.spi),
 					    tdbp ? (__u32)ntohl((tdbp->tdb_said.spi)) : 0,
 					    tdbp ? (__u16)(ntohl(tdbp->tdb_said.spi) & 0x0000ffff) : 0);
+				spin_unlock(&tdb_lock);
 				if(stats) {
 					stats->rx_dropped++;
 				}
-
-				spin_unlock(&tdb_lock);
 				goto rcvleave;
 			}
 
@@ -548,10 +563,10 @@
 
 			skb = skb_decompress(skb, tdbp, &flags);
 			if (!skb || flags) {
+				spin_unlock(&tdb_lock);
 				KLIPS_PRINT(debug_rcv,
 					    "klips_debug:ipsec_rcv: "
-					    "skb_decompress() returned "
-					    "error flags=%x, dropped.\n",
+					    "skb_decompress() returned error flags=%x, dropped.\n",
 					    flags);
 				if (stats) {
 				    if (flags)
@@ -559,8 +574,6 @@
 				    else
 					stats->rx_dropped++;
 				}
-
-				spin_unlock(&tdb_lock);
 				goto rcvleave;
 			}
 #ifdef NET_21
@@ -575,9 +588,8 @@
 
 			KLIPS_PRINT(debug_rcv,
 				    "klips_debug:ipsec_rcv: "
-				    "packet decompressed SA(IPCA):%s "
-				    "cpi->spi=%08x spi=%08x, spi->cpi=%04x, nh=%d.\n",
-				    sa,
+				    "packet decompressed SA(IPCA):%s cpi->spi=%08x spi=%08x, spi->cpi=%04x, nh=%d.\n",
+				    sa_len ? sa : " (error)",
 				    (__u32)ntohl(said.spi),
 				    tdbp ? (__u32)ntohl((tdbp->tdb_said.spi)) : 0,
 				    tdbp ? (__u16)(ntohl(tdbp->tdb_said.spi) & 0x0000ffff) : 0,
@@ -594,9 +606,9 @@
 		if (tdbp == NULL) {
 			spin_unlock(&tdb_lock);
 			KLIPS_PRINT(debug_rcv,
-				    "klips_debug:ipsec_rcv: no Tunnel Descriptor "
-				    "Block for SA:%s: incoming packet with no SA "
-				    "dropped\n", sa);
+				    "klips_debug:ipsec_rcv: "
+				    "no Tunnel Descriptor Block for SA:%s: incoming packet with no SA dropped\n",
+				    sa_len ? sa : " (error)");
 			if(stats) {
 				stats->rx_dropped++;
 			}
@@ -611,27 +623,27 @@
 				KLIPS_PRINT(debug_rcv,
 					    "klips_debug:ipsec_rcv: "
 					    "SA:%s, src=%s of pkt does not agree with expected SA source address policy.\n",
-					    sa, ipaddr_txt);
+					    sa_len ? sa : " (error)",
+					    ipaddr_txt);
 				if(stats) {
 					stats->rx_dropped++;
 				}
 				goto rcvleave;
 			}
-			{
 				ipaddr.s_addr = ipp->saddr;
 				addrtoa(ipaddr, 0, ipaddr_txt, sizeof(ipaddr_txt));
 				KLIPS_PRINT(debug_rcv,
 					    "klips_debug:ipsec_rcv: "
 					    "SA:%s, src=%s of pkt agrees with expected SA source address policy.\n",
-					    sa, ipaddr_txt);
-			}
+				    sa_len ? sa : " (error)",
+				    ipaddr_txt);
 			if(tdbnext) {
 				if(tdbnext != tdbp) {
 					spin_unlock(&tdb_lock);
 					KLIPS_PRINT(debug_rcv,
 						    "klips_debug:ipsec_rcv: "
 						    "unexpected SA:%s: does not agree with tdb->inext policy, dropped\n",
-						    sa);
+						    sa_len ? sa : " (error)");
 					if(stats) {
 						stats->rx_dropped++;
 					}
@@ -640,22 +652,21 @@
 				KLIPS_PRINT(debug_rcv,
 					    "klips_debug:ipsec_rcv: "
 					    "SA:%s grouping from previous SA is OK.\n",
-					    sa);
+					    sa_len ? sa : " (error)");
 			} else {
 				KLIPS_PRINT(debug_rcv,
 					    "klips_debug:ipsec_rcv: "
 					    "SA:%s First SA in group.\n",
-					    sa);
+					    sa_len ? sa : " (error)");
 			}
 			
-#if 1
 			if(tdbp->tdb_onext) {
 				if(tdbprev != tdbp->tdb_onext) {
 					spin_unlock(&tdb_lock);
 					KLIPS_PRINT(debug_rcv,
 						    "klips_debug:ipsec_rcv: "
 						    "unexpected SA:%s: does not agree with tdb->onext policy, dropped.\n",
-						    sa);
+						    sa_len ? sa : " (error)");
 					if(stats) {
 						stats->rx_dropped++;
 					}
@@ -664,15 +675,14 @@
 					KLIPS_PRINT(debug_rcv,
 						    "klips_debug:ipsec_rcv: "
 						    "SA:%s grouping to previous SA is OK.\n",
-						    sa);
+						    sa_len ? sa : " (error)");
 				}
 			} else {
 				KLIPS_PRINT(debug_rcv,
 					    "klips_debug:ipsec_rcv: "
 					    "SA:%s No previous backlink in group.\n",
-					    sa);
+					    sa_len ? sa : " (error)");
 			}
-#endif
 		}
 		
 		/* If it is in larval state, drop the packet, we cannot process yet. */
@@ -680,8 +690,7 @@
 			spin_unlock(&tdb_lock);
 			KLIPS_PRINT(debug_rcv,
 				    "klips_debug:ipsec_rcv: "
-				    "TDB in larval state, cannot be used yet, "
-				    "dropping packet.\n");
+				    "TDB in larval state, cannot be used yet, dropping packet.\n");
 			if(stats) {
 				stats->rx_dropped++;
 			}
@@ -692,8 +701,7 @@
 			spin_unlock(&tdb_lock);
 			KLIPS_PRINT(debug_rcv,
 				    "klips_debug:ipsec_rcv: "
-				    "TDB in dead state, cannot be used any more, "
-				    "dropping packet.\n");
+				    "TDB in dead state, cannot be used any more, dropping packet.\n");
 			if(stats) {
 				stats->rx_dropped++;
 			}
@@ -707,8 +715,8 @@
 			spin_unlock(&tdb_lock);
 			KLIPS_PRINT(debug_rcv,
 				    "klips_debug:ipsec_rcv: "
-				    "hard bytes lifetime of SA:%s has been reached, "
-				    "SA expired, incoming packet dropped.\n", sa);
+				    "hard bytes lifetime of SA:%s has been reached, SA expired, incoming packet dropped.\n",
+				    sa_len ? sa : " (error)");
 			if(stats) {
 				stats->rx_dropped++;
 			}
@@ -716,13 +724,14 @@
 		}
 		if(tdbp->tdb_lifetime_bytes_s &&
 		   (tdbp->tdb_lifetime_bytes_c > tdbp->tdb_lifetime_bytes_s)) {
+			if(tdbp->tdb_state != SADB_SASTATE_DYING) {
+				pfkey_expire(tdbp, 0);
+			}
 			tdbp->tdb_state = SADB_SASTATE_DYING;
 			KLIPS_PRINT(debug_rcv,
 				    "klips_debug:ipsec_rcv: "
-				    "soft bytes lifetime of SA:%s has been reached, "
-				    "SA expiring, soft expire message sent up, "
-				    "incoming packet still processed.\n", sa);
-			pfkey_expire(tdbp, 0);
+				    "soft bytes lifetime of SA:%s has been reached, SA expiring, soft expire message sent up, incoming packet still processed.\n",
+				    sa_len ? sa : " (error)");
 		}
 		
 		if(tdbp->tdb_lifetime_addtime_h &&
@@ -733,8 +742,8 @@
 			spin_unlock(&tdb_lock);
 			KLIPS_PRINT(debug_rcv,
 				    "klips_debug:ipsec_rcv: "
-				    "hard addtime lifetime of SA:%s has been reached, "
-				    "SA expired, incoming packet dropped.\n", sa);
+				    "hard addtime lifetime of SA:%s has been reached, SA expired, incoming packet dropped.\n",
+				    sa_len ? sa : " (error)");
 			if(stats) {
 				stats->rx_dropped++;
 			}
@@ -743,13 +752,14 @@
 		if(tdbp->tdb_lifetime_addtime_s &&
 		   ((jiffies / HZ) - tdbp->tdb_lifetime_addtime_c >
 		    tdbp->tdb_lifetime_addtime_s)) {
+			if(tdbp->tdb_state != SADB_SASTATE_DYING) {
+				pfkey_expire(tdbp, 0);
+			}
 			tdbp->tdb_state = SADB_SASTATE_DYING;
 			KLIPS_PRINT(debug_rcv,
 				    "klips_debug:ipsec_rcv: "
-				    "soft addtime lifetime of SA:%s has been reached, "
-				    "SA expiring, soft expire message sent up, "
-				    "incoming packet still processed.\n", sa);
-			pfkey_expire(tdbp, 0);
+				    "soft addtime lifetime of SA:%s has been reached, SA expiring, soft expire message sent up, incoming packet still processed.\n",
+				    sa_len ? sa : " (error)");
 		}
 		
 		if(tdbp->tdb_lifetime_usetime_c) {
@@ -761,8 +771,8 @@
 				spin_unlock(&tdb_lock);
 				KLIPS_PRINT(debug_rcv,
 					    "klips_debug:ipsec_rcv: "
-					    "hard usetime lifetime of SA:%s has been reached, "
-					    "SA expired, incoming packet dropped.\n", sa);
+					    "hard usetime lifetime of SA:%s has been reached, SA expired, incoming packet dropped.\n",
+					    sa_len ? sa : " (error)");
 				if(stats) {
 					stats->rx_dropped++;
 				}
@@ -771,13 +781,14 @@
 			if(tdbp->tdb_lifetime_usetime_s &&
 			   ((jiffies / HZ) - tdbp->tdb_lifetime_usetime_c >
 			    tdbp->tdb_lifetime_usetime_s)) {
+				if(tdbp->tdb_state != SADB_SASTATE_DYING) {
+					pfkey_expire(tdbp, 0);
+				}
 				tdbp->tdb_state = SADB_SASTATE_DYING;
 				KLIPS_PRINT(debug_rcv,
 					    "klips_debug:ipsec_rcv: "
-					    "soft usetime lifetime of SA:%s has been reached, "
-					    "SA expiring, soft expire message sent up, "
-					    "incoming packet still processed.\n", sa);
-				pfkey_expire(tdbp, 0);
+					    "soft usetime lifetime of SA:%s has been reached, SA expiring, soft expire message sent up, incoming packet still processed.\n",
+					    sa_len ? sa : " (error)");
 			}
 		}
 		
@@ -788,8 +799,8 @@
 			spin_unlock(&tdb_lock);
 			KLIPS_PRINT(debug_rcv,
 				    "klips_debug:ipsec_rcv: "
-				    "hard packets lifetime of SA:%s has been reached, "
-				    "SA expired, incoming packet dropped.\n", sa);
+				    "hard packets lifetime of SA:%s has been reached, SA expired, incoming packet dropped.\n",
+				    sa_len ? sa : " (error)");
 			if(stats) {
 				stats->rx_dropped++;
 			}
@@ -797,13 +808,14 @@
 		}
 		if(tdbp->tdb_lifetime_packets_s &&
 		   (tdbp->tdb_lifetime_packets_c > tdbp->tdb_lifetime_packets_s)) {
+			if(tdbp->tdb_state != SADB_SASTATE_DYING) {
+				pfkey_expire(tdbp, 0);
+			}
 			tdbp->tdb_state = SADB_SASTATE_DYING;
 			KLIPS_PRINT(debug_rcv,
 				    "klips_debug:ipsec_rcv: "
-				    "soft packets lifetime of SA:%s has been reached, "
-				    "SA expiring, soft expire message sent up, "
-				    "incoming packet still processed.\n", sa);
-			pfkey_expire(tdbp, 0);
+				    "soft packets lifetime of SA:%s has been reached, SA expiring, soft expire message sent up, incoming packet still processed.\n",
+				    sa_len ? sa : " (error)");
 		}
 		
 		/* authenticate, if required */
@@ -823,24 +835,26 @@
 			authlen = 0;
 			break;
 		default:
+			tdbp->tdb_alg_errs += 1;
+			spin_unlock(&tdb_lock);
 			if(stats) {
 				stats->rx_errors++;
 			}
-			tdbp->tdb_alg_errs += 1;
-			spin_unlock(&tdb_lock);
 			goto rcvleave;
 		}
 		ilen = len - iphlen - authlen;
 		
 #ifdef CONFIG_IPSEC_ESP
 		KLIPS_PRINT(proto == IPPROTO_ESP && debug_rcv, 
-			    "klips_debug:ipsec_rcv: packet from %s received with"
-			    " seq=%d (iv)=0x%08x%08x iplen=%d esplen=%d sa=%s\n",
+			    "klips_debug:ipsec_rcv: "
+			    "packet from %s received with seq=%d (iv)=0x%08x%08x iplen=%d esplen=%d sa=%s\n",
 			    ipaddr_txt,
 			    (__u32)ntohl(espp->esp_rpl),
 			    (__u32)ntohl(*((__u32 *)(espp->esp_iv)    )),
 			    (__u32)ntohl(*((__u32 *)(espp->esp_iv) + 1)),
-			    len, ilen, sa);
+			    len,
+			    ilen,
+			    sa_len ? sa : " (error)");
 #endif /* !CONFIG_IPSEC_ESP */
 		
 		switch(proto) {
@@ -863,7 +877,7 @@
 			deltdbchain(tdbp);
 			spin_unlock(&tdb_lock);
 			KLIPS_PRINT(debug_rcv,
-				    "klips_debug:ipsec_tunnel_start_xmit: "
+				    "klips_debug:ipsec_rcv: "
 				    "replay window counter rolled, expiring SA.\n");
 			if(stats) {
 				stats->rx_dropped++;
@@ -872,15 +886,15 @@
 		}
 
 		if (!ipsec_checkreplaywindow(tdbp, replay)) {
+			tdbp->tdb_replaywin_errs += 1;
+			spin_unlock(&tdb_lock);
 			KLIPS_PRINT(debug_rcv & DB_RX_REPLAY,
-				    "klips_debug:ipsec_rcv: duplicate frame from %s,"
-				    " packet dropped\n",
+				    "klips_debug:ipsec_rcv: "
+				    "duplicate frame from %s, packet dropped\n",
 				    ipaddr_txt);
 			if(stats) {
 				stats->rx_dropped++;
 			}
-			tdbp->tdb_replaywin_errs += 1;
-			spin_unlock(&tdb_lock);
 			goto rcvleave;
 		}
 		
@@ -889,8 +903,10 @@
 		 */
 		
 		KLIPS_PRINT(debug_rcv,
-			    "klips_debug:ipsec_rcv: encalg = %d, authalg = %d.\n",
-			    tdbp->tdb_encalg, tdbp->tdb_authalg);
+			    "klips_debug:ipsec_rcv: "
+			    "encalg = %d, authalg = %d.\n",
+			    tdbp->tdb_encalg,
+			    tdbp->tdb_authalg);
 		
 		if(tdbp->tdb_authalg) {
 			switch(tdbp->tdb_authalg) {
@@ -959,19 +975,21 @@
 			}
 		
 			if(!authenticator) {
+				tdbp->tdb_auth_errs += 1;
+				spin_unlock(&tdb_lock);
 				if(stats) {
 					stats->rx_dropped++;
 				}
-				tdbp->tdb_auth_errs += 1;
-				spin_unlock(&tdb_lock);
 				goto rcvleave;
 			}
 
 			if (memcmp(hash, authenticator, authlen)) {
+				tdbp->tdb_auth_errs += 1;
+				spin_unlock(&tdb_lock);
 				KLIPS_PRINT(debug_rcv & DB_RX_INAU,
-					    "klips_debug:ipsec_rcv: auth failed on incoming "
-					    "packet from %s: hash=%08x%08x%08x "
-					    "auth=%08x%08x%08x, dropped\n", ipaddr_txt,
+					    "klips_debug:ipsec_rcv: "
+					    "auth failed on incoming packet from %s: hash=%08x%08x%08x auth=%08x%08x%08x, dropped\n",
+					    ipaddr_txt,
 					    *(__u32*)&hash[0],
 					    *(__u32*)&hash[4],
 					    *(__u32*)&hash[8],
@@ -981,12 +999,11 @@
 				if(stats) {
 					stats->rx_dropped++;
 				}
-				tdbp->tdb_auth_errs += 1;
-				spin_unlock(&tdb_lock);
 				goto rcvleave;
 			} else {
 				KLIPS_PRINT(debug_rcv,
-					    "klips_debug:ipsec_rcv: authentication successful.\n");
+					    "klips_debug:ipsec_rcv: "
+					    "authentication successful.\n");
 			}
 			
 			memset((caddr_t)&tctx, 0, sizeof(tctx));
@@ -994,15 +1011,15 @@
 		}
 
 		if (!ipsec_updatereplaywindow(tdbp, replay)) {
+			tdbp->tdb_replaywin_errs += 1;
+			spin_unlock(&tdb_lock);
 			KLIPS_PRINT(debug_rcv & DB_RX_REPLAY,
-				    "klips_debug:ipsec_rcv: duplicate frame from %s,"
-				    " packet dropped\n",
+				    "klips_debug:ipsec_rcv: "
+				    "duplicate frame from %s, packet dropped\n",
 				    ipaddr_txt);
 			if(stats) {
 				stats->rx_dropped++;
 			}
-			tdbp->tdb_replaywin_errs += 1;
-			spin_unlock(&tdb_lock);
 			goto rcvleave;
 		}
 		
@@ -1010,37 +1027,52 @@
 #ifdef CONFIG_IPSEC_ESP
 		case IPPROTO_ESP:
 			switch(tdbp->tdb_encalg) {
+			case ESP_DES:
 			case ESP_3DES:
 				iv[0] = *((__u32 *)(espp->esp_iv)    );
 				iv[1] = *((__u32 *)(espp->esp_iv) + 1);
 				esphlen = sizeof(struct esp);
 				break;
-			case ESP_NULL:
-				esphlen = offsetof(struct esp, esp_iv);
-				break;
 			default:
+				tdbp->tdb_alg_errs += 1;
+				spin_unlock(&tdb_lock);
 				if(stats) {
 					stats->rx_errors++;
 				}
-				tdbp->tdb_alg_errs += 1;
-				spin_unlock(&tdb_lock);
 				goto rcvleave;
 			}
 			idat += esphlen;
 			ilen -= esphlen;
 			
 			switch(tdbp->tdb_encalg) {
-			case ESP_3DES:
+			case ESP_DES:
 				if ((ilen) % 8) {
+					tdbp->tdb_encsize_errs += 1;
+					spin_unlock(&tdb_lock);
 					printk("klips_error:ipsec_rcv: "
-					       "got packet with esplen = %d from %s "
-					       "-- should be on 8 octet boundary, packet dropped\n",
-					       ilen, ipaddr_txt);
+					       "got packet with esplen = %d from %s -- should be on 8 octet boundary, packet dropped\n",
+					       ilen,
+					       ipaddr_txt);
 					if(stats) {
 						stats->rx_errors++;
 					}
+					goto rcvleave;
+				}
+				des_cbc_encrypt(idat, idat, ilen,
+						     tdbp->tdb_key_e,
+						     (caddr_t)iv, 0);
+				break;
+			case ESP_3DES:
+				if ((ilen) % 8) {
 					tdbp->tdb_encsize_errs += 1;
 					spin_unlock(&tdb_lock);
+					printk("klips_error:ipsec_rcv: "
+					       "got packet with esplen = %d from %s -- should be on 8 octet boundary, packet dropped\n",
+					       ilen,
+					       ipaddr_txt);
+					if(stats) {
+						stats->rx_errors++;
+					}
 					goto rcvleave;
 				}
 				des_ede3_cbc_encrypt(idat, idat, ilen,
@@ -1049,8 +1081,6 @@
 						     tdbp->tdb_key_e + 2 * sizeof(struct des_eks),
 						     (caddr_t)iv, 0);
 				break;
-			case ESP_NULL:
-				break;
 			}
 			next_header = idat[ilen - 1];
 			padlen = idat[ilen - 2];
@@ -1123,23 +1153,25 @@
 				(void *)(skb->data), iphlen);
 			if(skb->len < esphlen) {
 				spin_unlock(&tdb_lock);
-				printk(KERN_WARNING "klips_error:ipsec_rcv: "
-				       "tried to skb_pull esphlen=%d, %d available.  "
-				       "This should never happen, please report.\n",
+				printk(KERN_WARNING
+				       "klips_error:ipsec_rcv: "
+				       "tried to skb_pull esphlen=%d, %d available.  This should never happen, please report.\n",
 				       esphlen, (int)(skb->len));
 				goto rcvleave;
 			}
 			skb_pull(skb, esphlen);
 
 			KLIPS_PRINT(debug_rcv & DB_RX_PKTRX,
-				    "klips_debug:ipsec_rcv: trimming to %d.\n",
+				    "klips_debug:ipsec_rcv: "
+				    "trimming to %d.\n",
 				    len - esphlen - pad);
 			if(pad + esphlen <= len) {
 			        skb_trim(skb, len - esphlen - pad);
 			} else {
 				spin_unlock(&tdb_lock);
 			        KLIPS_PRINT(debug_rcv & DB_RX_PKTRX,
-				            "klips_debug:ipsec_rcv: bogus packet, size is zero or negative, dropping.\n");
+				            "klips_debug:ipsec_rcv: "
+					    "bogus packet, size is zero or negative, dropping.\n");
 				goto rcvleave;
 			}
 		break;
@@ -1151,10 +1183,11 @@
 				(void *)(skb->data), iphlen);
 			if(skb->len < ahhlen) {
 				spin_unlock(&tdb_lock);
-				printk(KERN_WARNING "klips_error:ipsec_rcv: "
-				       "tried to skb_pull ahhlen=%d, %d available.  "
-				       "This should never happen, please report.\n",
-				       ahhlen, (int)(skb->len));
+				printk(KERN_WARNING
+				       "klips_error:ipsec_rcv: "
+				       "tried to skb_pull ahhlen=%d, %d available.  This should never happen, please report.\n",
+				       ahhlen,
+				       (int)(skb->len));
 				goto rcvleave;
 			}
 			skb_pull(skb, ahhlen);
@@ -1187,8 +1220,10 @@
 		ipp->check = ip_fast_csum((unsigned char *)dat, iphlen >> 2);
 		
 		KLIPS_PRINT(debug_rcv & DB_RX_PKTRX,
-			    "klips_debug:ipsec_rcv: after <%s%s%s>, SA:%s:\n",
-					    TDB_XFORM_NAME(tdbp), sa);
+			    "klips_debug:ipsec_rcv: "
+			    "after <%s%s%s>, SA:%s:\n",
+			    TDB_XFORM_NAME(tdbp),
+			    sa_len ? sa : " (error)");
 		KLIPS_IP_PRINT(debug_rcv & DB_RX_PKTRX, ipp);
 		
 		skb->protocol = htons(ETH_P_IP);
@@ -1203,7 +1238,7 @@
 					KLIPS_PRINT(debug_rcv,
 						    "klips_debug:ipsec_rcv: "
 						    "SA:%s, backpolicy does not agree with fwdpolicy.\n",
-						    sa);
+						    sa_len ? sa : " (error)");
 					if(stats) {
 						stats->rx_dropped++;
 					}
@@ -1212,7 +1247,7 @@
 				KLIPS_PRINT(debug_rcv,
 					    "klips_debug:ipsec_rcv: "
 					    "SA:%s, backpolicy agrees with fwdpolicy.\n",
-					    sa);
+					    sa_len ? sa : " (error)");
 				if(!(   (ipp->protocol == IPPROTO_AH  )
 					|| (ipp->protocol == IPPROTO_ESP )
 					|| (ipp->protocol == IPPROTO_IPIP)
@@ -1224,7 +1259,7 @@
 					KLIPS_PRINT(debug_rcv,
 						    "klips_debug:ipsec_rcv: "
 						    "packet with incomplete policy dropped, last successful SA:%s.\n",
-						    sa);
+						    sa_len ? sa : " (error)");
 					if(stats) {
 						stats->rx_dropped++;
 					}
@@ -1233,12 +1268,12 @@
 				KLIPS_PRINT(debug_rcv,
 					    "klips_debug:ipsec_rcv: "
 					    "SA:%s, Another IPSEC header to process.\n",
-					    sa);
+					    sa_len ? sa : " (error)");
 			} else {
 				KLIPS_PRINT(debug_rcv,
 					    "klips_debug:ipsec_rcv: "
 					    "No tdb_inext from this SA:%s.\n",
-					    sa);
+					    sa_len ? sa : " (error)");
 			}
 		}
 
@@ -1288,7 +1323,7 @@
 			KLIPS_PRINT(debug_rcv,
 				    "klips_debug:ipsec_rcv: "
 				    "SA:%s, Hey!  How did this get through?  Dropped.\n",
-				    sa);
+				    sa_len ? sa : " (error)");
 			if(stats) {
 				stats->rx_dropped++;
 			}
@@ -1296,12 +1331,14 @@
 		}
 		if(sysctl_ipsec_inbound_policy_check && (tdbnext = tdbp->tdb_inext)) {
 			char sa2[SATOA_BUF];
-			sa_len = satoa(tdbnext->tdb_said, 0, sa2, SATOA_BUF);
+			size_t sa_len2;
+			sa_len2 = satoa(tdbnext->tdb_said, 0, sa2, SATOA_BUF);
 			spin_unlock(&tdb_lock);
 			KLIPS_PRINT(debug_rcv,
 				    "klips_debug:ipsec_rcv: "
 				    "unexpected SA:%s after IPIP SA:%s\n",
-				    sa2, sa);
+				    sa_len2 ? sa2 : " (error)",
+				    sa_len ? sa : " (error)");
 			if(stats) {
 				stats->rx_dropped++;
 			}
@@ -1345,6 +1382,8 @@
 		policy_said = er->er_said;
 		policy_eaddr = er->er_eaddr;
 		policy_emask = er->er_emask;
+		er->er_count++;
+		er->er_lasttime = jiffies/HZ;
 	}
 	
 	spin_unlock(&eroute_lock);
@@ -1355,15 +1394,15 @@
 		 * accessing or deleting the tdb while we are using and
 		 * updating it.
 		 */
-		/* spin_lock(&tdb_lock); */
+		spin_lock(&tdb_lock);
 
 		policy_tdb = gettdb(&policy_said);
 		if (policy_tdb == NULL) {
-			/* spin_unlock(&tdb_lock); */
+			spin_unlock(&tdb_lock);
 			KLIPS_PRINT(debug_rcv,
 				    "klips_debug:ipsec_rcv: "
-				    "no Tunnel Descriptor Block for SA%s: "
-				    "incoming packet with no policy SA, dropped.\n", sa);
+				    "no Tunnel Descriptor Block for SA%s: incoming packet with no policy SA, dropped.\n",
+				    sa_len ? sa : " (error)");
 			goto rcvleave;
 		}
 		
@@ -1371,7 +1410,8 @@
 
 		KLIPS_PRINT(debug_rcv,
 			    "klips_debug:ipsec_rcv: "
-			    "found policy Tunnel Descriptor Block -- SA:%s\n", sa);
+			    "found policy Tunnel Descriptor Block -- SA:%s\n",
+			    sa_len ? sa : " (error)");
 		while(1) {
 			if(policy_tdb->tdb_inext) {
 				policy_tdb = policy_tdb->tdb_inext;
@@ -1380,11 +1420,11 @@
 			}
 		}
 		if(policy_tdb != tdbp) {
-			/* spin_unlock(&tdb_lock); */
+			spin_unlock(&tdb_lock);
 			KLIPS_PRINT(debug_rcv,
 				    "klips_debug:ipsec_rcv: "
-				    " Tunnel Descriptor Block for SA%s: "
-				    "incoming packet with different policy SA, dropped.\n", sa);
+				    "Tunnel Descriptor Block for SA%s: incoming packet with different policy SA, dropped.\n",
+				    sa_len ? sa : " (error)");
 			goto rcvleave;
 		}
 
@@ -1408,12 +1448,12 @@
 		}
 		
 		if(skb->len < iphlen) {
+			spin_unlock(&tdb_lock);
 			printk(KERN_WARNING "klips_debug:ipsec_rcv: "
-			       "tried to skb_pull iphlen=%d, %d available.  "
-			       "This should never happen, please report.\n",
-			       iphlen, (int)(skb->len));
+			       "tried to skb_pull iphlen=%d, %d available.  This should never happen, please report.\n",
+			       iphlen,
+			       (int)(skb->len));
 
-			spin_unlock(&tdb_lock);
 			goto rcvleave;
 		}
 		skb_pull(skb, iphlen);
@@ -1432,7 +1472,8 @@
 		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_debug:ipsec_rcv: "
+			    "IPIP tunnel stripped.\n");
 		KLIPS_IP_PRINT(debug_rcv & DB_RX_PKTRX, ipp);
 	}
 
@@ -1469,7 +1510,10 @@
 			}
 			goto rcvleave;
 		}
-		/* XXX need a tdb for updating ratio counters XXX */
+		/*
+		  XXX need a TDB for updating ratio counters but it is not
+		  following policy anyways so it is not a priority
+		*/
 		skb = skb_decompress(skb, NULL, &flags);
 		if (!skb || flags) {
 			KLIPS_PRINT(debug_rcv & DB_RX_PKTRX,
@@ -1481,11 +1525,6 @@
 			}
 			goto rcvleave;
 		}
-#ifdef NET_21
-		ipp = skb->nh.iph;
-#else /* NET_21 */
-		ipp = skb->ip_hdr;
-#endif /* NET_21 */
 	}
 #endif /* CONFIG_IPSEC_IPCOMP */
 
@@ -1497,7 +1536,8 @@
 #endif /* CONFIG_NETFILTER_DEBUG */
 #endif /* SKB_RESET_NFCT */
 	KLIPS_PRINT(debug_rcv & DB_RX_PKTRX,
-		    "klips_debug:ipsec_rcv: netif_rx() called.\n");
+		    "klips_debug:ipsec_rcv: "
+		    "netif_rx() called.\n");
 	netif_rx(skb);
 
 	MOD_DEC_USE_COUNT;
@@ -1558,6 +1598,43 @@
 
 /*
  * $Log: ipsec_rcv.c,v $
+ * 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.
@@ -1661,9 +1738,6 @@
  * 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
diff -bruN freeswan-1.9.orig/klips/net/ipsec/ipsec_rcv.h freeswan-1.9/klips/net/ipsec/ipsec_rcv.h
--- freeswan-1.9.orig/klips/net/ipsec/ipsec_rcv.h	Thu Sep 21 00:34:21 2000
+++ freeswan-1.9/klips/net/ipsec/ipsec_rcv.h	Mon Jun  4 11:34:31 2001
@@ -13,7 +13,7 @@
  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  * for more details.
  *
- * RCSID $Id: ipsec_rcv.h,v 1.11 2000/09/21 04:34:21 rgb Exp $
+ * RCSID $Id: ipsec_rcv.h,v 1.12 2001/03/16 07:36:44 rgb Exp $
  */
 
 #define DB_RX_PKTRX	0x0001
@@ -55,10 +55,13 @@
 extern int debug_rcv;
 #endif /* CONFIG_IPSEC_DEBUG */
 extern int sysctl_ipsec_inbound_policy_check;
-#endif __KERNEL__
+#endif /* __KERNEL__ */
 
 /*
  * $Log: ipsec_rcv.h,v $
+ * Revision 1.12  2001/03/16 07:36:44  rgb
+ * Fixed #endif comment to sate compiler.
+ *
  * Revision 1.11  2000/09/21 04:34:21  rgb
  * Moved declaration of sysctl_ipsec_inbound_policy_check outside
  * CONFIG_IPSEC_DEBUG. (MB)
diff -bruN freeswan-1.9.orig/klips/net/ipsec/ipsec_tunnel.c freeswan-1.9/klips/net/ipsec/ipsec_tunnel.c
--- freeswan-1.9.orig/klips/net/ipsec/ipsec_tunnel.c	Mon Feb 26 19:51:00 2001
+++ freeswan-1.9/klips/net/ipsec/ipsec_tunnel.c	Tue Jun 12 16:35:03 2001
@@ -14,7 +14,7 @@
  * for more details.
  */
 
-char ipsec_tunnel_c_version[] = "RCSID $Id: ipsec_tunnel.c,v 1.137.2.1 2001/02/27 00:51:00 henry Exp $";
+char ipsec_tunnel_c_version[] = "RCSID $Id: ipsec_tunnel.c,v 1.163 2001/06/06 20:28:51 rgb Exp $";
 
 #define __NO_VERSION__
 #include <linux/module.h>
@@ -80,7 +80,7 @@
 #include <net/ip.h>
 #ifdef NETDEV_23
 #include <linux/netfilter_ipv4.h>
-#endif
+#endif /* NETDEV_23 */
 
 #include "radij.h"
 #include "ipsec_encap.h"
@@ -103,6 +103,7 @@
 #ifdef MSS_HACK
 #include <net/tcp.h>		/* TCP options */
 #endif	/* MSS_HACK */
+extern void des_cbc_encrypt(caddr_t, caddr_t, int, caddr_t, caddr_t, int);
 extern void des_ede3_cbc_encrypt(caddr_t, caddr_t, int, caddr_t, caddr_t, caddr_t, caddr_t, int);
 static __u32 zeroes[64];
 
@@ -112,8 +113,6 @@
 #endif /* CONFIG_IPSEC_DEBUG */
 
 int sysctl_ipsec_icmp = 0;
-int sysctl_ipsec_no_eroute_pass = 0;
-int sysctl_ipsec_opportunistic = 0;
 int sysctl_ipsec_tos = 0;
 
 #ifdef CONFIG_IPSEC_DEBUG_
@@ -124,7 +123,10 @@
 	unsigned char *b = bb;
   
 	if (debug_tunnel) {
-		printk(KERN_INFO "klips_debug:ipsec_tunnel_:at %s, len=%d:", s, len);
+		printk(KERN_INFO "klips_debug:ipsec_tunnel_:dmp: "
+		       "at %s, len=%d:",
+		       s,
+		       len);
 		for (i=0; i < len; i++) {
 			if(!(i%16)){
 				printk("\nklips_debug:  ");
@@ -152,9 +154,11 @@
 	 *	Do sanity checking
 	 */
 	if((headroom < 0) || (tailroom < 0) || ((headroom+tailroom) < 0)) {
-		printk(KERN_WARNING "klips_error:skb_copy_expand: "
+		printk(KERN_WARNING
+		       "klips_error:skb_copy_expand: "
 		       "Illegal negative head,tailroom %d,%d\n",
-		       headroom, tailroom);
+		       headroom,
+		       tailroom);
 		return NULL;
 	}
 	/*
@@ -192,9 +196,9 @@
 	/* 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));
+		       "tried to skb_put %ld, %d available.  This should never happen, please report.\n",
+		       (unsigned long int)skb->len,
+		       skb_tailroom(n));
 		dev_kfree_skb(n, FREE_WRITE);
 		return NULL;
 	}
@@ -243,7 +247,9 @@
 	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;
 	
@@ -265,11 +271,15 @@
 	printk(" ver:%d", ip->version);
 	printk(" tos:%d", ip->tos);
 	printk(" tlen:%d", ntohs(ip->tot_len));
-	printk(" id:%d", ip->id);
-	printk(" frag_off:%d", ip->frag_off);
+	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);
-	printk(" chk:%d", ip->check);
+	printk(" chk:%d", ntohs(ip->check));
 	addrtoa(*((struct in_addr*)(&ip->saddr)), 0, buf, sizeof(buf));
 	printk(" saddr:%s", buf);
 	addrtoa(*((struct in_addr*)(&ip->daddr)), 0, buf, sizeof(buf));
@@ -283,7 +293,8 @@
 		c = ((__u8*)ip) + ip->ihl*4;
 		for(i = 0; i < ntohs(ip->tot_len) - ip->ihl*4; i++ /*, c++*/) {
 			if(!(i % 16)) {
-				printk(KERN_INFO "klips_debug:   @%03x:",
+				printk(KERN_INFO
+				       "klips_debug:   @%03x:",
 				       i);
 			}
 			printk(" %02x", /***/c[i]);
@@ -303,6 +314,7 @@
  *	Locking
  */
  
+#if 0
 DEBUG_NO_STATIC int
 ipsec_tunnel_lock(struct ipsecpriv *prv)
 {
@@ -322,13 +334,16 @@
 	restore_flags(flags);
 	return 1;
 }
+#endif
 
+#if 0
 DEBUG_NO_STATIC void
 ipsec_tunnel_unlock(struct ipsecpriv *prv)
 {
 	prv->locked=0;
 	wake_up(&prv->wait_queue);
 }
+#endif
 #endif /* REAL_LOCKING_P */
 
 DEBUG_NO_STATIC int
@@ -434,9 +449,6 @@
 	__u32   newsrc;			/* The new source SG's IP address */
 	__u32	orgsrc;			/* Original IP source address */
 	__u32	innersrc;		/* Innermost IP source address */
-#ifdef NETDEV_23
-	__u32	route_saddr;		/* source IP used in route lookup */
-#endif /* NETDEV_23 */
 	int	iphlen;			/* IP header length */
 	int	pyldsz;			/* upper protocol payload size */
 	int	headroom;
@@ -464,6 +476,11 @@
 	struct rtable *rt = NULL;
 #endif /* NET_21 */
 	struct sa_id outgoing_said;
+#ifdef NET_21
+	int pass = 0;
+#endif /* NET_21 */
+	int error = 0;
+	uint32_t eroute_pid = 0;
 
 	/*
 	 *	Return if there is nothing to do.  (Does this ever happen?) XXX
@@ -506,10 +523,17 @@
 	   tcpdump being momentarily attached to the interface), make
 	   a copy of our own to modify */
 	if(skb_cloned(skb)) {
-		if ((skb = skb_cow(skb, skb_headroom(skb))) == NULL) {
+		if
+#ifdef SKB_COW_NEW
+	       (skb_cow(skb, skb_headroom(skb)) != 0)
+#else /* SKB_COW_NEW */
+	       ((skb = skb_cow(skb, skb_headroom(skb))) == NULL)
+#endif /* SKB_COW_NEW */
+		{
 			KLIPS_PRINT(debug_tunnel & DB_TN_XMIT,
 		        	    "klips_error:ipsec_tunnel_start_xmit: "
 				    "skb_cow failed to allocate buffer, dropping.\n" );
+			stats->tx_dropped++;
 			goto cleanup;
 		}
 	}
@@ -572,8 +596,7 @@
 	if ((iph->ihl << 2) != sizeof (struct iphdr)) {
 		KLIPS_PRINT(debug_tunnel,
 			    "klips_debug:ipsec_tunnel_start_xmit: "
-			    "cannot process IP header options yet.  "
-			    "May be mal-formed packet.\n"); /* XXX */
+			    "cannot process IP header options yet.  May be mal-formed packet.\n"); /* XXX */
 		stats->tx_dropped++;
 		goto cleanup;
 	}
@@ -623,6 +646,9 @@
 	er = ipsec_findroute(&matcher);
 	if(er) {
 		outgoing_said = er->er_said;
+		eroute_pid = er->er_pid;
+		er->er_count++;
+		er->er_lasttime = jiffies/HZ;
 	}
 
 	spin_unlock(&eroute_lock);
@@ -632,24 +658,19 @@
 	 * without interference since it is most likely an IKE packet.
 	 */
 	if((ip_chk_addr((unsigned long)iph->saddr) == IS_MYADDR)
-	   && ((!er) || (iph->daddr == outgoing_said.dst.s_addr))) {
-		if(iph->protocol == IPPROTO_UDP) {
-			struct udphdr *udph = (struct udphdr*)((caddr_t)iph + (iph->ihl << 2));
-			if(ntohs(udph->dest) == 500) {
+	   && ((!er)
+	       || (iph->daddr == outgoing_said.dst.s_addr)
+	       || (INADDR_ANY == outgoing_said.dst.s_addr))
+	   && (iph->protocol == IPPROTO_UDP)
+	   && (ntohs(((struct udphdr*)((caddr_t)iph + (iph->ihl << 2)))->dest) == 500)) {
+#ifdef NET_21
+		pass = 1;
+#endif /* NET_21 */
 				KLIPS_PRINT(debug_tunnel & DB_TN_XMIT,
 					    "klips_debug:ipsec_tunnel_start_xmit: "
 					    "udp/500 IKE packet, sending unprocessed, "
 					    "calling dev_queue_xmit\n"); 
-#if 1
 				goto bypass;
-#else
-				DEV_QUEUE_XMIT(skb, physdev, SOPRI_NORMAL);
-				/* IP_SEND(skb, physdev); */
-				skb = NULL;
-				goto cleanup;
-#endif
-			}
-		}
 	}
 
 	KLIPS_PRINT(debug_tunnel & DB_TN_CROUT,
@@ -660,6 +681,8 @@
 	innersrc = iph->saddr;
 	/* start encapsulation loop here XXX */
 	do {
+		struct tdb *tdbprev = NULL;
+
 		newdst = orgdst = iph->daddr;
 		newsrc = orgsrc = iph->saddr;
 		orgedst = outgoing_said.dst.s_addr;
@@ -667,26 +690,55 @@
 		pyldsz = ntohs(iph->tot_len) - iphlen;
 		max_headroom = max_tailroom = 0;
 		
-		if (er == NULL)	{
-			if(sysctl_ipsec_no_eroute_pass) {
+		if(er == NULL || (outgoing_said.proto==IPPROTO_INT
+				  && outgoing_said.spi==htonl(SPI_DROP))) {
 				KLIPS_PRINT(debug_tunnel & DB_TN_XMIT,
 					    "klips_debug:ipsec_tunnel_start_xmit: "
-					    "no eroute!: calling dev_queue_xmit\n");
-#if 1
+				    "shunt SA of DROP or no eroute: dropping.\n");
+			stats->tx_dropped++;
+			goto cleanup;
+		}
+		
+		if(outgoing_said.proto==IPPROTO_INT
+		   && outgoing_said.spi==htonl(SPI_REJECT)) {
+			KLIPS_PRINT(debug_tunnel & DB_TN_XMIT,
+				    "klips_debug:ipsec_tunnel_start_xmit: "
+				    "shunt SA of REJECT: notifying when coded... and dropping.\n");
+			stats->tx_dropped++;
+			goto cleanup;
+		}
+		
+		if(outgoing_said.proto==IPPROTO_INT
+		   && outgoing_said.spi==htonl(SPI_PASS)) {
+#ifdef NET_21
+			pass = 1;
+#endif /* NET_21 */
+			KLIPS_PRINT(debug_tunnel & DB_TN_XMIT,
+				    "klips_debug:ipsec_tunnel_start_xmit: "
+				    "shunt SA of PASS: calling dev_queue_xmit\n");
 				goto bypass;
-#else
-				DEV_QUEUE_XMIT(skb, physdev, SOPRI_NORMAL);
-				/* IP_SEND(skb, physdev); */
-				skb = NULL;
-#endif
-			} else {
-				if(sysctl_ipsec_opportunistic && !er) {
+		}
+
+		if(outgoing_said.proto==IPPROTO_INT
+		   && outgoing_said.spi==htonl(SPI_HOLD)) {
+			KLIPS_PRINT(debug_tunnel & DB_TN_XMIT,
+				    "klips_debug:ipsec_tunnel_start_xmit: "
+				    "shunt SA of HOLD: will stash when coded..., dropping for now.\n");
+			stats->tx_dropped++;
+			goto cleanup;
+		}
+		
+		if(outgoing_said.proto==IPPROTO_INT
+		   && outgoing_said.spi==htonl(SPI_TRAP)) {
 					struct tdb tdb;
 					struct sockaddr_in src, dst;
 #ifdef CONFIG_IPSEC_DEBUG
 					char bufsrc[ADDRTOA_BUF], bufdst[ADDRTOA_BUF];
 #endif /* CONFIG_IPSEC_DEBUG */
+			struct eroute hold_eroute;
+			struct sa_id hold_said;
 					
+			/* Signal all listening KMds with a PF_KEY ACQUIRE */
 					tdb.tdb_said.proto = iph->protocol;
 					src.sin_family = AF_INET;
 					dst.sin_family = AF_INET;
@@ -723,41 +775,106 @@
 						    ((struct sockaddr_in*)(tdb.tdb_addr_d))->sin_port,
 						    tdb.tdb_said.proto);
 					pfkey_acquire(&tdb);
-				} else {
-					KLIPS_PRINT(debug_tunnel & DB_TN_XMIT,
+
+			/* install HOLD eroute */
+			memset((caddr_t)&hold_eroute, 0, sizeof(hold_eroute));
+			memset((caddr_t)&hold_said, 0, sizeof(hold_said));
+
+			hold_said.proto = IPPROTO_INT;
+			hold_said.spi = htonl(SPI_HOLD);
+			hold_said.dst.s_addr = 0L;
+
+			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_pid = eroute_pid;
+			hold_eroute.er_count = 0;
+			hold_eroute.er_lasttime = jiffies/HZ;
+
+#ifdef IPSEC_CONFIG_FULL_SELECTOR_LIST
+			/* These are ficticious.  Don't uncomment these until
+			   proto, sport and dport exist in the SPDB */
+			hold_eroute.er_proto = iph->protocol;
+			hold_eroute.er_src_port = 
+				(iph->protocol == IPPROTO_UDP
+				 ? ((struct udphdr*) (((caddr_t)iph) + (iph->ihl << 2)))->source
+				 : (iph->protocol == IPPROTO_TCP
+				    ? ((struct tcphdr*)((caddr_t)iph + (iph->ihl << 2)))->source
+				    : 0));
+			hold_eroute.er_dst_port = 
+				(iph->protocol == IPPROTO_UDP
+				 ? ((struct udphdr*) (((caddr_t)iph) + (iph->ihl << 2)))->dest
+				 : (iph->protocol == IPPROTO_TCP
+				    ? ((struct tcphdr*)((caddr_t)iph + (iph->ihl << 2)))->dest
+				    : 0));
+#endif /* IPSEC_CONFIG_FULL_SELECTOR_LIST */
+
+#ifdef CONFIG_IPSEC_DEBUG
+			if (debug_pfkey) {
+				char buf1[64], buf2[64];
+				subnettoa(hold_eroute.er_eaddr.sen_ip_src,
+					  hold_eroute.er_emask.sen_ip_src, 0, buf1, sizeof(buf1));
+				subnettoa(hold_eroute.er_eaddr.sen_ip_dst,
+					  hold_eroute.er_emask.sen_ip_dst, 0, buf2, sizeof(buf2));
+				KLIPS_PRINT(debug_pfkey,
 						    "klips_debug:ipsec_tunnel_start_xmit: "
-						    "no eroute!: dropping.\n");
-					stats->tx_dropped++;
+					    "calling breakeroute and makeroute for %s->%s HOLD eroute.\n",
+					    buf1, buf2);
 				}
-			}
-			goto cleanup;
+#endif /* CONFIG_IPSEC_DEBUG */
+			if (!(ipsec_breakroute(&(hold_eroute.er_eaddr),
+						      &(hold_eroute.er_emask)) == EINVAL)) {
+				KLIPS_PRINT(debug_pfkey,
+					    "klips_debug:ipsec_tunnel_start_xmit: "
+					    "breakeroute should have failed.\n");
+				/* SENDERR(-error); */
+			} else {
+				KLIPS_PRINT(debug_pfkey,
+					    "klips_debug:ipsec_tunnel_start_xmit: "
+					    "HOLD breakeroute found nothing as expected.\n");
 		}
 		
-		/*
-		  If the packet matches an eroute with an SA.proto of IP
-		  tunnelling and 
-		  an SA.spi of '0', then forward the packet unprotected.
-		  XXX -- This should eventually go into an SPD. 
-		*/
-		if((outgoing_said.proto == IPPROTO_IPIP) && (outgoing_said.spi == 0)) {
-			KLIPS_PRINT(debug_tunnel & DB_TN_XMIT,
+			if ((error = ipsec_makeroute(&(hold_eroute.er_eaddr),
+						     &(hold_eroute.er_emask),
+						     hold_said,
+						     eroute_pid))) {
+				KLIPS_PRINT(debug_pfkey,
 				    "klips_debug:ipsec_tunnel_start_xmit: "
-				    "passthrough eroute, packet sent.\n");
-#if 1
-			goto bypass;
-#else
-			DEV_QUEUE_XMIT(skb, physdev, SOPRI_NORMAL);
-			/* IP_SEND(skb, physdev); */
-			skb = NULL;
+					    "HOLD makeroute returned %d, failed.\n", error);
+				/* SENDERR(-error); */
+			} else {
+				KLIPS_PRINT(debug_pfkey,
+					    "klips_debug:ipsec_tunnel_start_xmit: "
+					    "HOLD makeroute call successful.\n");
+			}
+			
 			goto cleanup;
-#endif
 		}
 		
 		/*
-		 * The spinlock is to prevent any other process from accessing or deleting
-		 * the tdb while we are using and updating it.
+		  The spinlock is to prevent any other process from
+		  accessing or deleting the TDB hash table or any of the
+		  TDBs while we are using and updating them.
+		  
+		  This is not optimal, but was relatively straightforward
+		  at the time.  A better way to do it has been planned for
+		  more than a year, to lock the hash table and put reference
+		  counts on each TDB instead.  This is not likely to happen
+		  in KLIPS1 unless a volunteer contributes it, but will be
+		  designed into KLIPS2.
 		 */
+		if(tdbprev == NULL) {
 		spin_lock(&tdb_lock);
+		}
 
 		tdbp = gettdb(&outgoing_said);
 		sa_len = satoa(outgoing_said, 0, sa, SATOA_BUF);
@@ -766,8 +883,8 @@
 			spin_unlock(&tdb_lock);
 			KLIPS_PRINT(debug_tunnel & DB_TN_XMIT,
 				    "klips_debug:ipsec_tunnel_start_xmit: "
-				    "no Tunnel Descriptor Block for SA%s: "
-				    "outgoing packet with no SA, dropped.\n", sa);
+				    "no Tunnel Descriptor Block for SA%s: outgoing packet with no SA, dropped.\n",
+				    sa_len ? sa : " (error)");
 			stats->tx_dropped++;
 			goto cleanup;
 		}
@@ -775,7 +892,8 @@
 		KLIPS_PRINT(debug_tunnel & DB_TN_XMIT,
 			    "klips_debug:ipsec_tunnel_start_xmit: "
 			    "found Tunnel Descriptor Block -- SA:<%s%s%s> %s\n",
-			    TDB_XFORM_NAME(tdbp), sa);
+			    TDB_XFORM_NAME(tdbp),
+			    sa_len ? sa : " (error)");
 		
 		/*
 		 * How much headroom do we need to be able to apply
@@ -789,9 +907,9 @@
 			if(tdbp->tdb_state == SADB_SASTATE_LARVAL) {
 				KLIPS_PRINT(debug_tunnel & DB_TN_XMIT,
 					    "klips_debug:ipsec_tunnel_start_xmit: "
-					    "TDB in larval state for SA:<%s%s%s> %s, "
-					    "cannot be used yet, dropping packet.\n",
-					    TDB_XFORM_NAME(tdbp), sa);
+					    "TDB in larval state for SA:<%s%s%s> %s, cannot be used yet, dropping packet.\n",
+					    TDB_XFORM_NAME(tdbp),
+					    sa_len ? sa : " (error)");
 				spin_unlock(&tdb_lock);
 				stats->tx_errors++;
 				goto cleanup;
@@ -800,9 +918,9 @@
 			if(tdbp->tdb_state == SADB_SASTATE_DEAD) {
 				KLIPS_PRINT(debug_tunnel & DB_TN_XMIT,
 					    "klips_debug:ipsec_tunnel_start_xmit: "
-					    "TDB in dead state for SA:<%s%s%s> %s, "
-					    "can no longer be used, dropping packet.\n",
-					    TDB_XFORM_NAME(tdbp), sa);
+					    "TDB in dead state for SA:<%s%s%s> %s, can no longer be used, dropping packet.\n",
+					    TDB_XFORM_NAME(tdbp),
+					    sa_len ? sa : " (error)");
 				spin_unlock(&tdb_lock);
 				stats->tx_errors++;
 				goto cleanup;
@@ -813,9 +931,9 @@
 				pfkey_expire(tdbp, 1);
 				KLIPS_PRINT(debug_tunnel & DB_TN_XMIT,
 					    "klips_debug:ipsec_tunnel_start_xmit: "
-					    "replay window counter rolled for SA:<%s%s%s> %s, "
-					    "packet dropped, expiring SA.\n",
-					    TDB_XFORM_NAME(tdbp), sa);
+					    "replay window counter rolled for SA:<%s%s%s> %s, packet dropped, expiring SA.\n",
+					    TDB_XFORM_NAME(tdbp),
+					    sa_len ? sa : " (error)");
 				deltdbchain(tdbp);
 				spin_unlock(&tdb_lock);
 				stats->tx_errors++;
@@ -828,9 +946,9 @@
 				pfkey_expire(tdbp, 1);
 				KLIPS_PRINT(debug_tunnel & DB_TN_XMIT,
 					    "klips_debug:ipsec_tunnel_start_xmit: "
-					    "hard bytes lifetime of SA:<%s%s%s> %s has been reached, "
-					    "SA expired, outgoing packet dropped.\n",
-					    TDB_XFORM_NAME(tdbp), sa);
+					    "hard bytes lifetime of SA:<%s%s%s> %s has been reached, SA expired, outgoing packet dropped.\n",
+					    TDB_XFORM_NAME(tdbp),
+					    sa_len ? sa : " (error)");
 				deltdbchain(tdbp);
 				spin_unlock(&tdb_lock);
 				stats->tx_errors++;
@@ -838,14 +956,15 @@
 			}
 			if(tdbp->tdb_lifetime_bytes_s &&
 			   (tdbp->tdb_lifetime_bytes_c > tdbp->tdb_lifetime_bytes_s)) {
+				if(tdbp->tdb_state != SADB_SASTATE_DYING) {
 				pfkey_expire(tdbp, 0);
+				}
 				tdbp->tdb_state = SADB_SASTATE_DYING;
 				KLIPS_PRINT(debug_tunnel & DB_TN_XMIT,
 					    "klips_debug:ipsec_tunnel_start_xmit: "
-					    "soft bytes lifetime of SA:<%s%s%s> %s has been reached, "
-					    "SA expiring, soft expire message sent up, "
-					    "outgoing packet still processed.\n",
-					    TDB_XFORM_NAME(tdbp), sa);
+					    "soft bytes lifetime of SA:<%s%s%s> %s has been reached, SA expiring, soft expire message sent up, outgoing packet still processed.\n",
+					    TDB_XFORM_NAME(tdbp),
+					    sa_len ? sa : " (error)");
 			}
 
 			if(tdbp->tdb_lifetime_addtime_h &&
@@ -854,9 +973,9 @@
 				pfkey_expire(tdbp, 1);
 				KLIPS_PRINT(debug_tunnel & DB_TN_XMIT,
 					    "klips_debug:ipsec_tunnel_start_xmit: "
-					    "hard addtime lifetime of SA:<%s%s%s> %s has been reached, "
-					    "SA expired, outgoing packet dropped.\n",
-					    TDB_XFORM_NAME(tdbp), sa);
+					    "hard addtime lifetime of SA:<%s%s%s> %s has been reached, SA expired, outgoing packet dropped.\n",
+					    TDB_XFORM_NAME(tdbp),
+					    sa_len ? sa : " (error)");
 				deltdbchain(tdbp);
 				spin_unlock(&tdb_lock);
 				stats->tx_errors++;
@@ -865,14 +984,15 @@
 			if(tdbp->tdb_lifetime_addtime_s &&
 			   ((jiffies / HZ) - tdbp->tdb_lifetime_addtime_c >
 			    tdbp->tdb_lifetime_addtime_s)) {
+				if(tdbp->tdb_state != SADB_SASTATE_DYING) {
 				pfkey_expire(tdbp, 0);
+				}
 				tdbp->tdb_state = SADB_SASTATE_DYING;
 				KLIPS_PRINT(debug_tunnel & DB_TN_XMIT,
 					    "klips_debug:ipsec_tunnel_start_xmit: "
-					    "soft addtime lifetime of SA:<%s%s%s> %s has been reached, "
-					    "SA expiring, soft expire message sent up, "
-					    "outgoing packet still processed.\n",
-					    TDB_XFORM_NAME(tdbp), sa);
+					    "soft addtime lifetime of SA:<%s%s%s> %s has been reached, SA expiring, soft expire message sent up, outgoing packet still processed.\n",
+					    TDB_XFORM_NAME(tdbp),
+					    sa_len ? sa : " (error)");
 			}
 
 			if(tdbp->tdb_lifetime_usetime_c) {
@@ -882,9 +1002,9 @@
 					pfkey_expire(tdbp, 1);
 					KLIPS_PRINT(debug_tunnel & DB_TN_XMIT,
 						    "klips_debug:ipsec_tunnel_start_xmit: "
-						    "hard usetime lifetime of SA:<%s%s%s> %s has been reached, "
-						    "SA expired, outgoing packet dropped.\n",
-						    TDB_XFORM_NAME(tdbp), sa);
+						    "hard usetime lifetime of SA:<%s%s%s> %s has been reached, SA expired, outgoing packet dropped.\n",
+						    TDB_XFORM_NAME(tdbp),
+						    sa_len ? sa : " (error)");
 					deltdbchain(tdbp);
 					spin_unlock(&tdb_lock);
 					stats->tx_errors++;
@@ -893,14 +1013,15 @@
 				if(tdbp->tdb_lifetime_usetime_s &&
 				   ((jiffies / HZ) - tdbp->tdb_lifetime_usetime_c >
 				    tdbp->tdb_lifetime_usetime_s)) {
+					if(tdbp->tdb_state != SADB_SASTATE_DYING) {
 					pfkey_expire(tdbp, 0);
+					}
 					tdbp->tdb_state = SADB_SASTATE_DYING;
 					KLIPS_PRINT(debug_tunnel & DB_TN_XMIT,
 						    "klips_debug:ipsec_tunnel_start_xmit: "
-						    "soft usetime lifetime of SA:<%s%s%s> %s has been reached, "
-						    "SA expiring, soft expire message sent up, "
-						    "outgoing packet still processed.\n",
-						    TDB_XFORM_NAME(tdbp), sa);
+						    "soft usetime lifetime of SA:<%s%s%s> %s has been reached, SA expiring, soft expire message sent up, outgoing packet still processed.\n",
+						    TDB_XFORM_NAME(tdbp),
+						    sa_len ? sa : " (error)");
 				}
 			}
 
@@ -909,9 +1030,9 @@
 				pfkey_expire(tdbp, 1);
 				KLIPS_PRINT(debug_tunnel & DB_TN_XMIT,
 					    "klips_debug:ipsec_tunnel_start_xmit: "
-					    "hard packets lifetime of SA:<%s%s%s> %s has been reached, "
-					    "SA expired, outgoing packet dropped.\n",
-					    TDB_XFORM_NAME(tdbp), sa);
+					    "hard packets lifetime of SA:<%s%s%s> %s has been reached, SA expired, outgoing packet dropped.\n",
+					    TDB_XFORM_NAME(tdbp),
+					    sa_len ? sa : " (error)");
 				deltdbchain(tdbp);
 				spin_unlock(&tdb_lock);
 				stats->tx_errors++;
@@ -919,21 +1040,23 @@
 			}
 			if(tdbp->tdb_lifetime_packets_s &&
 			   (tdbp->tdb_lifetime_packets_c > tdbp->tdb_lifetime_packets_s)) {
+				if(tdbp->tdb_state != SADB_SASTATE_DYING) {
 				pfkey_expire(tdbp, 0);
+				}
 				tdbp->tdb_state = SADB_SASTATE_DYING;
 				KLIPS_PRINT(debug_tunnel & DB_TN_XMIT,
 					    "klips_debug:ipsec_tunnel_start_xmit: "
-					    "soft packets lifetime of SA:<%s%s%s> %s has been reached, "
-					    "SA expiring, soft expire message sent up, "
-					    "outgoing packet still processed.\n",
-					    TDB_XFORM_NAME(tdbp), sa);
+					    "soft packets lifetime of SA:<%s%s%s> %s has been reached, SA expiring, soft expire message sent up, outgoing packet still processed.\n",
+					    TDB_XFORM_NAME(tdbp),
+					    sa_len ? sa : " (error)");
 			}
 
 			headroom = tailroom = 0;
 			KLIPS_PRINT(debug_tunnel & DB_TN_CROUT,
 				    "klips_debug:ipsec_tunnel_start_xmit: "
 				    "calling room for <%s%s%s>, SA:%s\n", 
-				    TDB_XFORM_NAME(tdbp), sa);
+				    TDB_XFORM_NAME(tdbp),
+				    sa_len ? sa : " (error)");
 			switch(tdbp->tdb_said.proto) {
 #ifdef CONFIG_IPSEC_AH
 			case IPPROTO_AH:
@@ -943,16 +1066,16 @@
 #ifdef CONFIG_IPSEC_ESP
 			case IPPROTO_ESP:
 				switch(tdbp->tdb_encalg) {
+#ifdef CONFIG_IPSEC_ENC_DES
+				case ESP_DES:
+					headroom += sizeof(struct esp);
+					break;
+#endif /* CONFIG_IPSEC_ENC_DES */
 #ifdef CONFIG_IPSEC_ENC_3DES
 				case ESP_3DES:
 					headroom += sizeof(struct esp);
 					break;
 #endif /* CONFIG_IPSEC_ENC_3DES */
-#ifdef CONFIG_IPSEC_ENC_NULL
-				case ESP_NULL:
-					headroom += offsetof(struct esp, esp_iv);
-					break;
-#endif /* CONFIG_IPSEC_ENC_NULL */
 				default:
 					spin_unlock(&tdb_lock);
 					stats->tx_errors++;
@@ -1019,8 +1142,7 @@
 		
 		KLIPS_PRINT(debug_tunnel & DB_TN_CROUT,
 			    "klips_debug:ipsec_tunnel_start_xmit: "
-			    "existing head,tailroom: %d,%d "
-			    "before applying xforms with head,tailroom: %d,%d .\n",
+			    "existing head,tailroom: %d,%d before applying xforms with head,tailroom: %d,%d .\n",
 			    skb_headroom(skb), skb_tailroom(skb),
 			    max_headroom, max_tailroom);
 		
@@ -1030,18 +1152,21 @@
 		mtudiff = prv->mtu + tot_headroom + tot_tailroom - physmtu;
 
 		KLIPS_PRINT(debug_tunnel & DB_TN_CROUT,
-			    "klips_debug:ipsec_tunnel_start_xmit: mtu:%d physmtu:%d "
-			    "tothr:%d tottr:%d mtudiff:%d ippkttotlen:%d\n",
+			    "klips_debug:ipsec_tunnel_start_xmit: "
+			    "mtu:%d physmtu:%d tothr:%d tottr:%d mtudiff:%d ippkttotlen:%d\n",
 			    prv->mtu, physmtu,
 			    tot_headroom, tot_tailroom, mtudiff, ntohs(iph->tot_len));
 		if(mtudiff > 0) {
+			int newmtu = physmtu - (tot_headroom + ((tot_tailroom + 2) & ~7) + 5);
+
 			KLIPS_PRINT(debug_tunnel & DB_TN_CROUT,
 				    "klips_info:ipsec_tunnel_start_xmit: "
-				    "dev %s mtu of %d decreased by %d\n",
+				    "dev %s mtu of %d decreased by %d to %d\n",
 				    dev->name,
 				    prv->mtu,
-				    prv->mtu - (physmtu - tot_headroom - tot_tailroom));
-			prv->mtu = physmtu - (tot_headroom + tot_tailroom + 7);	/* add some slop? */
+				    prv->mtu - newmtu,
+				    newmtu);
+			prv->mtu = newmtu;
 #ifdef NET_21
 #if 0
 			skb->dst->pmtu = prv->mtu; /* RGB */
@@ -1053,6 +1178,34 @@
 #endif /* NET_21 */
 		}
 		
+		/* If the sender is doing PMTU discovery, and the packet doesn't fit within
+		 * prv->mtu, notify him (unless it was an ICMP packet) and drop it.
+		 * Note: buggy firewall configuration may prevent the ICMP packet from getting back.
+		 * Note2: Linux 2.4.x is trying to do PMTU discovery on ICMP packets, but this seems
+		 * bogus, and should be fixed in the kernel.
+		 */
+		if (iph->frag_off & __constant_htons(IP_DF)
+			&& prv->mtu < ntohs(iph->tot_len))
+		{
+			int notify = iph->protocol != IPPROTO_ICMP
+				     && (iph->frag_off & __constant_htons(IP_OFFSET)) == 0;
+
+			spin_unlock(&tdb_lock);
+			KLIPS_PRINT(debug_tunnel & DB_TN_CROUT,
+				    "klips_debug:ipsec_tunnel_start_xmit: "
+				    "fragmentation needed and DF set; %sdropping packet\n",
+				    notify ? "sending ICMP and " : "");
+			if (notify)
+				ICMP_SEND(skb,
+					  ICMP_DEST_UNREACH,
+					  ICMP_FRAG_NEEDED,
+					  prv->mtu,
+					  physdev);
+			stats->tx_dropped++;
+			goto cleanup;
+		}
+
+		
 #ifdef MSS_HACK
 		/*
 		 * If this is a transport mode TCP packet with
@@ -1065,7 +1218,8 @@
 			if (tcph->syn && !tcph->ack) {
 				if(!ipsec_adjust_mss(skb, tcph, prv->mtu)) {
 					spin_unlock(&tdb_lock);
-					printk(KERN_WARNING "klips: "
+					printk(KERN_WARNING
+					       "klips_warning:ipsec_tunnel_start_xmit: "
 					       "ipsec_adjust_mss() failed\n");
 					stats->tx_errors++;
 					goto cleanup;
@@ -1077,8 +1231,8 @@
 		if(!hard_header_stripped) {
 			if((saved_header = kmalloc(hard_header_len, GFP_ATOMIC)) == NULL) {
 				spin_unlock(&tdb_lock);
-				printk(KERN_WARNING "klips_debug:ipsec_tunnel_start_xmit: Failed, "
-				       "tried to allocate %d bytes for temp hard_header.\n", 
+				printk(KERN_WARNING "klips_debug:ipsec_tunnel_start_xmit: "
+				       "Failed, tried to allocate %d bytes for temp hard_header.\n", 
 				       hard_header_len);
 				stats->tx_errors++;
 				goto cleanup;
@@ -1089,8 +1243,7 @@
 			if(skb->len < hard_header_len) {
 				spin_unlock(&tdb_lock);
 				printk(KERN_WARNING "klips_error:ipsec_tunnel_start_xmit: "
-				       "tried to skb_pull hhlen=%d, %d available.  "
-				       "This should never happen, please report.\n",
+				       "tried to skb_pull hhlen=%d, %d available.  This should never happen, please report.\n",
 				       hard_header_len, (int)(skb->len));
 				stats->tx_errors++;
 				goto cleanup;
@@ -1144,8 +1297,9 @@
 			skb = tskb;
 			if (!skb) {
 				spin_unlock(&tdb_lock);
-				printk(KERN_WARNING "klips_debug:ipsec_tunnel_start_xmit: Failed, "
-				       "tried to allocate %d head and %d tailroom\n", 
+				printk(KERN_WARNING
+				       "klips_debug:ipsec_tunnel_start_xmit: "
+				       "Failed, tried to allocate %d head and %d tailroom\n", 
 				       max_headroom, max_tailroom);
 				stats->tx_errors++;
 				goto cleanup;
@@ -1190,7 +1344,8 @@
 			KLIPS_PRINT(debug_tunnel & DB_TN_OXFS,
 				    "klips_debug:ipsec_tunnel_start_xmit: "
 				    "calling output for <%s%s%s>, SA:%s\n", 
-				    TDB_XFORM_NAME(tdbp), sa);
+				    TDB_XFORM_NAME(tdbp),
+				    sa_len ? sa : " (error)");
 			
 			switch(tdbp->tdb_said.proto) {
 #ifdef CONFIG_IPSEC_AH
@@ -1201,16 +1356,16 @@
 #ifdef CONFIG_IPSEC_ESP
 			case IPPROTO_ESP:
 				switch(tdbp->tdb_encalg) {
+#ifdef CONFIG_IPSEC_ENC_DES
+				case ESP_DES:
+					headroom += sizeof(struct esp);
+					break;
+#endif /* CONFIG_IPSEC_ENC_DES */
 #ifdef CONFIG_IPSEC_ENC_3DES
 				case ESP_3DES:
 					headroom += sizeof(struct esp);
 					break;
 #endif /* CONFIG_IPSEC_ENC_3DES */
-#ifdef CONFIG_IPSEC_ENC_NULL
-				case ESP_NULL:
-					headroom += offsetof(struct esp, esp_iv);
-					break;
-#endif /* CONFIG_IPSEC_ENC_NULL */
 				default:
 					spin_unlock(&tdb_lock);
 					stats->tx_errors++;
@@ -1259,9 +1414,9 @@
 				    headroom, tailroom, tdbp->tdb_said.proto);
 			if(skb_headroom(skb) < headroom) {
 				spin_unlock(&tdb_lock);
-				printk(KERN_WARNING "klips_error:ipsec_tunnel_start_xmit: "
-				       "tried to skb_push headroom=%d, %d available.  "
-				       "This should never happen, please report.\n",
+				printk(KERN_WARNING
+				       "klips_error:ipsec_tunnel_start_xmit: "
+				       "tried to skb_push headroom=%d, %d available.  This should never happen, please report.\n",
 				       headroom, skb_headroom(skb));
 				stats->tx_errors++;
 				goto cleanup;
@@ -1270,9 +1425,9 @@
 			ilen = skb->len - tailroom;
 			if(skb_tailroom(skb) < tailroom) {
 				spin_unlock(&tdb_lock);
-				printk(KERN_WARNING "klips_error:ipsec_tunnel_start_xmit: "
-				       "tried to skb_put %d, %d available.  "
-				       "This should never happen, please report.\n",
+				printk(KERN_WARNING
+				       "klips_error:ipsec_tunnel_start_xmit: "
+				       "tried to skb_put %d, %d available.  This should never happen, please report.\n",
 				       tailroom, skb_tailroom(skb));
 				stats->tx_errors++;
 				goto cleanup;
@@ -1286,8 +1441,7 @@
 			if(len > 0xfff0) {
 				spin_unlock(&tdb_lock);
 				printk(KERN_WARNING "klips_error:ipsec_tunnel_start_xmit: "
-				       "tot_len (%d) > 65520.  "
-				       "This should never happen, please report.\n",
+				       "tot_len (%d) > 65520.  This should never happen, please report.\n",
 				       len);
 				stats->tx_errors++;
 				goto cleanup;
@@ -1304,20 +1458,19 @@
 				espp->esp_rpl = htonl(++(tdbp->tdb_replaywin_lastseq));
 				
 				switch(tdbp->tdb_encalg) {
-#if defined(CONFIG_IPSEC_ENC_3DES)
+#if defined(CONFIG_IPSEC_ENC_DES) || defined(CONFIG_IPSEC_ENC_3DES)
 #ifdef CONFIG_IPSEC_ENC_3DES
-				case ESP_3DES:
+				case ESP_DES:
 #endif /* CONFIG_IPSEC_ENC_3DES */
+#ifdef CONFIG_IPSEC_ENC_3DES
+				case ESP_3DES:
+#endif /* defined(CONFIG_IPSEC_ENC_DES) || CONFIG_IPSEC_ENC_3DES */
 					iv[0] = *((__u32*)&(espp->esp_iv)    ) =
 						((__u32*)(tdbp->tdb_iv))[0];
 					iv[1] = *((__u32*)&(espp->esp_iv) + 1) =
 						((__u32*)(tdbp->tdb_iv))[1];
 					break;
 #endif /* defined(CONFIG_IPSEC_ENC_3DES) */
-#ifdef CONFIG_IPSEC_ENC_NULL
-				case ESP_NULL:
-					break;
-#endif /* CONFIG_IPSEC_ENC_NULL */
 				default:
 					spin_unlock(&tdb_lock);
 					stats->tx_errors++;
@@ -1339,6 +1492,13 @@
 				iph->protocol = IPPROTO_ESP;
 				
 				switch(tdbp->tdb_encalg) {
+#ifdef CONFIG_IPSEC_ENC_DES
+                                case ESP_DES:
+                                       des_cbc_encrypt(idat, idat, ilen,
+                                                       (caddr_t)tdbp->tdb_key_e,
+                                                       (caddr_t)iv, 1);
+                                       break;
+#endif /* CONFIG_IPSEC_ENC_DES */
 #ifdef CONFIG_IPSEC_ENC_3DES
 				case ESP_3DES:
 					des_ede3_cbc_encrypt(idat, idat, ilen,
@@ -1348,10 +1508,6 @@
 							     (caddr_t)iv, 1);
 					break;
 #endif /* CONFIG_IPSEC_ENC_3DES */
-#ifdef CONFIG_IPSEC_ENC_NULL
-				case ESP_NULL:
-					break;
-#endif /* CONFIG_IPSEC_ENC_NULL */
 				default:
 					spin_unlock(&tdb_lock);
 					stats->tx_errors++;
@@ -1359,7 +1515,10 @@
 				}
 				
 				switch(tdbp->tdb_encalg) {
-#if defined(CONFIG_IPSEC_ENC_3DES)
+#if  defined(CONFIG_IPSEC_ENC_DES) || defined(CONFIG_IPSEC_ENC_3DES)
+#ifdef CONFIG_IPSEC_ENC_DES
+                               case ESP_DES:
+#endif /* CONFIG_IPSEC_ENC_DES */
 #ifdef CONFIG_IPSEC_ENC_3DES
 				case ESP_3DES:
 #endif /* CONFIG_IPSEC_ENC_3DES */
@@ -1369,11 +1528,7 @@
 					((__u32*)(tdbp->tdb_iv))[1] =
 						((__u32 *)(idat))[(ilen >> 2) - 1];
 					break;
-#endif /* defined(CONFIG_IPSEC_ENC_3DES) */
-#ifdef CONFIG_IPSEC_ENC_NULL
-				case ESP_NULL:
-					break;
-#endif /* CONFIG_IPSEC_ENC_NULL */
+#endif /* defined(CONFIG_IPSEC_ENC_DES) || defined(CONFIG_IPSEC_ENC_3DES) */
 				default:
 					spin_unlock(&tdb_lock);
 					stats->tx_errors++;
@@ -1540,10 +1695,14 @@
 				/* XXX use of skb->dst below is a questionable
 				   substitute for &rt->u.dst which is only
 				   available later-on */
+#ifdef IP_SELECT_IDENT_NEW
+				ip_select_ident(iph, skb->dst, NULL);
+#else /* IP_SELECT_IDENT_NEW */
 				ip_select_ident(iph, skb->dst);
-#else
+#endif /* IP_SELECT_IDENT_NEW */
+#else /* IP_SELECT_IDENT */
 				iph->id       = htons(ip_id_count++);   /* Race condition here? */
-#endif
+#endif /* IP_SELECT_IDENT */
 
 				newdst = (__u32)iph->daddr;
 				newsrc = (__u32)iph->saddr;
@@ -1559,7 +1718,7 @@
 					unsigned int flags = 0;
 #ifdef CONFIG_IPSEC_DEBUG
 					unsigned int old_tot_len = ntohs(iph->tot_len);
-#endif
+#endif /* CONFIG_IPSEC_DEBUG */
 					tdbp->tdb_comp_ratio_dbytes += ntohs(iph->tot_len);
 
 					skb = skb_compress(skb, tdbp, &flags);
@@ -1610,7 +1769,8 @@
 			KLIPS_PRINT(debug_tunnel & DB_TN_XMIT,
 				    "klips_debug:ipsec_tunnel_start_xmit: "
 				    "after <%s%s%s>, SA:%s:\n",
-				    TDB_XFORM_NAME(tdbp), sa);
+				    TDB_XFORM_NAME(tdbp),
+				    sa_len ? sa : " (error)");
 			KLIPS_IP_PRINT(debug_tunnel & DB_TN_XMIT, iph);
  			
 			tdbp->tdb_lifetime_bytes_c += len;
@@ -1620,6 +1780,7 @@
 			tdbp->tdb_lifetime_usetime_l = jiffies / HZ;
 			tdbp->tdb_lifetime_packets_c += 1;
 
+			tdbprev = tdbp;
 			tdbp = tdbp->tdb_onext;
 			
 		}
@@ -1633,14 +1794,18 @@
 		er = ipsec_findroute(&matcher);
 		if(er) {
 			outgoing_said = er->er_said;
+			eroute_pid = er->er_pid;
+			er->er_count++;
+			er->er_lasttime = jiffies/HZ;
 		}
 		spin_unlock(&eroute_lock);
-		KLIPS_PRINT(/* ((orgdst != newdst) || (orgsrc != newsrc)) */
+		KLIPS_PRINT((debug_tunnel & DB_TN_XMIT) &&
+			    /* ((orgdst != newdst) || (orgsrc != newsrc)) */
 			(orgedst != outgoing_said.dst.s_addr) &&
 			outgoing_said.dst.s_addr &&
-			er &&
-			(debug_tunnel & DB_TN_XMIT),
-			"klips_debug:ipsec_tunnel_start_xmit: We are recursing here.\n");
+			    er,
+			    "klips_debug:ipsec_tunnel_start_xmit: "
+			    "We are recursing here.\n");
 	} while(/*((orgdst != newdst) || (orgsrc != newsrc))*/
 		(orgedst != outgoing_said.dst.s_addr) &&
 		outgoing_said.dst.s_addr &&
@@ -1664,9 +1829,9 @@
 
 	if(saved_header) {
 		if(skb_headroom(skb) < hard_header_len) {
-			printk(KERN_WARNING "klips_error:ipsec_tunnel_start_xmit: "
-			       "tried to skb_push hhlen=%d, %d available.  "
-			       "This should never happen, please report.\n",
+			printk(KERN_WARNING
+			       "klips_error:ipsec_tunnel_start_xmit: "
+			       "tried to skb_push hhlen=%d, %d available.  This should never happen, please report.\n",
 			       hard_header_len, skb_headroom(skb));
 			stats->tx_errors++;
 			goto cleanup;
@@ -1682,28 +1847,21 @@
 		    "With hard_header, final head,tailroom: %d,%d\n",
 		    skb_headroom(skb), skb_tailroom(skb));
 
-#ifdef NET_21
+#ifdef NET_21	/* 2.2 and 2.4 kernels */
 	/* new route/dst cache code from James Morris */
 	skb->dev = physdev;
 	/*skb_orphan(skb);*/
-#ifdef NETDEV_23
-	if(sysctl_ipsec_no_eroute_pass) {
-		/* zero the saddr used in ip_route_output */
-		route_saddr=0;
-	}else{
-		route_saddr=skb->nh.iph->saddr;
-	}
-#endif /* NETDEV_23 */
-	if(ip_route_output(&rt,
+	if((error = ip_route_output(&rt,
 			   skb->nh.iph->daddr,
-#ifdef NETDEV_23
-			   route_saddr,
-#else /* NETDEV_23 */
-			   skb->nh.iph->saddr,
-#endif /* NETDEV_23 */
+				   pass ? 0 : skb->nh.iph->saddr,
 			   RT_TOS(skb->nh.iph->tos),
-			   physdev->iflink)) {
+				   physdev->iflink))) {
 		stats->tx_errors++;
+		KLIPS_PRINT(debug_tunnel & DB_TN_XMIT,
+			    "klips_debug:ipsec_tunnel_start_xmit: "
+			    "ip_route_output failed with error code %d, rt->u.dst.dev=%s, dropped\n",
+			    error,
+			    rt->u.dst.dev->name);
 		goto cleanup;
 	}
 	if(dev == rt->u.dst.dev) {
@@ -1719,11 +1877,11 @@
 	skb->dst = &rt->u.dst;
 	stats->tx_bytes += skb->len;
 	if(skb->len < skb->nh.raw - skb->data) {
-		printk(KERN_WARNING "klips_error:ipsec_tunnel_start_xmit: "
-		       "tried to __skb_pull nh-data=%d, %d available.  "
-		       "This should never happen, please report.\n",
-		       skb->nh.raw - skb->data, skb->len);
 		stats->tx_errors++;
+		printk(KERN_WARNING
+		       "klips_error:ipsec_tunnel_start_xmit: "
+		       "tried to __skb_pull nh-data=%d, %d available.  This should never happen, please report.\n",
+		       skb->nh.raw - skb->data, skb->len);
 		goto cleanup;
 	}
 	__skb_pull(skb, skb->nh.raw - skb->data);
@@ -1736,8 +1894,10 @@
 #endif /* SKB_RESET_NFCT */
 	KLIPS_PRINT(debug_tunnel & DB_TN_XMIT,
 		    "klips_debug:ipsec_tunnel_start_xmit: "
-		    "...done, calling ip_send()\n");
-#ifdef NETDEV_23
+		    "...done, calling ip_send() on device:%s\n",
+		    skb->dev ? skb->dev->name : "NULL");
+	KLIPS_IP_PRINT(debug_tunnel & DB_TN_XMIT, skb->nh.iph);
+#ifdef NETDEV_23	/* 2.4 kernels */
 	{
 		int err;
 
@@ -1746,7 +1906,8 @@
 		if(err != NET_XMIT_SUCCESS && err != NET_XMIT_CN) {
 			if(net_ratelimit())
 				printk(KERN_ERR
-				       "ipsec_tunnel_start_xmit: ip_send() failed, err=%d\n", 
+				       "klips_error:ipsec_tunnel_start_xmit: "
+				       "ip_send() failed, err=%d\n", 
 				       -err);
 			stats->tx_errors++;
 			stats->tx_aborted_errors++;
@@ -1754,10 +1915,10 @@
 			goto cleanup;
 		}
 	}
-#else
+#else /* NETDEV_23 */	/* 2.2 kernels */
 	ip_send(skb);
-#endif
-#else /* NET_21 */
+#endif /* NETDEV_23 */
+#else /* NET_21 */	/* 2.0 kernels */
 	skb->arp = 1;
 	/* ISDN/ASYNC PPP from Matjaz Godec. */
 	/*	skb->protocol = htons(ETH_P_IP); */
@@ -1772,16 +1933,18 @@
  cleanup:
 #if defined(HAS_NETIF_QUEUE) || defined (HAVE_NETIF_QUEUE)
 	netif_wake_queue(dev);
-#else
+#else /* defined(HAS_NETIF_QUEUE) || defined (HAVE_NETIF_QUEUE) */
 	dev->tbusy = 0;
-#endif
-	if(saved_header)
+#endif /* defined(HAS_NETIF_QUEUE) || defined (HAVE_NETIF_QUEUE) */
+	if(saved_header) {
 		kfree(saved_header);
+	}
 	if(skb) {
 		dev_kfree_skb(skb, FREE_WRITE);
 	}
-	if(oskb)
+	if(oskb) {
 		dev_kfree_skb(oskb, FREE_WRITE);
+	}
 	return 0;
 }
 
@@ -1803,6 +1966,46 @@
 	struct ipsecpriv *prv = dev->priv;
 	struct device *tmp;
 	int ret;
+	struct net_device_stats *stats;	/* This device's statistics */
+	
+	if(skb == NULL) {
+		KLIPS_PRINT(debug_tunnel & DB_TN_REVEC,
+			    "klips_debug:ipsec_tunnel_hard_header: "
+			    "no skb...");
+		return -ENODATA;
+	}
+
+	if(dev == NULL) {
+		KLIPS_PRINT(debug_tunnel & DB_TN_REVEC,
+			    "klips_debug:ipsec_tunnel_hard_header: "
+			    "no device...");
+		return -ENODEV;
+	}
+
+	KLIPS_PRINT(debug_tunnel & DB_TN_REVEC,
+		    "klips_debug:ipsec_tunnel_hard_header: "
+		    "skb->dev=%s dev=%s.",
+		    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",
+			    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",
+			    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
@@ -1820,9 +2023,12 @@
 		if(!prv->hard_header) {
 			KLIPS_PRINT(debug_tunnel & DB_TN_REVEC,
 				    "klips_debug:ipsec_tunnel_hard_header: "
-				    "physical device has been detached, packet dropped "
-				    "0x%p->0x%p len=%d type=%d dev=%s->NULL ",
-				    saddr, daddr, len, type, dev->name);
+				    "physical device has been detached, packet dropped 0x%p->0x%p len=%d type=%d dev=%s->NULL ",
+				    saddr,
+				    daddr,
+				    len,
+				    type,
+				    dev->name);
 #ifdef NET_21
 			KLIPS_PRINTMORE(debug_tunnel & DB_TN_REVEC,
 					"ip=%08x->%08x\n",
@@ -1834,15 +2040,20 @@
 					(__u32)ntohl(skb->ip_hdr->saddr),
 					(__u32)ntohl(skb->ip_hdr->daddr) );
 #endif /* NET_21 */
+			stats->tx_dropped++;
 			return -ENODEV;
 		}
 		
 #define da ((struct device *)(prv->dev))->dev_addr
 		KLIPS_PRINT(debug_tunnel & DB_TN_REVEC,
 			    "klips_debug:ipsec_tunnel_hard_header: "
-			    "Revectored 0x%p->0x%p len=%d type=%d dev=%s->%s "
-			    "dev_addr=%02x:%02x:%02x:%02x:%02x:%02x ",
-			    saddr, daddr, len, type, dev->name, prv->dev->name,
+			    "Revectored 0x%p->0x%p len=%d type=%d dev=%s->%s dev_addr=%02x:%02x:%02x:%02x:%02x:%02x ",
+			    saddr,
+			    daddr,
+			    len,
+			    type,
+			    dev->name,
+			    prv->dev->name,
 			    da[0], da[1], da[2], da[3], da[4], da[5]);
 #ifdef NET_21
 		KLIPS_PRINT(debug_tunnel & DB_TN_REVEC,
@@ -1878,12 +2089,38 @@
 	struct ipsecpriv *prv = skb->dev->priv;
 	struct device *tmp;
 	int ret;
+	struct net_device_stats *stats;	/* This device's statistics */
+	
+	if(skb->dev == NULL) {
+		KLIPS_PRINT(debug_tunnel & DB_TN_REVEC,
+			    "klips_debug:ipsec_tunnel_rebuild_header: "
+			    "no device...");
+		return -ENODEV;
+	}
+
+	if(prv == NULL) {
+		KLIPS_PRINT(debug_tunnel & DB_TN_REVEC,
+			    "klips_debug:ipsec_tunnel_rebuild_header: "
+			    "no private space associated with dev=%s",
+			    skb->dev->name ? skb->dev->name : "NULL");
+		return -ENODEV;
+	}
+
+	stats = (struct net_device_stats *) &(prv->mystats);
+
+	if(prv->dev == NULL) {
+		KLIPS_PRINT(debug_tunnel & DB_TN_REVEC,
+			    "klips_debug:ipsec_tunnel_rebuild_header: "
+			    "no physical device associated with dev=%s",
+			    skb->dev->name ? skb->dev->name : "NULL");
+		stats->tx_dropped++;
+		return -ENODEV;
+	}
 	
 	if(!prv->rebuild_header) {
 		KLIPS_PRINT(debug_tunnel & DB_TN_REVEC,
 			    "klips_debug:ipsec_tunnel_rebuild_header: "
-			    "physical device has been detached, packet dropped "
-			    "skb->dev=%s->NULL ",
+			    "physical device has been detached, packet dropped skb->dev=%s->NULL ",
 			    skb->dev->name);
 #ifdef NET_21
 		KLIPS_PRINT(debug_tunnel & DB_TN_REVEC,
@@ -1896,6 +2133,7 @@
 			    (__u32)ntohl(skb->ip_hdr->saddr),
 			    (__u32)ntohl(skb->ip_hdr->daddr) );
 #endif /* NET_21 */
+		stats->tx_dropped++;
 		return -ENODEV;
 	}
 
@@ -1931,11 +2169,38 @@
 {
 	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",
+			    "physical device has been detached, cannot set - skb->dev=%s->NULL\n",
 			    dev->name);
 		return -ENODEV;
 	}
@@ -1955,12 +2220,40 @@
 {
 	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",
+			    "physical device has been detached, cannot set - skb->dev=%s->NULL\n",
 			    dev->name);
+		stats->tx_dropped++;
 		return;
 	}
 
@@ -1978,11 +2271,38 @@
 {
 	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",
+			    "physical device has been detached, cannot set - skb->dev=%s->NULL\n",
 			    dev->name);
 		return;
 	}
@@ -1999,8 +2319,7 @@
 ipsec_tunnel_neigh_setup(struct neighbour *n)
 {
 	KLIPS_PRINT(debug_tunnel & DB_TN_REVEC,
-		    "klips_debug:ipsec_tunnel: "
-		    "ipsec_tunnel_neigh_setup\n");
+		    "klips_debug:ipsec_tunnel_neigh_setup:\n");
 
         if (n->nud_state == NUD_NONE) {
                 n->ops = &arp_broken_ops;
@@ -2013,8 +2332,9 @@
 ipsec_tunnel_neigh_setup_dev(struct device *dev, struct neigh_parms *p)
 {
 	KLIPS_PRINT(debug_tunnel & DB_TN_REVEC,
-		    "klips_debug:ipsec_tunnel: "
-		    "ipsec_tunnel_neigh_setup_dev\n");
+		    "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;
@@ -2030,70 +2350,86 @@
  */
 
 DEBUG_NO_STATIC int
-ipsec_tunnel_attach(struct device *tndev, struct ipsecpriv *prv, struct device *dev)
+ipsec_tunnel_attach(struct device *dev, struct device *physdev)
 {
         int i;
+	struct ipsecpriv *prv = dev->priv;
+
+	if(dev == NULL) {
+		KLIPS_PRINT(debug_tunnel & DB_TN_REVEC,
+			    "klips_debug:ipsec_tunnel_attach: "
+			    "no device...");
+		return -ENODEV;
+	}
 
-	prv->dev = dev;
-	prv->hard_start_xmit = dev->hard_start_xmit;
-	prv->get_stats = dev->get_stats;
-
-	if (dev->hard_header) {
-		prv->hard_header = dev->hard_header;
-		tndev->hard_header = ipsec_tunnel_hard_header;
+	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
-		tndev->hard_header = NULL;
+		dev->hard_header = NULL;
 	
-	if (dev->rebuild_header) {
-		prv->rebuild_header = dev->rebuild_header;
-		tndev->rebuild_header = ipsec_tunnel_rebuild_header;
+	if (physdev->rebuild_header) {
+		prv->rebuild_header = physdev->rebuild_header;
+		dev->rebuild_header = ipsec_tunnel_rebuild_header;
 	} else
-		tndev->rebuild_header = NULL;
+		dev->rebuild_header = NULL;
 	
-	if (dev->set_mac_address) {
-		prv->set_mac_address = dev->set_mac_address;
-		tndev->set_mac_address = ipsec_tunnel_set_mac_address;
+	if (physdev->set_mac_address) {
+		prv->set_mac_address = physdev->set_mac_address;
+		dev->set_mac_address = ipsec_tunnel_set_mac_address;
 	} else
-		tndev->set_mac_address = NULL;
+		dev->set_mac_address = NULL;
 	
 #ifndef NET_21
-	if (dev->header_cache_bind) {
-		prv->header_cache_bind = dev->header_cache_bind;
-		tndev->header_cache_bind = ipsec_tunnel_cache_bind;
+	if (physdev->header_cache_bind) {
+		prv->header_cache_bind = physdev->header_cache_bind;
+		dev->header_cache_bind = ipsec_tunnel_cache_bind;
 	} else
-		tndev->header_cache_bind = NULL;
+		dev->header_cache_bind = NULL;
 #endif /* !NET_21 */
 
-	if (dev->header_cache_update) {
-		prv->header_cache_update = dev->header_cache_update;
-		tndev->header_cache_update = ipsec_tunnel_cache_update;
+	if (physdev->header_cache_update) {
+		prv->header_cache_update = physdev->header_cache_update;
+		dev->header_cache_update = ipsec_tunnel_cache_update;
 	} else
-		tndev->header_cache_update = NULL;
+		dev->header_cache_update = NULL;
 
-	tndev->hard_header_len = dev->hard_header_len;
+	dev->hard_header_len = physdev->hard_header_len;
 
 #ifdef NET_21
-/*	prv->neigh_setup        = dev->neigh_setup; */
+/*	prv->neigh_setup        = physdev->neigh_setup; */
 	dev->neigh_setup        = ipsec_tunnel_neigh_setup_dev;
 #endif /* NET_21 */
-	tndev->mtu = 16260; /* 0xfff0; */ /* dev->mtu; */
-	prv->mtu = dev->mtu;
+	dev->mtu = 16260; /* 0xfff0; */ /* dev->mtu; */
+	prv->mtu = physdev->mtu;
 
 #ifdef PHYSDEV_TYPE
-	tndev->type = dev->type /* ARPHRD_TUNNEL */;	/* initially */
+	dev->type = physdev->type /* ARPHRD_TUNNEL */;	/* initially */
 #endif /*  PHYSDEV_TYPE */
 
-	tndev->addr_len = dev->addr_len;
-	for (i=0; i<tndev->addr_len; i++) {
-		tndev->dev_addr[i] = dev->dev_addr[i];
+	dev->addr_len = physdev->addr_len;
+	for (i=0; i<dev->addr_len; i++) {
+		dev->dev_addr[i] = physdev->dev_addr[i];
 	}
 #ifdef CONFIG_IPSEC_DEBUG
 	if(debug_tunnel & DB_TN_INIT) {
 		printk(KERN_INFO "klips_debug:ipsec_tunnel_attach: "
 		       "physical device %s being attached has HW address: %2x",
-		       dev->name, dev->dev_addr[0]);
-		for (i=1; i < dev->addr_len; i++) {
-			printk(":%02x", dev->dev_addr[i]);
+		       physdev->name, physdev->dev_addr[0]);
+		for (i=1; i < physdev->addr_len; i++) {
+			printk(":%02x", physdev->dev_addr[i]);
 		}
 		printk("\n");
 	}
@@ -2107,49 +2443,80 @@
  */
 
 DEBUG_NO_STATIC int
-ipsec_tunnel_detach(struct device *dev, struct ipsecpriv *prv)
+ipsec_tunnel_detach(struct device *dev)
 {
         int i;
+	struct ipsecpriv *prv = dev->priv;
+
+	if(dev == NULL) {
+		KLIPS_PRINT(debug_tunnel & DB_TN_REVEC,
+			    "klips_debug:ipsec_tunnel_detach: "
+			    "no device...");
+		return -ENODEV;
+	}
+
+	if(prv == NULL) {
+		KLIPS_PRINT(debug_tunnel & DB_TN_REVEC,
+			    "klips_debug:ipsec_tunnel_detach: "
+			    "no private space associated with dev=%s",
+			    dev->name ? dev->name : "NULL");
+		return -ENODATA;
+	}
 
 	KLIPS_PRINT(debug_tunnel & DB_TN_INIT,
 		    "klips_debug:ipsec_tunnel_detach: "
 		       "physical device %s being detached from virtual device %s\n",
-		       prv->dev->name, dev->name);
+		    prv->dev ? prv->dev->name : "NULL",
+		    dev->name);
 
 	prv->dev = NULL;
 	prv->hard_start_xmit = NULL;
 	prv->get_stats = NULL;
 
 	prv->hard_header = NULL;
+#ifdef DETACH_AND_DOWN
 	dev->hard_header = NULL;
+#endif /* DETACH_AND_DOWN */
 	
 	prv->rebuild_header = NULL;
+#ifdef DETACH_AND_DOWN
 	dev->rebuild_header = NULL;
+#endif /* DETACH_AND_DOWN */
 	
 	prv->set_mac_address = NULL;
+#ifdef DETACH_AND_DOWN
 	dev->set_mac_address = NULL;
+#endif /* DETACH_AND_DOWN */
 	
 #ifndef NET_21
 	prv->header_cache_bind = NULL;
+#ifdef DETACH_AND_DOWN
 	dev->header_cache_bind = NULL;
+#endif /* DETACH_AND_DOWN */
 #endif /* !NET_21 */
 
 	prv->header_cache_update = NULL;
+#ifdef DETACH_AND_DOWN
 	dev->header_cache_update = NULL;
+#endif /* DETACH_AND_DOWN */
 
 #ifdef NET_21
 /*	prv->neigh_setup        = NULL; */
+#ifdef DETACH_AND_DOWN
 	dev->neigh_setup        = NULL;
+#endif /* DETACH_AND_DOWN */
 #endif /* NET_21 */
 	dev->hard_header_len = 0;
+#ifdef DETACH_AND_DOWN
 	dev->mtu = 0;
+#endif /* DETACH_AND_DOWN */
 	prv->mtu = 0;
 	for (i=0; i<MAX_ADDR_LEN; i++) {
 		dev->dev_addr[i] = 0;
 	}
 	dev->addr_len = 0;
 #ifdef PHYSDEV_TYPE
-	dev->type = 0;
+	dev->type = ARPHRD_TUNNEL;
 #endif /*  PHYSDEV_TYPE */
 	
 	return 0;
@@ -2168,7 +2535,7 @@
 	int ret;
 
 	KLIPS_PRINT(debug_tunnel & DB_TN_INIT,
-		    "klips_debug:ipsec_tunnel_clear: called.\n");
+		    "klips_debug:ipsec_tunnel_clear: .\n");
 
 	for(i = 0; i < IPSEC_NUM_IF; i++) {
 		sprintf(name, "ipsec%d", i);
@@ -2180,7 +2547,7 @@
 						    "klips_debug:ipsec_tunnel_clear: "
 						    "physical device for device %s is %s\n",
 						    name, prvdev->name);
-					if((ret = ipsec_tunnel_detach(ipsecdev, prv))) {
+					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",
@@ -2205,12 +2572,24 @@
 	char realphysname[IFNAMSIZ];
 #endif /* CONFIG_IP_ALIAS */
 	
+	if(dev == NULL) {
 	KLIPS_PRINT(debug_tunnel & DB_TN_INIT,
 		    "klips_debug:ipsec_tunnel_ioctl: "
-		    "tncfg service call #%d\n", cmd);
+			    "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);
@@ -2225,19 +2604,41 @@
 		if (them == NULL) {
 			KLIPS_PRINT(debug_tunnel & DB_TN_INIT,
 				    "klips_debug:ipsec_tunnel_ioctl: "
-				    "physical device requested is null\n");
+				    "physical device %s requested is null\n",
+				    cf->cf_name);
+			return -ENXIO;
+		}
 
+#if 0
+		if (them->flags & IFF_UP) {
+			KLIPS_PRINT(debug_tunnel & DB_TN_INIT,
+				    "klips_debug:ipsec_tunnel_ioctl: "
+				    "physical device %s requested is not up.\n",
+				    cf->cf_name);
 			return -ENXIO;
 		}
+#endif
 		
-		if (prv->dev)
+		if (prv && prv->dev) {
+			KLIPS_PRINT(debug_tunnel & DB_TN_INIT,
+				    "klips_debug:ipsec_tunnel_ioctl: "
+				    "virtual device is already connected to %s.\n",
+				    prv->dev->name ? prv->dev->name : "NULL");
 			return -EBUSY;
-		return ipsec_tunnel_attach(dev, dev->priv, them);
+		}
+		return ipsec_tunnel_attach(dev, them);
 
 	case IPSEC_DEL_DEV:
-		if (! prv->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, dev->priv);
+		}
+		return ipsec_tunnel_detach(dev);
 	       
 	case IPSEC_CLR_DEV:
 		KLIPS_PRINT(debug_tunnel & DB_TN_INIT,
@@ -2246,6 +2647,10 @@
 		return ipsec_tunnel_clear();
 
 	default:
+		KLIPS_PRINT(debug_tunnel & DB_TN_INIT,
+			    "klips_debug:ipsec_tunnel_ioctl: "
+			    "unknown command %d.\n",
+			    cmd);
 		return -EOPNOTSUPP;
 	}
 }
@@ -2259,15 +2664,45 @@
 	char name[9];
 	int i;
 
+	if (dev == NULL) {
+		KLIPS_PRINT(debug_tunnel & DB_TN_INIT,
+			    "klips_debug:ipsec_device_event: "
+			    "dev=NULL for event type %ld.\n",
+			    event);
+		return(NOTIFY_DONE);
+	}
+
 	/* check for loopback devices */
-	if (dev->flags & IFF_LOOPBACK)
+	if (dev && (dev->flags & IFF_LOOPBACK)) {
 		return(NOTIFY_DONE);
+	}
 
-	switch (event) 
-	{
+	switch (event) {
+	case NETDEV_DOWN:
+		/* look carefully at the scope of these compiler
+		   #defines before changing anything... */
+#ifdef NET_21
+	case NETDEV_UNREGISTER:
+		switch (event) {
 		case NETDEV_DOWN:
+#endif /* NET_21 */
 			KLIPS_PRINT(debug_tunnel & DB_TN_INIT,
-				    "ipsec_device_event: NETDEV_DOWN...\n");
+				    "klips_debug:ipsec_device_event: "
+				    "NETDEV_DOWN dev=%s flags=%x\n",
+				    dev->name,
+				    dev->flags);
+#ifdef NET_21
+			break;
+		case NETDEV_UNREGISTER:
+			KLIPS_PRINT(debug_tunnel & DB_TN_INIT,
+				    "klips_debug:ipsec_device_event: "
+				    "NETDEV_UNREGISTER dev=%s flags=%x\n",
+				    dev->name,
+				    dev->flags);
+			break;
+		}
+#endif /* NET_21 */
+		
 			/* find the attached physical device and detach it. */
 			for(i = 0; i < IPSEC_NUM_IF; i++) {
 				sprintf(name, "ipsec%d", i);
@@ -2277,35 +2712,82 @@
 					if(priv) {
 						;
 						if(((struct device *)(priv->dev)) == dev) {
-							dev_close(ipsec_dev);
-							/* return */ ipsec_tunnel_detach(ipsec_dev, priv);
-							return NOTIFY_DONE;
+						/* 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",
+						    "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,
-				    "ipsec_device_event: NETDEV_UP...\n");
-			/* Only handle ethernet ports */
-			if(dev->type!=ARPHRD_ETHER && dev->type!=ARPHRD_LOOPBACK)
-				return NOTIFY_DONE;
-
+			    "klips_debug:ipsec_device_event: "
+			    "NETDEV_UP dev=%s\n",
+			    dev->name);
 			break;
 #ifdef NET_21
-		case NETDEV_UNREGISTER:
+	case NETDEV_REBOOT:
 			KLIPS_PRINT(debug_tunnel & DB_TN_INIT,
-				    "ipsec_device_event: NETDEV_UNREGISTER...\n");
-
+			    "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;
 }
@@ -2320,8 +2802,12 @@
 {
 	int i;
 
-	printk(KERN_INFO "IPsec: initialisation of device: %s\n",
+#if 0
+	printk(KERN_INFO
+	       "klips_debug:ipsec_tunnel_init: "
+	       "initialisation of device: %s\n",
 	       dev->name ? dev->name : "NULL");
+#endif
 
 	/* Add our tunnel functions to the device */
 	dev->open		= ipsec_tunnel_open;
@@ -2510,8 +2996,104 @@
 
 /*
  * $Log: ipsec_tunnel.c,v $
- * Revision 1.137.2.1  2001/02/27 00:51:00  henry
- * message improvements
+ * 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
@@ -2615,9 +3197,6 @@
  * 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.
diff -bruN freeswan-1.9.orig/klips/net/ipsec/ipsec_xform.c freeswan-1.9/klips/net/ipsec/ipsec_xform.c
--- freeswan-1.9.orig/klips/net/ipsec/ipsec_xform.c	Sun Nov  5 23:32:08 2000
+++ freeswan-1.9/klips/net/ipsec/ipsec_xform.c	Tue Jun 12 16:07:52 2001
@@ -13,7 +13,7 @@
  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  * for more details.
  *
- * RCSID $Id: ipsec_xform.c,v 1.47 2000/11/06 04:32:08 rgb Exp $
+ * RCSID $Id: ipsec_xform.c,v 1.51 2001/05/30 08:14:03 rgb Exp $
  */
 
 #include <linux/config.h>
@@ -61,7 +61,7 @@
 int debug_xform = 0;
 #endif /* CONFIG_IPSEC_DEBUG */
 
-#define SENDERR(_x) do { len = -(_x); goto errlab; } while (0)
+#define SENDERR(_x) do { error = -(_x); goto errlab; } while (0)
 
 extern int des_set_key(caddr_t, caddr_t);
 
@@ -69,6 +69,9 @@
 { XF_IP4,		0,		"IPv4_Encapsulation"},
 { XF_AHHMACMD5,		XFT_AUTH,	"HMAC_MD5_Authentication"},
 { XF_AHHMACSHA1,	XFT_AUTH,	"HMAC_SHA-1_Authentication"},
+{ XF_ESPDES,		XFT_CONF,	"DES_Encryption"},
+{ XF_ESPDESMD596,	XFT_CONF,	"DES-MD5-96_Encryption"},
+{ XF_ESPDESSHA196,	XFT_CONF,	"DES-SHA1-96_Encryption"},
 { XF_ESP3DES,		XFT_CONF,	"3DES_Encryption"},
 { XF_ESP3DESMD596,	XFT_CONF,	"3DES-MD5-96_Encryption"},
 { XF_ESP3DESSHA196,	XFT_CONF,	"3DES-SHA1-96_Encryption"},
@@ -101,25 +104,31 @@
 	int hashval;
 	struct tdb *tdbp;
         char sa[SATOA_BUF];
+	size_t sa_len;
 
 	if(!said) {
 		KLIPS_PRINT(debug_xform,
-			    "klips_error:gettdb: null pointer passed in!\n");
+			    "klips_error:gettdb: "
+			    "null pointer passed in!\n");
 		return NULL;
 	}
 
-	satoa(*said, 0, sa, SATOA_BUF);
+	sa_len = satoa(*said, 0, sa, SATOA_BUF);
 
 	hashval = (said->spi+said->dst.s_addr+said->proto) % TDB_HASHMOD;
 	
 	KLIPS_PRINT(debug_xform,
-		    "klips_debug:gettdb: linked entry in tdb table for hash=%d of SA:%s requested.\n",
-		    hashval, sa);
+		    "klips_debug:gettdb: "
+		    "linked entry in tdb table for hash=%d of SA:%s requested.\n",
+		    hashval,
+		    sa_len ? sa : " (error)");
 
 	if(!(tdbp = tdbh[hashval])) {
 		KLIPS_PRINT(debug_xform,
-			    "klips_debug:gettdb: no entries in tdb table for hash=%d of SA:%s.\n",
-			    hashval, sa);
+			    "klips_debug:gettdb: "
+			    "no entries in tdb table for hash=%d of SA:%s.\n",
+			    hashval,
+			    sa_len ? sa : " (error)");
 		return NULL;
 	}
 
@@ -132,12 +141,16 @@
 	}
 	
 	KLIPS_PRINT(debug_xform,
-		    "klips_debug:gettdb: no entry in linked list for hash=%d of SA:%s.\n",
-		    hashval, sa);
+		    "klips_debug:gettdb: "
+		    "no entry in linked list for hash=%d of SA:%s.\n",
+		    hashval,
+		    sa_len ? sa : " (error)");
 	return NULL;
 }
 
-/* void */
+/*
+  The tdb table better *NOT* be locked before it is handed in, or SMP locks will happen
+*/
 int
 puttdb(struct tdb *tdbp)
 {
@@ -146,7 +159,8 @@
 
 	if(!tdbp) {
 		KLIPS_PRINT(debug_xform,
-			    "klips_error:puttdb: null pointer passed in!\n");
+			    "klips_error:puttdb: "
+			    "null pointer passed in!\n");
 		return -ENODATA;
 	}
 	hashval = ((tdbp->tdb_said.spi + tdbp->tdb_said.dst.s_addr + tdbp->tdb_said.proto) % TDB_HASHMOD);
@@ -161,40 +175,46 @@
 	return error;
 }
 
-/* This tdb better be locked before it is handed in, or races might
- * happen */
-
-/* void */
+/*
+  The tdb table better be locked before it is handed in, or races might happen
+*/
 int
 deltdb(struct tdb *tdbp)
 {
 	unsigned int hashval;
 	struct tdb *tdbtp;
         char sa[SATOA_BUF];
+	size_t sa_len;
 
 	if(!tdbp) {
 		KLIPS_PRINT(debug_xform,
-			    "klips_error:deltdb: null pointer passed in!\n");
+			    "klips_error:deltdb: "
+			    "null pointer passed in!\n");
 		return -ENODATA;
 	}
 	
-	satoa(tdbp->tdb_said, 0, sa, SATOA_BUF);
+	sa_len = satoa(tdbp->tdb_said, 0, sa, SATOA_BUF);
 	if(tdbp->tdb_inext || tdbp->tdb_onext) {
 		KLIPS_PRINT(debug_xform,
-			    "klips_error:deltdb: SA:%s still linked!\n",
-			    sa);
+			    "klips_error:deltdb: "
+			    "SA:%s still linked!\n",
+			    sa_len ? sa : " (error)");
 		return -EMLINK;
 	}
 	
 	hashval = ((tdbp->tdb_said.spi + tdbp->tdb_said.dst.s_addr + tdbp->tdb_said.proto) % TDB_HASHMOD);
 	
 	KLIPS_PRINT(debug_xform,
-		    "klips_debug:deltdb: deleting SA:%s, hashval=%d.\n",
-		    sa, hashval);
+		    "klips_debug:deltdb: "
+		    "deleting SA:%s, hashval=%d.\n",
+		    sa_len ? sa : " (error)",
+		    hashval);
 	if(!tdbh[hashval]) {
 		KLIPS_PRINT(debug_xform,
-			    "klips_debug:deltdb: no entries in tdb table for hash=%d of SA:%s.\n",
-			    hashval, sa);
+			    "klips_debug:deltdb: "
+			    "no entries in tdb table for hash=%d of SA:%s.\n",
+			    hashval,
+			    sa_len ? sa : " (error)");
 		return -ENOENT;
 	}
 	
@@ -202,7 +222,8 @@
 		tdbh[hashval] = tdbh[hashval]->tdb_hnext;
 		tdbp->tdb_hnext = NULL;
 		KLIPS_PRINT(debug_xform,
-			    "klips_debug:deltdb: successfully deleted first tdb in chain.\n");
+			    "klips_debug:deltdb: "
+			    "successfully deleted first tdb in chain.\n");
 		return 0;
 	} else {
 		for (tdbtp = tdbh[hashval]; tdbtp; tdbtp = tdbtp->tdb_hnext) {
@@ -210,53 +231,62 @@
 				tdbtp->tdb_hnext = tdbp->tdb_hnext;
 				tdbp->tdb_hnext = NULL;
 				KLIPS_PRINT(debug_xform,
-					    "klips_debug:deltdb: successfully "
-					    "deleted link in tdb chain.\n");
+					    "klips_debug:deltdb: "
+					    "successfully deleted link in tdb chain.\n");
 				return 0;
 			}
 		}
 	}
 	
 	KLIPS_PRINT(debug_xform,
-		    "klips_debug:deltdb: no entries in linked list for hash=%d of SA:%s.\n",
-		    hashval, sa);
+		    "klips_debug:deltdb: "
+		    "no entries in linked list for hash=%d of SA:%s.\n",
+		    hashval,
+		    sa_len ? sa : " (error)");
 	return -ENOENT;
 }
 
-/* This tdb better be locked before it is handed in, or races might
- * happen */
-
+/*
+  The tdb table better be locked before it is handed in, or races might happen
+*/
 int
 deltdbchain(struct tdb *tdbp)
 {
 	struct tdb *tdbdel;
 	int error = 0;
         char sa[SATOA_BUF];
+	size_t sa_len;
 
 	if(!tdbp) {
 		KLIPS_PRINT(debug_xform,
-			    "klips_error:deltdbchain: null pointer passed in!\n");
+			    "klips_error:deltdbchain: "
+			    "null pointer passed in!\n");
 		return -ENODATA;
 	}
 
-	satoa(tdbp->tdb_said, 0, sa, SATOA_BUF);
+	sa_len = satoa(tdbp->tdb_said, 0, sa, SATOA_BUF);
 	KLIPS_PRINT(debug_xform,
-		    "klips_debug:deltdbchain: passed SA:%s\n", sa);
+		    "klips_debug:deltdbchain: "
+		    "passed SA:%s\n",
+		    sa_len ? sa : " (error)");
 	while(tdbp->tdb_onext) {
 		tdbp = tdbp->tdb_onext;
 	}
 
 	while(tdbp) {
 		/* XXX send a pfkey message up to advise of deleted TDB */
-		satoa(tdbp->tdb_said, 0, sa, SATOA_BUF);
+		sa_len = satoa(tdbp->tdb_said, 0, sa, SATOA_BUF);
 		KLIPS_PRINT(debug_xform,
-			    "klips_debug:deltdbchain: unlinking and delting SA:%s", sa);
+			    "klips_debug:deltdbchain: "
+			    "unlinking and delting SA:%s",
+			    sa_len ? sa : " (error)");
 		tdbdel = tdbp;
 		tdbp = tdbp->tdb_inext;
 		if(tdbp) {
-			satoa(tdbp->tdb_said, 0, sa, SATOA_BUF);
+			sa_len = satoa(tdbp->tdb_said, 0, sa, SATOA_BUF);
 			KLIPS_PRINT(debug_xform,
-				    ", inext=%s", sa);
+				    ", inext=%s",
+				    sa_len ? sa : " (error)");
 			tdbdel->tdb_inext = NULL;
 			tdbp->tdb_onext = NULL;
 		}
@@ -284,34 +314,39 @@
 {
 	int alg;
 	struct xformsw *xsp;
-	int len;
+	int error = 0;
         int i;
-#if defined(CONFIG_IPSEC_ENC_3DES)
+#if defined(CONFIG_IPSEC_ENC_DES) || defined(CONFIG_IPSEC_ENC_3DES)
         int error;
-#endif /* CONFIG_IPSEC_ENC_3DES */
+#endif /* CONFIG_IPSEC_ENC_{,3}DES */
 
         char sa[SATOA_BUF];
         size_t sa_len;
 
 	if(!tdbp || !em) {
 		KLIPS_PRINT(debug_xform,
-			    "klips_error:tdb_init: null pointer passed in!\n");
+			    "klips_error:tdb_init: "
+			    "null pointer passed in!\n");
 		SENDERR(ENODATA);
 	}
 
 	sa_len = satoa(em->em_said, 0, sa, SATOA_BUF);
 
         KLIPS_PRINT(debug_esp,
-		    "klips_debug:tdb_init: (algo_switch defined) called for SA:%s\n", sa);
+		    "klips_debug:tdb_init: "
+		    "(algo_switch defined) called for SA:%s\n",
+		    sa_len ? sa : " (error)");
 	alg = em->em_alg;
 	
 	for (xsp = xformsw; xsp < xformswNXFORMSW; xsp++) {
 		if (xsp->xf_type == alg) {
 			KLIPS_PRINT(debug_netlink,
-				    "klips_debug:tdb_init: called with tdbp=0x%p, xsp=0x%p, em=0x%p\n",
+				    "klips_debug:tdb_init: "
+				    "called with tdbp=0x%p, xsp=0x%p, em=0x%p\n",
 				    tdbp, xsp, em);
 			KLIPS_PRINT(debug_netlink,
-				    "klips_debug:tdb_init: calling init routine of %s\n",
+				    "klips_debug:tdb_init: "
+				    "calling init routine of %s\n",
 				    xsp->xf_name);
 			tdbp->tdb_xform = xsp;
 			tdbp->tdb_replaywin_lastseq = 0;
@@ -363,22 +398,23 @@
 				
 				if (ed->ame_klen != AHMD596_KLEN) {
 					KLIPS_PRINT(debug_ah,
-						    "klips_debug:tdb_init: incorrect key size: %d"
-						    "-- must be %d octets (bytes)\n",
+						    "klips_debug:tdb_init: "
+						    "incorrect key size: %d -- must be %d octets (bytes)\n",
 						    ed->ame_klen, AHMD596_KLEN);
 					SENDERR(EINVAL);
 				}
 				
 				if (ed->ame_alen != AHMD596_ALEN) {
 					KLIPS_PRINT(debug_ah,
-						    "klips_debug:tdb_init: authenticator size: %d"
-						    " -- must be %d octets (bytes)\n",
+						    "klips_debug:tdb_init: "
+						    "authenticator size: %d -- must be %d octets (bytes)\n",
 						    ed->ame_alen, AHMD596_ALEN);
 					SENDERR(EINVAL);
 				}
 				
 				KLIPS_PRINT(debug_ah,
-					    "klips_debug:tdb_init: hmac md5-96 key is 0x%08x %08x %08x %08x\n",
+					    "klips_debug:tdb_init: "
+					    "hmac md5-96 key is 0x%08x %08x %08x %08x\n",
 					    (__u32)ntohl(*(((__u32 *)ed->ame_key)+0)),
 					    (__u32)ntohl(*(((__u32 *)ed->ame_key)+1)),
 					    (__u32)ntohl(*(((__u32 *)ed->ame_key)+2)),
@@ -389,8 +425,8 @@
 				
 				if(ed->ame_ooowin > 64) {
 					KLIPS_PRINT(debug_ah,
-						    "klips_debug:tdb_init: replay window size: %d"
-						    " -- must be 0 <= size <= 64\n",
+						    "klips_debug:tdb_init: "
+						    "replay window size: %d -- must be 0 <= size <= 64\n",
 						    ed->ame_ooowin);
 					SENDERR(EINVAL);
 				}
@@ -422,8 +458,8 @@
 				MD5Update(octx, kb, AHMD596_BLKLEN);
 				
 				KLIPS_PRINT(debug_ah,
-					    "klips_debug:tdb_init: MD5 ictx=0x%08x %08x %08x %08x"
-					    " octx=0x%08x %08x %08x %08x\n",
+					    "klips_debug:tdb_init: "
+					    "MD5 ictx=0x%08x %08x %08x %08x octx=0x%08x %08x %08x %08x\n",
 					    ((__u32*)ictx)[0],
 					    ((__u32*)ictx)[1],
 					    ((__u32*)ictx)[2],
@@ -456,22 +492,23 @@
 				
 				if (ed->ame_klen != AHSHA196_KLEN) {
 					KLIPS_PRINT(debug_ah,
-						    "klips_debug:tdb_init: incorrect key size: %d"
-						    "-- must be %d octets (bytes)\n",
+						    "klips_debug:tdb_init: "
+						    "incorrect key size: %d -- must be %d octets (bytes)\n",
 						    ed->ame_klen, AHSHA196_KLEN);
 					SENDERR(EINVAL);
 				}
 				
 				if (ed->ame_alen != AHSHA196_ALEN) {
 					KLIPS_PRINT(debug_ah,
-						    "klips_debug:tdb_init: authenticator size: %d"
-						    " -- must be %d octets (bytes)\n",
+						    "klips_debug:tdb_init: "
+						    "authenticator size: %d -- must be %d octets (bytes)\n",
 						    ed->ame_alen, AHSHA196_ALEN);
 					SENDERR(EINVAL);
 				}
 				
 				KLIPS_PRINT(debug_ah,
-					    "klips_debug:tdb_init: hmac sha1-96 key is 0x%08x %08x %08x %08x\n",
+					    "klips_debug:tdb_init: "
+					    "hmac sha1-96 key is 0x%08x %08x %08x %08x\n",
 					    (__u32)ntohl(*(((__u32 *)ed->ame_key)+0)),
 					    (__u32)ntohl(*(((__u32 *)ed->ame_key)+1)),
 					    (__u32)ntohl(*(((__u32 *)ed->ame_key)+2)),
@@ -482,8 +519,8 @@
 				
 				if(ed->ame_ooowin > 64) {
 					KLIPS_PRINT(debug_ah,
-						    "klips_debug:tdb_init: replay window size: %d"
-						    " -- must be 0 <= size <= 64\n",
+						    "klips_debug:tdb_init: "
+						    "replay window size: %d -- must be 0 <= size <= 64\n",
 						    ed->ame_ooowin);
 					SENDERR(EINVAL);
 				}
@@ -513,8 +550,8 @@
 				SHA1Update(octx, kb, AHSHA196_BLKLEN);
 				
 				KLIPS_PRINT(debug_ah,
-					    "klips_debug:tdb_init: SHA1 ictx=0x%08x %08x %08x %08x"
-					    " octx=0x%08x %08x %08x %08x\n", 
+					    "klips_debug:tdb_init: "
+					    "SHA1 ictx=0x%08x %08x %08x %08x octx=0x%08x %08x %08x %08x\n", 
 					    ((__u32*)ictx)[0],
 					    ((__u32*)ictx)[1],
 					    ((__u32*)ictx)[2],
@@ -534,6 +571,16 @@
 #endif /* CONFIG_IPSEC_AH */
 
 #ifdef CONFIG_IPSEC_ESP
+#ifdef CONFIG_IPSEC_ENC_DES
+			case XF_ESPDES:
+#ifdef CONFIG_IPSEC_AUTH_HMAC_MD5
+			case XF_ESPDESMD596:
+#endif /* CONFIG_IPSEC_AUTH_HMAC_MD5 */
+#ifdef CONFIG_IPSEC_AUTH_HMAC_SHA1
+			case XF_ESPDESSHA196:
+#endif /* CONFIG_IPSEC_AUTH_HMAC_SHA1 */
+#endif /* CONFIG_IPSEC_ENC_DES */
+
 #ifdef CONFIG_IPSEC_ENC_3DES
 			case XF_ESP3DES:
 #ifdef CONFIG_IPSEC_AUTH_HMAC_MD5
@@ -543,14 +590,6 @@
 			case XF_ESP3DESSHA196:
 #endif /* CONFIG_IPSEC_AUTH_HMAC_SHA1 */
 #endif /* CONFIG_IPSEC_ENC_3DES */
-#ifdef CONFIG_IPSEC_ENC_NULL
-#ifdef CONFIG_IPSEC_AUTH_HMAC_MD5
-			case XF_ESPNULLMD596:
-#endif /* CONFIG_IPSEC_AUTH_HMAC_MD5 */
-#ifdef CONFIG_IPSEC_AUTH_HMAC_SHA1
-			case XF_ESPNULLSHA196:
-#endif /* CONFIG_IPSEC_AUTH_HMAC_SHA1 */
-#endif /* CONFIG_IPSEC_ENC_NULL */
 			{
 				struct espblkrply_edata *ed;
 				unsigned char kb[AHMD596_BLKLEN];
@@ -570,8 +609,8 @@
 
 				if(ed->eme_ooowin > 64) {
 					KLIPS_PRINT(debug_esp,
-						    "klips_debug:tdb_init: replay window size: %d"
-						    "-- must be 0 <= size <= 64\n",
+						    "klips_debug:tdb_init: "
+						    "replay window size: %d -- must be 0 <= size <= 64\n",
 						    ed->eme_ooowin);
 					SENDERR(EINVAL);
 				}
@@ -581,6 +620,9 @@
 				case XF_ESP3DES:
 				case XF_ESP3DESMD596:
 				case XF_ESP3DESSHA196:
+				case XF_ESPDES:
+				case XF_ESPDESMD596:
+				case XF_ESPDESSHA196:
 					if((tdbp->tdb_iv = (caddr_t)
 					   kmalloc((tdbp->tdb_iv_size = EMT_ESPDES_IV_SZ), GFP_ATOMIC)) == NULL) {
 						SENDERR(ENOMEM);
@@ -592,6 +634,45 @@
 				}
 
 				switch(alg) {
+
+#ifdef CONFIG_IPSEC_ENC_DES
+				case XF_ESPDES:
+				case XF_ESPDESMD596:
+				case XF_ESPDESSHA196:
+					tdbp->tdb_encalg = ESP_DES;
+				
+					if (ed->eme_klen != EMT_ESPDES_KEY_SZ) {
+						KLIPS_PRINT(debug_esp,
+							    "klips_debug:tdb_init: "
+							    "incorrect encryption key size: %d -- must be %d octets (bytes)\n",
+							    ed->eme_klen, EMT_ESPDES_KEY_SZ);
+						SENDERR(EINVAL);
+					}
+
+					tdbp->tdb_key_bits_e = ed->eme_klen;
+
+					if((tdbp->tdb_key_e = (caddr_t)
+					   kmalloc((tdbp->tdb_key_e_size = sizeof(struct des_eks)),
+						   GFP_ATOMIC)) == NULL) {
+						SENDERR(ENOMEM);
+					}
+
+						error = des_set_key((caddr_t)(ed->eme_key),
+								    (caddr_t)&((struct des_eks*)(tdbp->tdb_key_e)));
+						if (error == -1)
+							printk("klips_debug:tdb_init: "
+							       "parity error in des key\n");
+						else if (error == -2)
+							printk("klips_debug:tdb_init: "
+							       "illegal weak des key\n");
+						if (error) {
+							memset(tdbp->tdb_key_e, 0, sizeof(struct des_eks));
+							kfree(tdbp->tdb_key_e);
+							SENDERR(EINVAL);
+						}
+
+					break;
+#endif /* CONFIG_IPSEC_ENC_DES */
 #ifdef CONFIG_IPSEC_ENC_3DES
 				case XF_ESP3DES:
 				case XF_ESP3DESMD596:
@@ -600,8 +681,8 @@
 				
 					if (ed->eme_klen != EMT_ESP3DES_KEY_SZ) {
 						KLIPS_PRINT(debug_esp,
-							    "klips_debug:tdb_init: incorrect encryption "
-							    "key size: %d -- must be %d octets (bytes)\n",
+							    "klips_debug:tdb_init: "
+							    "incorrect encryption key size: %d -- must be %d octets (bytes)\n",
 							    ed->eme_klen, EMT_ESP3DES_KEY_SZ);
 						SENDERR(EINVAL);
 					}
@@ -617,7 +698,8 @@
 					for(i = 0; i < 3; i++) {
 #if 0
 						KLIPS_PRINT(debug_esp,
-							    "klips_debug:tdb_init: 3des key %d/3 is 0x%08lx%08lx\n",
+							    "klips_debug:tdb_init: "
+							    "3des key %d/3 is 0x%08lx%08lx\n",
 							    i + 1,
 							    ntohl(*((__u32 *)ed->eme_key + i * 2)),
 							    ntohl(*((__u32 *)ed->eme_key + i * 2 + 1)));
@@ -625,9 +707,11 @@
 						error = des_set_key((caddr_t)(ed->eme_key) + EMT_ESPDES_KEY_SZ * i,
 								    (caddr_t)&((struct des_eks*)(tdbp->tdb_key_e))[i]);
 						if (error == -1)
-							printk("klips_debug:tdb_init: parity error in des key %d/3\n", i + 1);
+							printk("klips_debug:tdb_init: "
+							       "parity error in des key %d/3\n", i + 1);
 						else if (error == -2)
-							printk("klips_debug:tdb_init: illegal weak des key %d/3\n", i + 1);
+							printk("klips_debug:tdb_init: "
+							       "illegal weak des key %d/3\n", i + 1);
 						if (error) {
 							memset(tdbp->tdb_key_e, 0, 3 * sizeof(struct des_eks));
 							kfree(tdbp->tdb_key_e);
@@ -643,6 +727,7 @@
 
 				switch(alg) {
 #ifdef CONFIG_IPSEC_AUTH_HMAC_MD5
+				case XF_ESPDESMD596:
 				case XF_ESP3DESMD596:
 				case XF_ESPNULLMD596:
 				{
@@ -653,8 +738,8 @@
 				
 					if (ed->ame_klen != AHMD596_KLEN) {
 						KLIPS_PRINT(debug_esp,
-							    "klips_debug:tdb_init: incorrect authorisation "
-							    " key size: %d -- must be %d octets (bytes)\n",
+							    "klips_debug:tdb_init: "
+							    "incorrect authorisation  key size: %d -- must be %d octets (bytes)\n",
 							    ed->ame_klen, AHMD596_KLEN);
 						SENDERR(EINVAL);
 					}
@@ -669,7 +754,8 @@
 						SENDERR(ENOMEM);
 					}
 					KLIPS_PRINT(debug_esp,
-						    "klips_debug:tdb_init: hmac md5-96 key is 0x%08x %08x %08x %08x\n",
+						    "klips_debug:tdb_init: "
+						    "hmac md5-96 key is 0x%08x %08x %08x %08x\n",
 						    (__u32)ntohl(*(((__u32 *)ed->ame_key)+0)),
 						    (__u32)ntohl(*(((__u32 *)ed->ame_key)+1)),
 						    (__u32)ntohl(*(((__u32 *)ed->ame_key)+2)),
@@ -698,8 +784,8 @@
 					MD5Update(octx, kb, AHMD596_BLKLEN);
 					
 					KLIPS_PRINT(debug_esp,
-						    "klips_debug:tdb_init: MD5 ictx=0x%08x %08x %08x %08x"
-						    " octx=0x%08x %08x %08x %08x\n",
+						    "klips_debug:tdb_init: "
+						    "MD5 ictx=0x%08x %08x %08x %08x octx=0x%08x %08x %08x %08x\n",
 						    ((__u32*)ictx)[0],
 						    ((__u32*)ictx)[1],
 						    ((__u32*)ictx)[2],
@@ -717,6 +803,7 @@
 #endif /* CONFIG_IPSEC_AUTH_HMAC_MD5 */
 #ifdef CONFIG_IPSEC_AUTH_HMAC_SHA1
 				case XF_ESPNULLSHA196:
+				case XF_ESPDESSHA196:
 				case XF_ESP3DESSHA196:
 				{
 					SHA1_CTX *ictx;
@@ -726,8 +813,8 @@
 				
 					if (ed->ame_klen != AHSHA196_KLEN) {
 						KLIPS_PRINT(debug_esp,
-							    "klips_debug:tdb_init: incorrect authorisation "
-							    " key size: %d -- must be %d octets (bytes)\n",
+							    "klips_debug:tdb_init: "
+							    "incorrect authorisation key size: %d -- must be %d octets (bytes)\n",
 							    ed->ame_klen, AHSHA196_KLEN);
 						SENDERR(EINVAL);
 					}
@@ -741,7 +828,8 @@
 						SENDERR(ENOMEM);
 					}
 					KLIPS_PRINT(debug_esp,
-						    "klips_debug:tdb_init: hmac sha1-96 key is 0x%08x %08x %08x %08x\n",
+						    "klips_debug:tdb_init: "
+						    "hmac sha1-96 key is 0x%08x %08x %08x %08x\n",
 						    (__u32)ntohl(*(((__u32 *)ed->ame_key)+0)),
 						    (__u32)ntohl(*(((__u32 *)ed->ame_key)+1)),
 						    (__u32)ntohl(*(((__u32 *)ed->ame_key)+2)),
@@ -768,8 +856,8 @@
 					SHA1Update(octx, kb, AHSHA196_BLKLEN);
 				
 					KLIPS_PRINT(debug_esp,
-						    "klips_debug:tdb_init: SHA1 ictx=0x%08x %08x %08x %08x"
-						    " octx=0x%08x %08x %08x %08x\n",
+						    "klips_debug:tdb_init: "
+						    "SHA1 ictx=0x%08x %08x %08x %08x octx=0x%08x %08x %08x %08x\n",
 						    ((__u32*)ictx)[0],
 						    ((__u32*)ictx)[1],
 						    ((__u32*)ictx)[2],
@@ -785,6 +873,7 @@
 					break;
 				}
 #endif /* CONFIG_IPSEC_AUTH_HMAC_SHA1 */
+				case XF_ESPDES:
 				case XF_ESP3DES:
 					tdbp->tdb_authalg = AH_NONE;
 					break;
@@ -795,18 +884,22 @@
 #endif /* !CONFIG_IPSEC_ESP */
 			default:
 				KLIPS_PRINT(debug_xform,
-					    "klips_debug:tdb_init: alg=%d not configured\n", alg);
+					    "klips_debug:tdb_init: "
+					    "alg=%d not configured\n",
+					    alg);
 				SENDERR(ESOCKTNOSUPPORT);
 			}
 			SENDERR(0);
 		}
 	}
 	KLIPS_PRINT(debug_xform & DB_XF_INIT,
-		    "klips_debug:tdb_init: unregistered algorithm %d requested\n"
-		    "klips_debug:   trying to setup SA:%s\n", alg, sa);
+		    "klips_debug:tdb_init: "
+		    "unregistered algorithm %d requested trying to setup SA:%s\n",
+		    alg,
+		    sa_len ? sa : " (error)");
 	SENDERR(EINVAL);
 errlab:
-	return len;
+	return error;
 }
 #endif
 
@@ -817,9 +910,12 @@
 	int error = 0;
 	struct tdb *tdbp, **tdbprev, *tdbdel;
         char sa[SATOA_BUF];
+	size_t sa_len;
 
 	KLIPS_PRINT(debug_xform,
-		    "klips_debug:ipsec_tdbcleanup: cleaning up proto=%d.\n", proto);
+		    "klips_debug:ipsec_tdbcleanup: "
+		    "cleaning up proto=%d.\n",
+		    proto);
 
 	spin_lock_bh(&tdb_lock);
 
@@ -827,56 +923,67 @@
 		tdbprev = &(tdbh[i]);
 		tdbp = tdbh[i];
 		for(; tdbp;) {
-			satoa(tdbp->tdb_said, 0, sa, SATOA_BUF);
+			sa_len = satoa(tdbp->tdb_said, 0, sa, SATOA_BUF);
 			KLIPS_PRINT(debug_xform,
-				    "klips_debug:ipsec_tdbcleanup: checking SA:%s, hash=%d",
-				    sa, i);
+				    "klips_debug:ipsec_tdbcleanup: "
+				    "checking SA:%s, hash=%d",
+				    sa_len ? sa : " (error)",
+				    i);
 			tdbdel = tdbp;
 			tdbp = tdbdel->tdb_hnext;
 			if(tdbp) {
-				satoa(tdbp->tdb_said, 0, sa, SATOA_BUF);
+				sa_len = satoa(tdbp->tdb_said, 0, sa, SATOA_BUF);
 				KLIPS_PRINT(debug_xform,
-					    ", hnext=%s", sa);
+					    ", hnext=%s",
+					    sa_len ? sa : " (error)");
 			}
 			if(*tdbprev) {
-				satoa((*tdbprev)->tdb_said, 0, sa, SATOA_BUF);
+				sa_len = satoa((*tdbprev)->tdb_said, 0, sa, SATOA_BUF);
 				KLIPS_PRINT(debug_xform,
-					    ", *tdbprev=%s", sa);
+					    ", *tdbprev=%s",
+					    sa_len ? sa : " (error)");
 				if((*tdbprev)->tdb_hnext) {
-					satoa((*tdbprev)->tdb_hnext->tdb_said, 0, sa, SATOA_BUF);
+					sa_len = satoa((*tdbprev)->tdb_hnext->tdb_said, 0, sa, SATOA_BUF);
 					KLIPS_PRINT(debug_xform,
-						    ", *tdbprev->tdb_hnext=%s", sa);
+						    ", *tdbprev->tdb_hnext=%s",
+						    sa_len ? sa : " (error)");
 				}
 			}
 			KLIPS_PRINT(debug_xform,
 				    ".\n");
 			if(!proto || (proto == tdbdel->tdb_said.proto)) {
-				satoa(tdbdel->tdb_said, 0, sa, SATOA_BUF);
+				sa_len = satoa(tdbdel->tdb_said, 0, sa, SATOA_BUF);
 				KLIPS_PRINT(debug_xform,
-					    "klips_debug:ipsec_tdbcleanup: deleting SA chain:%s.\n",
-					    sa);
-				/* *tdbprev = tdbdel->tdb_hnext; */
+					    "klips_debug:ipsec_tdbcleanup: "
+					    "deleting SA chain:%s.\n",
+					    sa_len ? sa : " (error)");
 				if((error = deltdbchain(tdbdel))) {
-					goto errlab;
+					SENDERR(-error);
 				}
 				tdbprev = &(tdbh[i]);
 				tdbp = tdbh[i];
 
 				KLIPS_PRINT(debug_xform,
-					    "klips_debug:ipsec_tdbcleanup: deleted SA chain:%s", sa);
+					    "klips_debug:ipsec_tdbcleanup: "
+					    "deleted SA chain:%s",
+					    sa_len ? sa : " (error)");
 				if(tdbp) {
-					satoa(tdbp->tdb_said, 0, sa, SATOA_BUF);
+					sa_len = satoa(tdbp->tdb_said, 0, sa, SATOA_BUF);
 					KLIPS_PRINT(debug_xform,
-						    ", tdbh[%d]=%s", i, sa);
+						    ", tdbh[%d]=%s",
+						    i,
+						    sa_len ? sa : " (error)");
 				}
 				if(*tdbprev) {
-					satoa((*tdbprev)->tdb_said, 0, sa, SATOA_BUF);
+					sa_len = satoa((*tdbprev)->tdb_said, 0, sa, SATOA_BUF);
 					KLIPS_PRINT(debug_xform,
-						    ", *tdbprev=%s", sa);
+						    ", *tdbprev=%s",
+						    sa_len ? sa : " (error)");
 					if((*tdbprev)->tdb_hnext) {
-						satoa((*tdbprev)->tdb_hnext->tdb_said, 0, sa, SATOA_BUF);
+						sa_len = satoa((*tdbprev)->tdb_hnext->tdb_said, 0, sa, SATOA_BUF);
 						KLIPS_PRINT(debug_xform,
-							    ", *tdbprev->tdb_hnext=%s", sa);
+							    ", *tdbprev->tdb_hnext=%s",
+							    sa_len ? sa : " (error)");
 					}
 				}
 				KLIPS_PRINT(debug_xform,
@@ -890,14 +997,14 @@
 
 	spin_unlock_bh(&tdb_lock);
 
-	return(-error);
+	return(error);
 }
 
 int
 ipsec_tdbwipe(struct tdb *tdbp)
 {
 	if(!tdbp) {
-		return -1;
+		return -ENODATA;
 	}
 
 	if(tdbp->tdb_addr_s) {
@@ -961,6 +1068,22 @@
 
 /*
  * $Log: ipsec_xform.c,v $
+ * 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.
  *
@@ -976,9 +1099,6 @@
  *
  * 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.
diff -bruN freeswan-1.9.orig/klips/net/ipsec/ipsec_xform.h freeswan-1.9/klips/net/ipsec/ipsec_xform.h
--- freeswan-1.9.orig/klips/net/ipsec/ipsec_xform.h	Tue Jan 30 18:42:47 2001
+++ freeswan-1.9/klips/net/ipsec/ipsec_xform.h	Tue Jun 12 16:08:37 2001
@@ -13,7 +13,7 @@
  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  * for more details.
  *
- * RCSID $Id: ipsec_xform.h,v 1.29 2001/01/30 23:42:47 rgb Exp $
+ * RCSID $Id: ipsec_xform.h,v 1.30 2001/05/30 08:14:03 rgb Exp $
  */
 
 #include <freeswan.h>
@@ -22,16 +22,22 @@
 #define XF_IP4			1	/* IPv4 inside IPv4 */
 #define XF_AHMD5		2	/* AH MD5 */
 #define XF_AHSHA		3	/* AH SHA */
+#define XF_ESPDESOLD		4	/* old ESP DES-CBC */
 #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_ESPDESMD5		8	/* DES, HMAC-MD-5, 128-bits of authentication */
 #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_ESPDESMD596		11	/* 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_ESPDESSHA196		15	/* DES, HMAC-SHA-1, 96-bits of authentication */
+#define	XF_ESPDES		16	/* ESP DES */
+
+#define XF_IP6			17	/* IPv6 inside IPv6 */
+#define XF_COMPDEFLATE		18	/* IPCOMP deflate */
 
 #define XF_CLR			126	/* Clear SA table */
 #define XF_DEL			127	/* Delete SA */
@@ -44,16 +50,20 @@
 #define AH_NONE                  0
 #define AH_MD5                   2
 #define AH_SHA                   3
+#define AH_DES                   4
 
 /* IPsec ESP transform values */
 
 #define ESP_NONE		 0
+#define ESP_DES_IV64             1
+#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_DES_IV32             9
 #define ESP_RC4                 10
 #define ESP_NULL                11
 
@@ -179,8 +189,8 @@
 		((x)->tdb_encalg == SADB_X_CALG_DEFLATE ? \
 		 "_DEFLATE" : "_UNKNOWN_comp") : \
 	(x)->tdb_encalg == ESP_NONE ? "" : \
+	(x)->tdb_encalg == ESP_DES ? "_DES" : \
 	(x)->tdb_encalg == ESP_3DES ? "_3DES" : \
-	(x)->tdb_encalg == ESP_NULL ? "_NULL_encr" : \
 	"_UNKNOWN_encr", \
 	(x)->tdb_authalg == AH_NONE ? "" : \
 	(x)->tdb_authalg == AH_MD5 ? "_HMAC_MD5" : \
@@ -216,6 +226,9 @@
 
 /*
  * $Log: ipsec_xform.h,v $
+ * 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.
@@ -247,9 +260,6 @@
  * 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.
diff -bruN freeswan-1.9.orig/klips/net/ipsec/pfkey_v2.c freeswan-1.9/klips/net/ipsec/pfkey_v2.c
--- freeswan-1.9.orig/klips/net/ipsec/pfkey_v2.c	Mon Feb 26 19:51:01 2001
+++ freeswan-1.9/klips/net/ipsec/pfkey_v2.c	Mon Jun  4 11:34:31 2001
@@ -12,7 +12,7 @@
  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  * for more details.
  *
- * RCSID $Id: pfkey_v2.c,v 1.51.2.1 2001/02/27 00:51:01 henry Exp $
+ * RCSID $Id: pfkey_v2.c,v 1.58 2001/05/04 16:37:24 rgb Exp $
  */
 
 /*
@@ -275,7 +275,10 @@
 pfkey_data_ready(struct sock *sk, int len)
 {
 	KLIPS_PRINT(debug_pfkey,
-		    "klips_debug:pfkey_data_ready: .sk=%p len=%d\n", sk, len);
+		    "klips_debug:pfkey_data_ready: "
+		    "sk=%p len=%d\n",
+		    sk,
+		    len);
 	if(!sk->dead) {
 		wake_up_interruptible(sk->sleep);
 		sock_wake_async(sk->socket, 1);
@@ -298,7 +301,9 @@
 pfkey_insert_socket(struct sock *sk)
 {
 	KLIPS_PRINT(debug_pfkey,
-		    "klips_debug:pfkey_insert_socket: sk=%p\n", sk);
+		    "klips_debug:pfkey_insert_socket: "
+		    "sk=%p\n",
+		    sk);
 	cli();
 	sk->next=pfkey_sock_list;
 	pfkey_sock_list=sk;
@@ -321,14 +326,16 @@
 			sk->next=NULL;
 			sti();
 			KLIPS_PRINT(debug_pfkey,
-				    "klips_debug:pfkey_remove_socket: succeeded.\n");
+				    "klips_debug:pfkey_remove_socket: "
+				    "succeeded.\n");
 			return;
 		}
 		s=&((*s)->next);
 	}
 	sti();
 	KLIPS_PRINT(debug_pfkey,
-		    "klips_debug:pfkey_remove_socket: not found.\n");
+		    "klips_debug:pfkey_remove_socket: "
+		    "not found.\n");
 	return;
 }
 
@@ -341,7 +348,8 @@
 		    "klips_debug:pfkey_destroy_socket: .\n");
 	pfkey_remove_socket(sk);
 	KLIPS_PRINT(debug_pfkey,
-		    "klips_debug:pfkey_destroy_socket: pfkey_remove_socket called.\n");
+		    "klips_debug:pfkey_destroy_socket: "
+		    "pfkey_remove_socket called.\n");
 	
 	KLIPS_PRINT(debug_pfkey,
 		    "klips_debug:pfkey_destroy_socket: "
@@ -355,8 +363,10 @@
 #ifdef CONFIG_IPSEC_DEBUG
 		if(debug_pfkey && sysctl_ipsec_debug_verbose) {
 			KLIPS_PRINT(debug_pfkey,
-				    "klips_debug:pfkey_destroy_socket: skb=%p dequeued.\n", skb);
-			printk(KERN_INFO "klips_debug: pfkey_skb contents:");
+				    "klips_debug:pfkey_destroy_socket: "
+				    "skb=%p dequeued.\n", skb);
+			printk(KERN_INFO "klips_debug:pfkey_destroy_socket: "
+			       "pfkey_skb contents:");
 			printk(" next:%p", skb->next);
 			printk(" prev:%p", skb->prev);
 			printk(" list:%p", skb->list);
@@ -386,8 +396,8 @@
 			}
 			printk(" len:%d", skb->len);
 			printk(" csum:%d", skb->csum);
-			printk(" used:%d", skb->used);
 #ifndef NETDEV_23
+			printk(" used:%d", skb->used);
 			printk(" is_clone:%d", skb->is_clone);
 #endif /* NETDEV_23 */
 			printk(" cloned:%d", skb->cloned);
@@ -413,12 +423,16 @@
 		}
 #endif /* CONFIG_IPSEC_DEBUG */
 		KLIPS_PRINT(debug_pfkey,
-			    "klips_debug:pfkey_destroy_socket: skb=%p freed.\n", skb);
+			    "klips_debug:pfkey_destroy_socket: "
+			    "skb=%p freed.\n",
+			    skb);
 		kfree_skb(skb);
 
 #else /* NET_21 */
 		KLIPS_PRINT(debug_pfkey,
-			    "klips_debug:pfkey_destroy_socket: skb=%p dequeued and freed.\n", skb);
+			    "klips_debug:pfkey_destroy_socket: "
+			    "skb=%p dequeued and freed.\n",
+			    skb);
 		kfree_skb(skb, FREE_WRITE);
 
 #endif /* NET_21 */
@@ -434,19 +448,21 @@
 int
 pfkey_upmsg(struct socket *sock, struct sadb_msg *pfkey_msg)
 {
-	int error;
+	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");
+			    "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");
+			    "klips_debug:pfkey_upmsg: "
+			    "NULL pfkey_msg passed in.\n");
 		return -EINVAL;
 	}
 
@@ -458,27 +474,31 @@
 
 	if(sk == NULL) {
 		KLIPS_PRINT(debug_pfkey,
-			    "klips_debug:pfkey_upmsg: NULL sock passed in.\n");
+			    "klips_debug:pfkey_upmsg: "
+			    "NULL sock passed in.\n");
 		return -EINVAL;
 	}
 
 	KLIPS_PRINT(debug_pfkey,
-		    "klips_debug:pfkey_upmsg: allocating %d bytes...\n",
+		    "klips_debug:pfkey_upmsg: "
+		    "allocating %d bytes...\n",
 		    pfkey_msg->sadb_msg_len * IPSEC_PFKEYv2_ALIGN);
 	if(!(skb = alloc_skb(pfkey_msg->sadb_msg_len * IPSEC_PFKEYv2_ALIGN, GFP_ATOMIC) )) {
 		KLIPS_PRINT(debug_pfkey,
-			    "klips_debug:pfkey_upmsg: no buffers left to send up a message.\n");
+			    "klips_debug:pfkey_upmsg: "
+			    "no buffers left to send up a message.\n");
 		return -ENOBUFS;
 	}
 	KLIPS_PRINT(debug_pfkey,
-		    "klips_debug:pfkey_upmsg: ...allocated at %p.\n", skb);
+		    "klips_debug:pfkey_upmsg: "
+		    "...allocated at %p.\n",
+		    skb);
 	
 	skb->dev = NULL;
 	
 	if(skb_tailroom(skb) < pfkey_msg->sadb_msg_len * IPSEC_PFKEYv2_ALIGN) {
 		printk(KERN_WARNING "klips_error:pfkey_upmsg: "
-		       "tried to skb_put %ld, %d available.  "
-		       "This should never happen, please report.\n",
+		       "tried to skb_put %ld, %d available.  This should never happen, please report.\n",
 		       (unsigned long int)pfkey_msg->sadb_msg_len * IPSEC_PFKEYv2_ALIGN,
 		       skb_tailroom(skb));
 #ifdef NET_21
@@ -505,10 +525,11 @@
 		KLIPS_PRINT(debug_pfkey,
 			    "klips_debug:pfkey_upmsg: "
 			    "error=%d calling sock_queue_rcv_skb with skb=%p.\n",
-			    error, skb);
+			    error,
+			    skb);
 		return error;
 	}
-	return 0;
+	return error;
 }
 
 DEBUG_NO_STATIC int
@@ -518,12 +539,14 @@
 
 	if(sock == NULL) {
 		KLIPS_PRINT(debug_pfkey,
-			    "klips_debug:pfkey_create: socket NULL.\n");
+			    "klips_debug:pfkey_create: "
+			    "socket NULL.\n");
 		return -EINVAL;
 	}
 
 	KLIPS_PRINT(debug_pfkey,
-		    "klips_debug:pfkey_create: sock=%p type:%d state:%d flags:%ld protocol:%d\n",
+		    "klips_debug:pfkey_create: "
+		    "sock=%p type:%d state:%d flags:%ld protocol:%d\n",
 		    sock,
 		    sock->type,
 		    (unsigned int)(sock->state),
@@ -531,19 +554,22 @@
 
 	if(sock->type != SOCK_RAW) {
 		KLIPS_PRINT(debug_pfkey,
-			    "klips_debug:pfkey_create: only SOCK_RAW supported.\n");
+			    "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");
+			    "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");
+			    "klips_debug:pfkey_create: "
+			    "must be root to open pfkey sockets.\n");
 		return -EACCES;
 	}
 
@@ -558,7 +584,8 @@
 #endif /* NET_21 */
 	{
 		KLIPS_PRINT(debug_pfkey,
-			    "klips_debug:pfkey_create: Out of memory trying to allocate.\n");
+			    "klips_debug:pfkey_create: "
+			    "Out of memory trying to allocate.\n");
 		MOD_DEC_USE_COUNT;
 		return -ENOMEM;
 	}
@@ -580,7 +607,8 @@
 	sk->protocol = protocol;
 	key_pid(sk) = current->pid;
 	KLIPS_PRINT(debug_pfkey,
-		    "klips_debug:pfkey_create: sock->fasync_list=%p sk->sleep=%p.\n",
+		    "klips_debug:pfkey_create: "
+		    "sock->fasync_list=%p sk->sleep=%p.\n",
 		    sock->fasync_list,
 		    sk->sleep);
 #else /* NET_21 */
@@ -608,7 +636,8 @@
 	pfkey_list_insert_socket(sock, &pfkey_open_sockets);
 
 	KLIPS_PRINT(debug_pfkey,
-		    "klips_debug:pfkey_create: Socket sock=%p sk=%p initialised.\n", sock, sk);
+		    "klips_debug:pfkey_create: "
+		    "Socket sock=%p sk=%p initialised.\n", sock, sk);
 	return 0;
 }
 
@@ -620,13 +649,15 @@
 
 	if(newsock==NULL) {
 		KLIPS_PRINT(debug_pfkey,
-			    "klips_debug:pfkey_dup: No new socket attached.\n");
+			    "klips_debug:pfkey_dup: "
+			    "No new socket attached.\n");
 		return -EINVAL;
 	}
 		
 	if(oldsock==NULL) {
 		KLIPS_PRINT(debug_pfkey,
-			    "klips_debug:pfkey_dup: No old socket attached.\n");
+			    "klips_debug:pfkey_dup: "
+			    "No old socket attached.\n");
 		return -EINVAL;
 	}
 		
@@ -639,7 +670,8 @@
 	/* May not have data attached */
 	if(sk==NULL) {
 		KLIPS_PRINT(debug_pfkey,
-			    "klips_debug:pfkey_dup: No sock attached to old socket.\n");
+			    "klips_debug:pfkey_dup: "
+			    "No sock attached to old socket.\n");
 		return -EINVAL;
 	}
 		
@@ -662,7 +694,8 @@
 
 	if(sock==NULL) {
 		KLIPS_PRINT(debug_pfkey,
-			    "klips_debug:pfkey_release: No socket attached.\n");
+			    "klips_debug:pfkey_release: "
+			    "No socket attached.\n");
 		return 0; /* -EINVAL; */
 	}
 		
@@ -675,12 +708,14 @@
 	/* May not have data attached */
 	if(sk==NULL) {
 		KLIPS_PRINT(debug_pfkey,
-			    "klips_debug:pfkey_release: No sk attached to sock=%p.\n", sock);
+			    "klips_debug:pfkey_release: "
+			    "No sk attached to sock=%p.\n", sock);
 		return 0; /* -EINVAL; */
 	}
 		
 	KLIPS_PRINT(debug_pfkey,
-		    "klips_debug:pfkey_release: .sock=%p sk=%p\n", sock, sk);
+		    "klips_debug:pfkey_release: "
+		    "sock=%p sk=%p\n", sock, sk);
 
 #ifdef NET_21
 	if(!sk->dead)
@@ -704,7 +739,8 @@
 
 	MOD_DEC_USE_COUNT;
 	KLIPS_PRINT(debug_pfkey,
-		    "klips_debug:pfkey_release: succeeded.\n");
+		    "klips_debug:pfkey_release: "
+		    "succeeded.\n");
 
 	return 0;
 }
@@ -714,7 +750,8 @@
 pfkey_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
 {
 	KLIPS_PRINT(debug_pfkey,
-		    "klips_debug:pfkey_bind: operation not supported.\n");
+		    "klips_debug:pfkey_bind: "
+		    "operation not supported.\n");
 	return -EINVAL;
 }
 
@@ -722,7 +759,8 @@
 pfkey_connect(struct socket *sock, struct sockaddr *uaddr, int addr_len, int flags)
 {
 	KLIPS_PRINT(debug_pfkey,
-		    "klips_debug:pfkey_connect: operation not supported.\n");
+		    "klips_debug:pfkey_connect: "
+		    "operation not supported.\n");
 	return -EINVAL;
 }
 
@@ -730,7 +768,8 @@
 pfkey_socketpair(struct socket *a, struct socket *b)
 {
 	KLIPS_PRINT(debug_pfkey,
-		    "klips_debug:pfkey_socketpair: operation not supported.\n");
+		    "klips_debug:pfkey_socketpair: "
+		    "operation not supported.\n");
 	return -EINVAL;
 }
 
@@ -738,7 +777,8 @@
 pfkey_accept(struct socket *sock, struct socket *newsock, int flags)
 {
 	KLIPS_PRINT(debug_pfkey,
-		    "klips_debug:pfkey_aaccept: operation not supported.\n");
+		    "klips_debug:pfkey_aaccept: "
+		    "operation not supported.\n");
 	return -EINVAL;
 }
 
@@ -760,13 +800,15 @@
 {
 	
 	KLIPS_PRINT(debug_pfkey,
-		    "klips_debug:pfkey_select: .sock=%p sk=%p sel_type=%d\n",
+		    "klips_debug:pfkey_select: "
+		    ".sock=%p sk=%p sel_type=%d\n",
 		    sock,
 		    sock->data,
 		    sel_type);
 	if(sock == NULL) {
 		KLIPS_PRINT(debug_pfkey,
-			    "klips_debug:pfkey_select: Null socket passed in.\n");
+			    "klips_debug:pfkey_select: "
+			    "Null socket passed in.\n");
 		return -EINVAL;
 	}
 	return datagram_select(sock->data, sel_type, wait);
@@ -776,7 +818,8 @@
 pfkey_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
 {
 	KLIPS_PRINT(debug_pfkey,
-		    "klips_debug:pfkey_ioctl: not supported.\n");
+		    "klips_debug:pfkey_ioctl: "
+		    "not supported.\n");
 	return -EINVAL;
 }
 
@@ -784,7 +827,8 @@
 pfkey_listen(struct socket *sock, int backlog)
 {
 	KLIPS_PRINT(debug_pfkey,
-		    "klips_debug:pfkey_listen: not supported.\n");
+		    "klips_debug:pfkey_listen: "
+		    "not supported.\n");
 	return -EINVAL;
 }
 #endif /* !NET_21 */
@@ -796,7 +840,8 @@
 
 	if(sock == NULL) {
 		KLIPS_PRINT(debug_pfkey,
-			    "klips_debug:pfkey_shutdown: NULL socket passed in.\n");
+			    "klips_debug:pfkey_shutdown: "
+			    "NULL socket passed in.\n");
 		return -EINVAL;
 	}
 
@@ -808,12 +853,14 @@
 	
 	if(sk == NULL) {
 		KLIPS_PRINT(debug_pfkey,
-			    "klips_debug:pfkey_shutdown: No sock attached to socket.\n");
+			    "klips_debug:pfkey_shutdown: "
+			    "No sock attached to socket.\n");
 		return -EINVAL;
 	}
 
 	KLIPS_PRINT(debug_pfkey,
-		    "klips_debug:pfkey_shutdown: mode=%x.\n", mode);
+		    "klips_debug:pfkey_shutdown: "
+		    "mode=%x.\n", mode);
 	mode++;
 	
 	if(mode&SEND_SHUTDOWN) {
@@ -837,7 +884,8 @@
 
 	if(sock == NULL) {
 		KLIPS_PRINT(debug_pfkey,
-			    "klips_debug:pfkey_setsockopt: Null socket passed in.\n");
+			    "klips_debug:pfkey_setsockopt: "
+			    "Null socket passed in.\n");
 		return -EINVAL;
 	}
 	
@@ -845,7 +893,8 @@
 	
 	if(sk == NULL) {
 		KLIPS_PRINT(debug_pfkey,
-			    "klips_debug:pfkey_setsockopt: Null sock passed in.\n");
+			    "klips_debug:pfkey_setsockopt: "
+			    "Null sock passed in.\n");
 		return -EINVAL;
 	}
 #endif /* !NET_21 */
@@ -870,7 +919,8 @@
 
 	if(sock == NULL) {
 		KLIPS_PRINT(debug_pfkey,
-			    "klips_debug:pfkey_setsockopt: Null socket passed in.\n");
+			    "klips_debug:pfkey_setsockopt: "
+			    "Null socket passed in.\n");
 		return -EINVAL;
 	}
 	
@@ -878,7 +928,8 @@
 	
 	if(sk == NULL) {
 		KLIPS_PRINT(debug_pfkey,
-			    "klips_debug:pfkey_setsockopt: Null sock passed in.\n");
+			    "klips_debug:pfkey_setsockopt: "
+			    "Null sock passed in.\n");
 		return -EINVAL;
 	}
 #endif /* !NET_21 */
@@ -1073,17 +1124,19 @@
 		for(pfkey_socketsp = pfkey_open_sockets;
 		    pfkey_socketsp;
 		    pfkey_socketsp = pfkey_socketsp->next) {
+			int error_upmsg = 0;
 			KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_sendmsg: "
 				    "sending up error=%d message=%p to socket=%p.\n",
 				    error,
 				    pfkey_reply,
 				    pfkey_socketsp->socketp);
-			if((error = pfkey_upmsg(pfkey_socketsp->socketp, pfkey_reply))) {
+			if((error_upmsg = pfkey_upmsg(pfkey_socketsp->socketp, pfkey_reply))) {
 				KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_sendmsg: "
 					    "sending up error message to socket=%p failed with error=%d.\n",
-					    pfkey_socketsp->socketp, error);
+					    pfkey_socketsp->socketp,
+					    error_upmsg);
 				pfkey_msg_free(&pfkey_reply);
-				goto errlab;
+				SENDERR(-error);
 			}
 			KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_sendmsg: "
 				    "sending up error message to socket=%p succeeded.\n",
@@ -1127,7 +1180,8 @@
 
 	if(sock == NULL) {
 		KLIPS_PRINT(debug_pfkey,
-			    "klips_debug:pfkey_recvmsg: Null socket passed in.\n");
+			    "klips_debug:pfkey_recvmsg: "
+			    "Null socket passed in.\n");
 		return -EINVAL;
 	}
 
@@ -1139,13 +1193,15 @@
 
 	if(sk == NULL) {
 		KLIPS_PRINT(debug_pfkey,
-			    "klips_debug:pfkey_recvmsg: Null sock passed in for sock=%p.\n", sock);
+			    "klips_debug:pfkey_recvmsg: "
+			    "Null sock passed in for sock=%p.\n", sock);
 		return -EINVAL;
 	}
 
 	if(msg == NULL) {
 		KLIPS_PRINT(debug_pfkey,
-			    "klips_debug:pfkey_recvmsg: Null msghdr passed in for sock=%p, sk=%p.\n",
+			    "klips_debug:pfkey_recvmsg: "
+			    "Null msghdr passed in for sock=%p, sk=%p.\n",
 			    sock, sk);
 		return -EINVAL;
 	}
@@ -1155,7 +1211,8 @@
 		    sock, sk, msg, size);
 	if(flags & ~MSG_PEEK) {
 		KLIPS_PRINT(debug_pfkey,
-			    "klips_debug:pfkey_sendmsg: flags (%d) other than MSG_PEEK not supported.\n",
+			    "klips_debug:pfkey_sendmsg: "
+			    "flags (%d) other than MSG_PEEK not supported.\n",
 			    flags);
 		return -EOPNOTSUPP;
 	}
@@ -1170,7 +1227,8 @@
 		
 	if(sk->err) {
 		KLIPS_PRINT(debug_pfkey,
-			    "klips_debug:pfkey_sendmsg: sk->err=%d.\n", sk->err);
+			    "klips_debug:pfkey_sendmsg: "
+			    "sk->err=%d.\n", sk->err);
 		return sock_error(sk);
 	}
 
@@ -1286,10 +1344,12 @@
 #ifdef CONFIG_IPSEC_DEBUG
 	if(!sysctl_ipsec_debug_verbose) {
 #endif CONFIG_IPSEC_DEBUG
-	len+= sprintf(buffer,"    sock   pid   socket     next     prev e n p sndbf    Flags     Type St\n");
+	len+= sprintf(buffer,
+		      "    sock   pid   socket     next     prev e n p sndbf    Flags     Type St\n");
 #ifdef CONFIG_IPSEC_DEBUG
 	} else {
-	len+= sprintf(buffer,"    sock   pid d    sleep   socket     next     prev e r z n p sndbf    stamp    Flags     Type St\n");
+	len+= sprintf(buffer,
+		      "    sock   pid d    sleep   socket     next     prev e r z n p sndbf    stamp    Flags     Type St\n");
 	}
 #endif CONFIG_IPSEC_DEBUG
 	
@@ -1297,7 +1357,8 @@
 #ifdef CONFIG_IPSEC_DEBUG
 		if(!sysctl_ipsec_debug_verbose) {
 #endif CONFIG_IPSEC_DEBUG
-		len+=sprintf(buffer+len,"%8p %5d %8p %8p %8p %d %d %d %5d %08lX %8X %2X\n",
+		len+=sprintf(buffer+len,
+			     "%8p %5d %8p %8p %8p %d %d %d %5d %08lX %8X %2X\n",
 			     sk,
 			     key_pid(sk),
 			     sk->socket,
@@ -1312,7 +1373,8 @@
 			     sk->socket->state);
 #ifdef CONFIG_IPSEC_DEBUG
 		} else {
-		len+=sprintf(buffer+len,"%8p %5d %d %8p %8p %8p %8p %d %d %d %d %d %5d %d.%06d %08lX %8X %2X\n",
+		len+=sprintf(buffer+len,
+			     "%8p %5d %d %8p %8p %8p %8p %d %d %d %d %d %5d %d.%06d %08lX %8X %2X\n",
 			     sk,
 			     key_pid(sk),
 			     sk->dead,
@@ -1367,12 +1429,14 @@
 	int satype;
 	struct supported_list *pfkey_supported_p;
 	
-	len+= sprintf(buffer,"satype exttype alg_id ivlen minbits maxbits\n");
+	len+= sprintf(buffer,
+		      "satype exttype alg_id ivlen minbits maxbits\n");
 	
 	for(satype = SADB_SATYPE_UNSPEC; satype <= SADB_SATYPE_MAX; satype++) {
 		pfkey_supported_p = pfkey_supported_list[satype];
 		while(pfkey_supported_p) {
-			len+=sprintf(buffer+len,"    %2d      %2d     %2d   %3d     %3d     %3d\n",
+			len+=sprintf(buffer+len,
+				     "    %2d      %2d     %2d   %3d     %3d     %3d\n",
 				     satype,
 				     pfkey_supported_p->supportedp->supported_alg_exttype,
 				     pfkey_supported_p->supportedp->supported_alg_id,
@@ -1413,19 +1477,22 @@
 	int satype;
 	struct socket_list *pfkey_sockets;
 	
-	len+= sprintf(buffer,"satype   socket   pid       sk\n");
+	len+= sprintf(buffer,
+		      "satype   socket   pid       sk\n");
 	
 	for(satype = SADB_SATYPE_UNSPEC; satype <= SADB_SATYPE_MAX; satype++) {
 		pfkey_sockets = pfkey_registered_sockets[satype];
 		while(pfkey_sockets) {
 #ifdef NET_21
-			len+=sprintf(buffer+len,"    %2d %8p %5d %8p\n",
+			len+=sprintf(buffer+len,
+				     "    %2d %8p %5d %8p\n",
 				     satype,
 				     pfkey_sockets->socketp,
 				     key_pid(pfkey_sockets->socketp->sk),
 				     pfkey_sockets->socketp->sk);
 #else /* NET_21 */
-			len+=sprintf(buffer+len,"    %2d %8p   N/A %8p\n",
+			len+=sprintf(buffer+len,
+				     "    %2d %8p   N/A %8p\n",
 				     satype,
 				     pfkey_sockets->socketp,
 #if 0
@@ -1565,36 +1632,40 @@
 	};
 #endif /* CONFIG_IPSEC_IPCOMP */
 
-        printk(KERN_INFO "IPsec: initialising PF_KEY domain sockets.\n");
+#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;
 	}
 
-	supported_add_all(SADB_SATYPE_AH, supported_init_ah, sizeof(supported_init_ah));
-	supported_add_all(SADB_SATYPE_ESP, supported_init_esp, sizeof(supported_init_esp));
+	error |= supported_add_all(SADB_SATYPE_AH, supported_init_ah, sizeof(supported_init_ah));
+	error |= supported_add_all(SADB_SATYPE_ESP, supported_init_esp, sizeof(supported_init_esp));
 #ifdef CONFIG_IPSEC_IPCOMP
-	supported_add_all(SADB_X_SATYPE_COMP, supported_init_ipcomp, sizeof(supported_init_ipcomp));
+	error |= supported_add_all(SADB_X_SATYPE_COMP, supported_init_ipcomp, sizeof(supported_init_ipcomp));
 #endif /* CONFIG_IPSEC_IPCOMP */
-	supported_add_all(SADB_X_SATYPE_IPIP, supported_init_ipip, sizeof(supported_init_ipip));
+	error |= supported_add_all(SADB_X_SATYPE_IPIP, supported_init_ipip, sizeof(supported_init_ipip));
 
 #ifdef NET_21
-        sock_register(&pfkey_family_ops);
+        error |= sock_register(&pfkey_family_ops);
 #else /* NET_21 */
-        sock_register(pfkey_proto_ops.family, &pfkey_proto_ops);
+        error |= sock_register(pfkey_proto_ops.family, &pfkey_proto_ops);
 #endif /* NET_21 */
 
 #ifdef CONFIG_PROC_FS
 #  ifndef PROC_FS_2325
 #    ifdef PROC_FS_21
-	proc_register(proc_net, &proc_net_pfkey);
-	proc_register(proc_net, &proc_net_pfkey_supported);
-	proc_register(proc_net, &proc_net_pfkey_registered);
+	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 */
-	proc_register_dynamic(&proc_net, &proc_net_pfkey);
-	proc_register_dynamic(&proc_net, &proc_net_pfkey_supported);
-	proc_register_dynamic(&proc_net, &proc_net_pfkey_registered);
+	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);
@@ -1611,28 +1682,32 @@
 {
 	int error = 0;
 	
-        printk(KERN_INFO "FreeS/WAN: shutting down PF_KEY domain sockets.\n");
+        printk(KERN_INFO "klips_info:pfkey_cleanup: "
+	       "shutting down PF_KEY domain sockets.\n");
 #ifdef NET_21
-        sock_unregister(PF_KEY);
+        error |= sock_unregister(PF_KEY);
 #else /* NET_21 */
-        sock_unregister(pfkey_proto_ops.family);
+        error |= sock_unregister(pfkey_proto_ops.family);
 #endif /* NET_21 */
 
-	supported_remove_all(SADB_SATYPE_AH);
-	supported_remove_all(SADB_SATYPE_ESP);
+	error |= supported_remove_all(SADB_SATYPE_AH);
+	error |= supported_remove_all(SADB_SATYPE_ESP);
 #ifdef CONFIG_IPSEC_IPCOMP
-	supported_remove_all(SADB_X_SATYPE_COMP);
+	error |= supported_remove_all(SADB_X_SATYPE_COMP);
 #endif /* CONFIG_IPSEC_IPCOMP */
-	supported_remove_all(SADB_X_SATYPE_IPIP);
+	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");
+		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");
+		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");
+		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");
@@ -1669,8 +1744,30 @@
 
 /*
  * $Log: pfkey_v2.c,v $
- * Revision 1.51.2.1  2001/02/27 00:51:01  henry
- * message improvements
+ * 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
diff -bruN freeswan-1.9.orig/klips/net/ipsec/pfkey_v2_parser.c freeswan-1.9/klips/net/ipsec/pfkey_v2_parser.c
--- freeswan-1.9.orig/klips/net/ipsec/pfkey_v2_parser.c	Mon Feb 26 19:51:01 2001
+++ freeswan-1.9/klips/net/ipsec/pfkey_v2_parser.c	Tue Jun 12 16:51:59 2001
@@ -12,14 +12,14 @@
  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  * for more details.
  *
- * RCSID $Id: pfkey_v2_parser.c,v 1.68.2.1 2001/02/27 00:51:01 henry Exp $
+ * RCSID $Id: pfkey_v2_parser.c,v 1.82 2001/05/30 08:14:04 rgb Exp $
  */
 
 /*
  *		Template from klips/net/ipsec/ipsec/ipsec_netlink.c.
  */
 
-char pfkey_v2_parser_c_version[] = "$Id: pfkey_v2_parser.c,v 1.68.2.1 2001/02/27 00:51:01 henry Exp $";
+char pfkey_v2_parser_c_version[] = "$Id: pfkey_v2_parser.c,v 1.82 2001/05/30 08:14:04 rgb Exp $";
 
 #include <linux/config.h>
 #include <linux/version.h>
@@ -94,13 +94,15 @@
 	int error = 0;
 	if(*tdb) {
 		KLIPS_PRINT(debug_pfkey,
-			    "klips_debug:pfkey_alloc_tdb: tdb struct already allocated\n");
+			    "klips_debug:pfkey_alloc_tdb: "
+			    "tdb struct already allocated\n");
 		SENDERR(EEXIST);
 	}
 
 	if((*tdb = kmalloc(sizeof(**tdb), GFP_ATOMIC) ) == NULL) {
 		KLIPS_PRINT(debug_pfkey,
-			    "klips_debug:pfkey_alloc_tdb: memory allocation error\n");
+			    "klips_debug:pfkey_alloc_tdb: "
+			    "memory allocation error\n");
 		SENDERR(ENOMEM);
 	}
 	KLIPS_PRINT(debug_pfkey,
@@ -118,13 +120,15 @@
 	int error = 0;
 	if(*eroute) {
 		KLIPS_PRINT(debug_pfkey,
-			    "klips_debug:pfkey_alloc_eroute: eroute struct already allocated\n");
+			    "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");
+			    "klips_debug:pfkey_alloc_eroute: "
+			    "memory allocation error\n");
 		SENDERR(ENOMEM);
 	}
 	KLIPS_PRINT(debug_pfkey,
@@ -137,6 +141,9 @@
 		(*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);
@@ -171,7 +178,8 @@
 		break;
 	default:
 		KLIPS_PRINT(debug_pfkey,
-			    "klips_debug:pfkey_sa_process: invalid exttype=%d.\n",
+			    "klips_debug:pfkey_sa_process: "
+			    "invalid exttype=%d.\n",
 			    pfkey_ext->sadb_ext_type);
 		SENDERR(EINVAL);
 	}
@@ -201,6 +209,10 @@
 		tdbp->tdb_encalg = pfkey_sa->sadb_sa_encrypt;
 		break;
 #endif /* CONFIG_IPSEC_IPCOMP */
+	case IPPROTO_INT:
+		tdbp->tdb_authalg = AH_NONE;
+		tdbp->tdb_encalg = ESP_NONE;
+		break;
 	case 0:
 		break;
 	default:
@@ -324,7 +336,8 @@
 		break;
 	default:
 		KLIPS_PRINT(debug_pfkey,
-			    "klips_debug: pfkey_lifetime_process: invalid exttype=%d.\n",
+			    "klips_debug:pfkey_lifetime_process: "
+			    "invalid exttype=%d.\n",
 			    pfkey_ext->sadb_ext_type);
 		SENDERR(EINVAL);
 	}
@@ -349,7 +362,7 @@
 	
 	if(!extr || !extr->tdb) {
 		KLIPS_PRINT(debug_pfkey,
-			    "klips_debug:pfkey_address_process:\n"
+			    "klips_debug:pfkey_address_process: "
 			    "extr or extr->tdb is NULL, fatal\n");
 		SENDERR(EINVAL);
 	}
@@ -359,8 +372,10 @@
 		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);
+			    "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:
@@ -369,7 +384,8 @@
 #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",
+			    "klips_debug:pfkey_address_process: "
+			    "s->sa_family=%d not supported.\n",
 			    s->sa_family);
 		SENDERR(EPFNOSUPPORT);
 	}
@@ -377,25 +393,29 @@
 	switch(pfkey_address->sadb_address_exttype) {
 	case SADB_EXT_ADDRESS_SRC:
 		KLIPS_PRINT(debug_pfkey,
-			    "klips_debug:pfkey_address_process: found src address.\n");
+			    "klips_debug:pfkey_address_process: "
+			    "found src address.\n");
 		sap = (unsigned char **)&(extr->tdb->tdb_addr_s);
 		extr->tdb->tdb_addr_s_size = saddr_len;
 		break;
 	case SADB_EXT_ADDRESS_DST:
 		KLIPS_PRINT(debug_pfkey,
-			    "klips_debug:pfkey_address_process: found dst address.\n");
+			    "klips_debug:pfkey_address_process: "
+			    "found dst address.\n");
 		sap = (unsigned char **)&(extr->tdb->tdb_addr_d);
 		extr->tdb->tdb_addr_d_size = saddr_len;
 		break;
 	case SADB_EXT_ADDRESS_PROXY:
 		KLIPS_PRINT(debug_pfkey,
-			    "klips_debug:pfkey_address_process: found proxy address.\n");
+			    "klips_debug:pfkey_address_process: "
+			    "found proxy address.\n");
 		sap = (unsigned char **)&(extr->tdb->tdb_addr_p);
 		extr->tdb->tdb_addr_p_size = saddr_len;
 		break;
 	case SADB_X_EXT_ADDRESS_DST2:
 		KLIPS_PRINT(debug_pfkey,
-			    "klips_debug:pfkey_address_process: found 2nd dst address.\n");
+			    "klips_debug:pfkey_address_process: "
+			    "found 2nd dst address.\n");
 		if(pfkey_alloc_tdb(&(extr->tdb2)) == ENOMEM) {
 			SENDERR(ENOMEM);
 		}
@@ -404,7 +424,8 @@
 		break;
 	case SADB_X_EXT_ADDRESS_SRC_FLOW:
 		KLIPS_PRINT(debug_pfkey,
-			    "klips_debug:pfkey_address_process: found src flow address.\n");
+			    "klips_debug:pfkey_address_process: "
+			    "found src flow address.\n");
 		if(pfkey_alloc_eroute(&(extr->eroute)) == ENOMEM) {
 			SENDERR(ENOMEM);
 		}
@@ -412,7 +433,8 @@
 		break;
 	case SADB_X_EXT_ADDRESS_DST_FLOW:
 		KLIPS_PRINT(debug_pfkey,
-			    "klips_debug:pfkey_address_process: found dst flow address.\n");
+			    "klips_debug:pfkey_address_process: "
+			    "found dst flow address.\n");
 		if(pfkey_alloc_eroute(&(extr->eroute)) == ENOMEM) {
 			SENDERR(ENOMEM);
 		}
@@ -420,7 +442,8 @@
 		break;
 	case SADB_X_EXT_ADDRESS_SRC_MASK:
 		KLIPS_PRINT(debug_pfkey,
-			    "klips_debug:pfkey_address_process: found src mask address.\n");
+			    "klips_debug:pfkey_address_process: "
+			    "found src mask address.\n");
 		if(pfkey_alloc_eroute(&(extr->eroute)) == ENOMEM) {
 			SENDERR(ENOMEM);
 		}
@@ -428,7 +451,8 @@
 		break;
 	case SADB_X_EXT_ADDRESS_DST_MASK:
 		KLIPS_PRINT(debug_pfkey,
-			    "klips_debug:pfkey_address_process: found dst mask address.\n");
+			    "klips_debug:pfkey_address_process: "
+			    "found dst mask address.\n");
 		if(pfkey_alloc_eroute(&(extr->eroute)) == ENOMEM) {
 			SENDERR(ENOMEM);
 		}
@@ -436,7 +460,8 @@
 		break;
 	default:
 		KLIPS_PRINT(debug_pfkey,
-			    "klips_debug:pfkey_address_process: unrecognised ext_type=%d.\n",
+			    "klips_debug:pfkey_address_process: "
+			    "unrecognised ext_type=%d.\n",
 			    pfkey_address->sadb_address_exttype);
 		SENDERR(EINVAL);
 	}
@@ -454,7 +479,8 @@
 	default:
 		if(s->sa_family	!= AF_INET) {
 			KLIPS_PRINT(debug_pfkey,
-				    "klips_debug:pfkey_address_process: s->sa_family=%d not supported.\n",
+				    "klips_debug:pfkey_address_process: "
+				    "s->sa_family=%d not supported.\n",
 				    s->sa_family);
 			SENDERR(EPFNOSUPPORT);
 		}
@@ -483,24 +509,26 @@
 	case SADB_EXT_ADDRESS_DST:
 		if(s->sa_family == AF_INET) {
 			tdbp->tdb_said.dst.s_addr = ((struct sockaddr_in*)(tdbp->tdb_addr_d))->sin_addr.s_addr;
+#if 0
 			KLIPS_PRINT(debug_pfkey,
-				    "klips_debug:pfkey_address_process: tdbp->tdb_said.dst.s_addr=%08x,\n"
-				    "klips_debug:                     ((struct sockaddr_in*)(tdbp->tdb_addr_d))->sin_addr.s_addr=%08x,\n",
+				    "klips_debug:pfkey_address_process: "
+				    "tdbp->tdb_said.dst.s_addr=%08x, ((struct sockaddr_in*)(tdbp->tdb_addr_d))->sin_addr.s_addr=%08x,\n",
 				    tdbp->tdb_said.dst.s_addr,
 				    ((struct sockaddr_in*)(tdbp->tdb_addr_d))->sin_addr.s_addr
 				);
+#endif
 			addrtoa(((struct sockaddr_in*)(tdbp->tdb_addr_d))->sin_addr,
 				0,
 				ipaddr_txt,
 				sizeof(ipaddr_txt));
 			KLIPS_PRINT(debug_pfkey,
-				    "klips_debug:pfkey_address_process: tdb_said.dst set to %s.\n",
+				    "klips_debug:pfkey_address_process: "
+				    "tdb_said.dst set to %s.\n",
 				    ipaddr_txt);
 		} else {
 			KLIPS_PRINT(debug_pfkey,
 				    "klips_debug:pfkey_address_process: "
-				    "uh, tdb_said.dst doesn't do address family=%d yet, "
-				    "said will be invalid.\n",
+				    "uh, tdb_said.dst doesn't do address family=%d yet, said will be invalid.\n",
 				    s->sa_family);
 		}
 	default:
@@ -532,33 +560,38 @@
 
         switch(pfkey_key->sadb_key_exttype) {
         case SADB_EXT_KEY_AUTH:
-                extr->tdb->tdb_key_bits_a = pfkey_key->sadb_key_bits;
 		if(!(extr->tdb->tdb_key_a = kmalloc(DIVUP(pfkey_key->sadb_key_bits, 8), GFP_KERNEL))) {
 			KLIPS_PRINT(debug_pfkey,
-				    "klips_debug:pfkey_key_process: memory allocation error.\n");
+				    "klips_debug:pfkey_key_process: "
+				    "memory allocation error.\n");
 			SENDERR(ENOMEM);
 		}
+                extr->tdb->tdb_key_bits_a = pfkey_key->sadb_key_bits;
+                extr->tdb->tdb_key_a_size = DIVUP(pfkey_key->sadb_key_bits, 8);
 		memcpy(extr->tdb->tdb_key_a,
 		       (char*)pfkey_key + sizeof(struct sadb_key),
-		       DIVUP(pfkey_key->sadb_key_bits, 8));
+		       extr->tdb->tdb_key_a_size);
 		break;
 	case SADB_EXT_KEY_ENCRYPT: /* Key(s) */
-		extr->tdb->tdb_key_bits_e = pfkey_key->sadb_key_bits;
 		if(!(extr->tdb->tdb_key_e = kmalloc(DIVUP(pfkey_key->sadb_key_bits, 8), GFP_KERNEL))) {
 			KLIPS_PRINT(debug_pfkey,
-				    "klips_debug:pfkey_key_process: memory allocation error.\n");
+				    "klips_debug:pfkey_key_process: "
+				    "memory allocation error.\n");
 			SENDERR(ENOMEM);
 		}
+		extr->tdb->tdb_key_bits_e = pfkey_key->sadb_key_bits;
+		extr->tdb->tdb_key_e_size = DIVUP(pfkey_key->sadb_key_bits, 8);
 		memcpy(extr->tdb->tdb_key_e,
 		       (char*)pfkey_key + sizeof(struct sadb_key),
-		       DIVUP(pfkey_key->sadb_key_bits, 8));
+		       extr->tdb->tdb_key_e_size);
 		break;
 	default:
 		SENDERR(EINVAL);
  	}
 
 	KLIPS_PRINT(debug_pfkey,
-		    "klips_debug:pfkey_key_process: success.\n");
+		    "klips_debug:pfkey_key_process: "
+		    "success.\n");
 errlab:
 	return error;
 }
@@ -629,7 +662,8 @@
         int error = 0;
 	
 	KLIPS_PRINT(debug_pfkey,
-		    "klips_debug: pfkey_sens_process: Sorry, I can't process exttype=%d yet.\n",
+		    "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:
@@ -642,7 +676,8 @@
         int error = 0;
 	
 	KLIPS_PRINT(debug_pfkey,
-		    "klips_debug: pfkey_prop_process: Sorry, I can't process exttype=%d yet.\n",
+		    "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 */
 	
@@ -656,7 +691,8 @@
         int error = 0;
 
 	KLIPS_PRINT(debug_pfkey,
-		    "klips_debug: pfkey_supported_process: Sorry, I can't process exttype=%d yet.\n",
+		    "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 */
 
@@ -670,7 +706,7 @@
         int error = 0;
 
 	KLIPS_PRINT(debug_pfkey,
-		    "klips_debug: pfkey_spirange_process: .\n");
+		    "klips_debug:pfkey_spirange_process: .\n");
 /* errlab: */
 	return error;
 }
@@ -681,7 +717,8 @@
 	int error = 0;
 
 	KLIPS_PRINT(debug_pfkey,
-		    "klips_debug: pfkey_x_kmprivate_process: Sorry, I can't process exttype=%d yet.\n",
+		    "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 */
 
@@ -696,11 +733,11 @@
 	struct sadb_x_satype *pfkey_x_satype = (struct sadb_x_satype *)pfkey_ext;
 
 	KLIPS_PRINT(debug_pfkey,
-		    "klips_debug: pfkey_x_satype_process: .\n");
+		    "klips_debug:pfkey_x_satype_process: .\n");
 
 	if(!extr || !extr->tdb) {
 		KLIPS_PRINT(debug_pfkey,
-			    "klips_debug: pfkey_x_satype_process: "
+			    "klips_debug:pfkey_x_satype_process: "
 			    "extr or extr->tdb is NULL, fatal\n");
 		SENDERR(EINVAL);
 	}
@@ -710,10 +747,17 @@
 	}
 	if(!(extr->tdb2->tdb_said.proto = satype2proto(pfkey_x_satype->sadb_x_satype_satype))) {
 		KLIPS_PRINT(debug_pfkey,
-			    "klips_debug: pfkey_x_satype_process: proto lookup from satype=%d failed.\n",
+			    "klips_debug:pfkey_x_satype_process: "
+			    "proto lookup from satype=%d failed.\n",
 			    pfkey_x_satype->sadb_x_satype_satype);
 		SENDERR(EINVAL);
 	}
+	KLIPS_PRINT(debug_pfkey,
+		    "klips_debug:pfkey_x_satype_process: "
+		    "protocol==%d decoded from satype==%d(%s).\n",
+		    extr->tdb2->tdb_said.proto,
+		    pfkey_x_satype->sadb_x_satype_satype,
+		    satype2name(pfkey_x_satype->sadb_x_satype_satype));
 
 errlab:
 	return error;
@@ -726,7 +770,8 @@
 	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");
+		printk("klips_debug:pfkey_x_debug_process: "
+		       "null pointer passed in\n");
 		SENDERR(EINVAL);
 	}
 
@@ -752,10 +797,8 @@
 			sysctl_ipsec_debug_ipcomp  |= pfkey_x_debug->sadb_x_debug_ipcomp;
 #endif /* CONFIG_IPSEC_IPCOMP */
 			sysctl_ipsec_debug_verbose |= pfkey_x_debug->sadb_x_debug_verbose;
-			if(debug_netlink)
 				printk(KERN_INFO "klips_debug:pfkey_x_debug_process: set\n");
 		} else {
-			if(debug_netlink)
 				printk(KERN_INFO "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;
@@ -773,7 +816,8 @@
 			sysctl_ipsec_debug_verbose &= pfkey_x_debug->sadb_x_debug_verbose;
 		}
 #else /* CONFIG_IPSEC_DEBUG */
-		printk("klips_debug:pfkey_x_debug_process: debugging not enabled\n");
+		printk("klips_debug:pfkey_x_debug_process: "
+		       "debugging not enabled\n");
 		SENDERR(EINVAL);
 #endif /* CONFIG_IPSEC_DEBUG */
 	
@@ -788,6 +832,7 @@
         int i;
         int error = 0;
         char sa[SATOA_BUF];
+	size_t sa_len;
 	char ipaddr_txt[ADDRTOA_BUF];
 	char ipaddr2_txt[ADDRTOA_BUF];
 	unsigned char kb[AHMD596_BLKLEN];
@@ -799,13 +844,16 @@
 		SENDERR(EINVAL);
 	}
 
-	satoa(tdbp->tdb_said, 0, sa, SATOA_BUF);
+	sa_len = satoa(tdbp->tdb_said, 0, sa, SATOA_BUF);
 
         KLIPS_PRINT(debug_pfkey,
-		    "klips_debug:pfkey_tdb_init: (pfkey defined) called for SA:%s\n", sa);
+		    "klips_debug:pfkey_tdb_init: "
+		    "(pfkey defined) called for SA:%s\n",
+		    sa_len ? sa : " (error)");
 
 	KLIPS_PRINT(debug_pfkey,
-		    "klips_debug:pfkey_tdb_init: calling init routine of %s%s%s\n",
+		    "klips_debug:pfkey_tdb_init: "
+		    "calling init routine of %s%s%s\n",
 		    TDB_XFORM_NAME(tdbp));
 	
 	switch(tdbp->tdb_said.proto) {
@@ -832,20 +880,22 @@
 # ifdef CONFIG_IPSEC_AUTH_HMAC_MD5
 		case AH_MD5: {
 			unsigned char *akp;
+			unsigned int aks;
 			MD5_CTX *ictx;
 			MD5_CTX *octx;
 			
 			if(tdbp->tdb_key_bits_a != (AHMD596_KLEN * 8)) {
 				KLIPS_PRINT(debug_pfkey,
-					    "klips_debug:pfkey_tdb_init: incorrect key size: %d bits"
-					    "-- must be %d bits\n"/*octets (bytes)\n"*/,
+					    "klips_debug:pfkey_tdb_init: "
+					    "incorrect key size: %d bits -- must be %d bits\n"/*octets (bytes)\n"*/,
 					    tdbp->tdb_key_bits_a, AHMD596_KLEN * 8);
 				SENDERR(EINVAL);
 			}
 			
 #  if 0 /* we don't really want to print these unless there are really big problems */
 			KLIPS_PRINT(debug_pfkey && sysctl_ipsec_debug_verbose,
-					    "klips_debug:pfkey_tdb_init: hmac md5-96 key is 0x%08lx %08lx %08lx %08lx\n",
+				    "klips_debug:pfkey_tdb_init: "
+				    "hmac md5-96 key is 0x%08lx %08lx %08lx %08lx\n",
 				    ntohl(*(((__u32 *)tdbp->tdb_key_a)+0)),
 				    ntohl(*(((__u32 *)tdbp->tdb_key_a)+1)),
 				    ntohl(*(((__u32 *)tdbp->tdb_key_a)+2)),
@@ -856,12 +906,14 @@
 			
 			/* save the pointer to the key material */
 			akp = tdbp->tdb_key_a;
+			aks = tdbp->tdb_key_a_size;
 			
 			if((tdbp->tdb_key_a = (caddr_t)
-			    kmalloc((tdbp->tdb_key_a_size = sizeof(struct md5_ctx)),
-				    GFP_ATOMIC)) == NULL) {
+			    kmalloc(sizeof(struct md5_ctx), GFP_ATOMIC)) == NULL) {
+				tdbp->tdb_key_a = akp;
 				SENDERR(ENOMEM);
 			}
+			tdbp->tdb_key_a_size = sizeof(struct md5_ctx);
 
 			for (i = 0; i < DIVUP(tdbp->tdb_key_bits_a, 8); i++) {
 				kb[i] = akp[i] ^ HMAC_IPAD;
@@ -884,8 +936,8 @@
 			
 #  if 0 /* we don't really want to print these unless there are really big problems */
 			KLIPS_PRINT(debug_pfkey && sysctl_ipsec_debug_verbose,
-				    "klips_debug:pfkey_tdb_init: MD5 ictx=0x%08x %08x %08x %08x"
-				    " octx=0x%08x %08x %08x %08x\n",
+				    "klips_debug:pfkey_tdb_init: "
+				    "MD5 ictx=0x%08x %08x %08x %08x octx=0x%08x %08x %08x %08x\n",
 				    ((__u32*)ictx)[0],
 				    ((__u32*)ictx)[1],
 				    ((__u32*)ictx)[2],
@@ -897,28 +949,30 @@
 #  endif
 			
 				/* zero key buffer -- paranoid */
-			memset(akp, 0, DIVUP(tdbp->tdb_key_bits_a, BITS_PER_OCTET));
+			memset(akp, 0, aks);
+			kfree(akp);
 		}
 		break;
 # endif /* CONFIG_IPSEC_AUTH_HMAC_MD5 */
 # ifdef CONFIG_IPSEC_AUTH_HMAC_SHA1
 		case AH_SHA: {
-			
 			unsigned char *akp;
+			unsigned int aks;
 			SHA1_CTX *ictx;
 			SHA1_CTX *octx;
 			
 			if(tdbp->tdb_key_bits_a != (AHSHA196_KLEN * 8)) {
 				KLIPS_PRINT(debug_pfkey,
-					    "klips_debug:pfkey_tdb_init: incorrect key size: %d bits"
-					    "-- must be %d bits\n"/*octets (bytes)\n"*/,
+					    "klips_debug:pfkey_tdb_init: "
+					    "incorrect key size: %d bits -- must be %d bits\n"/*octets (bytes)\n"*/,
 					    tdbp->tdb_key_bits_a, AHSHA196_KLEN * 8);
 				SENDERR(EINVAL);
 			}
 			
 #  if 0 /* we don't really want to print these unless there are really big problems */
 			KLIPS_PRINT(debug_pfkey && sysctl_ipsec_debug_verbose,
-				    "klips_debug:pfkey_tdb_init: hmac sha1-96 key is 0x%08lx %08lx %08lx %08lx\n",
+				    "klips_debug:pfkey_tdb_init: "
+				    "hmac sha1-96 key is 0x%08lx %08lx %08lx %08lx\n",
 				    ntohl(*(((__u32 *)tdbp->tdb_key_a)+0)),
 				    ntohl(*(((__u32 *)tdbp->tdb_key_a)+1)),
 				    ntohl(*(((__u32 *)tdbp->tdb_key_a)+2)),
@@ -929,12 +983,14 @@
 			
 			/* save the pointer to the key material */
 			akp = tdbp->tdb_key_a;
+			aks = tdbp->tdb_key_a_size;
 			
 			if((tdbp->tdb_key_a = (caddr_t)
-			    kmalloc((tdbp->tdb_key_a_size = sizeof(struct sha1_ctx)),
-				    GFP_ATOMIC)) == NULL) {
+			    kmalloc(sizeof(struct sha1_ctx), GFP_ATOMIC)) == NULL) {
+				tdbp->tdb_key_a = akp;
 				SENDERR(ENOMEM);
 			}
+			tdbp->tdb_key_a_size = sizeof(struct sha1_ctx);
 			
 			for (i = 0; i < DIVUP(tdbp->tdb_key_bits_a, 8); i++) {
 				kb[i] = akp[i] ^ HMAC_IPAD;
@@ -957,8 +1013,8 @@
 			
 #  if 0 /* we don't really want to print these unless there are really big problems */
 			KLIPS_PRINT(debug_pfkey && sysctl_ipsec_debug_verbose,
-				    "klips_debug:pfkey_tdb_init: SHA1 ictx=0x%08x %08x %08x %08x"
-				    " octx=0x%08x %08x %08x %08x\n", 
+				    "klips_debug:pfkey_tdb_init: "
+				    "SHA1 ictx=0x%08x %08x %08x %08x octx=0x%08x %08x %08x %08x\n", 
 				    ((__u32*)ictx)[0],
 				    ((__u32*)ictx)[1],
 				    ((__u32*)ictx)[2],
@@ -969,7 +1025,8 @@
 				    ((__u32*)octx)[3] );
 #  endif			
 				/* zero key buffer -- paranoid */
-			memset(akp, 0, DIVUP(tdbp->tdb_key_bits_a, BITS_PER_OCTET));
+			memset(akp, 0, aks);
+			kfree(akp);
 		}
 		break;
 # endif /* CONFIG_IPSEC_AUTH_HMAC_SHA1 */
@@ -985,12 +1042,16 @@
 #ifdef CONFIG_IPSEC_ESP
 	case IPPROTO_ESP: {
 		unsigned char *akp, *ekp;
+		unsigned int aks, eks;
 		
 		switch(tdbp->tdb_encalg) {
-# ifdef CONFIG_IPSEC_ENC_3DES
+#ifdef CONFIG_IPSEC_ENC_DES
+		case ESP_DES:
+#endif /* CONFIG_IPSEC_ENC_DES */
+#ifdef CONFIG_IPSEC_ENC_3DES
 		case ESP_3DES:
-# endif /* CONFIG_IPSEC_ENC_3DES */
-# if defined(CONFIG_IPSEC_ENC_3DES)
+#endif /* CONFIG_IPSEC_ENC_3DES */
+#if defined(CONFIG_IPSEC_ENC_DES) || defined(CONFIG_IPSEC_ENC_3DES)
 			if((tdbp->tdb_iv = (caddr_t)
 			    kmalloc((tdbp->tdb_iv_size = EMT_ESPDES_IV_SZ), GFP_ATOMIC)) == NULL) {
 				SENDERR(ENOMEM);
@@ -998,11 +1059,8 @@
 			get_random_bytes((void *)tdbp->tdb_iv, EMT_ESPDES_IV_SZ);
 			tdbp->tdb_iv_bits = tdbp->tdb_iv_size * 8;
 			break;
-# endif /* defined(CONFIG_IPSEC_ENC_3DES) */
+#endif /* defined(CONFIG_IPSEC_ENC_DES) || defined(CONFIG_IPSEC_ENC_3DES) */
 		case ESP_NONE:
-# ifdef CONFIG_IPSEC_ENC_NULL
-		case ESP_NULL:
-# endif /* CONFIG_IPSEC_ENC_NULL */
 			break;
 		default:
 			KLIPS_PRINT(debug_pfkey,
@@ -1013,55 +1071,103 @@
 		}
 		
 		switch(tdbp->tdb_encalg) {
-# ifdef CONFIG_IPSEC_ENC_3DES
+#ifdef CONFIG_IPSEC_ENC_DES
+		case ESP_DES:
+			if(tdbp->tdb_key_bits_e != (EMT_ESPDES_KEY_SZ * 8)) {
+				KLIPS_PRINT(debug_pfkey,
+					    "klips_debug:pfkey_tdb_init: "
+					    "incorrect encryption key size: %d bits -- must be %d bits\n"/*octets (bytes)\n"*/,
+					    tdbp->tdb_key_bits_e, EMT_ESPDES_KEY_SZ * 8);
+				SENDERR(EINVAL);
+			}
+			
+			/* save encryption key pointer */
+			ekp = tdbp->tdb_key_e;
+			eks = tdbp->tdb_key_e_size;
+			
+			if((tdbp->tdb_key_e = (caddr_t)
+			    kmalloc(sizeof(struct des_eks), GFP_ATOMIC)) == NULL) {
+				tdbp->tdb_key_e = ekp;
+				SENDERR(ENOMEM);
+			}
+			tdbp->tdb_key_e_size = sizeof(struct des_eks);
+
+#if 0 /* we don't really want to print these unless there are really big problems */
+                       KLIPS_PRINT(debug_pfkey,
+                                   "klips_debug:pfkey_tdb_init: des key 1 is 0x%08lx%08lx\n",
+                                   ntohl(*((__u32 *)ed->eme_key)),
+                                   ntohl(*((__u32 *)ed->eme_key + 1)));
+#endif
+			error = des_set_key((caddr_t)ekp, 
+					    (caddr_t)(tdbp->tdb_key_e));
+			if (error == -1)
+					printk("klips_debug:pfkey_tdb_init: "
+					       "parity error in des key\n");
+				else if (error == -2)
+					printk("klips_debug:pfkey_tdb_init: "
+					       "illegal weak des key\n");
+				if (error) {
+					memset(ekp, 0, eks);
+					kfree(ekp);
+					SENDERR(EINVAL);
+				}
+
+			/* paranoid */
+			memset(ekp, 0, eks);
+			kfree(ekp);
+			break;
+#endif /* CONFIG_IPSEC_ENC_DES */
+#ifdef CONFIG_IPSEC_ENC_3DES
 		case ESP_3DES:
 			if(tdbp->tdb_key_bits_e != (EMT_ESP3DES_KEY_SZ * 8)) {
 				KLIPS_PRINT(debug_pfkey,
-					    "klips_debug:pfkey_tdb_init: incorrect encryption"
-					    "key size: %d bits -- must be %d bits\n"/*octets (bytes)\n"*/,
+					    "klips_debug:pfkey_tdb_init: "
+					    "incorrect encryption key size: %d bits -- must be %d bits\n"/*octets (bytes)\n"*/,
 					    tdbp->tdb_key_bits_e, EMT_ESP3DES_KEY_SZ * 8);
 				SENDERR(EINVAL);
 			}
 			
 			/* save encryption key pointer */
 			ekp = tdbp->tdb_key_e;
+			eks = tdbp->tdb_key_e_size;
 			
 			if((tdbp->tdb_key_e = (caddr_t)
-			    kmalloc((tdbp->tdb_key_e_size = 3 * sizeof(struct des_eks)),
-				    GFP_ATOMIC)) == NULL) {
+			    kmalloc(3 * sizeof(struct des_eks), GFP_ATOMIC)) == NULL) {
+				tdbp->tdb_key_e = ekp;
 				SENDERR(ENOMEM);
 			}
+			tdbp->tdb_key_e_size = 3 * sizeof(struct des_eks);
 			
 			for(i = 0; i < 3; i++) {
-#  if 0 /* we don't really want to print these unless there are really big problems */
+#if 0 /* we don't really want to print these unless there are really big problems */
 				KLIPS_PRINT(debug_pfkey && sysctl_ipsec_debug_verbose,
-					    "klips_debug:pfkey_tdb_init: 3des key %d/3 is 0x%08lx%08lx\n",
+					    "klips_debug:pfkey_tdb_init: "
+					    "3des key %d/3 is 0x%08lx%08lx\n",
 					    i + 1,
-					    ntohl(*((__u32 *)tdbp->tdb_key_e + i * 2)),
-					    ntohl(*((__u32 *)tdbp->tdb_key_e + i * 2 + 1)));
-#  endif
+					    ntohl(*((__u32 *)ekp + i * 2)),
+					    ntohl(*((__u32 *)ekp + i * 2 + 1)));
+#endif
 				error = des_set_key((caddr_t)ekp + EMT_ESPDES_KEY_SZ * i,
 						    (caddr_t)&((struct des_eks*)(tdbp->tdb_key_e))[i]);
 				if (error == -1)
-					printk("klips_debug:pfkey_tdb_init: parity error in des key %d/3\n", i + 1);
+					printk("klips_debug:pfkey_tdb_init: "
+					       "parity error in des key %d/3\n",
+					       i + 1);
 				else if (error == -2)
-					printk("klips_debug:pfkey_tdb_init: illegal weak des key %d/3\n", i + 1);
+					printk("klips_debug:pfkey_tdb_init: "
+					       "illegal weak des key %d/3\n", i + 1);
 				if (error) {
-					memset(tdbp->tdb_key_e, 0, 3 * sizeof(struct des_eks));
-					kfree(tdbp->tdb_key_e);
-					memset(ekp, 0, DIVUP(tdbp->tdb_key_bits_e, BITS_PER_OCTET));
+					memset(ekp, 0, eks);
+					kfree(ekp);
 					SENDERR(EINVAL);
 				}
 			}
 
 			/* paranoid */
-			memset(ekp, 0, DIVUP(tdbp->tdb_key_bits_e, BITS_PER_OCTET));
-			
+			memset(ekp, 0, eks);
+			kfree(ekp);
 			break;
-# endif /* CONFIG_IPSEC_ENC_3DES */
-# ifdef CONFIG_IPSEC_ENC_NULL
-		case ESP_NULL:
-# endif /* CONFIG_IPSEC_ENC_NULL */
+#endif /* CONFIG_IPSEC_ENC_3DES */
 		case ESP_NONE:
 			break;
 		default:
@@ -1073,37 +1179,41 @@
 		}
 		
 		switch(tdbp->tdb_authalg) {
-# ifdef CONFIG_IPSEC_AUTH_HMAC_MD5
+#ifdef CONFIG_IPSEC_AUTH_HMAC_MD5
 		case AH_MD5: {
 			MD5_CTX *ictx;
 			MD5_CTX *octx;
 
 			if(tdbp->tdb_key_bits_a != (AHMD596_KLEN * 8)) {
 				KLIPS_PRINT(debug_pfkey,
-					    "klips_debug:pfkey_tdb_init: incorrect authorisation"
-					    " key size: %d bits -- must be %d bits\n"/*octets (bytes)\n"*/,
-					    tdbp->tdb_key_bits_a, AHMD596_KLEN * 8);
+					    "klips_debug:pfkey_tdb_init: "
+					    "incorrect authorisation key size: %d bits -- must be %d bits\n"/*octets (bytes)\n"*/,
+					    tdbp->tdb_key_bits_a,
+					    AHMD596_KLEN * 8);
 				SENDERR(EINVAL);
 			}
 			
-#  if 0 /* we don't really want to print these unless there are really big problems */
+#if 0 /* we don't really want to print these unless there are really big problems */
 			KLIPS_PRINT(debug_pfkey && sysctl_ipsec_debug_verbose,
-				    "klips_debug:pfkey_tdb_init: hmac md5-96 key is 0x%08lx %08lx %08lx %08lx\n",
+				    "klips_debug:pfkey_tdb_init: "
+				    "hmac md5-96 key is 0x%08lx %08lx %08lx %08lx\n",
 				    ntohl(*(((__u32 *)(tdbp->tdb_key_a))+0)),
 				    ntohl(*(((__u32 *)(tdbp->tdb_key_a))+1)),
 				    ntohl(*(((__u32 *)(tdbp->tdb_key_a))+2)),
 				    ntohl(*(((__u32 *)(tdbp->tdb_key_a))+3)));
-#  endif
+#endif
 			tdbp->tdb_auth_bits = AHMD596_ALEN * 8;
 			
 			/* save the pointer to the key material */
 			akp = tdbp->tdb_key_a;
+			aks = tdbp->tdb_key_a_size;
 			
 			if((tdbp->tdb_key_a = (caddr_t)
-			    kmalloc((tdbp->tdb_key_a_size = sizeof(struct md5_ctx)),
-				    GFP_ATOMIC)) == NULL) {
+			    kmalloc(sizeof(struct md5_ctx), GFP_ATOMIC)) == NULL) {
+				tdbp->tdb_key_a = akp;
 				SENDERR(ENOMEM);
 			}
+			tdbp->tdb_key_a_size = sizeof(struct md5_ctx);
 			
 			for (i = 0; i < DIVUP(tdbp->tdb_key_bits_a, 8); i++) {
 				kb[i] = akp[i] ^ HMAC_IPAD;
@@ -1126,8 +1236,8 @@
 			
 #  if 0 /* we don't really want to print these unless there are really big problems */
 			KLIPS_PRINT(debug_pfkey && sysctl_ipsec_debug_verbose,
-				    "klips_debug:pfkey_tdb_init: MD5 ictx=0x%08x %08x %08x %08x"
-				    " octx=0x%08x %08x %08x %08x\n",
+				    "klips_debug:pfkey_tdb_init: "
+				    "MD5 ictx=0x%08x %08x %08x %08x octx=0x%08x %08x %08x %08x\n",
 				    ((__u32*)ictx)[0],
 				    ((__u32*)ictx)[1],
 				    ((__u32*)ictx)[2],
@@ -1138,7 +1248,8 @@
 				    ((__u32*)octx)[3] );
 #  endif
 			/* paranoid */
-			memset(akp, 0, DIVUP(tdbp->tdb_key_bits_a, BITS_PER_OCTET));
+			memset(akp, 0, aks);
+			kfree(akp);
 			break;
 		}
 # endif /* CONFIG_IPSEC_AUTH_HMAC_MD5 */
@@ -1149,15 +1260,17 @@
 
 			if(tdbp->tdb_key_bits_a != (AHSHA196_KLEN * 8)) {
 				KLIPS_PRINT(debug_pfkey,
-					    "klips_debug:pfkey_tdb_init: incorrect authorisation"
-					    " key size: %d bits -- must be %d bits\n"/*octets (bytes)\n"*/,
-					    tdbp->tdb_key_bits_a, AHSHA196_KLEN * 8);
+					    "klips_debug:pfkey_tdb_init: "
+					    "incorrect authorisation key size: %d bits -- must be %d bits\n"/*octets (bytes)\n"*/,
+					    tdbp->tdb_key_bits_a,
+					    AHSHA196_KLEN * 8);
 				SENDERR(EINVAL);
 			}
 			
 #  if 0 /* we don't really want to print these unless there are really big problems */
 			KLIPS_PRINT(debug_pfkey && sysctl_ipsec_debug_verbose,
-				    "klips_debug:pfkey_tdb_init: hmac sha1-96 key is 0x%08lx %08lx %08lx %08lx\n",
+				    "klips_debug:pfkey_tdb_init: "
+				    "hmac sha1-96 key is 0x%08lx %08lx %08lx %08lx\n",
 				    ntohl(*(((__u32 *)tdbp->tdb_key_a)+0)),
 				    ntohl(*(((__u32 *)tdbp->tdb_key_a)+1)),
 				    ntohl(*(((__u32 *)tdbp->tdb_key_a)+2)),
@@ -1167,12 +1280,14 @@
 			
 			/* save the pointer to the key material */
 			akp = tdbp->tdb_key_a;
+			aks = tdbp->tdb_key_a_size;
 
 			if((tdbp->tdb_key_a = (caddr_t)
-			    kmalloc((tdbp->tdb_key_a_size = sizeof(struct sha1_ctx)),
-				    GFP_ATOMIC)) == NULL) {
+			    kmalloc(sizeof(struct sha1_ctx), GFP_ATOMIC)) == NULL) {
+				tdbp->tdb_key_a = akp;
 				SENDERR(ENOMEM);
 			}
+			tdbp->tdb_key_a_size = sizeof(struct sha1_ctx);
 			
 			for (i = 0; i < DIVUP(tdbp->tdb_key_bits_a, 8); i++) {
 				kb[i] = akp[i] ^ HMAC_IPAD;
@@ -1195,8 +1310,8 @@
 			
 #  if 0 /* we don't really want to print these unless there are really big problems */
 			KLIPS_PRINT(debug_pfkey && sysctl_ipsec_debug_verbose,
-				    "klips_debug:pfkey_tdb_init: SHA1 ictx=0x%08x %08x %08x %08x"
-				    " octx=0x%08x %08x %08x %08x\n",
+				    "klips_debug:pfkey_tdb_init: "
+				    "SHA1 ictx=0x%08x %08x %08x %08x octx=0x%08x %08x %08x %08x\n",
 				    ((__u32*)ictx)[0],
 				    ((__u32*)ictx)[1],
 				    ((__u32*)ictx)[2],
@@ -1206,7 +1321,8 @@
 				    ((__u32*)octx)[2],
 				    ((__u32*)octx)[3] );
 #  endif
-			memset(akp, 0, DIVUP(tdbp->tdb_key_bits_a, BITS_PER_OCTET));
+			memset(akp, 0, aks);
+			kfree(akp);
 			break;
 		}
 # endif /* CONFIG_IPSEC_AUTH_HMAC_SHA1 */
@@ -1246,14 +1362,17 @@
 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);
+	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);
+			    "caught error %d\n",
+			    error);
 		pfkey_extensions_free(extensions);
 		return 0;
 	}
@@ -1268,6 +1387,7 @@
 	int found_avail = 0;
 	struct tdb *tdbq;
 	char sa[SATOA_BUF];
+	size_t sa_len;
 	struct sadb_ext *extensions_reply[SADB_EXT_MAX+1];
 	struct sadb_msg *pfkey_reply = NULL;
 	struct socket_list *pfkey_socketsp;
@@ -1280,7 +1400,8 @@
 
 	if(!extr || !extr->tdb) {
 		KLIPS_PRINT(debug_pfkey,
-			    "klips_debug:pfkey_getspi_parse: error, extr or extr->tdb pointer NULL\n");
+			    "klips_debug:pfkey_getspi_parse: "
+			    "error, extr or extr->tdb pointer NULL\n");
 		SENDERR(EINVAL);
 	}
 
@@ -1292,10 +1413,11 @@
 	if(maxspi == minspi) {
 		extr->tdb->tdb_said.spi = maxspi;
 		if((tdbq = gettdb(&(extr->tdb->tdb_said)))) {
-			satoa(extr->tdb->tdb_said, 0, sa, SATOA_BUF);
+			sa_len = satoa(extr->tdb->tdb_said, 0, sa, SATOA_BUF);
 			KLIPS_PRINT(debug_pfkey,
-				    "klips_debug: pfkey_getspi_parse: EMT_GETSPI found an old Tunnel Descriptor Block\n"
-				    "klips_debug:                for SA: %s, delete it first.\n", sa);
+				    "klips_debug:pfkey_getspi_parse: "
+				    "EMT_GETSPI found an old Tunnel Descriptor Block for SA: %s, delete it first.\n",
+				    sa_len ? sa : " (error)");
 			SENDERR(EEXIST);
 		} else {
 			found_avail = 1;
@@ -1322,12 +1444,13 @@
 		}
 	}
 
-	satoa(extr->tdb->tdb_said, 0, sa, SATOA_BUF);
+	sa_len = satoa(extr->tdb->tdb_said, 0, sa, SATOA_BUF);
 
 	if (!found_avail) {
 		KLIPS_PRINT(debug_pfkey,
-			    "klips_debug: pfkey_getspi_parse: found an old Tunnel Descriptor Block\n"
-			    "klips_debug:                for SA: %s, delete it first.\n", sa);
+			    "klips_debug:pfkey_getspi_parse: "
+			    "found an old Tunnel Descriptor Block for SA: %s, delete it first.\n",
+			    sa_len ? sa : " (error)");
 		SENDERR(EEXIST);
 	}
 
@@ -1336,9 +1459,10 @@
 	}
 
 	KLIPS_PRINT(debug_pfkey,
-		    "klips_debug: pfkey_getspi_parse: existing Tunnel Descriptor Block not found (this\n"
-		    "klips_debug:                is good) for SA: %s, %s-bound, allocating.\n",
-		    sa, extr->tdb->tdb_flags & EMT_INBOUND ? "in" : "out");
+		    "klips_debug:pfkey_getspi_parse: "
+		    "existing Tunnel Descriptor Block not found (this is good) for SA: %s, %s-bound, allocating.\n",
+		    sa_len ? sa : " (error)",
+		    extr->tdb->tdb_flags & EMT_INBOUND ? "in" : "out");
 	
 	/* XXX extr->tdb->tdb_rcvif = &(enc_softc[em->em_if].enc_if);*/
 	extr->tdb->tdb_rcvif = NULL;
@@ -1357,7 +1481,7 @@
 							  ((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(pfkey_sa_build(&extensions_reply[SADB_EXT_SA],
+	     && pfkey_safe_build(error = pfkey_sa_build(&extensions_reply[SADB_EXT_SA],
 						SADB_EXT_SA,
 						extr->tdb->tdb_said.spi,
 						0,
@@ -1366,13 +1490,13 @@
 						0,
 						0),
 				 extensions_reply)
-	     && pfkey_safe_build(pfkey_address_build(&extensions_reply[SADB_EXT_ADDRESS_SRC],
+	     && pfkey_safe_build(error = pfkey_address_build(&extensions_reply[SADB_EXT_ADDRESS_SRC],
 						     SADB_EXT_ADDRESS_SRC,
 						     0, /*extr->tdb->tdb_said.proto,*/
 						     0,
 						     extr->tdb->tdb_addr_s),
 				 extensions_reply)
-	     && pfkey_safe_build(pfkey_address_build(&extensions_reply[SADB_EXT_ADDRESS_DST],
+	     && pfkey_safe_build(error = pfkey_address_build(&extensions_reply[SADB_EXT_ADDRESS_DST],
 						     SADB_EXT_ADDRESS_DST,
 						     0, /*extr->tdb->tdb_said.proto,*/
 						     0,
@@ -1387,29 +1511,37 @@
 		KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_getspi_parse: "
 			    "failed to add the larval SA with error=%d.\n",
 			    error);
-		goto errlab;
+		SENDERR(-error);
 	}
+	extr->tdb = NULL;
 	
 	KLIPS_PRINT(debug_pfkey,
-		    "klips_debug:pfkey_getspi_parse: successful for SA: %s\n", sa);
+		    "klips_debug:pfkey_getspi_parse: "
+		    "successful for SA: %s\n",
+		    sa_len ? sa : " (error)");
 	
 	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");
-		goto errlab;
+		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 to socket=%p failed with error=%d.\n",
-				    satype, pfkey_socketsp->socketp, error);
-			goto errlab;
+				    "sending up getspi reply message for satype=%d(%s) to socket=%p failed with error=%d.\n",
+				    satype,
+				    satype2name(satype),
+				    pfkey_socketsp->socketp,
+				    error);
+			SENDERR(-error);
 		}
 		KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_getspi_parse: "
-			    "sending up getspi reply message for satype=%d to socket=%p succeeded.\n",
-			    satype, pfkey_socketsp->socketp);
+			    "sending up getspi reply message for satype=%d(%s) to socket=%p succeeded.\n",
+			    satype,
+			    satype2name(satype),
+			    pfkey_socketsp->socketp);
 	}
 
  errlab:
@@ -1426,6 +1558,7 @@
 	int error = 0;
 	struct tdb* tdbq;
 	char sa[SATOA_BUF];
+	size_t sa_len;
 	struct sadb_ext *extensions_reply[SADB_EXT_MAX+1];
 	struct sadb_msg *pfkey_reply = NULL;
 	struct socket_list *pfkey_socketsp;
@@ -1447,11 +1580,12 @@
 
 	if(!extr || !extr->tdb) {
 		KLIPS_PRINT(debug_pfkey,
-			    "klips_debug:pfkey_update_parse: error, extr or extr->tdb pointer NULL\n");
+			    "klips_debug:pfkey_update_parse: "
+			    "error, extr or extr->tdb pointer NULL\n");
 		SENDERR(EINVAL);
 	}
 
-	satoa(extr->tdb->tdb_said, 0, sa, SATOA_BUF);
+	sa_len = satoa(extr->tdb->tdb_said, 0, sa, SATOA_BUF);
 
 	spin_lock_bh(&tdb_lock);
 
@@ -1459,8 +1593,9 @@
 	if (!tdbq) {
 		spin_unlock_bh(&tdb_lock);
 		KLIPS_PRINT(debug_pfkey,
-			    "klips_debug: pfkey_update_parse: reserved Tunnel Descriptor Block\n"
-			    "klips_debug:            for SA: %s not found.  Call SADB_GETSPI first or call SADB_ADD instead.\n", sa);
+			    "klips_debug:pfkey_update_parse: "
+			    "reserved Tunnel Descriptor Block for SA: %s not found.  Call SADB_GETSPI first or call SADB_ADD instead.\n",
+			    sa_len ? sa : " (error)");
 		SENDERR(EEXIST);
 	}
 
@@ -1469,9 +1604,10 @@
 	}
 
 	KLIPS_PRINT(debug_pfkey,
-		    "klips_debug: pfkey_update_parse: existing Tunnel Descriptor Block found (this\n"
-		    "klips_debug:                is good) for SA: %s, %s-bound, updating.\n",
-		    sa, extr->tdb->tdb_flags & EMT_INBOUND ? "in" : "out");
+		    "klips_debug:pfkey_update_parse: "
+		    "existing Tunnel Descriptor Block found (this is good) for SA: %s, %s-bound, updating.\n",
+		    sa_len ? sa : " (error)",
+		    extr->tdb->tdb_flags & EMT_INBOUND ? "in" : "out");
 	
 	/* XXX extr->tdb->tdb_rcvif = &(enc_softc[em->em_if].enc_if);*/
 	extr->tdb->tdb_rcvif = NULL;
@@ -1479,8 +1615,8 @@
 		spin_unlock_bh(&tdb_lock);
 		KLIPS_PRINT(debug_pfkey,
 			    "klips_debug:pfkey_update_parse: "
-			    "not successful for SA: %s, deleting.\n", sa);
-		ipsec_tdbwipe(extr->tdb);
+			    "not successful for SA: %s, deleting.\n",
+			    sa_len ? sa : " (error)");
 		SENDERR(-error);
 	}
 
@@ -1490,7 +1626,8 @@
 		KLIPS_PRINT(debug_pfkey,
 			    "klips_debug:pfkey_update_parse: "
 			    "error=%d, trouble deleting intermediate tdb for SA=%s.\n",
-			    error, sa);
+			    error,
+			    sa_len ? sa : " (error)");
 		SENDERR(-error);
 	}
 
@@ -1587,36 +1724,45 @@
 		)) {
 		KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_update_parse: "
 			    "failed to build the update reply message extensions\n");
-		goto errlab;
+		SENDERR(-error);
 	}
 		
 	if((error = puttdb(extr->tdb))) {
 		KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_update_parse: "
-			    "failed to add the mature SA with error=%d.\n",
+			    "failed to update the mature SA=%s with error=%d.\n",
+			    sa_len ? sa : " (error)",
 			    error);
-		goto errlab;
+		SENDERR(-error);
 	}
+	extr->tdb = NULL;
 	
 	KLIPS_PRINT(debug_pfkey,
-		    "klips_debug:pfkey_update_parse: successful for SA: %s\n", sa);
+		    "klips_debug:pfkey_update_parse: "
+		    "successful for SA: %s\n",
+		    sa_len ? sa : " (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");
-		goto errlab;
+		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 to socket=%p failed with error=%d.\n",
-				    satype, pfkey_socketsp->socketp, error);
-			goto errlab;
+				    "sending up update reply message for satype=%d(%s) to socket=%p failed with error=%d.\n",
+				    satype,
+				    satype2name(satype),
+				    pfkey_socketsp->socketp,
+				    error);
+			SENDERR(-error);
 		}
 		KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_update_parse: "
-			    "sending up update reply message for satype=%d to socket=%p succeeded.\n",
-			    satype, pfkey_socketsp->socketp);
+			    "sending up update reply message for satype=%d(%s) to socket=%p succeeded.\n",
+			    satype,
+			    satype2name(satype),
+			    pfkey_socketsp->socketp);
 	}
 	
  errlab:
@@ -1633,13 +1779,14 @@
 	int error = 0;
 	struct tdb* tdbq;
 	char sa[SATOA_BUF];
+	size_t sa_len;
 	struct sadb_ext *extensions_reply[SADB_EXT_MAX+1];
 	struct sadb_msg *pfkey_reply = NULL;
 	struct socket_list *pfkey_socketsp;
 	uint8_t satype = ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_satype;
 
 	KLIPS_PRINT(debug_pfkey,
-		    "klips_debug:pfkey_add_parse: parsing add message\n");
+		    "klips_debug:pfkey_add_parse: .\n");
 
 	pfkey_extensions_init(extensions_reply);
 
@@ -1654,17 +1801,19 @@
 
 	if(!extr || !extr->tdb) {
 		KLIPS_PRINT(debug_pfkey,
-			    "klips_debug:pfkey_add_parse: extr or extr->tdb pointer NULL\n");
+			    "klips_debug:pfkey_add_parse: "
+			    "extr or extr->tdb pointer NULL\n");
 		SENDERR(EINVAL);
 	}
 
-	satoa(extr->tdb->tdb_said, 0, sa, SATOA_BUF);
+	sa_len = satoa(extr->tdb->tdb_said, 0, sa, SATOA_BUF);
 
 	tdbq = gettdb(&(extr->tdb->tdb_said));
 	if (tdbq) {
 		KLIPS_PRINT(debug_pfkey,
-			    "klips_debug:pfkey_add_parse: found an old Tunnel Descriptor Block\n"
-			    "klips_debug:                for SA: %s, delete it first.\n", sa);
+			    "klips_debug:pfkey_add_parse: "
+			    "found an old Tunnel Descriptor Block for SA%s, delete it first.\n",
+			    sa_len ? sa : " (error)");
 		SENDERR(EEXIST);
 	}
 
@@ -1673,18 +1822,20 @@
 	}
 
 	KLIPS_PRINT(debug_pfkey,
-		    "klips_debug:pfkey_add_parse: existing Tunnel Descriptor Block not found (this\n"
-		    "klips_debug:                is good) for SA: %s, %s-bound, allocating.\n",
-		    sa, extr->tdb->tdb_flags & EMT_INBOUND ? "in" : "out");
+		    "klips_debug:pfkey_add_parse: "
+		    "existing Tunnel Descriptor Block not found (this is good) for SA%s, %s-bound, allocating.\n",
+		    sa_len ? sa : " (error)",
+		    extr->tdb->tdb_flags & EMT_INBOUND ? "in" : "out");
 	
 	/* XXX extr->tdb->tdb_rcvif = &(enc_softc[em->em_if].enc_if);*/
 	extr->tdb->tdb_rcvif = NULL;
 	
 	if ((error = pfkey_tdb_init(extr->tdb, extensions))) {
 		KLIPS_PRINT(debug_pfkey,
-			    "klips_debug:pfkey_add_parse: not successful for SA: %s, deleting.\n", sa);
-		ipsec_tdbwipe(extr->tdb);
-		goto errlab;
+			    "klips_debug:pfkey_add_parse: "
+			    "not successful for SA: %s, deleting.\n",
+			    sa_len ? sa : " (error)");
+		SENDERR(-error);
 	}
 
 	extr->tdb->tdb_lifetime_addtime_c = jiffies / HZ;
@@ -1772,36 +1923,44 @@
 		)) {
 		KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_add_parse: "
 			    "failed to build the add reply message extensions\n");
-		goto errlab;
+		SENDERR(-error);
 	}
 		
 	if((error = puttdb(extr->tdb))) {
 		KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_add_parse: "
 			    "failed to add the mature SA with error=%d.\n",
 			    error);
-		goto errlab;
+		SENDERR(-error);
 	}
+	extr->tdb = NULL;
 	
 	KLIPS_PRINT(debug_pfkey,
-		    "klips_debug:pfkey_add_parse: successful for SA: %s\n", sa);
+		    "klips_debug:pfkey_add_parse: "
+		    "successful for SA: %s\n",
+		    sa_len ? sa : " (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");
-		goto errlab;
+		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 to socket=%p failed with error=%d.\n",
-				    satype, pfkey_socketsp->socketp, error);
-			goto errlab;
+				    "sending up add reply message for satype=%d(%s) to socket=%p failed with error=%d.\n",
+				    satype,
+				    satype2name(satype),
+				    pfkey_socketsp->socketp,
+				    error);
+			SENDERR(-error);
 		}
 		KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_add_parse: "
-			    "sending up add reply message for satype=%d to socket=%p succeeded.\n",
-			    satype, pfkey_socketsp->socketp);
+			    "sending up add reply message for satype=%d(%s) to socket=%p succeeded.\n",
+			    satype,
+			    satype2name(satype),
+			    pfkey_socketsp->socketp);
 	}
 	
  errlab:
@@ -1817,6 +1976,7 @@
 {
 	struct tdb *tdbp;
 	char sa[SATOA_BUF];
+	size_t sa_len;
 	int error = 0;
 	struct sadb_ext *extensions_reply[SADB_EXT_MAX+1];
 	struct sadb_msg *pfkey_reply = NULL;
@@ -1835,7 +1995,7 @@
 		SENDERR(EINVAL);
 	}
 
-	satoa(extr->tdb->tdb_said, 0, sa, SATOA_BUF);
+	sa_len = satoa(extr->tdb->tdb_said, 0, sa, SATOA_BUF);
 
 	spin_lock_bh(&tdb_lock);
 
@@ -1845,7 +2005,7 @@
 		KLIPS_PRINT(debug_pfkey,
 			    "klips_debug:pfkey_delete_parse: "
 			    "Tunnel Descriptor Block not found for SA:%s, could not delete.\n",
-			    sa);
+			    sa_len ? sa : " (error)");
 		SENDERR(ESRCH);
 	}
 
@@ -1854,7 +2014,8 @@
 		KLIPS_PRINT(debug_pfkey,
 			    "klips_debug:pfkey_delete_parse: "
 			    "error=%d returned trying to delete Tunnel Descriptor Block for SA:%s.\n",
-			    error, sa);
+			    error,
+			    sa_len ? sa : " (error)");
 		SENDERR(-error);
 	}
 	spin_unlock_bh(&tdb_lock);
@@ -1890,31 +2051,34 @@
 		)) {
 		KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_delete_parse: "
 			    "failed to build the delete reply message extensions\n");
-		goto errlab;
+		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");
-		goto errlab;
+		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 to socket=%p failed with error=%d.\n",
-				    satype, pfkey_socketsp->socketp, error);
-			goto errlab;
+				    "sending up delete reply message for satype=%d(%s) to socket=%p failed with error=%d.\n",
+				    satype,
+				    satype2name(satype),
+				    pfkey_socketsp->socketp,
+				    error);
+			SENDERR(-error);
 		}
 		KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_delete_parse: "
-			    "sending up delete reply message for satype=%d to socket=%p succeeded.\n",
-			    satype, pfkey_socketsp->socketp);
+			    "sending up delete reply message for satype=%d(%s) to socket=%p succeeded.\n",
+			    satype,
+			    satype2name(satype),
+			    pfkey_socketsp->socketp);
 	}
 	
  errlab:
-	ipsec_tdbwipe(extr->tdb);
-
 	if (pfkey_reply) {
 		pfkey_msg_free(&pfkey_reply);
 	}
@@ -1928,6 +2092,7 @@
 	int error = 0;
 	struct tdb *tdbp;
 	char sa[SATOA_BUF];
+	size_t sa_len;
 	struct sadb_ext *extensions_reply[SADB_EXT_MAX+1];
 	struct sadb_msg *pfkey_reply = NULL;
 
@@ -1943,7 +2108,7 @@
 		SENDERR(EINVAL);
 	}
 
-	satoa(extr->tdb->tdb_said, 0, sa, SATOA_BUF);
+	sa_len = satoa(extr->tdb->tdb_said, 0, sa, SATOA_BUF);
 
 	spin_lock_bh(&tdb_lock);
 
@@ -1952,7 +2117,7 @@
 		spin_unlock_bh(&tdb_lock);
 		KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_get_parse: "
 			    "Tunnel Descriptor Block not found for SA=%s, could not get.\n",
-			    sa);
+			    sa_len ? sa : " (error)");
 		SENDERR(ESRCH);
 	}
 	
@@ -2079,7 +2244,7 @@
 		KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_get_parse: "
 			    "failed to build the get reply message extensions\n");
 		spin_unlock_bh(&tdb_lock);
-		goto errlab;
+		SENDERR(-error);
 	}
 		
 	spin_unlock_bh(&tdb_lock);
@@ -2087,13 +2252,13 @@
 	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");
-		goto errlab;
+		SENDERR(-error);
 	}
 	
 	if((error = pfkey_upmsg(sk->socket, pfkey_reply))) {
 		KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_get_parse: "
 			    "failed to send the get reply message\n");
-		goto errlab;
+		SENDERR(-error);
 	}
 	
 	KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_get_parse: "
@@ -2117,7 +2282,7 @@
 	KLIPS_PRINT(debug_pfkey,
 		    "klips_debug:pfkey_acquire_parse: .\n");
 
-	/* I don't know if we want an upper bound, since userspace may
+	/* 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,
@@ -2129,8 +2294,9 @@
 
 	if(!(pfkey_registered_sockets[satype])) {
 		KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_acquire_parse: "
-			    "no sockets registered for SAtype=%d.\n",
-			    satype);
+			    "no sockets registered for SAtype=%d(%s).\n",
+			    satype,
+			    satype2name(satype));
 		SENDERR(EPROTONOSUPPORT);
 	}
 
@@ -2140,13 +2306,18 @@
 		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 to socket=%p failed with error=%d.\n",
-				    satype, pfkey_socketsp->socketp, error);
-			goto errlab;
+				    "sending up acquire reply message for satype=%d(%s) to socket=%p failed with error=%d.\n",
+				    satype,
+				    satype2name(satype),
+				    pfkey_socketsp->socketp,
+				    error);
+			SENDERR(-error);
 		}
 		KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_acquire_parse: "
-			    "sending up acquire reply message for satype=%d to socket=%p succeeded.\n",
-			    satype, pfkey_socketsp->socketp);
+			    "sending up acquire reply message for satype=%d(%s) to socket=%p succeeded.\n",
+			    satype,
+			    satype2name(satype),
+			    pfkey_socketsp->socketp);
 	}
 	
  errlab:
@@ -2170,7 +2341,7 @@
 
 	pfkey_extensions_init(extensions_reply);
 
-	/* I don't know if we want an upper bound, since userspace may
+	/* 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,
@@ -2184,8 +2355,10 @@
 				 &(pfkey_registered_sockets[satype]))) {
 		KLIPS_PRINT(debug_pfkey,
 			    "klips_debug:pfkey_register_parse: "
-			    "SATYPE=%02d successfully registered by KMd on pid=%d.\n",
-			    satype, key_pid(sk));
+			    "SATYPE=%02d(%s) successfully registered by KMd (pid=%d).\n",
+			    satype,
+			    satype2name(satype),
+			    key_pid(sk));
 	};
 	
 	/* send up register msg with supported SATYPE algos */
@@ -2218,7 +2391,8 @@
 	if(alg_num_a) {
 		if((alg_a = kmalloc(alg_num_a * sizeof(struct sadb_alg), GFP_ATOMIC) ) == NULL) {
 			KLIPS_PRINT(debug_pfkey,
-				    "klips_debug:pfkey_register_parse: auth alg memory allocation error\n");
+				    "klips_debug:pfkey_register_parse: "
+				    "auth alg memory allocation error\n");
 			SENDERR(ENOMEM);
 		}
 		alg_ap = alg_a;
@@ -2227,7 +2401,8 @@
 	if(alg_num_e) {
 		if((alg_e = kmalloc(alg_num_e * sizeof(struct sadb_alg), GFP_ATOMIC) ) == NULL) {
 			KLIPS_PRINT(debug_pfkey,
-				    "klips_debug:pfkey_register_parse: enc alg memory allocation error\n");
+				    "klips_debug:pfkey_register_parse: "
+				    "enc alg memory allocation error\n");
 			SENDERR(ENOMEM);
 		}
 		alg_ep = alg_e;
@@ -2265,8 +2440,9 @@
 		}
 		KLIPS_PRINT(debug_pfkey,
 			    "klips_debug:pfkey_register_parse: "
-			    "found satype=%d exttype=%d id=%d ivlen=%d minbits=%d maxbits=%d.\n",
+			    "found satype=%d(%s) exttype=%d id=%d ivlen=%d minbits=%d maxbits=%d.\n",
 			    satype,
+			    satype2name(satype),
 			    pfkey_supported_listp->supportedp->supported_alg_exttype,
 			    pfkey_supported_listp->supportedp->supported_alg_id,
 			    pfkey_supported_listp->supportedp->supported_alg_ivlen,
@@ -2294,26 +2470,31 @@
 					  extensions_reply) : 1))) {
 		KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_register_parse: "
 			    "failed to build the register message extensions\n");
-		goto errlab;
+		SENDERR(-error);
 	}
 	
 	if((error = pfkey_msg_build(&pfkey_reply, extensions_reply, EXT_BITS_OUT))) {
 		KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_register_parse: "
 			    "failed to build the register message\n");
-		goto errlab;
+		SENDERR(-error);
 	}
 	for(pfkey_socketsp = pfkey_registered_sockets[satype];
 	    pfkey_socketsp;
 	    pfkey_socketsp = pfkey_socketsp->next) {
 		if((error = pfkey_upmsg(pfkey_socketsp->socketp, pfkey_reply))) {
 			KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_register_parse: "
-				    "sending up register reply message for satype=%d to socket=%p failed with error=%d.\n",
-				    satype, pfkey_socketsp->socketp, error);
-			goto errlab;
+				    "sending up register reply message for satype=%d(%s) to socket=%p failed with error=%d.\n",
+				    satype,
+				    satype2name(satype),
+				    pfkey_socketsp->socketp,
+				    error);
+			SENDERR(-error);
 		}
 		KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_register_parse: "
-			    "sending up register reply message for satype=%d to socket=%p succeeded.\n",
-			    satype, pfkey_socketsp->socketp);
+			    "sending up register reply message for satype=%d(%s) to socket=%p succeeded.\n",
+			    satype,
+			    satype2name(satype),
+			    pfkey_socketsp->socketp);
 	}
 	
  errlab:
@@ -2343,13 +2524,18 @@
 			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 to socket=%p failed with error=%d.\n",
-					    satype, pfkey_socketsp->socketp, error);
-				goto errlab;
+					    "sending up expire reply message for satype=%d(%s) to socket=%p failed with error=%d.\n",
+					    satype,
+					    satype2name(satype),
+					    pfkey_socketsp->socketp,
+					    error);
+				SENDERR(-error);
 			}
 			KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_expire_parse: "
-				    "sending up expire reply message for satype=%d to socket=%p succeeded.\n",
-				    satype, pfkey_socketsp->socketp);
+				    "sending up expire reply message for satype=%d(%s) to socket=%p succeeded.\n",
+				    satype,
+				    satype2name(satype),
+				    pfkey_socketsp->socketp);
 		}
 	}
 
@@ -2363,14 +2549,24 @@
 	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 ((error = ipsec_tdbcleanup(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_tdbcleanup(proto))) {
 		SENDERR(-error);
+	}
 
 	if(pfkey_open_sockets) {
 		for(pfkey_socketsp = pfkey_open_sockets;
@@ -2379,15 +2575,18 @@
 			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 to socket=%p failed with error=%d.\n",
+					    "sending up flush reply message for satype=%d(%s) (proto=%d) to socket=%p failed with error=%d.\n",
 					    satype,
+					    satype2name(satype),
+					    proto,
 					    pfkey_socketsp->socketp,
 					    error);
-				goto errlab;
+				SENDERR(-error);
 			}
 			KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_flush_parse: "
-				    "sending up flush reply message for satype=%d to socket=%p succeeded.\n",
+				    "sending up flush reply message for satype=%d(%s) to socket=%p succeeded.\n",
 				    satype,
+				    satype2name(satype),
 				    pfkey_socketsp->socketp);
 		}
 	}
@@ -2444,6 +2643,7 @@
 	struct socket_list *pfkey_socketsp;
 	uint8_t satype = ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_satype;
 	char sa1[SATOA_BUF], sa2[SATOA_BUF];
+	size_t sa_len1, sa_len2 = 0;
 	int error = 0;
 
 	KLIPS_PRINT(debug_pfkey,
@@ -2451,33 +2651,34 @@
 
 	pfkey_extensions_init(extensions_reply);
 
-	spin_lock_bh(&tdb_lock);
-
 	if(!extr || !extr->tdb) {
 		KLIPS_PRINT(debug_pfkey,
 			    "klips_debug:pfkey_x_grpsa_parse: "
 			    "extr or extr->tdb is NULL, fatal.\n");
-		spin_unlock_bh(&tdb_lock);
 		SENDERR(EINVAL);
 	}
 
-	satoa(extr->tdb->tdb_said, 0, sa1, SATOA_BUF);
+	sa_len1 = satoa(extr->tdb->tdb_said, 0, sa1, SATOA_BUF);
 	if(extr->tdb2) {
-		satoa(extr->tdb2->tdb_said, 0, sa2, SATOA_BUF);
+		sa_len2 = satoa(extr->tdb2->tdb_said, 0, sa2, SATOA_BUF);
 	}
 
+	spin_lock_bh(&tdb_lock);
+
 	if(!(tdb1p = gettdb(&(extr->tdb->tdb_said)))) {
 		KLIPS_PRINT(debug_pfkey,
-			    "klips_debug: pfkey_x_grpsa_parse: reserved Tunnel Descriptor Block\n"
-			    "klips_debug:            for SA: %s not found.  Call SADB_ADD/UPDATE first.\n", sa1);
+			    "klips_debug:pfkey_x_grpsa_parse: "
+			    "reserved Tunnel Descriptor Block for SA: %s not found.  Call SADB_ADD/UPDATE first.\n",
+			    sa_len1 ? sa1 : " (error)");
 		spin_unlock_bh(&tdb_lock);
 		SENDERR(EEXIST);
 	}
 	if(extr->tdb2) { /* GRPSA */
 		if(!(tdb2p = gettdb(&(extr->tdb2->tdb_said)))) {
 			KLIPS_PRINT(debug_pfkey,
-				    "klips_debug: pfkey_x_grpsa_parse: reserved Tunnel Descriptor Block\n"
-				    "klips_debug:            for SA: %s not found.  Call SADB_ADD/UPDATE first.\n", sa2);
+				    "klips_debug:pfkey_x_grpsa_parse: "
+				    "reserved Tunnel Descriptor Block for SA: %s not found.  Call SADB_ADD/UPDATE first.\n",
+				    sa_len2 ? sa2 : " (error)");
 			spin_unlock_bh(&tdb_lock);
 			SENDERR(EEXIST);
 		}
@@ -2485,15 +2686,17 @@
 		/* Is either one already linked? */
 		if(tdb1p->tdb_onext) {
 			KLIPS_PRINT(debug_pfkey,
-				    "klips_debug: pfkey_x_grpsa_parse: Tunnel Descriptor Block\n"
-				    "klips_debug:                for SA: %s is already linked.\n", sa1);
+				    "klips_debug:pfkey_x_grpsa_parse: "
+				    "Tunnel Descriptor Block for SA: %s is already linked.\n",
+				    sa_len1 ? sa1 : " (error)");
 			spin_unlock_bh(&tdb_lock);
 			SENDERR(EEXIST);
 		}
 		if(tdb2p->tdb_inext) {
 			KLIPS_PRINT(debug_pfkey,
-				    "klips_debug: pfkey_x_grpsa_parse: Tunnel Descriptor Block\n"
-				    "klips_debug:                for SA: %s is already linked.\n", sa2);
+				    "klips_debug:pfkey_x_grpsa_parse: "
+				    "Tunnel Descriptor Block for SA: %s is already linked.\n",
+				    sa_len2 ? sa2 : " (error)");
 			spin_unlock_bh(&tdb_lock);
 			SENDERR(EEXIST);
 		}
@@ -2527,7 +2730,7 @@
 
 	if(!(pfkey_safe_build(error = pfkey_msg_hdr_build(&extensions_reply[0],
 							  SADB_X_GRPSA,
-							  ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_satype,
+							  satype,
 							  0,
 							  ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_seq,
 							  ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_pid),
@@ -2547,8 +2750,10 @@
 							     0,
 							     extr->tdb->tdb_addr_d),
 				 extensions_reply)
-	     && pfkey_safe_build(error = pfkey_x_satype_build(&extensions_reply[SADB_X_EXT_SATYPE2],
-							      proto2satype(extr->tdb2->tdb_said.proto)),
+	     && (extr->tdb2
+		 ? (pfkey_safe_build(error = pfkey_x_satype_build(&extensions_reply[SADB_X_EXT_SATYPE2],
+								  ((struct sadb_x_satype*)extensions[SADB_X_EXT_SATYPE2])->sadb_x_satype_satype
+								  /* proto2satype(extr->tdb2->tdb_said.proto) */),
 				 extensions_reply)
 	     && pfkey_safe_build(error = pfkey_sa_build(&extensions_reply[SADB_X_EXT_SA2],
 							SADB_X_EXT_SA2,
@@ -2564,17 +2769,17 @@
 							     0, /*extr->tdb->tdb_said.proto,*/
 							     0,
 							     extr->tdb2->tdb_addr_d),
-				 extensions_reply)
+							 extensions_reply) ) : 1 )
 		     )) {
 		KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_grpsa_parse: "
 			    "failed to build the x_grpsa reply message extensions\n");
-		goto errlab;
+		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");
-		goto errlab;
+		SENDERR(-error);
 	}
 	
 	for(pfkey_socketsp = pfkey_open_sockets;
@@ -2582,24 +2787,28 @@
 	    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 to socket=%p failed with error=%d.\n",
-				    satype, pfkey_socketsp->socketp, error);
-			goto errlab;
+				    "sending up x_grpsa reply message for satype=%d(%s) to socket=%p failed with error=%d.\n",
+				    satype,
+				    satype2name(satype),
+				    pfkey_socketsp->socketp,
+				    error);
+			SENDERR(-error);
 		}
 		KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_grpsa_parse: "
-			    "sending up x_grpsa reply message for satype=%d to socket=%p succeeded.\n",
-			    satype, pfkey_socketsp->socketp);
+			    "sending up x_grpsa reply message for satype=%d(%s) to socket=%p succeeded.\n",
+			    satype,
+			    satype2name(satype),
+			    pfkey_socketsp->socketp);
 	}
 	
 	KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_grpsa_parse: "
 		    "succeeded in sending x_grpsa reply message.\n");
 	
  errlab:
-	ipsec_tdbwipe(extr->tdb);
-	if(extr->tdb2) {
-		ipsec_tdbwipe(extr->tdb2);
+	if (pfkey_reply) {
+		pfkey_msg_free(&pfkey_reply);
 	}
-
+	pfkey_extensions_free(extensions_reply);
 	return error;
 }
 
@@ -2673,7 +2882,8 @@
 
 	if ((error = ipsec_makeroute(&(extr->eroute->er_eaddr),
 				     &(extr->eroute->er_emask),
-				     extr->tdb->tdb_said))) {
+				     extr->tdb->tdb_said,
+				     ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_pid))) {
 		KLIPS_PRINT(debug_pfkey,
 			    "klips_debug:pfkey_x_addflow_parse: "
 			    "makeroute returned %d.\n", error);
@@ -2686,7 +2896,7 @@
 
 	if(!(pfkey_safe_build(error = pfkey_msg_hdr_build(&extensions_reply[0],
 							  SADB_X_ADDFLOW,
-							  ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_satype,
+							  satype,
 							  0,
 							  ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_seq,
 							  ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_pid),
@@ -2741,13 +2951,13 @@
 		)) {
 		KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_addflow_parse: "
 			    "failed to build the x_addflow reply message extensions\n");
-		goto errlab;
+		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");
-		goto errlab;
+		SENDERR(-error);
 	}
 	
 	for(pfkey_socketsp = pfkey_open_sockets;
@@ -2755,22 +2965,30 @@
 	    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 to socket=%p failed with error=%d.\n",
-				    satype, pfkey_socketsp->socketp, error);
-			goto errlab;
+				    "sending up x_addflow reply message for satype=%d(%s) to socket=%p failed with error=%d.\n",
+				    satype,
+				    satype2name(satype),
+				    pfkey_socketsp->socketp,
+				    error);
+			SENDERR(-error);
 		}
 		KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_addflow_parse: "
-			    "sending up x_addflow reply message for satype=%d to socket=%p succeeded.\n",
-			    satype, pfkey_socketsp->socketp);
+			    "sending up x_addflow reply message for satype=%d(%s) (proto=%d) to socket=%p succeeded.\n",
+			    satype,
+			    satype2name(satype),
+			    extr->tdb->tdb_said.proto,
+			    pfkey_socketsp->socketp);
 	}
 	
-	ipsec_tdbwipe(extr->tdb);
-
 	KLIPS_PRINT(debug_pfkey,
 		    "klips_debug:pfkey_x_addflow_parse: "
 		    "extr->tdb cleaned up and freed.\n");
 
  errlab:
+	if (pfkey_reply) {
+		pfkey_msg_free(&pfkey_reply);
+	}
+	pfkey_extensions_free(extensions_reply);
 	return error;
 }
 
@@ -2853,7 +3071,7 @@
 	
 	if(!(pfkey_safe_build(error = pfkey_msg_hdr_build(&extensions_reply[0],
 							  SADB_X_DELFLOW,
-							  ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_satype,
+							  satype,
 							  0,
 							  ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_seq,
 							  ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_pid),
@@ -2894,13 +3112,13 @@
 		)) {
 		KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_delflow_parse: "
 			    "failed to build the x_delflow reply message extensions\n");
-		goto errlab;
+		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");
-		goto errlab;
+		SENDERR(-error);
 	}
 	
 	for(pfkey_socketsp = pfkey_open_sockets;
@@ -2908,22 +3126,29 @@
 	    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 to socket=%p failed with error=%d.\n",
-				    satype, pfkey_socketsp->socketp, error);
-			goto errlab;
+				    "sending up x_delflow reply message for satype=%d(%s) to socket=%p failed with error=%d.\n",
+				    satype,
+				    satype2name(satype),
+				    pfkey_socketsp->socketp,
+				    error);
+			SENDERR(-error);
 		}
 		KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_delflow_parse: "
-			    "sending up x_delflow reply message for satype=%d to socket=%p succeeded.\n",
-			    satype, pfkey_socketsp->socketp);
+			    "sending up x_delflow reply message for satype=%d(%s) to socket=%p succeeded.\n",
+			    satype,
+			    satype2name(satype),
+			    pfkey_socketsp->socketp);
 	}
 	
-	ipsec_tdbwipe(extr->tdb);
-
 	KLIPS_PRINT(debug_pfkey,
 		    "klips_debug:pfkey_x_delflow_parse: "
 		    "extr->tdb cleaned up and freed.\n");
 
  errlab:
+	if (pfkey_reply) {
+		pfkey_msg_free(&pfkey_reply);
+	}
+	pfkey_extensions_free(extensions_reply);
 	return error;
 }
 
@@ -2947,10 +3172,18 @@
 	struct sadb_msg *pfkey_msg = NULL;
 	struct socket_list *pfkey_socketsp;
 	int error = 0;
-	uint8_t satype = proto2satype(tdbp->tdb_said.proto);
+	uint8_t satype;
 
 	pfkey_extensions_init(extensions);
 
+	if(!(satype = proto2satype(tdbp->tdb_said.proto))) {
+		KLIPS_PRINT(debug_pfkey,
+			    "klips_debug:pfkey_expire: "
+			    "satype lookup for protocol %d lookup failed.\n", 
+			    tdbp->tdb_said.proto);
+		SENDERR(EINVAL);
+	}
+	
 	if(!pfkey_open_sockets) {
 		KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_expire: "
 			    "no sockets listening.\n");
@@ -3007,16 +3240,16 @@
 							      0,
 							      tdbp->tdb_addr_d),
 				  extensions))) {
-		KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_expire: failed to "
-			    "build the expire message extensions\n");
+		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");
-		goto errlab;
+		KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_expire: "
+			    "failed to build the expire message\n");
+		SENDERR(-error);
 	}
 	
 	for(pfkey_socketsp = pfkey_open_sockets;
@@ -3024,13 +3257,19 @@
 	    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 to socket=%p failed with error=%d.\n",
-				    satype, pfkey_socketsp->socketp, error);
-			goto errlab;
+				    "sending up expire message for satype=%d(%s) to socket=%p failed with error=%d.\n",
+				    satype,
+				    satype2name(satype),
+				    pfkey_socketsp->socketp,
+				    error);
+			SENDERR(-error);
 		}
 		KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_expire: "
-			    "sending up expire message for satype=%d to socket=%p succeeded.\n",
-			    satype, pfkey_socketsp->socketp);
+			    "sending up expire message for satype=%d(%s) (proto=%d) to socket=%p succeeded.\n",
+			    satype,
+			    satype2name(satype),
+			    tdbp->tdb_said.proto,
+			    pfkey_socketsp->socketp);
 	}
 	
  errlab:
@@ -3053,6 +3292,14 @@
 		/* 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; */
+		{ SADB_AALG_MD5HMAC,  SADB_EALG_DESCBC, SADB_SAFLAGS_PFS,
+		  128, 128, 56, 56,
+		  0, 0, 0, 0, 0,
+		  57600, 86400, 57600, 86400 },
+		{ SADB_AALG_SHA1HMAC, SADB_EALG_DESCBC, SADB_SAFLAGS_PFS,
+		  160, 160, 56, 56,
+		  0, 0, 0, 0, 0,
+		  57600, 86400, 57600, 86400 },
 		{ SADB_AALG_MD5HMAC,  SADB_EALG_3DESCBC, SADB_SAFLAGS_PFS,
 		  128, 128, 168, 168,
 		  0, 0, 0, 0, 0,
@@ -3063,7 +3310,7 @@
 		  57600, 86400, 57600, 86400 }
 	};
        
-	/* This should not be hard-coded.  It should be taken from the spdb */
+	/* XXX This should not be hard-coded.  It should be taken from the spdb */
 	uint8_t satype = SADB_SATYPE_ESP;
 
 	pfkey_extensions_init(extensions);
@@ -3077,8 +3324,9 @@
 
 	if(!(pfkey_registered_sockets[satype])) {
 		KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_acquire: "
-			    "no sockets registered for SAtype=%d.\n",
-			    satype);
+			    "no sockets registered for SAtype=%d(%s).\n",
+			    satype,
+			    satype2name(satype));
 		SENDERR(EPROTONOSUPPORT);
 	}
 	
@@ -3146,15 +3394,15 @@
 							   &(comb[0])),
 				  extensions)
 		)) {
-		KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_acquire: failed to "
-			    "build the acquire message extensions\n");
-		goto errlab;
+		KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_acquire: "
+			    "failed to build the acquire message extensions\n");
+		SENDERR(-error);
 	}
 	
 	if ((error = pfkey_msg_build(&pfkey_msg, extensions, EXT_BITS_OUT))) {
-		KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_acquire: failed to "
-			    "build the acquire message\n");
-		goto errlab;
+		KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_acquire: "
+			    "failed to build the acquire message\n");
+		SENDERR(-error);
 	}
 	
 	/* this should go to all registered sockets for that satype only */
@@ -3163,13 +3411,18 @@
 	    pfkey_socketsp = pfkey_socketsp->next) {
 		if((error = pfkey_upmsg(pfkey_socketsp->socketp, pfkey_msg))) {
 			KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_acquire: "
-				    "sending up acquire message for satype=%d to socket=%p failed with error=%d.\n",
-				    satype, pfkey_socketsp->socketp, error);
-			goto errlab;
+				    "sending up acquire message for satype=%d(%s) to socket=%p failed with error=%d.\n",
+				    satype,
+				    satype2name(satype),
+				    pfkey_socketsp->socketp,
+				    error);
+			SENDERR(-error);
 		}
 		KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_acquire: "
-			    "sending up acquire message for satype=%d to socket=%p succeeded.\n",
-			    satype, pfkey_socketsp->socketp);
+			    "sending up acquire message for satype=%d(%s) to socket=%p succeeded.\n",
+			    satype,
+			    satype2name(satype),
+			    pfkey_socketsp->socketp);
 	}
 	
  errlab:
@@ -3243,12 +3496,13 @@
 	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);
+	KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_build_reply: "
+		    "building reply with type: %d\n",
+		    msg_type);
 	pfkey_extensions_init(extensions);
 	if (!extr || !extr->tdb) {
-			KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_build_reply: bad TDB"
-							"passed\n");
+			KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_build_reply: "
+				    "bad TDB passed\n");
 			return EINVAL;
 	}
 	error = pfkey_safe_build(pfkey_msg_hdr_build(&extensions[0],
@@ -3302,10 +3556,13 @@
 		return EINVAL;
 	}
 
-	KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_build_reply: built extensions"
-		    ", proceed to build the message\n");
-	KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_build_reply: extensions[1]="
-		    " %p\n", extensions[1]);
+	KLIPS_PRINT(debug_pfkey,
+		    "klips_debug:pfkey_build_reply: "
+		    "built extensions, proceed to build the message\n");
+	KLIPS_PRINT(debug_pfkey,
+		    "klips_debug:pfkey_build_reply: "
+		    "extensions[1]= %p\n",
+		    extensions[1]);
 	error = pfkey_msg_build(pfkey_reply, extensions, EXT_BITS_OUT);
 	pfkey_extensions_free(extensions);
 
@@ -3323,12 +3580,13 @@
 	
 	pfkey_extensions_init(extensions);
 	KLIPS_PRINT(debug_pfkey,
-		    "klips_debug:pfkey_msg_interp: parsing message "
-		    "ver=%d, type=%d, errno=%d, satype=%d, len=%d, res=%d, seq=%d, pid=%d.\n", 
+		    "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,
@@ -3337,18 +3595,22 @@
 	if((error = pfkey_alloc_tdb(&(extr.tdb)))) {
 		KLIPS_PRINT(debug_pfkey,
 			    "klips_debug:pfkey_msg_interp: "
-			    "something's really wrong, extr.tdb=%p should be NULL.\n", extr.tdb);
+			    "something's really wrong, extr.tdb=%p should be NULL.\n",
+			    extr.tdb);
 		SENDERR(-error);
 	}
 
 	KLIPS_PRINT(debug_pfkey,
 		    "klips_debug:pfkey_msg_interp: "
-		    "allocated extr->tdb=%p.\n", extr.tdb);
+		    "allocated extr->tdb=%p.\n",
+		    extr.tdb);
 	
 	if(pfkey_msg->sadb_msg_satype > SADB_SATYPE_MAX) {
 		KLIPS_PRINT(debug_pfkey,
-			    "klips_debug:pfkey_msg_interp: satype %d > max %d\n", 
-			    pfkey_msg->sadb_msg_satype, SADB_SATYPE_MAX);
+			    "klips_debug:pfkey_msg_interp: "
+			    "satype %d > max %d\n", 
+			    pfkey_msg->sadb_msg_satype,
+			    SADB_SATYPE_MAX);
 		SENDERR(EINVAL);
 	}
 	
@@ -3358,16 +3620,21 @@
 	case SADB_ADD:
 	case SADB_DELETE:
 	case SADB_X_GRPSA:
+	case SADB_X_ADDFLOW:
 		if(!(extr.tdb->tdb_said.proto = satype2proto(pfkey_msg->sadb_msg_satype))) {
 			KLIPS_PRINT(debug_pfkey,
-				    "klips_debug:pfkey_msg_interp: satype %d lookup failed.\n", 
+				    "klips_debug:pfkey_msg_interp: "
+				    "satype %d lookup failed.\n", 
 				    pfkey_msg->sadb_msg_satype);
 			SENDERR(EINVAL);
+		} else {
+			KLIPS_PRINT(debug_pfkey,
+				    "klips_debug:pfkey_msg_interp: "
+				    "satype %d lookups to proto=%d.\n", 
+				    pfkey_msg->sadb_msg_satype,
+				    extr.tdb->tdb_said.proto);
 		}
 		break;
-	case SADB_X_ADDFLOW:
-		extr.tdb->tdb_said.proto = satype2proto(pfkey_msg->sadb_msg_satype);
-		break;
 	default:
 	}
 	
@@ -3376,7 +3643,8 @@
 	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",
+			    "klips_debug:pfkey_msg_interp: "
+			    "message parsing failed with error %d.\n",
 			    error); 
 		SENDERR(-error);
 	}
@@ -3390,8 +3658,10 @@
 				    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); 
+					    "klips_debug:pfkey_msg_interp: "
+					    "extension processing for type %d failed with error %d.\n",
+					    i,
+					    error); 
 				SENDERR(-error);
 			}
 			
@@ -3407,7 +3677,8 @@
 		    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",
+			    "klips_debug:pfkey_msg_interp: "
+			    "message parsing failed with error %d.\n",
 			    error); 
 		SENDERR(-error);
 	}
@@ -3419,13 +3690,76 @@
 	}
 #endif	
  errlab:
+	if(extr.tdb != NULL) {
+		ipsec_tdbwipe(extr.tdb);
+	}
+	if(extr.tdb2 != NULL) {
+		ipsec_tdbwipe(extr.tdb2);
+	}
+	if (extr.eroute != NULL) {
+		kfree(extr.eroute);
+	}
 	return(error);
 }
 
 /*
  * $Log: pfkey_v2_parser.c,v $
- * Revision 1.68.2.1  2001/02/27 00:51:01  henry
- * message improvements
+ * 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().
@@ -3570,9 +3904,6 @@
  *
  * 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.
diff -bruN freeswan-1.9.orig/klips/net/ipsec/radij.c freeswan-1.9/klips/net/ipsec/radij.c
--- freeswan-1.9.orig/klips/net/ipsec/radij.c	Sun Nov  5 23:35:21 2000
+++ freeswan-1.9/klips/net/ipsec/radij.c	Mon Jun  4 11:34:31 2001
@@ -1,4 +1,4 @@
-char radij_c_version[] = "RCSID $Id: radij.c,v 1.31 2000/11/06 04:35:21 rgb Exp $";
+char radij_c_version[] = "RCSID $Id: radij.c,v 1.34 2001/05/03 19:44:26 rgb Exp $";
 
 /*
  * This file is defived from ${SRC}/sys/net/radix.c of BSD 4.4lite
@@ -213,7 +213,8 @@
 	 * 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");
+		    "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++)
@@ -230,7 +231,8 @@
 	matched_off = cp - v;
 	saved_t = t;
 	KLIPS_PRINT(debug_radij,
-		    "klips_debug:rj_match: ** try to match a leaf, t=0x%p\n", t);
+		    "klips_debug:rj_match: "
+		    "** try to match a leaf, t=0x%p\n", t);
 	do {
 	    if (t->rj_mask) {
 		/*
@@ -251,13 +253,17 @@
 	t = saved_t;
 	/* start searching up the tree */
 	KLIPS_PRINT(debug_radij,
-		    "klips_debug:rj_match: *** start searching up the tree, t=0x%p\n", t);
+		    "klips_debug:rj_match: "
+		    "*** start searching up the tree, t=0x%p\n",
+		    t);
 	do {
 		register struct radij_mask *m;
 		
 		t = t->rj_p;
 		KLIPS_PRINT(debug_radij,
-			    "klips_debug:rj_match: **** t=0x%p\n", t);
+			    "klips_debug:rj_match: "
+			    "**** t=0x%p\n",
+			    t);
 		if ((m = t->rj_mklist)) {
 			/*
 			 * After doing measurements here, it may
@@ -271,7 +277,9 @@
 				cp2 = mstart;
 				cp3 = m->rm_mask + off;
 				KLIPS_PRINT(debug_radij,
-					    "klips_debug:rj_match: ***** cp2=0x%p cp3=0x%p\n", cp2, cp3);
+					    "klips_debug:rj_match: "
+					    "***** cp2=0x%p cp3=0x%p\n",
+					    cp2, cp3);
 				for (cp = v + off; cp < cplim;)
 					*cp2++ =  *cp++ & *cp3++;
 				x = rj_search(maskedKey, t);
@@ -285,7 +293,8 @@
 		}
 	} while (t != top);
 	KLIPS_PRINT(debug_radij,
-		    "klips_debug:rj_match: ***** not found.\n");
+		    "klips_debug:rj_match: "
+		    "***** not found.\n");
 	return 0;
 };
 		
@@ -363,7 +372,7 @@
 	} while (b > (unsigned) x->rj_b); /* x->rj_b < b && x->rj_b >= 0 */
 #ifdef RJ_DEBUG
 	if (rj_debug)
-		printk("klips_debug:Going In:\n"), traverse(p);
+		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)
@@ -378,7 +387,7 @@
 	}
 #ifdef RJ_DEBUG
 	if (rj_debug)
-		printk("klips_debug:Coming out:\n"), traverse(p);
+		printk("klips_debug:rj_insert: Coming out:\n"), traverse(p);
 #endif /* RJ_DEBUG */
     }
 	return (tt);
@@ -460,7 +469,7 @@
 		if (Bcmp(netmask, x->rj_key, mlen) != 0) {
 			x = rj_addmask(netmask, 0, top->rj_off);
 			if (x == 0)
-				return /* (0) rgb */ ENOMEM;
+				return /* (0) rgb */ -ENOMEM;
 		}
 		netmask = x->rj_key;
 		b = -1 - x->rj_b;
@@ -472,7 +481,7 @@
 	if (keyduplicated) {
 		do {
 			if (tt->rj_mask == netmask)
-				return /* (0) rgb */ ENXIO;
+				return /* (0) rgb */ -ENXIO;
 			t = tt;
 			if (netmask == 0 ||
 			    (tt->rj_mask && rj_refines(netmask, tt->rj_mask)))
@@ -569,7 +578,8 @@
 	}
 	MKGet(m);
 	if (m == 0) {
-		printk("klips_debug:Mask for route not entered\n");
+		printk("klips_debug:rj_addroute: "
+		       "Mask for route not entered\n");
 		return /* (tt) rgb */ 0;
 	}
 	Bzero(m, sizeof *m);
@@ -617,7 +627,8 @@
 	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");
+		printk("klips_debug:rj_delete: "
+		       "inconsistent annotation\n");
 		goto on1;
 	}
 	if (--m->rm_refs >= 0)
@@ -637,7 +648,8 @@
 			break;
 		}
 	if (m == 0)
-		printk("klips_debug:rj_delete: couldn't find our annotation\n");
+		printk("klips_debug:rj_delete: "
+		       "couldn't find our annotation\n");
 on1:
 	/*
 	 * Eliminate us from tree
@@ -658,7 +670,8 @@
 			for (x = p = saved_tt; p && p->rj_dupedkey != tt;)
 				p = p->rj_dupedkey;
 			if (p) p->rj_dupedkey = tt->rj_dupedkey;
-			else printk("klips_debug:rj_delete: couldn't find us\n");
+			else printk("klips_debug:rj_delete: "
+				       "couldn't find us\n");
 		}
 		t = tt + 1;
 		if  (t->rj_flags & RJF_ACTIVE) {
@@ -691,8 +704,8 @@
 					x->rj_mklist = 0;
 					MKFree(m);
 				} else 
-					printk("klips_debug:%s %p at %p\n",
-					    "rj_delete: Orphaned Mask", m, x);
+					printk("klips_debug:rj_delete: "
+					    "Orphaned Mask %p at %p\n", m, x);
 				m = mm;
 			}
 		}
@@ -729,7 +742,7 @@
 	register struct radij_node *rn;
 
 	if(!h || !f /* || !w */) {
-		return -1;
+		return -ENODATA;
 	}
 
 	rn = h->rnh_treetop;
@@ -744,9 +757,14 @@
 	for (;;) {
 #ifdef CONFIG_IPSEC_DEBUG
 		if(debug_radij) {
-			printk("klips_debug:RN_WALKTREE: for: rn=%p rj_b=%d rj_flags=%x", rn, rn->rj_b, rn->rj_flags);
+			printk("klips_debug:rj_walktree: "
+			       "for: rn=%p rj_b=%d rj_flags=%x",
+			       rn,
+			       rn->rj_b,
+			       rn->rj_flags);
 			rn->rj_b >= 0 ?
-				printk(" node off=%x\n", rn->rj_off) :
+				printk(" 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))
@@ -763,9 +781,14 @@
 		next = rn;
 #ifdef CONFIG_IPSEC_DEBUG
 		if(debug_radij) {
-			printk("klips_debug:RN_WALKTREE: processing leaves, rn=%p rj_b=%d rj_flags=%x", rn, rn->rj_b, rn->rj_flags);
+			printk("klips_debug:rj_walktree: "
+			       "processing leaves, rn=%p rj_b=%d rj_flags=%x",
+			       rn,
+			       rn->rj_b,
+			       rn->rj_flags);
 			rn->rj_b >= 0 ?
-				printk(" node off=%x\n", rn->rj_off) :
+				printk(" 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))
@@ -777,10 +800,15 @@
 			base = rn->rj_dupedkey;
 #ifdef CONFIG_IPSEC_DEBUG
 			if(debug_radij) {
-				printk("klips_debug:RN_WALKTREE: while: base=%p rn=%p rj_b=%d rj_flags=%x",
-				       base, rn, rn->rj_b, rn->rj_flags);
+				printk("klips_debug:rj_walktree: "
+				       "while: base=%p rn=%p rj_b=%d rj_flags=%x",
+				       base,
+				       rn,
+				       rn->rj_b,
+				       rn->rj_flags);
 				rn->rj_b >= 0 ?
-					printk(" node off=%x\n", rn->rj_off) :
+					printk(" 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))
@@ -807,7 +835,7 @@
 	if (*head)
 		return (1);
 	R_Malloc(rnh, struct radij_node_head *, sizeof (*rnh));
-	if (rnh == 0)
+	if (rnh == NULL)
 		return (0);
 	Bzero(rnh, sizeof (*rnh));
 	*head = rnh;
@@ -834,7 +862,8 @@
 	char *cp, *cplim;
 
 	if (maj_keylen == 0) {
-		printk("klips_debug:rj_init: radij functions require maj_keylen be set\n");
+		printk("klips_debug:rj_init: "
+		       "radij functions require maj_keylen be set\n");
 		return;
 	}
 	R_Malloc(rj_zeroes, char *, 3 * maj_keylen);
@@ -855,7 +884,8 @@
 	int i;
 	
 	if (rn == NULL){
-		printk("klips_debug:rj_preorder: NULL pointer\n");
+		printk("klips_debug:rj_preorder: "
+		       "NULL pointer\n");
 		return;
 	}
 	
@@ -865,27 +895,29 @@
 		printk("klips_debug:");
 		for (i=0; i<l; i++)
 			printk("*");
-		printk(" off = %d\n", rn->rj_off);
+		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);
+		printk(" flags = %x",
+		       (u_int)rn->rj_flags);
 		if (rn->rj_flags & RJF_ACTIVE) {
-			printk(" @key = %p", rn->rj_key);
-			
+			printk(" @key = %p",
+			       rn->rj_key);
 			printk(" key = %08x->%08x",
 			       (u_int)ntohl(((struct sockaddr_encap *)rn->rj_key)->sen_ip_src.s_addr),
 			       (u_int)ntohl(((struct sockaddr_encap *)rn->rj_key)->sen_ip_dst.s_addr));
-
-			printk(" @mask = %p", rn->rj_mask);
+			printk(" @mask = %p",
+			       rn->rj_mask);
 			if (rn->rj_mask)
 				printk(" mask = %08x->%08x",
 				       (u_int)ntohl(((struct sockaddr_encap *)rn->rj_mask)->sen_ip_src.s_addr),
 				       (u_int)ntohl(((struct sockaddr_encap *)rn->rj_mask)->sen_ip_dst.s_addr));
-		
 			if (rn->rj_dupedkey)
-				printk(" dupedkey = %08x", (u_int)rn->rj_dupedkey);
+				printk(" dupedkey = %08x",
+				       (u_int)rn->rj_dupedkey);
 		}
 		printk("\n");
 	}
@@ -951,6 +983,16 @@
 
 /*
  * $Log: radij.c,v $
+ * 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.
  *
diff -bruN freeswan-1.9.orig/klips/net/ipsec/sysctl_net_ipsec.c freeswan-1.9/klips/net/ipsec/sysctl_net_ipsec.c
--- freeswan-1.9.orig/klips/net/ipsec/sysctl_net_ipsec.c	Fri Sep 15 21:50:15 2000
+++ freeswan-1.9/klips/net/ipsec/sysctl_net_ipsec.c	Mon Jun  4 11:34:31 2001
@@ -12,7 +12,7 @@
  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  * for more details.
  *
- * RCSID $Id: sysctl_net_ipsec.c,v 1.10 2000/09/16 01:50:15 rgb Exp $
+ * RCSID $Id: sysctl_net_ipsec.c,v 1.11 2001/02/26 19:58:13 rgb Exp $
  */
 
 /* -*- linux-c -*-
@@ -44,9 +44,7 @@
 #endif /* CONFIG_IPSEC_DEBUG */
 
 extern int sysctl_ipsec_icmp;
-extern int sysctl_ipsec_no_eroute_pass;
 extern int sysctl_ipsec_inbound_policy_check;
-extern int sysctl_ipsec_opportunistic;
 extern int sysctl_ipsec_tos;
 
 enum {
@@ -65,10 +63,8 @@
 	NET_IPSEC_DEBUG_IPCOMP=12,
 #endif /* CONFIG_IPSEC_DEBUG */
 	NET_IPSEC_ICMP=13,
-	NET_IPSEC_NO_EROUTE_PASS=14,
-	NET_IPSEC_INBOUND_POLICY_CHECK=15,
-	NET_IPSEC_OPPORTUNISTIC=16,
-	NET_IPSEC_TOS=17
+	NET_IPSEC_INBOUND_POLICY_CHECK=14,
+	NET_IPSEC_TOS=15
 };
 
 static ctl_table ipsec_table[] = {
@@ -102,12 +98,8 @@
 #endif /* CONFIG_IPSEC_DEBUG */
 	{ NET_IPSEC_ICMP, "icmp", &sysctl_ipsec_icmp,
 	  sizeof(int), 0644, NULL, &proc_dointvec},    
-	{ NET_IPSEC_NO_EROUTE_PASS, "no_eroute_pass", &sysctl_ipsec_no_eroute_pass,
-	  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_OPPORTUNISTIC, "opportunistic", &sysctl_ipsec_opportunistic,
-	  sizeof(int), 0644, NULL, &proc_dointvec},    
 	{ NET_IPSEC_TOS, "tos", &sysctl_ipsec_tos,
 	  sizeof(int), 0644, NULL, &proc_dointvec},    
 	{0}
@@ -143,6 +135,9 @@
 
 /*
  * $Log: sysctl_net_ipsec.c,v $
+ * 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...
diff -bruN freeswan-1.9.orig/klips/net/ipsec/version.c freeswan-1.9/klips/net/ipsec/version.c
--- freeswan-1.9.orig/klips/net/ipsec/version.c	Mon Feb 26 18:56:08 2001
+++ freeswan-1.9/klips/net/ipsec/version.c	Thu Jun  7 14:53:47 2001
@@ -1,2 +1,2 @@
-/* silly pointless RCSID $Id: version.c,v 1.17.2.1 2001/02/26 23:56:08 henry Exp $ */
-static const char freeswan_version[] = "1.9";
+/* silly pointless RCSID $Id: version.c,v 1.19 2001/05/30 13:02:20 henry Exp $ */
+static const char freeswan_version[] = "FreeSWAN-1.9-pkix2";
diff -bruN freeswan-1.9.orig/klips/test/ipsec.funcs freeswan-1.9/klips/test/ipsec.funcs
--- freeswan-1.9.orig/klips/test/ipsec.funcs	Wed Dec 31 19:00:00 1969
+++ freeswan-1.9/klips/test/ipsec.funcs	Mon Jun  4 11:34:31 2001
@@ -0,0 +1,209 @@
+#!/bin/sh
+#
+# ipsec.func	This file contains functions for use by klips/test
+#		shell scripts.
+# Version:	0.0
+#
+# Author:	Richard Guy Briggs, <rgb@conscoop.ottawa.on.ca>
+#
+# Default search path:
+export PATH="/sbin:/usr/sbin:/usr/local/sbin:/bin:/usr/bin:/usr/local/bin"
+#
+# The following (environment) variables are expected to be set before
+# calling these functions as apropriate.
+#
+# net1=
+# net2=
+# gw1=
+# gw2=
+# h_mask=
+# n_mask=
+# ipsec_dev=
+# phys_dev=
+## iv=
+## esp_key=
+## ah_key=
+#
+# xform1a=
+# xform1b=
+# xform1c=
+# xform2a=
+# xform2b=
+# xform2c=
+#
+# spi1a=
+# spi1b=
+# spi1c=
+# spi2a=
+# spi2b=
+# spi2c=
+#
+
+# Setup module and interface
+#
+ipsec_setup() {
+	# Load the module
+	depmod -a
+	modprobe ipsec
+	# Attach and configure the interface
+	tncfg attach $ipsecdev $physdev
+	ifconfig $ipsecdev $gw1 
+}
+#
+# Clean up and unload the module
+ipsec_unload() {
+	ifconfig ipsec0 down
+	ifconfig ipsec1 down
+	rmmod ipsec
+}
+#
+# Display configuration from /proc/net/ipsec* filesystem.
+#
+ipsec_proc() {
+	echo /proc/net/ipsec-spi
+	cat /proc/net/ipsec-spi
+	echo
+	echo /proc/net/ipsec-route
+	cat /proc/net/ipsec-route
+}
+#
+# Setup a secure connection
+#
+ipsec_setconn() {
+case "$1" in
+	# Transport mode
+	trespah)
+		spi $gw1 $spi1a esp $xform1a i \
+			$iv $esp_key
+
+		route del $gw2
+		route add -host $gw2 dev ipsec0
+
+		eroute add $gw1 $hmask \
+			$gw2 $hmask \
+			$gw2 $spi2a
+		spi $gw2 $spi2a esp $xform2a i \
+			$iv $esp_key
+		;;
+	trespahdel)
+		spi $gw1 $spi1a del
+
+		spi $gw2 $spi2a del
+
+		eroute del $gw1 $hmask $gw2 $hmask
+
+		route del $gw2
+		;;
+	trah)
+		spi $gw1 $spi1a ah $xform1a $ah_key
+
+		route del $gw2
+		route add -host $gw2 dev ipsec0
+
+		eroute add $gw1 $hmask \
+			$gw2 $hmask \
+			$gw2 $spi2a
+		spi $gw2 $spi2a ah $xform2a $ah_key
+		;;
+	tresp)
+		spi $gw1 $spi1a esp $xform1a $iv $esp_key
+
+		route del $gw2
+		route add -host $gw2 dev ipsec0
+
+		eroute add $gw1 $hmask \
+			$gw2 $hmask \
+			$gw2 $spi2a
+		spi $gw2 $spi2a esp $xform2a $iv $esp_key
+		;;
+	# Tunnel mode
+	tu)
+		# return path
+		spi $gw1 $spi1b esp $xform1b $iv $esp_key
+		spi $gw1 $spi1c ah $xform1c $ah_key
+
+		route del $net2
+		route add -net $net2 dev ipsec0 gw $gw2
+
+		# forward path
+		eroute add $net1 $nmask \
+			$net2 $nmask \
+			$gw2 $spi2a
+
+		spi $gw2 $spi2a $xform2a \
+			$gw1 $gw2
+		spi $gw2 $spi2b esp $xform2b $iv $esp_key
+		spi $gw2 $spi2c ah $xform2c $ah_key
+
+		spigrp $gw2 $spi2a \
+			$gw2 $spi2b \
+			$gw2 $spi2c
+		;;
+	turoad)
+		# return path
+		spi $gw1 $spi1b esp $xform1b $iv $esp_key
+		spi $gw1 $spi1c ah $xform1c $ah_key
+
+		route del $gw2
+		route add -host $gw2 dev ipsec0 gw $gw2a
+
+		# forward path
+		eroute add $net1 $nmask \
+			$gw2 $hmask \
+			$gw2 $spi2a
+
+		spi $gw2 $spi2a $xform2a \
+			$gw1 $gw2
+		spi $gw2 $spi2b esp $xform2b $iv $esp_key
+		spi $gw2 $spi2c ah $xform2c $ah_key
+
+		spigrp $gw2 $spi2a \
+			$gw2 $spi2b \
+			$gw2 $spi2c
+		;;
+	turoad2)
+		# return path
+		spi $gw1 $spi1b esp $xform1b $iv $esp_key
+		spi $gw1 $spi1c ah $xform1c $ah_key
+
+		route del $net2
+		route add -net $net2 dev ipsec0 gw $gw2
+
+		# forward path
+		eroute add $gw1 $hmask \
+			$net2 $nmask \
+			$gw2 $spi2a
+
+		spi $gw2 $spi2a $xform2a \
+			$gw1 $gw2
+		spi $gw2 $spi2b esp $xform2b $iv $esp_key
+		spi $gw2 $spi2c ah $xform2c $ah_key
+
+		spigrp $gw2 $spi2a \
+			$gw2 $spi2b \
+			$gw2 $spi2c
+		;;
+	tugw)
+		# return path
+		spi $gw1 $spi1b esp $xform1b $iv $esp_key
+		spi $gw1 $spi1c ah $xform1c $ah_key
+
+		route del $gw2
+		route add -host $gw2 dev ipsec0
+
+		# forward path
+		eroute add $gw1 $hmask \
+			$gw2 $hmask \
+			$gw2 $spi2a
+
+		spi $gw2 $spi2a $xform2a \
+			$gw1 $gw2
+		spi $gw2 $spi2b esp $xform2b $iv $esp_key
+		spi $gw2 $spi2c ah $xform2c $ah_key
+
+		spigrp $gw2 $spi2a \
+			$gw2 $spi2b \
+			$gw2 $spi2c
+		;;
+esac
+}
diff -bruN freeswan-1.9.orig/klips/utils/Makefile freeswan-1.9/klips/utils/Makefile
--- freeswan-1.9.orig/klips/utils/Makefile	Fri Jun 30 02:20:25 2000
+++ freeswan-1.9/klips/utils/Makefile	Mon Jun  4 11:34:31 2001
@@ -30,8 +30,8 @@
 CFLAGS+= -Wbad-function-cast 
 
 ALL=spi eroute spigrp tncfg klipsdebug
-BINDIR=/usr/local/lib/ipsec
-MANTREE=/usr/local/man
+BINDIR=/usr/lib/ipsec
+MANTREE=/usr/man
 MANDIR8=$(MANTREE)/man8
 MANDIR5=$(MANTREE)/man5
 FREESWANLIB=../../lib/libfreeswan.a
@@ -40,11 +40,11 @@
 all: $(ALL)
 
 install: $(ALL)
-	$(INSTALL) $(ALL) $(BINDIR)
+	$(INSTALL) $(ALL) $(PREFIX)/$(BINDIR)
 	for f in $(addsuffix .8, $(ALL)) ; do \
-		$(INSTALL) $$f $(MANDIR8)/ipsec_$$f || exit 1 ; done
+		$(INSTALL) $$f $(PREFIX)/$(MANDIR8)/ipsec_$$f || exit 1 ; done
 	for f in $(addsuffix .5, $(ALL) version pf_key) ; do \
-		$(INSTALL) $$f $(MANDIR5)/ipsec_$$f || exit 1 ; done
+		$(INSTALL) $$f $(PREFIX)/$(MANDIR5)/ipsec_$$f || exit 1 ; done
 
 spi: spi.o
 	$(CC) $(DFLAGS) -o $@ $? $(FREESWANLIB)
diff -bruN freeswan-1.9.orig/klips/utils/eroute.5 freeswan-1.9/klips/utils/eroute.5
--- freeswan-1.9.orig/klips/utils/eroute.5	Sun Sep 17 14:56:48 2000
+++ freeswan-1.9/klips/utils/eroute.5	Mon Jun  4 12:56:04 2001
@@ -1,6 +1,6 @@
 .TH IPSEC_EROUTE 5 "26 Jun 2000"
 .\"
-.\" RCSID $Id: eroute.5,v 1.5 2000/09/17 18:56:48 rgb Exp $
+.\" RCSID $Id: eroute.5,v 1.7 2001/05/29 05:15:31 rgb Exp $
 .\"
 .SH NAME
 ipsec_eroute \- list of existing eroutes
@@ -19,6 +19,8 @@
 .PP
 A table entry consists of:
 .IP + 3
+packet count,
+.IP +
 source address with mask,
 .IP +
 a '->' separator for visual and automated parsing between src and dst
@@ -33,6 +35,10 @@
 protocol
 (\fIproto\fR),
 .IP +
+address family
+(\fIaf\fR),
+where '.' stands for IPv4 and ':' for IPv6
+.IP +
 Security Parameters Index
 (\fISPI\fR),
 .IP +
@@ -41,10 +47,6 @@
 where the packet should be forwarded after processing
 (normally the other security gateway)
 together indicate which Security Association should be used to process the packet
-.IP +
-address family
-(\fIaf\fR),
-where '.' stands for IPv4 and ':' for IPv6
 .PP
 Addresses are written as IPv4 dotted quads or IPv6 coloned hex,
 protocol is one of "ah", "esp", "comp" or "tun"
@@ -52,16 +54,36 @@
 SPIs are prefixed hexadecimal numbers where the prefix '.' is for IPv4 and the prefix ':' is for IPv6
 .
 .PP
-SAIDs are written as "protoafSPI@edst".
+SAIDs are written as "protoafSPI@edst".  There are also 5
+"magic" SAIDs which have special meaning:
+.IP + 3
+.B %drop
+means that matches are to be dropped
+.IP +
+.B %reject
+means that matches are to be dropped and an ICMP returned, if
+possible to inform
+.IP +
+.B %trap
+means that matches are to trigger an ACQUIRE message to the Key
+Management daemon(s) and a hold eroute will be put in place to
+prevent subsequent packets also triggering ACQUIRE messages.
+.IP +
+.B %hold
+means that matches are to stored until the eroute is replaced or
+until that eroute gets reaped
+.IP +
+.B %pass
+means that matches are to allowed to pass without IPSEC processing
 .br
 .ne 5
 .SH EXAMPLES
 .LP
-.B 172.31.252.0/24    -> 0.0.0.0/0          => tun.130@192.168.43.1
+.B 1867     172.31.252.0/24    -> 0.0.0.0/0          => tun.130@192.168.43.1
 .LP
-means that an
+means that 1,867 packets have been sent to an
 .BR eroute
-has been set up to protect traffic between the subnet
+that has been set up to protect traffic between the subnet
 .BR 172.31.252.0
 with a subnet mask of
 .BR 24
@@ -79,11 +101,11 @@
 .BR 130
 in hexadecimal.
 .LP
-.B 3049:1::/64    -> 0:0/0          => tun:130@3058:4::5
+.B 125      3049:1::/64    -> 0:0/0          => tun:130@3058:4::5
 .LP
-means that an
+means that 125 packets have been sent to an
 .BR eroute
-has been set up to protect traffic between the subnet
+that has been set up to protect traffic between the subnet
 .BR 3049:1::
 with a subnet mask of
 .BR 64
@@ -101,11 +123,11 @@
 .BR 130
 in hexadecimal.
 .LP
-.B 192.168.6.0/24     -> 192.168.7.0/24     => %passthrough
+.B 42         192.168.6.0/24     -> 192.168.7.0/24     => %passthrough
 .LP
-means that an
+means that 42 packets have been sent to an
 .BR eroute
-has been set up to pass the traffic from the subnet
+that has been set up to pass the traffic from the subnet
 .BR 192.168.6.0
 with a subnet mask of
 .BR 24
@@ -115,13 +137,25 @@
 .BR 24
 bits without any IPSEC processing.
 .LP
-.B "192.168.2.110/32   -> 192.168.2.120/32   => "
+.B 2112     192.168.8.55/32    -> 192.168.9.47/24    => %hold
+.LP
+means that 2112 packets have been sent to an
+.BR eroute
+that has been set up to hold the traffic from the host
+.BR 192.168.8.55
+and to host
+.BR 192.168.9.47
+until a key exchange from a Key Management daemon
+succeeds and puts in an SA or fails and puts in a pass
+or drop eroute depending on the default configuration.
+.LP
+.B "2001     192.168.2.110/32   -> 192.168.2.120/32   => "
 .br
 .B "        esp.e6de@192.168.2.120"
 .LP
-means that an
+means that 2001 packets have been sent to an
 .BR eroute
-has been set up to protect traffic between the host
+that has been set up to protect traffic between the host
 .BR 192.168.2.110
 and the host
 .BR 192.168.2.120
@@ -138,13 +172,13 @@
 in hexadecimal using Encapsuation Security Payload protocol (50,
 IPPROTO_ESP).
 .LP
-.B "3049:1::110/128   -> 3049:1::120/128   => "
+.B "1984     3049:1::110/128   -> 3049:1::120/128   => "
 .br
 .B "        ah:f5ed@3049:1::120"
 .LP
-means that an
+means that 1984 packets have been sent to an
 .BR eroute
-has been set up to authenticate traffic between the host
+that has been set up to authenticate traffic between the host
 .BR 3049:1::110
 and the host
 .BR 3049:1::120
@@ -172,6 +206,14 @@
 by Richard Guy Briggs.
 .\"
 .\" $Log: eroute.5,v $
+.\" Revision 1.7  2001/05/29 05:15:31  rgb
+.\" Added packet count field at beginning of line.
+.\"
+.\" Revision 1.6  2001/02/26 19:58:32  rgb
+.\" Put SAID elements in order they appear in SAID.
+.\" Implement magic SAs %drop, %reject, %trap, %hold, %pass as part
+.\" of the new SPD and to support opportunistic.
+.\"
 .\" Revision 1.5  2000/09/17 18:56:48  rgb
 .\" Added IPCOMP support.
 .\"
diff -bruN freeswan-1.9.orig/klips/utils/eroute.8 freeswan-1.9/klips/utils/eroute.8
--- freeswan-1.9.orig/klips/utils/eroute.8	Sun Sep 17 14:56:48 2000
+++ freeswan-1.9/klips/utils/eroute.8	Mon Jun  4 12:56:04 2001
@@ -1,6 +1,6 @@
 .TH IPSEC_EROUTE 8 "21 Jun 2000"
 .\"
-.\" RCSID $Id: eroute.8,v 1.23 2000/09/17 18:56:48 rgb Exp $
+.\" RCSID $Id: eroute.8,v 1.24 2001/02/26 19:58:49 rgb Exp $
 .\"
 .SH NAME
 ipsec eroute \- manipulate IPSEC extended routing tables
@@ -89,23 +89,24 @@
 .IP +
 Security Association IDentifier, comprised of:
 .IP + 6
+protocol
+(\fIproto\fR), indicating (together with the
+effective destination and the security parameters index)
+which Security Association should be used to process the packet
+.IP +
 address family
 (\fIaf\fR),
 .IP +
-effective destination
-(\fIedst\fR),
-where the packet should be forwarded after processing
-(normally the other security gateway)
-.IP +
 Security Parameters Index
 (\fIspi\fR), indicating (together with the
 effective destination and protocol)
 which Security Association should be used to process the packet
+(must be larger than or equal to 0x100)
 .IP +
-protocol
-(\fIproto\fR), indicating (together with the
-effective destination and the security parameters index)
-which Security Association should be used to process the packet
+effective destination
+(\fIedst\fR),
+where the packet should be forwarded after processing
+(normally the other security gateway)
 .IP + 3
 OR
 .IP + 6
@@ -113,11 +114,32 @@
 (\fIsaid\fR), indicating 
 which Security Association should be used to process the packet
 .PP
-Addresses are written as IPv4 dotted quads or IPv6 coloned hex, protocol is one
-of "ah", "esp", "comp" or "tun" and SPIs are prefixed hexadecimal numbers where '.' represents
-IPv4 and ':' stands for IPv6.
+Addresses are written as IPv4 dotted quads or IPv6 coloned hex,
+protocol is one of "ah", "esp", "comp" or "tun" and SPIs are
+prefixed hexadecimal numbers where '.' represents IPv4 and ':'
+stands for IPv6.
 .PP
-SAIDs are written as "protoafSPI@address".
+SAIDs are written as "protoafSPI@address".  There are also 5
+"magic" SAIDs which have special meaning:
+.IP + 3
+.B %drop
+means that matches are to be dropped
+.IP +
+.B %reject
+means that matches are to be dropped and an ICMP returned, if
+possible to inform
+.IP +
+.B %trap
+means that matches are to trigger an ACQUIRE message to the Key
+Management daemon(s) and a hold eroute will be put in place to
+prevent subsequent packets also triggering ACQUIRE messages.
+.IP +
+.B %hold
+means that matches are to stored until the eroute is replaced or
+until that eroute gets reaped
+.IP +
+.B %pass
+means that matches are to allowed to pass without IPSEC processing
 .PP
 The format of /proc/net/ipsec_eroute is listed in ipsec_eroute(5).
 .br
@@ -213,6 +235,11 @@
 by Richard Guy Briggs.
 .\"
 .\" $Log: eroute.8,v $
+.\" Revision 1.24  2001/02/26 19:58:49  rgb
+.\" Added a comment on the restriction of spi > 0x100.
+.\" Implement magic SAs %drop, %reject, %trap, %hold, %pass as part
+.\" of the new SPD and to support opportunistic.
+.\"
 .\" Revision 1.23  2000/09/17 18:56:48  rgb
 .\" Added IPCOMP support.
 .\"
diff -bruN freeswan-1.9.orig/klips/utils/eroute.c freeswan-1.9/klips/utils/eroute.c
--- freeswan-1.9.orig/klips/utils/eroute.c	Sun Sep 17 14:56:48 2000
+++ freeswan-1.9/klips/utils/eroute.c	Mon Jun  4 12:56:04 2001
@@ -14,7 +14,7 @@
  * for more details.
  */
 
-char eroute_c_version[] = "RCSID $Id: eroute.c,v 1.38 2000/09/17 18:56:48 rgb Exp $";
+char eroute_c_version[] = "RCSID $Id: eroute.c,v 1.41 2001/05/21 02:02:54 rgb Exp $";
 
 
 #include <sys/types.h>
@@ -63,13 +63,14 @@
 usage(char* arg)
 {
 	fprintf(stdout, "usage: %s --{add,replace} --eraf <inet | inet6> --src <src>/<srcmaskbits>|<srcmask> --dst <dst>/<dstmaskbits>|<dstmask> <SA>\n", arg);
-	fprintf(stdout, "            where <SA> is '--af <inet | inet6> --edst <edst> --spi <spi> --proto <proto>' OR '--said <said>' OR '--said <%%passthrough | %%passthrough4 | %%passthrough6>'.\n");
+	fprintf(stdout, "            where <SA> is '--af <inet | inet6> --edst <edst> --spi <spi> --proto <proto>' OR '--said <said>' OR '--said <%%passthrough | %%passthrough4 | %%passthrough6 | %%drop | %%reject | %%trap | %%hold | %%pass>'.\n");
 	fprintf(stdout, "       %s --del --eraf <inet | inet6>--src <src>/<srcmaskbits>|<srcmask> --dst <dst>/<dstmaskbits>|<dstmask>\n", arg);
 	fprintf(stdout, "       %s --clear\n", arg);
 	fprintf(stdout, "       %s --help\n", arg);
 	fprintf(stdout, "       %s --version\n", arg);
 	fprintf(stdout, "       %s\n", arg);
 	fprintf(stdout, "        [ --debug ] is optional to any %s command.\n", arg);
+	fprintf(stdout, "        [ --label <label> ] is optional to any %s command.\n", arg);
 exit(1);
 }
 
@@ -122,20 +123,17 @@
  	int eroute_af = 0;
  	int said_af = 0;
 
-	if(argc == 1) {
-		system("cat /proc/net/ipsec_eroute");
-		exit(0);
-	}
+	int argcount = argc;
 
 	program_name = argv[0];
 	eroute_af_opt = said_af_opt = edst_opt = spi_opt = proto_opt = said_opt = dst_opt = src_opt = NULL;
 
-	while((c = getopt_long(argc, argv, "acdD:e:i:hprs:S:f:vl:+:g", longopts, 0)) != EOF)
-	{
+	while((c = getopt_long(argc, argv, ""/*"acdD:e:i:hprs:S:f:vl:+:g"*/, longopts, 0)) != EOF) {
 		switch(c) {
 		case 'g':
 			debug = 1;
 			pfkey_lib_debug = 1;
+			argcount--;
 			break;
 		case 'a':
 			if(action_type) {
@@ -210,9 +208,9 @@
 					program_name, optarg);
 				exit (1);
 			}
-			if(said.spi < 0x100) {
+			if(ntohl(said.spi) < 0x100) {
 				fprintf(stderr, "%s: Illegal reserved spi: %s => 0x%x Must be larger than 0x100.\n",
-					program_name, optarg, said.spi);
+					program_name, optarg, ntohl(said.spi));
 				exit(1);
 			}
 			spi_opt = optarg;
@@ -280,7 +278,7 @@
 				fprintf(stderr, "%s: Error, %s converting --sa argument:%s\n",
 					program_name, error_s, optarg);
 				exit (1);
-			} else if((said.spi < 0x100) && (said.spi > 0x0)){
+			} else if(ntohl(said.spi) < 0x100){
 				fprintf(stderr, "%s: Illegal reserved spi: %s => 0x%x Must be larger than or equal to 0x100.\n",
 					program_name, optarg, said.spi);
 				exit(1);
@@ -318,7 +316,13 @@
 			src_opt = optarg;
 			break;
 		case 'l':
-			program_name = optarg;
+			program_name = malloc(strlen(argv[0])
+					      + 10 /* update this when changing the sprintf() */
+					      + strlen(optarg));
+			sprintf(program_name, "%s --label %s",
+				argv[0],
+				optarg);
+			argcount -= 2;
 			break;
 		case 'i': /* specifies the address family of the SAID, stored in said_af */
 			if(said_af_opt) {
@@ -367,6 +371,11 @@
 		fprintf(stdout, "%s: DEBUG: argc=%d\n", program_name, argc);
 	}
 
+	if(argcount == 1) {
+		system("cat /proc/net/ipsec_eroute");
+		exit(0);
+	}
+
 	/* Sanity checks */
 
 	if(debug) {
@@ -699,6 +708,19 @@
 }
 /*
  * $Log: eroute.c,v $
+ * Revision 1.41  2001/05/21 02:02:54  rgb
+ * Eliminate 1-letter options.
+ *
+ * Revision 1.40  2001/05/16 04:39:57  rgb
+ * Fix --label option to add to command name rather than replace it.
+ * Fix 'print table' option to ignore --label and --debug options.
+ *
+ * Revision 1.39  2001/02/26 19:59:03  rgb
+ * Added a number of missing ntohl() conversions for debug output.
+ * Implement magic SAs %drop, %reject, %trap, %hold, %pass as part
+ * of the new SPD and to support opportunistic.
+ * Enforced spi > 0x100 requirement, now that pass uses a magic SA.
+ *
  * Revision 1.38  2000/09/17 18:56:48  rgb
  * Added IPCOMP support.
  *
diff -bruN freeswan-1.9.orig/klips/utils/klipsdebug.c freeswan-1.9/klips/utils/klipsdebug.c
--- freeswan-1.9.orig/klips/utils/klipsdebug.c	Tue Oct 10 23:56:54 2000
+++ freeswan-1.9/klips/utils/klipsdebug.c	Mon Jun  4 12:54:13 2001
@@ -14,7 +14,7 @@
  * for more details.
  */
 
-char klipsdebug_c_version[] = "RCSID $Id: klipsdebug.c,v 1.38 2000/10/11 03:56:54 rgb Exp $";
+char klipsdebug_c_version[] = "RCSID $Id: klipsdebug.c,v 1.40 2001/05/21 02:02:54 rgb Exp $";
 
 
 #include <sys/types.h>
@@ -84,6 +84,7 @@
 	fprintf(stdout, "       %s --version\n", arg);
 	fprintf(stdout, "       %s\n", arg);
 	fprintf(stdout, "        [ --debug ] is optional to any %s command\n", arg);
+	fprintf(stdout, "        [ --label <label> ] is optional to any %s command.\n", arg);
 	exit(1);
 }
 
@@ -113,24 +114,21 @@
 	struct encap_msghdr *em = (struct encap_msghdr *)bigbuf;
 	int debug = 0;
 	int error = 0;
+	int argcount = argc;
 
 	struct sadb_ext *extensions[SADB_EXT_MAX + 1];
 	struct sadb_msg *pfkey_msg;
 	
 	bitfieldp = (int *)&em->em_db_tn;
 
-	if(argc == 1) {
-		system("cat /proc/net/ipsec_klipsdebug");
-		exit(0);
-	}
-
 	program_name = argv[0];
 
-	while((c = getopt_long(argc, argv, "s:c:anhvl:+:d", longopts, 0)) != EOF) {
+	while((c = getopt_long(argc, argv, ""/*"s:c:anhvl:+:d"*/, longopts, 0)) != EOF) {
 		switch(c) {
 		case 'd':
 			debug = 1;
 			pfkey_lib_debug = 1;
+			argcount--;
 			break;
 		case 's':
 			if(action) {
@@ -247,7 +245,13 @@
 			fputs(copyright, stdout);
 			exit(0);
 		case 'l':
-			program_name = optarg;
+			program_name = malloc(strlen(argv[0])
+					      + 10 /* update this when changing the sprintf() */
+					      + strlen(optarg));
+			sprintf(program_name, "%s --label %s",
+				argv[0],
+				optarg);
+			argcount -= 2;
 			break;
 		case '+': /* optionsfrom */
 			optionsfrom(optarg, &argc, &argv, optind, stderr);
@@ -258,6 +262,11 @@
 		previous = c;
 	}
 
+	if(argcount == 1) {
+		system("cat /proc/net/ipsec_klipsdebug");
+		exit(0);
+	}
+
  	em->em_magic = EM_MAGIC;
 	em->em_version = 0;
 	if(action) {
@@ -418,6 +427,15 @@
 }
 /*
  * $Log: klipsdebug.c,v $
+ * Revision 1.40  2001/05/21 02:02:54  rgb
+ * Eliminate 1-letter options.
+ *
+ * Revision 1.39  2001/05/16 05:07:19  rgb
+ * Fixed --label option in KLIPS manual utils to add the label to the
+ * command name rather than replace it in error text.
+ * Fix 'print table' non-option in KLIPS manual utils to deal with --label
+ * and --debug options.
+ *
  * Revision 1.38  2000/10/11 03:56:54  rgb
  * Initialise verbose field to zero on --all.
  *
diff -bruN freeswan-1.9.orig/klips/utils/spi.8 freeswan-1.9/klips/utils/spi.8
--- freeswan-1.9.orig/klips/utils/spi.8	Wed Nov 29 14:15:20 2000
+++ freeswan-1.9/klips/utils/spi.8	Mon Jun  4 12:54:13 2001
@@ -1,6 +1,6 @@
 .TH IPSEC_SPI 8 "21 Jun 2000"
 .\"
-.\" RCSID $Id: spi.8,v 1.28 2000/11/29 19:15:20 rgb Exp $
+.\" RCSID $Id: spi.8,v 1.29 2001/05/30 08:14:04 rgb Exp $
 .\"
 .SH NAME
 ipsec spi \- manage IPSEC Security Associations
@@ -69,19 +69,6 @@
 .B <SA>
 .B \-\-src
 src
-.B \-\-esp
-.BR null-md5-96 | null-sha1-96
-[
-.B \-\-replay_window
-replayw ]
-.B \-\-authkey
-akey
-.PP
-.B ipsec
-.B spi
-.B <SA>
-.B \-\-src
-src
 .B \-\-comp
 .BR deflate
 .PP
@@ -289,20 +276,6 @@
 .I akey
 (RFC2451, RFC2404)
 .TP
-.B null-md5-96
-encryption using the identity transform with authentication
-provided by HMAC and MD5 (96-bit authenticator), using
-a 128-bit HMAC-MD5
-.I akey
-(RFC2410, RFC2403)
-.TP
-.B null-sha1-96
-encryption using the identity transform with authentication
-provided by HMAC and SHA1 (96-bit authenticator), using
-a 160-bit HMAC-SHA1
-.I akey
-(RFC2410, RFC2404)
-.TP
 .BR \-\-replay_window " replayw"
 sets the replay window size; valid values are decimal, 1 to 64
 .TP
@@ -452,6 +425,9 @@
 The syntax is messy and the transform naming needs work.
 .\"
 .\" $Log: spi.8,v $
+.\" Revision 1.29  2001/05/30 08:14:04  rgb
+.\" Removed vestiges of esp-null transforms.
+.\"
 .\" Revision 1.28  2000/11/29 19:15:20  rgb
 .\" Add --src requirement for inbound policy routing.
 .\"
diff -bruN freeswan-1.9.orig/klips/utils/spi.c freeswan-1.9/klips/utils/spi.c
--- freeswan-1.9.orig/klips/utils/spi.c	Sun Nov  5 23:36:57 2000
+++ freeswan-1.9/klips/utils/spi.c	Mon Jun  4 12:54:13 2001
@@ -14,7 +14,7 @@
  * for more details.
  */
 
-char spi_c_version[] = "RCSID $Id: spi.c,v 1.70 2000/11/06 04:36:57 rgb Exp $";
+char spi_c_version[] = "RCSID $Id: spi.c,v 1.73 2001/05/30 08:14:05 rgb Exp $";
 
 #include <asm/types.h>
 #include <sys/types.h>
@@ -99,7 +99,8 @@
 	where <algo> is:	3des\n\
 spi --comp <algo> <SA>\n\
 	where <algo> is:	deflate\n\
-[ --debug ] is optional to any spi command.
+[ --debug ] is optional to any spi command.\n\
+[ --label <label> ] is optional to any spi command.
 ";
 
 
@@ -315,6 +316,7 @@
 	char ipsaid_txt[SATOT_BUF];
 
 	int error = 0;
+	int argcount = argc;
 
 	unsigned char authalg, encryptalg;
 	struct sadb_ext *extensions[SADB_EXT_MAX + 1];
@@ -325,18 +327,26 @@
 	ip_address pfkey_ident_d_ska;
 #endif
 	
-	if(argc == 1) {
-		system("cat /proc/net/ipsec_spi");
-		exit(0);
-	}
-
 	program_name = argv[0];
 	memset(&said, 0, sizeof(said));
 	iv_opt = akey_opt = ekey_opt = alg_opt = edst_opt = spi_opt = proto_opt = af_opt = said_opt = dst_opt = src_opt = NULL;
 	
-	while((c = getopt_long(argc, argv, "H:P:Z:46dcA:E:e:s:a:w:i:D:S:hvgl:+:", longopts, 0)) != EOF)
-	{
+	while((c = getopt_long(argc, argv, ""/*"H:P:Z:46dcA:E:e:s:a:w:i:D:S:hvgl:+:"*/, longopts, 0)) != EOF) {
 		switch(c) {
+		case 'g':
+			debug = 1;
+			pfkey_lib_debug = 1;
+			argcount--;
+			break;
+		case 'l':
+			program_name = malloc(strlen(argv[0])
+					      + 10 /* update this when changing the sprintf() */
+					      + strlen(optarg));
+			sprintf(program_name, "%s --label %s",
+				argv[0],
+				optarg);
+			argcount -= 2;
+			break;
 		case 'H':
 			if(alg) {
 				fprintf(stderr, "%s: Only one of '--ah', '--esp', '--comp', '--ip4', '--ip6', '--del' or '--clear'  options permitted.\n",
@@ -365,10 +375,6 @@
 			}
 			if       (!strcmp(optarg, "3des-md5-96")) {
 				alg = XF_ESP3DESMD596;
-			} else if(!strcmp(optarg, "null-md5-96")) {
-				alg = XF_ESPNULLMD596;
-			} else if(!strcmp(optarg, "null-sha1-96")) {
-				alg = XF_ESPNULLSHA196;
 			} else if(!strcmp(optarg, "3des-sha1-96")) {
 				alg = XF_ESP3DESSHA196;
 			} else if(!strcmp(optarg, "3des")) {
@@ -742,13 +748,6 @@
 		case 'v':
 			fprintf(stdout, "%s, %s\n", program_name, spi_c_version);
 			exit(1);
-		case 'l':
-			program_name = optarg;
-			break;
-		case 'g':
-			debug = 1;
-			pfkey_lib_debug = 1;
-			break;
 		case '+': /* optionsfrom */
 			optionsfrom(optarg, &argc, &argv, optind, stderr);
 			/* no return on error */
@@ -760,6 +759,12 @@
 	if(debug) {
 		fprintf(stdout, "All options processed.\n");
 	}
+
+	if(argcount == 1) {
+		system("cat /proc/net/ipsec_spi");
+		exit(0);
+	}
+
 	switch(alg) {
 	case XF_IP4:
 	case XF_IP6:
@@ -768,8 +773,6 @@
 	case XF_AHHMACSHA1:
 	case XF_ESP3DESMD596:
 	case XF_ESP3DESSHA196:
-	case XF_ESPNULLMD596:
-	case XF_ESPNULLSHA196:
 	case XF_ESP3DES:
 	case XF_COMPDEFLATE:
 		if(!said_opt) {
@@ -822,8 +825,6 @@
 	case XF_AHHMACSHA1:
 	case XF_ESP3DESMD596:
 	case XF_ESP3DESSHA196:
-	case XF_ESPNULLMD596:
-	case XF_ESPNULLSHA196:
 	case XF_ESP3DES:
 	case XF_COMPDEFLATE:
 		break;
@@ -1068,12 +1069,10 @@
 	switch(alg) {
 	case XF_AHHMACMD5:
 	case XF_ESP3DESMD596:
-	case XF_ESPNULLMD596:
 		authalg = SADB_AALG_MD5HMAC;
 		break;
 	case XF_AHHMACSHA1:
 	case XF_ESP3DESSHA196:
-	case XF_ESPNULLSHA196:
 		authalg = SADB_AALG_SHA1HMAC;
 		break;
 	case XF_ESP3DESMD5:
@@ -1086,10 +1085,6 @@
 	case XF_ESP3DESSHA196:
 		encryptalg = SADB_EALG_3DESCBC;
 		break;
-	case XF_ESPNULLMD596:
-	case XF_ESPNULLSHA196:
-		encryptalg = SADB_EALG_NULL;
-		break;
 	case XF_COMPDEFLATE:
 		encryptalg = SADB_X_CALG_DEFLATE;
 		break;
@@ -1255,10 +1250,8 @@
 		switch(alg) {
 		case XF_AHHMACMD5:
 		case XF_ESP3DESMD596:
-		case XF_ESPNULLMD596:
 		case XF_AHHMACSHA1:
 		case XF_ESP3DESSHA196:
-		case XF_ESPNULLSHA196:
 			if((error = pfkey_key_build(&extensions[SADB_EXT_KEY_AUTH],
 						    SADB_EXT_KEY_AUTH,
 						    authkeylen * 8,
@@ -1479,6 +1472,18 @@
 
 /*
  * $Log: spi.c,v $
+ * Revision 1.73  2001/05/30 08:14:05  rgb
+ * Removed vestiges of esp-null transforms.
+ *
+ * Revision 1.72  2001/05/21 02:02:55  rgb
+ * Eliminate 1-letter options.
+ *
+ * Revision 1.71  2001/05/16 05:07:20  rgb
+ * Fixed --label option in KLIPS manual utils to add the label to the
+ * command name rather than replace it in error text.
+ * Fix 'print table' non-option in KLIPS manual utils to deal with --label
+ * and --debug options.
+ *
  * Revision 1.70  2000/11/06 04:36:57  rgb
  * Display conversion on replay_window failure.
  * Don't register SATYPEs for manual.
diff -bruN freeswan-1.9.orig/klips/utils/spigrp.c freeswan-1.9/klips/utils/spigrp.c
--- freeswan-1.9.orig/klips/utils/spigrp.c	Tue Jan 23 15:24:12 2001
+++ freeswan-1.9/klips/utils/spigrp.c	Mon Jun  4 12:54:13 2001
@@ -14,7 +14,7 @@
  * for more details.
  */
 
-char spigrp_c_version[] = "RCSID $Id: spigrp.c,v 1.36 2001/01/23 20:24:12 rgb Exp $";
+char spigrp_c_version[] = "RCSID $Id: spigrp.c,v 1.37 2001/05/16 05:07:20 rgb Exp $";
 
 
 #include <sys/types.h>
@@ -72,6 +72,8 @@
 	fprintf(stdout, "usage: %s --help\n", s);
 	fprintf(stdout, "usage: %s --version\n", s);
 	fprintf(stdout, "usage: %s\n", s);
+	fprintf(stdout, "        [ --debug ] is optional to any %s command.\n", s);
+	fprintf(stdout, "        [ --label <label> ] is optional to any %s command.\n", s);
 }
 
 	
@@ -119,7 +121,12 @@
 
         if(argc > 1 && strcmp(argv[1], "--label") == 0) {
 		if(argc > 2) {
-			program_name = argv[2];
+			program_name = malloc(strlen(argv[0])
+					      + 10 /* update this when changing the sprintf() */
+					      + strlen(argv[2]));
+			sprintf(program_name, "%s --label %s",
+				argv[0],
+				argv[2]);
 			if(debug) {
 				fprintf(stdout, "using \"%s\" as a label.\n", program_name);
 			}
@@ -475,6 +482,12 @@
 }
 /*
  * $Log: spigrp.c,v $
+ * Revision 1.37  2001/05/16 05:07:20  rgb
+ * Fixed --label option in KLIPS manual utils to add the label to the
+ * command name rather than replace it in error text.
+ * Fix 'print table' non-option in KLIPS manual utils to deal with --label
+ * and --debug options.
+ *
  * Revision 1.36  2001/01/23 20:24:12  rgb
  * Fix comment to reflect reality that src is not needed for grouping.
  *
diff -bruN freeswan-1.9.orig/klips/utils/tncfg.5 freeswan-1.9/klips/utils/tncfg.5
--- freeswan-1.9.orig/klips/utils/tncfg.5	Fri Jun 30 14:21:55 2000
+++ freeswan-1.9/klips/utils/tncfg.5	Mon Jun  4 12:54:13 2001
@@ -1,6 +1,6 @@
 .TH IPSEC_TNCFG 5 "27 Jun 2000"
 .\"
-.\" RCSID $Id: tncfg.5,v 1.3 2000/06/30 18:21:55 rgb Exp $
+.\" RCSID $Id: tncfg.5,v 1.4 2001/05/29 05:15:53 rgb Exp $
 .\"
 .SH NAME
 ipsec_tncfg \- lists IPSEC virtual interfaces attached to real interfaces
@@ -32,6 +32,8 @@
 .IP +
 the MTU of the ipsec virtual I/F,
 .IP +
+the automatically adjusted effective MTU for PMTU discovery, in brackets,
+.IP +
 a visual and machine parsable separator '->', separating the virtual I/F
 MTU and the physical I/F MTU,
 .IP +
@@ -39,7 +41,7 @@
 .BR 
 .SH EXAMPLES
 .TP
-.B ipsec2 -> eth3 mtu=16260 -> 1500
+.B ipsec2 -> eth3 mtu=16260(1443) -> 1500
 .LP
 shows that virtual device
 .B ipsec2
@@ -48,9 +50,12 @@
 is connected to physical device
 .B eth3
 with an MTU of
-.B 1500.
+.B 1500
+and that the effective MTU as a result of PMTU discovery has been
+automatically set to
+.BR 1443.
 .TP
-.B ipsec0 \-> wvlan0 mtu=1400 \-> 1500
+.B ipsec0 \-> wvlan0 mtu=1400(16260) \-> 1500
 .LP
 shows that virtual device
 .B ipsec0
@@ -59,9 +64,11 @@
 is connected to physical device
 .B wvlan0
 with an MTU of
-.B 1500.
+.B 1500
+and no PMTU packets have gotten far enough to bump down the effective MTU
+from its default of 16260.
 .TP
-.B ipsec3 \-> NULL mtu=0 \-> 0
+.B ipsec3 \-> NULL mtu=0(0) \-> 0
 .LP
 shows that virtual device
 .B ipsec3
@@ -79,6 +86,9 @@
 by Richard Guy Briggs.
 .\"
 .\" $Log: tncfg.5,v $
+.\" Revision 1.4  2001/05/29 05:15:53  rgb
+.\" Added PMTU to output format.
+.\"
 .\" Revision 1.3  2000/06/30 18:21:55  rgb
 .\" Update SEE ALSO sections to include ipsec_version(5) and ipsec_pf_key(5)
 .\" and correct FILES sections to no longer refer to /dev/ipsec which has
diff -bruN freeswan-1.9.orig/klips/utils/tncfg.c freeswan-1.9/klips/utils/tncfg.c
--- freeswan-1.9.orig/klips/utils/tncfg.c	Tue Sep 12 09:09:05 2000
+++ freeswan-1.9/klips/utils/tncfg.c	Mon Jun  4 12:54:13 2001
@@ -14,7 +14,7 @@
  * for more details.
  */
 
-char tncfg_c_version[] = "RCSID $Id: tncfg.c,v 1.24 2000/09/12 13:09:05 rgb Exp $";
+char tncfg_c_version[] = "RCSID $Id: tncfg.c,v 1.26 2001/05/21 02:02:55 rgb Exp $";
 
 
 #include <stdio.h>
@@ -55,6 +55,8 @@
 		name);
 	fprintf(stdout,"%s\n",
 		name);
+	fprintf(stdout, "        [ --debug ] is optional to any %s command.\n", name);
+	fprintf(stdout, "        [ --label <label> ] is optional to any %s command.\n", name);
 	exit(1);
 }
 
@@ -82,19 +84,16 @@
 	int c, previous = -1;
 	char *program_name;
 	int debug = 0;
-     
-	if(argc == 1) {
-		system("cat /proc/net/ipsec_tncfg");
-		exit(0);
-	}
+	int argcount = argc;
 
 	memset(&ifr, 0, sizeof(ifr));
 	program_name = argv[0];
 
-	while((c = getopt_long_only(argc, argv, "adchvV:P:l:+:", longopts, 0)) != EOF) {
+	while((c = getopt_long_only(argc, argv, ""/*"adchvV:P:l:+:"*/, longopts, 0)) != EOF) {
 		switch(c) {
 		case 'g':
 			debug = 1;
+			argcount--;
 			break;
 		case 'a':
 			if(shc->cf_cmd) {
@@ -135,7 +134,13 @@
 			strcpy(shc->cf_name, optarg);
 			break;
 		case 'l':
-			program_name = optarg;
+			program_name = malloc(strlen(argv[0])
+					      + 10 /* update this when changing the sprintf() */
+					      + strlen(optarg));
+			sprintf(program_name, "%s --label %s",
+				argv[0],
+				optarg);
+			argcount -= 2;
 			break;
 		case '+': /* optionsfrom */
 			optionsfrom(optarg, &argc, &argv, optind, stderr);
@@ -148,6 +153,11 @@
 		previous = c;
 	}
 
+	if(argcount == 1) {
+		system("cat /proc/net/ipsec_tncfg");
+		exit(0);
+	}
+
 	switch(shc->cf_cmd) {
 	case IPSEC_SET_DEV:
 		if(!shc->cf_name) {
@@ -263,6 +273,15 @@
 	
 /*
  * $Log: tncfg.c,v $
+ * Revision 1.26  2001/05/21 02:02:55  rgb
+ * Eliminate 1-letter options.
+ *
+ * Revision 1.25  2001/05/16 05:07:20  rgb
+ * Fixed --label option in KLIPS manual utils to add the label to the
+ * command name rather than replace it in error text.
+ * Fix 'print table' non-option in KLIPS manual utils to deal with --label
+ * and --debug options.
+ *
  * Revision 1.24  2000/09/12 13:09:05  rgb
  * Fixed real/physical discrepancy between tncfg.8 and tncfg.c.
  *
diff -bruN freeswan-1.9.orig/klips/utils/version.c freeswan-1.9/klips/utils/version.c
--- freeswan-1.9.orig/klips/utils/version.c	Mon Feb 26 18:56:08 2001
+++ freeswan-1.9/klips/utils/version.c	Thu Jun  7 14:53:56 2001
@@ -1,2 +1,2 @@
-/* silly pointless RCSID $Id: version.c,v 1.17.2.1 2001/02/26 23:56:08 henry Exp $ */
-static const char freeswan_version[] = "1.9";
+/* silly pointless RCSID $Id: version.c,v 1.19 2001/05/30 13:02:20 henry Exp $ */
+static const char freeswan_version[] = "FreeSWAN-1.9-pkix2";
diff -bruN freeswan-1.9.orig/lib/Makefile freeswan-1.9/lib/Makefile
--- freeswan-1.9.orig/lib/Makefile	Wed Oct 25 19:58:57 2000
+++ freeswan-1.9/lib/Makefile	Wed May 16 10:57:20 2001
@@ -1,5 +1,3 @@
-# FreeS/WAN library
-# Copyright (C) 1998, 1999  Henry Spencer.
 # 
 # This program is free software; you can redistribute it and/or modify it
 # under the terms of the GNU General Public License as published by the
@@ -57,11 +55,11 @@
 all:	$(EXTHDRS) $(LIB) $(EXTLIBS)
 
 install:
-	mkdir -p $(MANDIR)
+	mkdir -p $(PREFIX)/$(MANDIR)
 	for f in $(MANS) ; \
 	do \
-		$(INSTALL) $$f $(MANDIR)/ipsec_$$f || exit 1 ; \
-		../utils/manlink $(MANDIR) ipsec_$$f ; \
+		$(INSTALL) $$f $(PREFIX)/$(MANDIR)/ipsec_$$f || exit 1 ; \
+		../utils/manlink $(PREFIX)/$(MANDIR) ipsec_$$f ; \
 	done
 
 $(LIB):	$(OBJS)
diff -bruN freeswan-1.9.orig/lib/freeswan.h freeswan-1.9/lib/freeswan.h
--- freeswan-1.9.orig/lib/freeswan.h	Tue Jan 23 15:25:37 2001
+++ freeswan-1.9/lib/freeswan.h	Wed May 16 10:57:20 2001
@@ -13,7 +13,7 @@
  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
  * License for more details.
  *
- * RCSID $Id: freeswan.h,v 1.46 2001/01/23 20:25:37 rgb Exp $
+ * RCSID $Id: freeswan.h,v 1.51 2001/05/03 19:44:40 rgb Exp $
  */
 #define	_FREESWAN_H	/* seen it, no need to see it again */
 
@@ -70,6 +70,12 @@
 #define IP_SELECT_IDENT
 #endif
 
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,4)
+#define IP_SELECT_IDENT_NEW
+#define IPH_is_SKB_PULLED
+#define SKB_COW_NEW
+#endif
+
 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,50)) && defined(CONFIG_NETFILTER)
 #define SKB_RESET_NFCT
 #endif
@@ -155,6 +161,10 @@
 #define IPPROTO_COMP 108
 #endif /* !IPPROTO_COMP */
 
+#ifndef IPPROTO_INT
+#define IPPROTO_INT 61
+#endif /* !IPPROTO_INT */
+
 #ifdef CONFIG_IPSEC_DEBUG
 #define DEBUG_NO_STATIC
 #else /* CONFIG_IPSEC_DEBUG */
@@ -221,11 +231,17 @@
 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
 	int proto;		/* C. protocol */
 #		define	SA_ESP	50	/* IPPROTO_ESP */
 #		define	SA_AH	51	/* IPPROTO_AH */
 #		define	SA_IPIP	4	/* IPPROTO_IPIP */
 #		define	SA_COMP	108	/* IPPROTO_COMP */
+#		define	SA_INT	61	/* IANA reserved for internal use */
 } ip_said;
 struct sa_id {			/* old v4-only version */
         struct in_addr dst;
diff -bruN freeswan-1.9.orig/lib/pfkey.h freeswan-1.9/lib/pfkey.h
--- freeswan-1.9.orig/lib/pfkey.h	Tue Oct 10 16:10:19 2000
+++ freeswan-1.9/lib/pfkey.h	Wed May 16 10:57:20 2001
@@ -12,7 +12,7 @@
  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  * for more details.
  *
- * RCSID $Id: pfkey.h,v 1.28 2000/10/10 20:10:19 rgb Exp $
+ * RCSID $Id: pfkey.h,v 1.30 2001/02/27 07:04:52 rgb Exp $
  */
 
 #ifndef __NET_IPSEC_PF_KEY_H
@@ -55,8 +55,6 @@
 extern int pfkey_list_insert_supported(struct supported*, struct supported_list**);
 extern int pfkey_list_remove_supported(struct supported*, struct supported_list**);
 
-extern uint8_t sadb_satype2proto[];
-
 /*
 #if defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2)
  */
@@ -84,6 +82,7 @@
 
 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
@@ -231,6 +230,12 @@
 
 /*
  * $Log: pfkey.h,v $
+ * 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.
  *
diff -bruN freeswan-1.9.orig/lib/pfkey_v2_build.c freeswan-1.9/lib/pfkey_v2_build.c
--- freeswan-1.9.orig/lib/pfkey_v2_build.c	Fri Nov 17 13:10:30 2000
+++ freeswan-1.9/lib/pfkey_v2_build.c	Wed May 16 10:57:20 2001
@@ -12,14 +12,14 @@
  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  * for more details.
  *
- * RCSID $Id: pfkey_v2_build.c,v 1.21 2000/11/17 18:10:30 rgb Exp $
+ * RCSID $Id: pfkey_v2_build.c,v 1.24 2001/03/20 03:49:45 rgb Exp $
  */
 
 /*
  *		Template from klips/net/ipsec/ipsec/ipsec_parser.c.
  */
 
-char pfkey_v2_build_c_version[] = "$Id: pfkey_v2_build.c,v 1.21 2000/11/17 18:10:30 rgb Exp $";
+char pfkey_v2_build_c_version[] = "$Id: pfkey_v2_build.c,v 1.24 2001/03/20 03:49:45 rgb Exp $";
 
 /*
  * Some ugly stuff to allow consistent debugging code for use in the
@@ -41,10 +41,10 @@
 # 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;
 
 # define MALLOC(size) kmalloc(size, GFP_ATOMIC)
 # define FREE(obj) kfree(obj)
+# include <freeswan.h>
 #else /* __KERNEL__ */
 
 # include <sys/types.h>
@@ -53,6 +53,7 @@
 # include <malloc.h>
 # include <string.h> /* memset */
 
+# include <freeswan.h>
 # include "../pluto/constants.h" 
 # include "../pluto/defs.h"  /* for PRINTF_LIKE */
 # include "../pluto/log.h"  /* for debugging and DBG_log */
@@ -71,7 +72,6 @@
 # define FREE(obj) free(obj)
 #endif /* __KERNEL__ */
 
-#include <freeswan.h>
 #include <pfkeyv2.h>
 #include <pfkey.h>
 
@@ -147,33 +147,38 @@
 	DEBUGGING(
 		"pfkey_msg_hdr_build:\n");
 	DEBUGGING(
-		"pfkey_msg_hdr_build: on_entry &pfkey_ext=%p pfkey_ext=%p *pfkey_ext=%p.\n",
+		"pfkey_msg_hdr_build: "
+		"on_entry &pfkey_ext=%p pfkey_ext=%p *pfkey_ext=%p.\n",
 		&pfkey_ext,
 		pfkey_ext,
 		*pfkey_ext);
 	/* sanity checks... */
 	if(pfkey_msg) {
 		DEBUGGING(
-			"pfkey_msg_hdr_build:why is pfkey_msg already pointing to something?\n");
+			"pfkey_msg_hdr_build: "
+			"why is pfkey_msg already pointing to something?\n");
 		SENDERR(EINVAL);
 	}
 
 	if(!msg_type) {
 		DEBUGGING(
-			"pfkey_msg_hdr_build: msg type not set, must be non-zero..\n");
+			"pfkey_msg_hdr_build: "
+			"msg type not set, must be non-zero..\n");
 		SENDERR(EINVAL);
 	}
 
 	if(msg_type > SADB_MAX) {
 		DEBUGGING(
-			"pfkey_msg_hdr_build: msg type too large:%d.\n",
+			"pfkey_msg_hdr_build: "
+			"msg type too large:%d.\n",
 			msg_type);
 		SENDERR(EINVAL);
 	}
 
 	if(satype > SADB_SATYPE_MAX) {
 		DEBUGGING(
-			"pfkey_msg_hdr_build: satype %d > max %d\n", 
+			"pfkey_msg_hdr_build: "
+			"satype %d > max %d\n", 
 			satype, SADB_SATYPE_MAX);
 		SENDERR(EINVAL);
 	}
@@ -182,7 +187,8 @@
 	     pfkey_msg = (struct sadb_msg*)
 	     MALLOC(sizeof(struct sadb_msg)))) {
 		DEBUGGING(
-			"pfkey_msg_hdr_build: memory allocation failed\n");
+			"pfkey_msg_hdr_build: "
+			"memory allocation failed\n");
 		SENDERR(ENOMEM);
 	}
 	memset(pfkey_msg, 0, sizeof(struct sadb_msg));
@@ -198,7 +204,8 @@
 	pfkey_msg->sadb_msg_seq = seq;
 	pfkey_msg->sadb_msg_pid = pid;
 	DEBUGGING(
-		"pfkey_msg_hdr_build: on_exit &pfkey_ext=%p pfkey_ext=%p *pfkey_ext=%p.\n",
+		"pfkey_msg_hdr_build: "
+		"on_exit &pfkey_ext=%p pfkey_ext=%p *pfkey_ext=%p.\n",
 		&pfkey_ext,
 		pfkey_ext,
 		*pfkey_ext);
@@ -220,7 +227,8 @@
 	struct sadb_sa *pfkey_sa = (struct sadb_sa *)*pfkey_ext;
 
 	DEBUGGING(
-		    "pfkey_sa_build: spi=%08x replay=%d sa_state=%d auth=%d encrypt=%d flags=%d\n",
+		    "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,
@@ -230,29 +238,32 @@
 	/* sanity checks... */
 	if(pfkey_sa) {
 		DEBUGGING(
-			"pfkey_sa_build:why is pfkey_sa already pointing to something?\n");
+			"pfkey_sa_build: "
+			"why is pfkey_sa already pointing to something?\n");
 		SENDERR(EINVAL);
 	}
 
 	if(exttype != SADB_EXT_SA &&
 	   exttype != SADB_X_EXT_SA2) {
 		DEBUGGING(
-			"pfkey_sa_build: invalid exttype=%d.\n",
+			"pfkey_sa_build: "
+			"invalid exttype=%d.\n",
 			exttype);
 		SENDERR(EINVAL);
 	}
 
 	if(replay_window > 64) {
 		DEBUGGING(
-			"pfkey_sa_build: replay window size: %d"
-			" -- must be 0 <= size <= 64\n",
+			"pfkey_sa_build: "
+			"replay window size: %d -- must be 0 <= size <= 64\n",
 			replay_window);
 		SENDERR(EINVAL);
 	}
 
 	if(auth > SADB_AALG_MAX) {
 		DEBUGGING(
-			"pfkey_sa_build: auth=%d > SADB_AALG_MAX=%d.\n",
+			"pfkey_sa_build: "
+			"auth=%d > SADB_AALG_MAX=%d.\n",
 			auth,
 			SADB_AALG_MAX);
 		SENDERR(EINVAL);
@@ -260,7 +271,8 @@
 
 	if(encrypt > SADB_EALG_MAX) {
 		DEBUGGING(
-			"pfkey_sa_build: encrypt=%d > SADB_EALG_MAX=%d.\n",
+			"pfkey_sa_build: "
+			"encrypt=%d > SADB_EALG_MAX=%d.\n",
 			encrypt,
 			SADB_EALG_MAX);
 		SENDERR(EINVAL);
@@ -268,7 +280,8 @@
 
 	if(sa_state > SADB_SASTATE_MAX) {
 		DEBUGGING(
-			"pfkey_sa_build: sa_state=%d exceeds MAX=%d.\n",
+			"pfkey_sa_build: "
+			"sa_state=%d exceeds MAX=%d.\n",
 			sa_state,
 			SADB_SASTATE_MAX);
 		SENDERR(EINVAL);
@@ -276,7 +289,8 @@
 
 	if(sa_state == SADB_SASTATE_DEAD) {
 		DEBUGGING(
-			"pfkey_sa_build: sa_state=%d is DEAD=%d is not allowed.\n",
+			"pfkey_sa_build: "
+			"sa_state=%d is DEAD=%d is not allowed.\n",
 			sa_state,
 			SADB_SASTATE_DEAD);
 		SENDERR(EINVAL);
@@ -286,7 +300,8 @@
 	     pfkey_sa = (struct sadb_sa*)
 	     MALLOC(sizeof(struct sadb_sa)))) {
 		DEBUGGING(
-			"pfkey_sa_build: memory allocation failed\n");
+			"pfkey_sa_build: "
+			"memory allocation failed\n");
 		SENDERR(ENOMEM);
 	}
 	memset(pfkey_sa, 0, sizeof(struct sadb_sa));
@@ -320,7 +335,8 @@
 	/* sanity checks... */
 	if(pfkey_lifetime) {
 		DEBUGGING(
-			"pfkey_lifetime_build:why is pfkey_lifetime already pointing to something?\n");
+			"pfkey_lifetime_build: "
+			"why is pfkey_lifetime already pointing to something?\n");
 		SENDERR(EINVAL);
 	}
 
@@ -328,7 +344,8 @@
 	   exttype != SADB_EXT_LIFETIME_HARD &&
 	   exttype != SADB_EXT_LIFETIME_SOFT) {
 		DEBUGGING(
-			"pfkey_lifetime_build: invalid exttype=%d.\n",
+			"pfkey_lifetime_build: "
+			"invalid exttype=%d.\n",
 			exttype);
 		SENDERR(EINVAL);
 	}
@@ -337,7 +354,8 @@
 	     pfkey_lifetime = (struct sadb_lifetime*)
 	     MALLOC(sizeof(struct sadb_lifetime)))) {
 		DEBUGGING(
-			"pfkey_lifetime_build: memory allocation failed\n");
+			"pfkey_lifetime_build: "
+			"memory allocation failed\n");
 		SENDERR(ENOMEM);
 	}
 	memset(pfkey_lifetime, 0, sizeof(struct sadb_lifetime));
@@ -366,16 +384,22 @@
 	struct sadb_address *pfkey_address = (struct sadb_address *)*pfkey_ext;
 	
 	DEBUGGING(
-		"pfkey_address_build: exttype=%d proto=%d prefixlen=%d\n", exttype, proto, prefixlen);
+		"pfkey_address_build: "
+		"exttype=%d proto=%d prefixlen=%d\n",
+		exttype,
+		proto,
+		prefixlen);
 	/* sanity checks... */
 	if(pfkey_address) {
 		DEBUGGING(
-			"pfkey_address_build:why is pfkey_address already pointing to something?\n");
+			"pfkey_address_build: "
+			"why is pfkey_address already pointing to something?\n");
 		SENDERR(EINVAL);
 	}
 
 	if (!address)  {
-			DEBUGGING("pfkey_address_build: address is NULL\n");
+			DEBUGGING("pfkey_address_build: "
+				  "address is NULL\n");
 			SENDERR(EINVAL);
 	}
 	
@@ -391,7 +415,8 @@
 		break;
 	default:
 		DEBUGGING( 
-			"pfkey_address_build: unrecognised ext_type=%d.\n", 
+			"pfkey_address_build: "
+			"unrecognised ext_type=%d.\n", 
 			exttype); 
 		SENDERR(EINVAL); 
 	}
@@ -399,7 +424,8 @@
 	switch(address->sa_family) {
 	case AF_INET:
 		DEBUGGING(
-			"pfkey_address_build: found address family AF_INET.\n");
+			"pfkey_address_build: "
+			"found address family AF_INET.\n");
 		saddr_len = sizeof(struct sockaddr_in);
 		sprintf(ipaddr_txt, "%d.%d.%d.%d"
 			, (((struct sockaddr_in*)address)->sin_addr.s_addr >>  0) & 0xFF
@@ -409,7 +435,8 @@
 		break;
 	case AF_INET6:
 		DEBUGGING(
-			"pfkey_address_build: found address family AF_INET6.\n");
+			"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"
 			, ntohs(((struct sockaddr_in6*)address)->sin6_addr.s6_addr16[0])
@@ -423,17 +450,20 @@
 		break;
 	default:
 		DEBUGGING(
-			"pfkey_address_build: address->sa_family=%d not supported.\n",
+			"pfkey_address_build: "
+			"address->sa_family=%d not supported.\n",
 			address->sa_family);
 		SENDERR(EPFNOSUPPORT);
 	}
 
 	DEBUGGING(
-		"pfkey_address_build: found address=%s.\n",
+		"pfkey_address_build: "
+		"found address=%s.\n",
 		ipaddr_txt);
 	if(prefixlen != 0) {
 		DEBUGGING(
-			"pfkey_address_build: address prefixes not supported yet.\n");
+			"pfkey_address_build: "
+			"address prefixes not supported yet.\n");
 		SENDERR(EAFNOSUPPORT); /* not supported yet */
 	}
 
@@ -441,7 +471,8 @@
 	     pfkey_address = (struct sadb_address*)
 	     MALLOC(ALIGN_N(sizeof(struct sadb_address) + saddr_len, IPSEC_PFKEYv2_ALIGN) ))) {
 		DEBUGGING(
-			"pfkey_lifetime_build: memory allocation failed\n");
+			"pfkey_lifetime_build: "
+			"memory allocation failed\n");
 		SENDERR(ENOMEM);
 	}
 	memset(pfkey_address,
@@ -467,7 +498,8 @@
 	}
 #endif
 	DEBUGGING(
-		"pfkey_address_build: successful.\n");
+		"pfkey_address_build: "
+		"successful.\n");
 
  errlab:
 	return error;
@@ -487,19 +519,22 @@
 	/* sanity checks... */
 	if(pfkey_key) {
 		DEBUGGING(
-			"pfkey_key_build:why is pfkey_key already pointing to something?\n");
+			"pfkey_key_build: "
+			"why is pfkey_key already pointing to something?\n");
 		SENDERR(EINVAL);
 	}
 
 	if(!key_bits) {
 		DEBUGGING(
-			"pfkey_key_build: key_bits is zero, it must be non-zero.\n");
+			"pfkey_key_build: "
+			"key_bits is zero, it must be non-zero.\n");
 		SENDERR(EINVAL);
 	}
 
 	if( !((exttype == SADB_EXT_KEY_AUTH) || (exttype == SADB_EXT_KEY_ENCRYPT))) {
 		DEBUGGING(
-			"pfkey_key_build: unsupported extension type=%d.\n",
+			"pfkey_key_build: "
+			"unsupported extension type=%d.\n",
 			exttype);
 		SENDERR(EINVAL);
 	}
@@ -509,7 +544,8 @@
 	     MALLOC(sizeof(struct sadb_key) +
 				    DIVUP(key_bits, 64) * IPSEC_PFKEYv2_ALIGN))) {
 		DEBUGGING(
-			"pfkey_key_build: memory allocation failed\n");
+			"pfkey_key_build: "
+			"memory allocation failed\n");
 		SENDERR(ENOMEM);
 	}
 	memset(pfkey_key,
@@ -545,27 +581,31 @@
 	/* sanity checks... */
 	if(pfkey_ident) {
 		DEBUGGING(
-			"pfkey_ident_build:why is pfkey_ident already pointing to something?\n");
+			"pfkey_ident_build: "
+			"why is pfkey_ident already pointing to something?\n");
 		SENDERR(EINVAL);
 	}
 
 	if( ! ((exttype == SADB_EXT_IDENTITY_SRC) ||
 	       (exttype == SADB_EXT_IDENTITY_DST))) {
 		DEBUGGING(
-			"pfkey_ident_build: unsupported extension type=%d.\n",
+			"pfkey_ident_build: "
+			"unsupported extension type=%d.\n",
 			exttype);
 		SENDERR(EINVAL);
 	}
 
 	if((ident_type == SADB_IDENTTYPE_RESERVED)) {
 		DEBUGGING(
-			"pfkey_ident_build: ident_type must be non-zero.\n");
+			"pfkey_ident_build: "
+			"ident_type must be non-zero.\n");
 		SENDERR(EINVAL);
 	}
 
 	if(ident_type > SADB_IDENTTYPE_MAX) {
 		DEBUGGING(
-			"pfkey_ident_build: identtype=%d out of range.\n",
+			"pfkey_ident_build: "
+			"identtype=%d out of range.\n",
 			ident_type);
 		SENDERR(EINVAL);
 	}
@@ -574,7 +614,8 @@
 	    (ident_type == SADB_IDENTTYPE_FQDN)) &&
 	   !ident_string) {
 		DEBUGGING(
-			"pfkey_ident_build: string required to allocate size of extension.\n");
+			"pfkey_ident_build: "
+			"string required to allocate size of extension.\n");
 		SENDERR(EINVAL);
 	}
 	
@@ -587,7 +628,8 @@
 	     pfkey_ident = (struct sadb_ident*)
 	     MALLOC(ALIGN_N(sizeof(struct sadb_key) + strlen(ident_string), IPSEC_PFKEYv2_ALIGN)))) {
 		DEBUGGING(
-			"pfkey_ident_build: memory allocation failed\n");
+			"pfkey_ident_build: "
+			"memory allocation failed\n");
 		SENDERR(ENOMEM);
 	}
 	memset(pfkey_ident,
@@ -645,12 +687,14 @@
 	/* sanity checks... */
 	if(pfkey_sens) {
 		DEBUGGING(
-			"pfkey_sens_build:why is pfkey_sens already pointing to something?\n");
+			"pfkey_sens_build: "
+			"why is pfkey_sens already pointing to something?\n");
 		SENDERR(EINVAL);
 	}
 
 	DEBUGGING(
-		"pfkey_sens_build: Sorry, I can't build exttype=%d yet.\n",
+		"pfkey_sens_build: "
+		"Sorry, I can't build exttype=%d yet.\n",
 		(*pfkey_ext)->sadb_ext_type);
 	SENDERR(EINVAL); /* don't process these yet */
 
@@ -659,7 +703,8 @@
 	     MALLOC(sizeof(struct sadb_sens) +
 		    (sens_len + integ_len) * sizeof(uint64_t)))) {
 		DEBUGGING(
-			"pfkey_sens_build: memory allocation failed\n");
+			"pfkey_sens_build: "
+			"memory allocation failed\n");
 		SENDERR(ENOMEM);
 	}
 	memset(pfkey_sens,
@@ -707,7 +752,8 @@
 	/* sanity checks... */
 	if(pfkey_prop) {
 		DEBUGGING(
-			"pfkey_prop_build:why is pfkey_prop already pointing to something?\n");
+			"pfkey_prop_build: "
+			"why is pfkey_prop already pointing to something?\n");
 		SENDERR(EINVAL);
 	}
 
@@ -716,7 +762,8 @@
 	     MALLOC(sizeof(struct sadb_prop) +
 		    comb_num * sizeof(struct sadb_comb)))) {
 		DEBUGGING(
-			"pfkey_prop_build: memory allocation failed\n");
+			"pfkey_prop_build: "
+			"memory allocation failed\n");
 		SENDERR(ENOMEM);
 	}
 	memset(pfkey_prop,
@@ -776,13 +823,15 @@
 	/* sanity checks... */
 	if(pfkey_supported) {
 		DEBUGGING(
-			"pfkey_supported_build:why is pfkey_supported already pointing to something?\n");
+			"pfkey_supported_build: "
+			"why is pfkey_supported already pointing to something?\n");
 		SENDERR(EINVAL);
 	}
 
 	if( !((exttype == SADB_EXT_SUPPORTED_AUTH) || (exttype == SADB_EXT_SUPPORTED_ENCRYPT))) {
 		DEBUGGING(
-			"pfkey_supported_build: unsupported extension type=%d.\n",
+			"pfkey_supported_build: "
+			"unsupported extension type=%d.\n",
 			exttype);
 		SENDERR(EINVAL);
 	}
@@ -793,7 +842,8 @@
 					       alg_num *
 					       sizeof(struct sadb_alg)))) {
 		DEBUGGING(
-			"pfkey_supported_build: memory allocation failed\n");
+			"pfkey_supported_build: "
+			"memory allocation failed\n");
 		SENDERR(ENOMEM);
 	}
 	memset(pfkey_supported,
@@ -818,7 +868,8 @@
 	
 #if 0
 	DEBUGGING(
-		"pfkey_supported_build: Sorry, I can't build exttype=%d yet.\n",
+		"pfkey_supported_build: "
+		"Sorry, I can't build exttype=%d yet.\n",
 		(*pfkey_ext)->sadb_ext_type);
 	SENDERR(EINVAL); /* don't process these yet */
 
@@ -844,13 +895,15 @@
 	/* sanity checks... */
 	if(pfkey_spirange) {
 		DEBUGGING(
-			"pfkey_spirange_build:why is pfkey_spirange already pointing to something?\n");
+			"pfkey_spirange_build: "
+			"why is pfkey_spirange already pointing to something?\n");
 		SENDERR(EINVAL);
 	}
 	
         if(ntohl(max) < ntohl(min)) {
 		DEBUGGING(
-			"pfkey_spirange_build: minspi=%08x must be < maxspi=%08x.\n",
+			"pfkey_spirange_build: "
+			"minspi=%08x must be < maxspi=%08x.\n",
 			ntohl(min),
 			ntohl(max));
                 SENDERR(EINVAL);
@@ -858,7 +911,8 @@
 	
 	if(ntohl(min) <= 255) {
 		DEBUGGING(
-			"pfkey_spirange_build: minspi=%08x must be > 255.\n",
+			"pfkey_spirange_build: "
+			"minspi=%08x must be > 255.\n",
 			ntohl(min));
 		SENDERR(EEXIST);
 	}
@@ -867,7 +921,8 @@
 	     pfkey_spirange = (struct sadb_spirange*)
 	     MALLOC(sizeof(struct sadb_spirange)))) {
 		DEBUGGING(
-			"pfkey_spirange_build: memory allocation failed\n");
+			"pfkey_spirange_build: "
+			"memory allocation failed\n");
 		SENDERR(ENOMEM);
 	}
 	memset(pfkey_spirange,
@@ -893,14 +948,16 @@
 	/* sanity checks... */
 	if(pfkey_x_kmprivate) {
 		DEBUGGING(
-			"pfkey_x_kmprivate_build:why is pfkey_x_kmprivate already pointing to something?\n");
+			"pfkey_x_kmprivate_build: "
+			"why is pfkey_x_kmprivate already pointing to something?\n");
 		SENDERR(EINVAL);
 	}
 	
 	pfkey_x_kmprivate->sadb_x_kmprivate_reserved = 0;
 
 	DEBUGGING(
-		"pfkey_x_kmprivate_build: Sorry, I can't build exttype=%d yet.\n",
+		"pfkey_x_kmprivate_build: "
+		"Sorry, I can't build exttype=%d yet.\n",
 		(*pfkey_ext)->sadb_ext_type);
 	SENDERR(EINVAL); /* don't process these yet */
 
@@ -908,7 +965,8 @@
 	     pfkey_x_kmprivate = (struct sadb_x_kmprivate*)
 	     MALLOC(sizeof(struct sadb_x_kmprivate)))) {
 		DEBUGGING(
-			"pfkey_x_kmprivate_build: memory allocation failed\n");
+			"pfkey_x_kmprivate_build: "
+			"memory allocation failed\n");
 		SENDERR(ENOMEM);
 	}
 	memset(pfkey_x_kmprivate,
@@ -937,19 +995,22 @@
 	/* sanity checks... */
 	if(pfkey_x_satype) {
 		DEBUGGING(
-			"pfkey_x_satype_build:why is pfkey_x_satype already pointing to something?\n");
+			"pfkey_x_satype_build: "
+			"why is pfkey_x_satype already pointing to something?\n");
 		SENDERR(EINVAL);
 	}
 	
 	if(!satype) {
 		DEBUGGING(
-			"pfkey_x_satype_build: SA type not set, must be non-zero.\n");
+			"pfkey_x_satype_build: "
+			"SA type not set, must be non-zero.\n");
 		SENDERR(EINVAL);
 	}
 
 	if(satype > SADB_SATYPE_MAX) {
 		DEBUGGING(
-			"pfkey_x_satype_build: satype %d > max %d\n", 
+			"pfkey_x_satype_build: "
+			"satype %d > max %d\n", 
 			satype, SADB_SATYPE_MAX);
 		SENDERR(EINVAL);
 	}
@@ -957,7 +1018,8 @@
 	if(!(*pfkey_ext = (struct sadb_ext*)pfkey_x_satype = (struct sadb_x_satype*)
 	     MALLOC(sizeof(struct sadb_x_satype)))) {
 		DEBUGGING(
-			"pfkey_x_satype_build: memory allocation failed\n");
+			"pfkey_x_satype_build: "
+			"memory allocation failed\n");
 		SENDERR(ENOMEM);
 	}
 	memset(pfkey_x_satype,
@@ -1000,18 +1062,21 @@
 	/* sanity checks... */
 	if(pfkey_x_debug) {
 		DEBUGGING(
-			"pfkey_x_debug_build:why is pfkey_x_debug already pointing to something?\n");
+			"pfkey_x_debug_build: "
+			"why is pfkey_x_debug already pointing to something?\n");
 		SENDERR(EINVAL);
 	}
 	
 	DEBUGGING(
-		"pfkey_x_debug_build:tunnel=%x netlink=%x xform=%x eroute=%x spi=%x radij=%x esp=%x ah=%x rcv=%x pfkey=%x ipcomp=%x verbose=%x?\n",
+		"pfkey_x_debug_build: "
+		"tunnel=%x netlink=%x xform=%x eroute=%x spi=%x radij=%x esp=%x ah=%x rcv=%x pfkey=%x ipcomp=%x verbose=%x?\n",
 		tunnel, netlink, xform, eroute, spi, radij, esp, ah, rcv, pfkey, ipcomp, verbose);
 
 	if(!(*pfkey_ext = (struct sadb_ext*)pfkey_x_debug = (struct sadb_x_debug*)
 	     MALLOC(sizeof(struct sadb_x_debug)))) {
 		DEBUGGING(
-			"pfkey_x_debug_build: memory allocation failed\n");
+			"pfkey_x_debug_build: "
+			"memory allocation failed\n");
 		SENDERR(ENOMEM);
 	}
 #if 0
@@ -1089,7 +1154,8 @@
 	
 	if(!extensions[0]) {
 		DEBUGGING(
-			"pfkey_msg_build: extensions[0] must be specified (struct sadb_msg).\n");
+			"pfkey_msg_build: "
+			"extensions[0] must be specified (struct sadb_msg).\n");
 		SENDERR(EINVAL);
 	}
 
@@ -1102,12 +1168,14 @@
 
 	if(!(*pfkey_msg = (struct sadb_msg*)MALLOC(total_size * IPSEC_PFKEYv2_ALIGN))) {
 		DEBUGGING(
-			"pfkey_msg_build: memory allocation failed\n");
+			"pfkey_msg_build: "
+			"memory allocation failed\n");
 		SENDERR(ENOMEM);
 	}
 
 	DEBUGGING(
-		"pfkey_msg_build: pfkey_msg=%p allocated %d bytes, &(extensions[0])=%p\n",
+		"pfkey_msg_build: "
+		"pfkey_msg=%p allocated %d bytes, &(extensions[0])=%p\n",
 		*pfkey_msg,
 		total_size * IPSEC_PFKEYv2_ALIGN,
 		&(extensions[0]));
@@ -1135,7 +1203,8 @@
 				SENDERR(EINVAL);
 			}
 			DEBUGGING(
-				"pfkey_msg_build: copying %d bytes from extensions[%d]=%p to=%p\n",
+				"pfkey_msg_build: "
+				"copying %d bytes from extensions[%d]=%p to=%p\n",
 				(extensions[ext])->sadb_ext_len * IPSEC_PFKEYv2_ALIGN,
 				ext,
 				(extensions[ext]),
@@ -1151,8 +1220,8 @@
 
 	/* check required extensions */
 	DEBUGGING(
-		"pfkey_msg_build: extensions "
-		"permitted=%08x, seen=%08x, required=%08x.\n",
+		"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]);
@@ -1161,7 +1230,8 @@
 	    extensions_bitmaps[dir][EXT_BITS_REQ][(*pfkey_msg)->sadb_msg_type]) !=
 	   extensions_bitmaps[dir][EXT_BITS_REQ][(*pfkey_msg)->sadb_msg_type]) {
 		DEBUGGING(
-			"pfkey_msg_build: required extensions missing:%08x.\n",
+			"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]) );
@@ -1170,7 +1240,8 @@
 	
 	if((error = pfkey_msg_parse(*pfkey_msg, NULL, extensions_check, dir))) {
 		DEBUGGING(
-			"pfkey_msg_build: Trouble parsing newly built pfkey message, error=%d.\n",
+			"pfkey_msg_build: "
+			"Trouble parsing newly built pfkey message, error=%d.\n",
 			error);
 		SENDERR(-error);
 	}
@@ -1182,6 +1253,17 @@
 
 /*
  * $Log: pfkey_v2_build.c,v $
+ * Revision 1.24  2001/03/20 03:49:45  rgb
+ * Ditch superfluous debug_pfkey declaration.
+ * Move misplaced freeswan.h inclusion for kernel case.
+ *
+ * Revision 1.23  2001/03/16 07:41:50  rgb
+ * Put freeswan.h include before pluto includes.
+ *
+ * Revision 1.22  2001/02/27 22:24:56  rgb
+ * Re-formatting debug output (line-splitting, joining, 1arg/line).
+ * Check for satoa() return codes.
+ *
  * Revision 1.21  2000/11/17 18:10:30  rgb
  * Fixed bugs mostly relating to spirange, to treat all spi variables as
  * network byte order since this is the way PF_KEYv2 stored spis.
diff -bruN freeswan-1.9.orig/lib/pfkey_v2_ext_bits.c freeswan-1.9/lib/pfkey_v2_ext_bits.c
--- freeswan-1.9.orig/lib/pfkey_v2_ext_bits.c	Tue Sep 12 18:35:37 2000
+++ freeswan-1.9/lib/pfkey_v2_ext_bits.c	Wed May 16 10:57:20 2001
@@ -12,14 +12,14 @@
  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  * for more details.
  *
- * RCSID $Id: pfkey_v2_ext_bits.c,v 1.7 2000/09/12 22:35:37 rgb Exp $
+ * RCSID $Id: pfkey_v2_ext_bits.c,v 1.8 2001/03/26 23:07:36 rgb 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.7 2000/09/12 22:35:37 rgb Exp $";
+char pfkey_v2_ext_bits_c_version[] = "$Id: pfkey_v2_ext_bits.c,v 1.8 2001/03/26 23:07:36 rgb Exp $";
 
 /*
  * Some ugly stuff to allow consistent debugging code for use in the
@@ -226,8 +226,8 @@
 | 1<<SADB_EXT_SA
 | 1<<SADB_EXT_ADDRESS_SRC
 | 1<<SADB_EXT_ADDRESS_DST
-| 1<<SADB_EXT_KEY_AUTH
-| 1<<SADB_EXT_KEY_ENCRYPT
+/*| 1<<SADB_EXT_KEY_AUTH*/
+/*| 1<<SADB_EXT_KEY_ENCRYPT*/
 ,
 /* SADB_ADD */
 1<<SADB_EXT_RESERVED
@@ -670,6 +670,9 @@
 
 /*
  * $Log: pfkey_v2_ext_bits.c,v $
+ * 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.
  *
diff -bruN freeswan-1.9.orig/lib/pfkey_v2_parse.c freeswan-1.9/lib/pfkey_v2_parse.c
--- freeswan-1.9.orig/lib/pfkey_v2_parse.c	Fri Dec  1 02:09:00 2000
+++ freeswan-1.9/lib/pfkey_v2_parse.c	Wed May 16 10:57:20 2001
@@ -12,14 +12,14 @@
  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  * for more details.
  *
- * RCSID $Id: pfkey_v2_parse.c,v 1.31 2000/12/01 07:09:00 rgb Exp $
+ * RCSID $Id: pfkey_v2_parse.c,v 1.35 2001/05/03 19:44:51 rgb Exp $
  */
 
 /*
  *		Template from klips/net/ipsec/ipsec/ipsec_parser.c.
  */
 
-char pfkey_v2_parse_c_version[] = "$Id: pfkey_v2_parse.c,v 1.31 2000/12/01 07:09:00 rgb Exp $";
+char pfkey_v2_parse_c_version[] = "$Id: pfkey_v2_parse.c,v 1.35 2001/05/03 19:44:51 rgb Exp $";
 
 /*
  * Some ugly stuff to allow consistent debugging code for use in the
@@ -43,12 +43,14 @@
 # endif /* if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) */
 extern int debug_pfkey;
 
+# include <freeswan.h>
 #else /* __KERNEL__ */
 
 # include <sys/types.h>
 # include <linux/types.h>
 # include <linux/errno.h>
 
+# include <freeswan.h>
 # include "../pluto/constants.h" 
 # include "../pluto/defs.h"  /* for PRINTF_LIKE */
 # include "../pluto/log.h"  /* for debugging and DBG_log */
@@ -66,7 +68,6 @@
 #endif /* __KERNEL__ */
 
 
-#include <freeswan.h>
 #include <pfkeyv2.h>
 #include <pfkey.h>
 
@@ -94,13 +95,15 @@
 #ifdef CONFIG_IPSEC_IPCOMP
 	{ IPPROTO_COMP,	SADB_X_SATYPE_COMP,	"COMP" },
 #endif /* CONFIG_IPSEC_IPCOMP */
+	{ IPPROTO_INT,	SADB_X_SATYPE_INT,	"INT" },
 #else /* __KERNEL__ */
 	{ SA_ESP,	SADB_SATYPE_ESP,	"ESP"  },
 	{ SA_AH,	SADB_SATYPE_AH,		"AH"   },
 	{ SA_IPIP,	SADB_X_SATYPE_IPIP,	"IPIP" },
 	{ SA_COMP,	SADB_X_SATYPE_COMP,	"COMP" },
+	{ SA_INT,	SADB_X_SATYPE_INT,	"INT" },
 #endif /* __KERNEL__ */
-	{ 0, 0 }
+	{ 0,		0,			"UNKNOWN" }
 };
 
 uint8_t satype2proto(uint8_t satype) {
@@ -121,6 +124,15 @@
 	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;
 
@@ -130,38 +142,6 @@
 	return satype_tbl[i].name;
 }
 
-uint8_t sadb_satype2proto[] = {
-#ifdef __KERNEL__
-	0,
-	0,
-	IPPROTO_AH,
-	IPPROTO_ESP,
-	0,
-	0,
-	0,
-	0,
-	0,
-	IPPROTO_IPIP,
-#ifdef CONFIG_IPSEC_IPCOMP
-	IPPROTO_COMP
-#else /* CONFIG_IPSEC_IPCOMP */
-	0
-#endif /* CONFIG_IPSEC_IPCOMP */
-#else /* __KERNEL__ */
-	0,
-	0,
-	SA_AH,
-	SA_ESP,
-	0,
-	0,
-	0,
-	0,
-	0,
-	SA_IPIP,
-	SA_COMP
-#endif /* __KERNEL__ */
-};
-
 /* Default extension parsers taken from the KLIPS code */
 
 DEBUG_NO_STATIC int
@@ -175,13 +155,15 @@
 	/* sanity checks... */
 	if(!pfkey_sa) {
 		DEBUGGING(
-			"pfkey_sa_parse: NULL pointer passed in.\n");
+			"pfkey_sa_parse: "
+			"NULL pointer passed in.\n");
 		SENDERR(EINVAL);
 	}
 	
 	if(pfkey_sa->sadb_sa_len != sizeof(struct sadb_sa) / IPSEC_PFKEYv2_ALIGN) {
 		DEBUGGING(
-			"pfkey_sa_parse: length wrong pfkey_sa->sadb_sa_len=%d sizeof(struct sadb_sa)=%d.\n",
+			"pfkey_sa_parse: "
+			"length wrong pfkey_sa->sadb_sa_len=%d sizeof(struct sadb_sa)=%d.\n",
 			pfkey_sa->sadb_sa_len,
 			sizeof(struct sadb_sa));
 		SENDERR(EINVAL);
@@ -189,7 +171,8 @@
 	
 	if(pfkey_sa->sadb_sa_encrypt > SADB_EALG_MAX) {
 		DEBUGGING(
-			"pfkey_sa_parse: pfkey_sa->sadb_sa_encrypt=%d > SADB_EALG_MAX=%d.\n",
+			"pfkey_sa_parse: "
+			"pfkey_sa->sadb_sa_encrypt=%d > SADB_EALG_MAX=%d.\n",
 			pfkey_sa->sadb_sa_encrypt,
 			SADB_EALG_MAX);
 		SENDERR(EINVAL);
@@ -197,7 +180,8 @@
 	
 	if(pfkey_sa->sadb_sa_auth > SADB_AALG_MAX) {
 		DEBUGGING(
-			"pfkey_sa_parse: pfkey_sa->sadb_sa_auth=%d > SADB_AALG_MAX=%d.\n",
+			"pfkey_sa_parse: "
+			"pfkey_sa->sadb_sa_auth=%d > SADB_AALG_MAX=%d.\n",
 			pfkey_sa->sadb_sa_auth,
 			SADB_AALG_MAX);
 		SENDERR(EINVAL);
@@ -205,7 +189,8 @@
 	
 	if(pfkey_sa->sadb_sa_state > SADB_SASTATE_MAX) {
 		DEBUGGING(
-			"pfkey_sa_parse: state=%d exceeds MAX=%d.\n",
+			"pfkey_sa_parse: "
+			"state=%d exceeds MAX=%d.\n",
 			pfkey_sa->sadb_sa_state,
 			SADB_SASTATE_MAX);
 		SENDERR(EINVAL);
@@ -213,7 +198,8 @@
 	
 	if(pfkey_sa->sadb_sa_state == SADB_SASTATE_DEAD) {
 		DEBUGGING(
-			"pfkey_sa_parse: state=%d is DEAD=%d.\n",
+			"pfkey_sa_parse: "
+			"state=%d is DEAD=%d.\n",
 			pfkey_sa->sadb_sa_state,
 			SADB_SASTATE_DEAD);
 		SENDERR(EINVAL);
@@ -221,8 +207,8 @@
 	
 	if(pfkey_sa->sadb_sa_replay > 64) {
 		DEBUGGING(
-			"pfkey_sa_parse: replay window size: %d"
-			" -- must be 0 <= size <= 64\n",
+			"pfkey_sa_parse: "
+			"replay window size: %d -- must be 0 <= size <= 64\n",
 			pfkey_sa->sadb_sa_replay);
 		SENDERR(EINVAL);
 	}
@@ -231,14 +217,16 @@
 	      (pfkey_sa->sadb_sa_exttype ==  SADB_X_EXT_SA2)))
 	{
 		DEBUGGING(
-			"pfkey_sa_parse: unknown exttype=%d, expecting SADB_EXT_SA=%d or SADB_X_EXT_SA2=%d.\n",
+			"pfkey_sa_parse: "
+			"unknown exttype=%d, expecting SADB_EXT_SA=%d or SADB_X_EXT_SA2=%d.\n",
 			pfkey_sa->sadb_sa_exttype,
 			SADB_EXT_SA,
 			SADB_X_EXT_SA2);
 		SENDERR(EINVAL);
 	}
 	DEBUGGING(
-		"pfkey_sa_parse: successfully found len=%d exttype=%d spi=%08lx replay=%d state=%d auth=%d encrypt=%d flags=%d.\n",
+		"pfkey_sa_parse: "
+		"successfully found len=%d exttype=%d spi=%08lx replay=%d state=%d auth=%d encrypt=%d flags=%d.\n",
 		pfkey_sa->sadb_sa_len,
 		pfkey_sa->sadb_sa_exttype,
 		(long unsigned int)ntohl(pfkey_sa->sadb_sa_spi),
@@ -263,14 +251,16 @@
 	/* sanity checks... */
 	if(!pfkey_lifetime) {
 		DEBUGGING(
-			"pfkey_lifetime_parse: NULL pointer passed in.\n");
+			"pfkey_lifetime_parse: "
+			"NULL pointer passed in.\n");
 		SENDERR(EINVAL);
 	}
 
 	if(pfkey_lifetime->sadb_lifetime_len !=
 	   sizeof(struct sadb_lifetime) / IPSEC_PFKEYv2_ALIGN) {
 		DEBUGGING(
-			"pfkey_lifetime_parse: length wrong pfkey_lifetime->sadb_lifetime_len=%d sizeof(struct sadb_lifetime)=%d.\n",
+			"pfkey_lifetime_parse: "
+			"length wrong pfkey_lifetime->sadb_lifetime_len=%d sizeof(struct sadb_lifetime)=%d.\n",
 			pfkey_lifetime->sadb_lifetime_len,
 			sizeof(struct sadb_lifetime));
 		SENDERR(EINVAL);
@@ -280,7 +270,8 @@
 	   (pfkey_lifetime->sadb_lifetime_exttype != SADB_EXT_LIFETIME_SOFT) &&
 	   (pfkey_lifetime->sadb_lifetime_exttype != SADB_EXT_LIFETIME_CURRENT)) {
 		DEBUGGING( 
-			"pfkey_lifetime_parse: unexpected ext_type=%d.\n", 
+			"pfkey_lifetime_parse: "
+			"unexpected ext_type=%d.\n", 
 			pfkey_lifetime->sadb_lifetime_exttype); 
 		SENDERR(EINVAL);
 	}
@@ -303,7 +294,8 @@
 	/* sanity checks... */
 	if(!pfkey_address) {
 		DEBUGGING(
-			"pfkey_address_parse: NULL pointer passed in.\n");
+			"pfkey_address_parse: "
+			"NULL pointer passed in.\n");
 		SENDERR(EINVAL);
 	}
 	
@@ -311,7 +303,8 @@
 	   (sizeof(struct sadb_address) + sizeof(struct sockaddr))/
 	   IPSEC_PFKEYv2_ALIGN) {
 		DEBUGGING(
-			"pfkey_address_parse: size wrong 1 ext_len=%d, adr_ext_len=%d, saddr_len=%d.\n",
+			"pfkey_address_parse: "
+			"size wrong 1 ext_len=%d, adr_ext_len=%d, saddr_len=%d.\n",
 			pfkey_address->sadb_address_len,
 			sizeof(struct sadb_address),
 			sizeof(struct sockaddr));
@@ -320,7 +313,8 @@
 	
 	if(pfkey_address->sadb_address_reserved) {
 		DEBUGGING(
-			"pfkey_address_parse: res=%d, must be zero.\n",
+			"pfkey_address_parse: "
+			"res=%d, must be zero.\n",
 			pfkey_address->sadb_address_reserved);
 		SENDERR(EINVAL);
 	}
@@ -337,7 +331,8 @@
 		break;
 	default:
 		DEBUGGING( 
-			"pfkey_address_parse: unexpected ext_type=%d.\n", 
+			"pfkey_address_parse: "
+			"unexpected ext_type=%d.\n", 
 			pfkey_address->sadb_address_exttype); 
 		SENDERR(EINVAL); 
 	}
@@ -345,7 +340,8 @@
 	switch(s->sa_family) {
 	case AF_INET:
 		DEBUGGING(
-			"pfkey_address_parse: found address family=%d, AF_INET.\n",
+			"pfkey_address_parse: "
+			"found address family=%d, AF_INET.\n",
 			s->sa_family);
 		saddr_len = sizeof(struct sockaddr_in);
 		sprintf(ipaddr_txt, "%d.%d.%d.%d"
@@ -354,12 +350,14 @@
 			, (((struct sockaddr_in*)s)->sin_addr.s_addr >> 16) & 0xFF
 			, (((struct sockaddr_in*)s)->sin_addr.s_addr >> 24) & 0xFF);
 		DEBUGGING(
-			"pfkey_address_parse: found address=%s.\n",
+			"pfkey_address_parse: "
+			"found address=%s.\n",
 			ipaddr_txt);
 		break;
 	case AF_INET6:
 		DEBUGGING(
-			"pfkey_address_parse: found address family=%d, AF_INET6.\n",
+			"pfkey_address_parse: "
+			"found address family=%d, AF_INET6.\n",
 			s->sa_family);
 		saddr_len = sizeof(struct sockaddr_in6);
 		sprintf(ipaddr_txt, "%x:%x:%x:%x:%x:%x:%x:%x"
@@ -372,12 +370,14 @@
 			, ntohs(((struct sockaddr_in6*)s)->sin6_addr.s6_addr16[6])
 			, ntohs(((struct sockaddr_in6*)s)->sin6_addr.s6_addr16[7]));
 		DEBUGGING(
-			"pfkey_address_parse: found address=%s.\n",
+			"pfkey_address_parse: "
+			"found address=%s.\n",
 			ipaddr_txt);
 		break;
 	default:
 		DEBUGGING(
-			"pfkey_address_parse: s->sa_family=%d not supported.\n",
+			"pfkey_address_parse: "
+			"s->sa_family=%d not supported.\n",
 			s->sa_family);
 		SENDERR(EPFNOSUPPORT);
 	}
@@ -385,7 +385,8 @@
 	if(pfkey_address->sadb_address_len !=
 	   DIVUP(sizeof(struct sadb_address) + saddr_len, IPSEC_PFKEYv2_ALIGN)) {
 		DEBUGGING(
-			"pfkey_address_parse: size wrong 2 ext_len=%d, adr_ext_len=%d, saddr_len=%d.\n",
+			"pfkey_address_parse: "
+			"size wrong 2 ext_len=%d, adr_ext_len=%d, saddr_len=%d.\n",
 			pfkey_address->sadb_address_len,
 			sizeof(struct sadb_address),
 			saddr_len);
@@ -394,7 +395,8 @@
 	
 	if(pfkey_address->sadb_address_prefixlen != 0) {
 		DEBUGGING(
-			"pfkey_address_parse: address prefixes not supported yet.\n");
+			"pfkey_address_parse: "
+			"address prefixes not supported yet.\n");
 		SENDERR(EAFNOSUPPORT); /* not supported yet */
 	}
 	
@@ -418,13 +420,15 @@
 
 	if(!pfkey_key) {
 		DEBUGGING(
-			"pfkey_key_parse: NULL pointer passed in.\n");
+			"pfkey_key_parse: "
+			"NULL pointer passed in.\n");
 		SENDERR(EINVAL);
 	}
 
 	if(pfkey_key->sadb_key_len < sizeof(struct sadb_key) / IPSEC_PFKEYv2_ALIGN) {
 		DEBUGGING(
-			"pfkey_key_parse: size wrong ext_len=%d, key_ext_len=%d.\n",
+			"pfkey_key_parse: "
+			"size wrong ext_len=%d, key_ext_len=%d.\n",
 			pfkey_key->sadb_key_len,
 			sizeof(struct sadb_key));
 		SENDERR(EINVAL);
@@ -432,7 +436,8 @@
 
 	if(!pfkey_key->sadb_key_bits) {
 		DEBUGGING(
-			"pfkey_key_parse: key length set to zero, must be non-zero.\n");
+			"pfkey_key_parse: "
+			"key length set to zero, must be non-zero.\n");
 		SENDERR(EINVAL);
 	}
 
@@ -440,7 +445,8 @@
 	   DIVUP(sizeof(struct sadb_key) * OCTETBITS + pfkey_key->sadb_key_bits,
 		 PFKEYBITS)) {
 		DEBUGGING(
-			"pfkey_key_parse: key length=%d does not agree with extension length=%d.\n",
+			"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);
@@ -448,7 +454,8 @@
 	
 	if(pfkey_key->sadb_key_reserved) {
 		DEBUGGING(
-			"pfkey_key_parse: res=%d, must be zero.\n",
+			"pfkey_key_parse: "
+			"res=%d, must be zero.\n",
 			pfkey_key->sadb_key_reserved);
 		SENDERR(EINVAL);
 	}
@@ -456,13 +463,15 @@
 	if(! ( (pfkey_key->sadb_key_exttype == SADB_EXT_KEY_AUTH) ||
 	       (pfkey_key->sadb_key_exttype == SADB_EXT_KEY_ENCRYPT))) {
 		DEBUGGING(
-			"pfkey_key_parse: expecting extension type AUTH or ENCRYPT, got %d.\n",
+			"pfkey_key_parse: "
+			"expecting extension type AUTH or ENCRYPT, got %d.\n",
 			pfkey_key->sadb_key_exttype);
 		SENDERR(EINVAL);
 	}
 
 	DEBUGGING(
-		"pfkey_key_parse: success, found len=%d exttype=%d bits=%d reserved=%d.\n",
+		"pfkey_key_parse: "
+		"success, found len=%d exttype=%d bits=%d reserved=%d.\n",
 		pfkey_key->sadb_key_len,
 		pfkey_key->sadb_key_exttype,
 		pfkey_key->sadb_key_bits,
@@ -481,7 +490,8 @@
 	/* sanity checks... */
 	if(pfkey_ident->sadb_ident_len < sizeof(struct sadb_ident) / IPSEC_PFKEYv2_ALIGN) {
 		DEBUGGING(
-			"pfkey_ident_parse: size wrong ext_len=%d, key_ext_len=%d.\n",
+			"pfkey_ident_parse: "
+			"size wrong ext_len=%d, key_ext_len=%d.\n",
 			pfkey_ident->sadb_ident_len,
 			sizeof(struct sadb_ident));
 		SENDERR(EINVAL);
@@ -489,7 +499,8 @@
 
 	if(pfkey_ident->sadb_ident_type > SADB_IDENTTYPE_MAX) {
 		DEBUGGING(
-			"pfkey_ident_parse: ident_type=%d out of range, must be less than %d.\n",
+			"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);
@@ -497,7 +508,8 @@
 
 	if(pfkey_ident->sadb_ident_reserved) {
 		DEBUGGING(
-			"pfkey_ident_parse: res=%d, must be zero.\n",
+			"pfkey_ident_parse: "
+			"res=%d, must be zero.\n",
 			pfkey_ident->sadb_ident_reserved);
 		SENDERR(EINVAL);
 	}
@@ -506,7 +518,8 @@
 	if(pfkey_ident->sadb_ident_len > sizeof(struct sadb_ident) / IPSEC_PFKEYv2_ALIGN) {
 		if(*((char*)pfkey_ident + pfkey_ident->sadb_ident_len * IPSEC_PFKEYv2_ALIGN - 1)) {
 			DEBUGGING(
-				"pfkey_ident_parse: string padding must be zero, last is 0x%02x.\n",
+				"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);
@@ -516,7 +529,8 @@
 	if( ! ((pfkey_ident->sadb_ident_exttype == SADB_EXT_IDENTITY_SRC) ||
 	       (pfkey_ident->sadb_ident_exttype == SADB_EXT_IDENTITY_DST))) {
 		DEBUGGING(
-			"pfkey_key_parse: expecting extension type IDENTITY_SRC or IDENTITY_DST, got %d.\n",
+			"pfkey_key_parse: "
+			"expecting extension type IDENTITY_SRC or IDENTITY_DST, got %d.\n",
 			pfkey_ident->sadb_ident_exttype);
 		SENDERR(EINVAL);
 	}
@@ -534,14 +548,16 @@
 	/* sanity checks... */
 	if(pfkey_sens->sadb_sens_len < sizeof(struct sadb_sens) / IPSEC_PFKEYv2_ALIGN) {
 		DEBUGGING(
-			"pfkey_sens_parse: size wrong ext_len=%d, key_ext_len=%d.\n",
+			"pfkey_sens_parse: "
+			"size wrong ext_len=%d, key_ext_len=%d.\n",
 			pfkey_sens->sadb_sens_len,
 			sizeof(struct sadb_sens));
 		SENDERR(EINVAL);
 	}
 
 	DEBUGGING(
-		"pfkey_sens_parse: Sorry, I can't parse exttype=%d yet.\n",
+		"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 */
@@ -563,7 +579,8 @@
 	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(
-			"pfkey_prop_parse: size wrong ext_len=%d, prop_ext_len=%d comb_ext_len=%d.\n",
+			"pfkey_prop_parse: "
+			"size wrong ext_len=%d, prop_ext_len=%d comb_ext_len=%d.\n",
 			pfkey_prop->sadb_prop_len,
 			sizeof(struct sadb_prop),
 			sizeof(struct sadb_comb));
@@ -572,8 +589,8 @@
 
 	if(pfkey_prop->sadb_prop_replay > 64) {
 		DEBUGGING(
-			"pfkey_prop_parse: replay window size: %d"
-			" -- must be 0 <= size <= 64\n",
+			"pfkey_prop_parse: "
+			"replay window size: %d -- must be 0 <= size <= 64\n",
 			pfkey_prop->sadb_prop_replay);
 		SENDERR(EINVAL);
 	}
@@ -581,7 +598,8 @@
 	for(i=0; i<3; i++) {
 		if(pfkey_prop->sadb_prop_reserved[i]) {
 			DEBUGGING(
-				"pfkey_prop_parse: res[%d]=%d, must be zero.\n",
+				"pfkey_prop_parse: "
+				"res[%d]=%d, must be zero.\n",
 				i, pfkey_prop->sadb_prop_reserved[i]);
 			SENDERR(EINVAL);
 		}
@@ -592,7 +610,8 @@
 	for(i = 0; i < num_comb; i++) {
 		if(pfkey_comb->sadb_comb_auth > SADB_AALG_MAX) {
 			DEBUGGING(
-				"pfkey_prop_parse: pfkey_comb[%d]->sadb_comb_auth=%d > SADB_AALG_MAX=%d.\n",
+				"pfkey_prop_parse: "
+				"pfkey_comb[%d]->sadb_comb_auth=%d > SADB_AALG_MAX=%d.\n",
 				i,
 				pfkey_comb->sadb_comb_auth,
 				SADB_AALG_MAX);
@@ -602,19 +621,22 @@
 		if(pfkey_comb->sadb_comb_auth) {
 			if(!pfkey_comb->sadb_comb_auth_minbits) {
 				DEBUGGING(
-					"pfkey_prop_parse: pfkey_comb[%d]->sadb_comb_auth_minbits=0, fatal.\n",
+					"pfkey_prop_parse: "
+					"pfkey_comb[%d]->sadb_comb_auth_minbits=0, fatal.\n",
 					i);
 				SENDERR(EINVAL);
 			}
 			if(!pfkey_comb->sadb_comb_auth_maxbits) {
 				DEBUGGING(
-					"pfkey_prop_parse: pfkey_comb[%d]->sadb_comb_auth_maxbits=0, fatal.\n",
+					"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(
-					"pfkey_prop_parse: pfkey_comb[%d]->sadb_comb_auth_minbits=%d > maxbits=%d, fatal.\n",
+					"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);
@@ -623,14 +645,16 @@
 		} else {
 			if(pfkey_comb->sadb_comb_auth_minbits) {
 				DEBUGGING(
-					"pfkey_prop_parse: pfkey_comb[%d]->sadb_comb_auth_minbits=%d != 0, fatal.\n",
+					"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(
-					"pfkey_prop_parse: pfkey_comb[%d]->sadb_comb_auth_maxbits=%d != 0, fatal.\n",
+					"pfkey_prop_parse: "
+					"pfkey_comb[%d]->sadb_comb_auth_maxbits=%d != 0, fatal.\n",
 					i,
 					pfkey_comb->sadb_comb_auth_maxbits);
 				SENDERR(EINVAL);
@@ -639,7 +663,8 @@
 
 		if(pfkey_comb->sadb_comb_encrypt > SADB_EALG_MAX) {
 			DEBUGGING(
-				"pfkey_comb_parse: pfkey_comb[%d]->sadb_comb_encrypt=%d > SADB_EALG_MAX=%d.\n",
+				"pfkey_comb_parse: "
+				"pfkey_comb[%d]->sadb_comb_encrypt=%d > SADB_EALG_MAX=%d.\n",
 				i,
 				pfkey_comb->sadb_comb_encrypt,
 				SADB_EALG_MAX);
@@ -649,19 +674,22 @@
 		if(pfkey_comb->sadb_comb_encrypt) {
 			if(!pfkey_comb->sadb_comb_encrypt_minbits) {
 				DEBUGGING(
-					"pfkey_prop_parse: pfkey_comb[%d]->sadb_comb_encrypt_minbits=0, fatal.\n",
+					"pfkey_prop_parse: "
+					"pfkey_comb[%d]->sadb_comb_encrypt_minbits=0, fatal.\n",
 					i);
 				SENDERR(EINVAL);
 			}
 			if(!pfkey_comb->sadb_comb_encrypt_maxbits) {
 				DEBUGGING(
-					"pfkey_prop_parse: pfkey_comb[%d]->sadb_comb_encrypt_maxbits=0, fatal.\n",
+					"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(
-					"pfkey_prop_parse: pfkey_comb[%d]->sadb_comb_encrypt_minbits=%d > maxbits=%d, fatal.\n",
+					"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);
@@ -670,14 +698,16 @@
 		} else {
 			if(pfkey_comb->sadb_comb_encrypt_minbits) {
 				DEBUGGING(
-					"pfkey_prop_parse: pfkey_comb[%d]->sadb_comb_encrypt_minbits=%d != 0, fatal.\n",
+					"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(
-					"pfkey_prop_parse: pfkey_comb[%d]->sadb_comb_encrypt_maxbits=%d != 0, fatal.\n",
+					"pfkey_prop_parse: "
+					"pfkey_comb[%d]->sadb_comb_encrypt_maxbits=%d != 0, fatal.\n",
 					i,
 					pfkey_comb->sadb_comb_encrypt_maxbits);
 				SENDERR(EINVAL);
@@ -688,7 +718,8 @@
 
 		if(pfkey_comb->sadb_comb_hard_allocations && pfkey_comb->sadb_comb_soft_allocations > pfkey_comb->sadb_comb_hard_allocations) {
 			DEBUGGING(
-				"pfkey_prop_parse: pfkey_comb[%d]->sadb_comb_soft_allocations=%d > hard_allocations=%d, fatal.\n",
+				"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);
@@ -697,7 +728,8 @@
 
 		if(pfkey_comb->sadb_comb_hard_bytes && pfkey_comb->sadb_comb_soft_bytes > pfkey_comb->sadb_comb_hard_bytes) {
 			DEBUGGING(
-				"pfkey_prop_parse: pfkey_comb[%d]->sadb_comb_soft_bytes=%Ld > hard_bytes=%Ld, fatal.\n",
+				"pfkey_prop_parse: "
+				"pfkey_comb[%d]->sadb_comb_soft_bytes=%Ld > hard_bytes=%Ld, fatal.\n",
 				i,
 				pfkey_comb->sadb_comb_soft_bytes,
 				pfkey_comb->sadb_comb_hard_bytes);
@@ -706,7 +738,8 @@
 
 		if(pfkey_comb->sadb_comb_hard_addtime && pfkey_comb->sadb_comb_soft_addtime > pfkey_comb->sadb_comb_hard_addtime) {
 			DEBUGGING(
-				"pfkey_prop_parse: pfkey_comb[%d]->sadb_comb_soft_addtime=%Ld > hard_addtime=%Ld, fatal.\n",
+				"pfkey_prop_parse: "
+				"pfkey_comb[%d]->sadb_comb_soft_addtime=%Ld > hard_addtime=%Ld, fatal.\n",
 				i,
 				pfkey_comb->sadb_comb_soft_addtime,
 				pfkey_comb->sadb_comb_hard_addtime);
@@ -715,7 +748,8 @@
 
 		if(pfkey_comb->sadb_comb_hard_usetime && pfkey_comb->sadb_comb_soft_usetime > pfkey_comb->sadb_comb_hard_usetime) {
 			DEBUGGING(
-				"pfkey_prop_parse: pfkey_comb[%d]->sadb_comb_soft_usetime=%Ld > hard_usetime=%Ld, fatal.\n",
+				"pfkey_prop_parse: "
+				"pfkey_comb[%d]->sadb_comb_soft_usetime=%Ld > hard_usetime=%Ld, fatal.\n",
 				i,
 				pfkey_comb->sadb_comb_soft_usetime,
 				pfkey_comb->sadb_comb_hard_usetime);
@@ -724,7 +758,8 @@
 
 		if(pfkey_comb->sadb_comb_reserved) {
 			DEBUGGING(
-				"pfkey_prop_parse: comb[%d].res=%d, must be zero.\n",
+				"pfkey_prop_parse: "
+				"comb[%d].res=%d, must be zero.\n",
 				i,
 				pfkey_comb->sadb_comb_reserved);
 			SENDERR(EINVAL);
@@ -751,7 +786,8 @@
 	     sizeof(struct sadb_supported)) % sizeof(struct sadb_alg))) {
 
 		DEBUGGING(
-			"pfkey_supported_parse: size wrong ext_len=%d, supported_ext_len=%d alg_ext_len=%d.\n",
+			"pfkey_supported_parse: "
+			"size wrong ext_len=%d, supported_ext_len=%d alg_ext_len=%d.\n",
 			pfkey_supported->sadb_supported_len,
 			sizeof(struct sadb_supported),
 			sizeof(struct sadb_alg));
@@ -760,7 +796,8 @@
 
 	if(pfkey_supported->sadb_supported_reserved) {
 		DEBUGGING(
-			"pfkey_supported_parse: res=%d, must be zero.\n",
+			"pfkey_supported_parse: "
+			"res=%d, must be zero.\n",
 			pfkey_supported->sadb_supported_reserved);
 		SENDERR(EINVAL);
 	}
@@ -771,7 +808,8 @@
 		/* process algo description */
 		if(pfkey_alg->sadb_alg_reserved) {
 			DEBUGGING(
-				"pfkey_supported_parse: alg[%d], id=%d, ivlen=%d, minbits=%d, maxbits=%d, res=%d, must be zero.\n",
+				"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,
@@ -789,7 +827,8 @@
 		case SADB_EXT_SUPPORTED_AUTH:
 			if(pfkey_alg->sadb_alg_id > SADB_AALG_MAX) {
 				DEBUGGING(
-					"pfkey_supported_parse: alg[%d], alg_id=%d > SADB_AALG_MAX=%d, fatal.\n",
+					"pfkey_supported_parse: "
+					"alg[%d], alg_id=%d > SADB_AALG_MAX=%d, fatal.\n",
 					i,
 					pfkey_alg->sadb_alg_id,
 					SADB_AALG_MAX);
@@ -799,7 +838,8 @@
 		case SADB_EXT_SUPPORTED_ENCRYPT:
 			if(pfkey_alg->sadb_alg_id > SADB_EALG_MAX) {
 				DEBUGGING(
-					"pfkey_supported_parse: alg[%d], alg_id=%d > SADB_EALG_MAX=%d, fatal.\n",
+					"pfkey_supported_parse: "
+					"alg[%d], alg_id=%d > SADB_EALG_MAX=%d, fatal.\n",
 					i,
 					pfkey_alg->sadb_alg_id,
 					SADB_EALG_MAX);
@@ -808,7 +848,8 @@
 			break;
 		default:
 			DEBUGGING(
-				"pfkey_supported_parse: alg[%d], alg_id=%d > SADB_EALG_MAX=%d, fatal.\n",
+				"pfkey_supported_parse: "
+				"alg[%d], alg_id=%d > SADB_EALG_MAX=%d, fatal.\n",
 				i,
 				pfkey_alg->sadb_alg_id,
 				SADB_EALG_MAX);
@@ -831,7 +872,8 @@
         if(pfkey_spirange->sadb_spirange_len !=
 	   sizeof(struct sadb_spirange) / IPSEC_PFKEYv2_ALIGN) {
 		DEBUGGING(
-			"pfkey_spirange_parse: size wrong ext_len=%d, key_ext_len=%d.\n",
+			"pfkey_spirange_parse: "
+			"size wrong ext_len=%d, key_ext_len=%d.\n",
 			pfkey_spirange->sadb_spirange_len,
 			sizeof(struct sadb_spirange));
                 SENDERR(EINVAL);
@@ -839,14 +881,16 @@
 	
         if(pfkey_spirange->sadb_spirange_reserved) {
 		DEBUGGING(
-			" pfkey_spirange_parse: reserved=%d must be set to zero.\n",
+			"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(
-			" pfkey_spirange_parse: minspi=%08x must be < maxspi=%08x.\n",
+			"pfkey_spirange_parse: "
+			"minspi=%08x must be < maxspi=%08x.\n",
 			ntohl(pfkey_spirange->sadb_spirange_min),
 			ntohl(pfkey_spirange->sadb_spirange_max));
                 SENDERR(EINVAL);
@@ -854,7 +898,8 @@
 	
 	if(ntohl(pfkey_spirange->sadb_spirange_min) <= 255) {
 		DEBUGGING(
-			" pfkey_spirange_parse: minspi=%08x must be > 255.\n",
+			"pfkey_spirange_parse: "
+			"minspi=%08x must be > 255.\n",
 			ntohl(pfkey_spirange->sadb_spirange_min));
 		SENDERR(EEXIST);
 	}
@@ -873,7 +918,8 @@
 	if(pfkey_x_kmprivate->sadb_x_kmprivate_len <
 	   sizeof(struct sadb_x_kmprivate) / IPSEC_PFKEYv2_ALIGN) {
 		DEBUGGING(
-			"pfkey_x_kmprivate_parse: size wrong ext_len=%d, key_ext_len=%d.\n",
+			"pfkey_x_kmprivate_parse: "
+			"size wrong ext_len=%d, key_ext_len=%d.\n",
 			pfkey_x_kmprivate->sadb_x_kmprivate_len,
 			sizeof(struct sadb_x_kmprivate));
 		SENDERR(EINVAL);
@@ -881,13 +927,15 @@
 
 	if(pfkey_x_kmprivate->sadb_x_kmprivate_reserved) {
 		DEBUGGING(
-			" pfkey_x_kmprivate_parse: reserved=%d must be set to zero.\n",
+			"pfkey_x_kmprivate_parse: "
+			"reserved=%d must be set to zero.\n",
 			pfkey_x_kmprivate->sadb_x_kmprivate_reserved);
 		SENDERR(EINVAL);
 	}
 
 	DEBUGGING(
-		"pfkey_x_kmprivate_parse: Sorry, I can't parse exttype=%d yet.\n",
+		"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 */
 
@@ -908,7 +956,8 @@
 	if(pfkey_x_satype->sadb_x_satype_len !=
 	   sizeof(struct sadb_x_satype) / IPSEC_PFKEYv2_ALIGN) {
 		DEBUGGING(
-			"pfkey_x_satype_parse: size wrong ext_len=%d, key_ext_len=%d.\n",
+			"pfkey_x_satype_parse: "
+			"size wrong ext_len=%d, key_ext_len=%d.\n",
 			pfkey_x_satype->sadb_x_satype_len,
 			sizeof(struct sadb_x_satype));
 		SENDERR(EINVAL);
@@ -916,20 +965,23 @@
 	
 	if(!pfkey_x_satype->sadb_x_satype_satype) {
 		DEBUGGING(
-			"pfkey_x_satype_parse: satype is zero, must be non-zero.\n");
+			"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(
-			"pfkey_x_satype_parse: satype %d > max %d\n", 
+			"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(
-			"pfkey_x_satype_parse: proto lookup from satype=%d failed.\n",
+			"pfkey_x_satype_parse: "
+			"proto lookup from satype=%d failed.\n",
 			pfkey_x_satype->sadb_x_satype_satype);
 		SENDERR(EINVAL);
 	}
@@ -937,7 +989,8 @@
 	for(i = 0; i < 3; i++) {
 		if(pfkey_x_satype->sadb_x_satype_reserved[i]) {
 			DEBUGGING(
-				" pfkey_x_satype_parse: reserved[%d]=%d must be set to zero.\n",
+				"pfkey_x_satype_parse: "
+				"reserved[%d]=%d must be set to zero.\n",
 				i, pfkey_x_satype->sadb_x_satype_reserved[i]);
 			SENDERR(EINVAL);
 		}
@@ -960,7 +1013,8 @@
 	if(pfkey_x_debug->sadb_x_debug_len !=
 	   sizeof(struct sadb_x_debug) / IPSEC_PFKEYv2_ALIGN) {
 		DEBUGGING(
-			"pfkey_x_debug_parse: size wrong ext_len=%d, key_ext_len=%d.\n",
+			"pfkey_x_debug_parse: "
+			"size wrong ext_len=%d, key_ext_len=%d.\n",
 			pfkey_x_debug->sadb_x_debug_len,
 			sizeof(struct sadb_x_debug));
 		SENDERR(EINVAL);
@@ -969,7 +1023,8 @@
 	for(i = 0; i < 4; i++) {
 		if(pfkey_x_debug->sadb_x_debug_reserved[i]) {
 			DEBUGGING(
-				" pfkey_x_debug_parse: reserved[%d]=%d must be set to zero.\n",
+				"pfkey_x_debug_parse: "
+				"reserved[%d]=%d must be set to zero.\n",
 				i, pfkey_x_debug->sadb_x_debug_reserved[i]);
 			SENDERR(EINVAL);
 		}
@@ -1021,12 +1076,13 @@
 	int extensions_seen = 0;
 	
 	DEBUGGING(
-		"pfkey_msg_parse: parsing message "
-		"ver=%d, type=%d, errno=%d, satype=%d, len=%d, res=%d, seq=%d, pid=%d.\n", 
+		"pfkey_msg_parse: "
+		"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,
@@ -1056,13 +1112,15 @@
 
 	if(!pfkey_msg->sadb_msg_type) {
 		DEBUGGING(
-			"pfkey_msg_parse: msg type not set, must be non-zero..\n");
+			"pfkey_msg_parse: "
+			"msg type not set, must be non-zero..\n");
 		SENDERR(EINVAL);
 	}
 
 	if(pfkey_msg->sadb_msg_type > SADB_MAX) {
 		DEBUGGING(
-			"pfkey_msg_parse: msg type=%d > max=%d.\n",
+			"pfkey_msg_parse: "
+			"msg type=%d > max=%d.\n",
 			pfkey_msg->sadb_msg_type,
 			SADB_MAX);
 		SENDERR(EINVAL);
@@ -1074,33 +1132,34 @@
 	case SADB_ADD:
 	case SADB_DELETE:
 	case SADB_GET:
-	case SADB_ACQUIRE:
-	case SADB_REGISTER:
-	case SADB_EXPIRE:
-#if 0
-	case SADB_X_PROMISC:
-	case SADB_X_PCHANGE:
-#endif
 	case SADB_X_GRPSA:
-		if(!pfkey_msg->sadb_msg_satype) {
+	case SADB_X_ADDFLOW:
+		if(!satype2proto(pfkey_msg->sadb_msg_satype)) {
 			DEBUGGING(
-				"pfkey_msg_parse: satype is zero, must be non-zero for msg_type %d.\n", pfkey_msg->sadb_msg_type);
+				"pfkey_msg_parse: "
+				"satype %d conversion to proto failed for msg_type %d.\n",
+				pfkey_msg->sadb_msg_satype,
+				pfkey_msg->sadb_msg_type);
 			SENDERR(EINVAL);
+		} else {
+			DEBUGGING(
+				"pfkey_msg_parse: "
+				"satype %d(%s) conversion to proto gives %d for msg_type %d.\n",
+				pfkey_msg->sadb_msg_satype,
+				satype2name(pfkey_msg->sadb_msg_satype),
+				satype2proto(pfkey_msg->sadb_msg_satype),
+				pfkey_msg->sadb_msg_type);
 		}
-		switch(pfkey_msg->sadb_msg_satype) {
-		case SADB_SATYPE_ESP:
-		case SADB_SATYPE_AH:
-		case SADB_X_SATYPE_IPIP:
-		case SADB_X_SATYPE_COMP:
-			break;
-		default:
+	case SADB_ACQUIRE:
+	case SADB_REGISTER:
+	case SADB_EXPIRE:
+		if(!pfkey_msg->sadb_msg_satype) {
 			DEBUGGING(
 				"pfkey_msg_parse: "
-				"satype=%d is not supported yet.\n",
-				pfkey_msg->sadb_msg_satype);
+				"satype is zero, must be non-zero for msg_type %d.\n",
+				pfkey_msg->sadb_msg_type);
 			SENDERR(EINVAL);
 		}
-		break;
 	default:
 	}
 	
@@ -1115,12 +1174,13 @@
 	}
 
 	DEBUGGING(
-		"pfkey_msg_parse: remain=%d, ext_type=%d, ext_len=%d.\n", 
+		"pfkey_msg_parse: "
+		"remain=%d, ext_type=%d, ext_len=%d.\n", 
 		remain, pfkey_ext->sadb_ext_type, pfkey_ext->sadb_ext_len);
 	
 	DEBUGGING(
-		"pfkey_msg_parse: extensions "
-		"permitted=%08x, required=%08x.\n",
+		"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]);
 	
@@ -1130,20 +1190,23 @@
 		/* Is there enough message left to support another extension header? */
 		if(remain < pfkey_ext->sadb_ext_len) {
 			DEBUGGING(
-				"pfkey_msg_parse: remain %d less than ext len %d.\n", 
+				"pfkey_msg_parse: "
+				"remain %d less than ext len %d.\n", 
 				remain, pfkey_ext->sadb_ext_len);
 			SENDERR(EINVAL);
 		}
 		
 		DEBUGGING(
-			"pfkey_msg_parse: parsing ext type=%d remain=%d.\n",
+			"pfkey_msg_parse: "
+			"parsing ext type=%d remain=%d.\n",
 			pfkey_ext->sadb_ext_type,
 			remain);
 		
 		/* Is the extension header type valid? */
 		if((pfkey_ext->sadb_ext_type > SADB_EXT_MAX) || (!pfkey_ext->sadb_ext_type)) {
 			DEBUGGING(
-				"pfkey_msg_parse: ext type %d invalid, SADB_EXT_MAX=%d.\n", 
+				"pfkey_msg_parse: "
+				"ext type %d invalid, SADB_EXT_MAX=%d.\n", 
 				pfkey_ext->sadb_ext_type, SADB_EXT_MAX);
 			SENDERR(EINVAL);
 		}
@@ -1152,7 +1215,8 @@
 		if((extensions_seen & ( 1 << pfkey_ext->sadb_ext_type )) != 0)
 		{
 			DEBUGGING(
-				"pfkey_msg_parse: ext type %d already seen.\n", 
+				"pfkey_msg_parse: "
+				"ext type %d already seen.\n", 
 				pfkey_ext->sadb_ext_type);
 			SENDERR(EINVAL);
 		}
@@ -1160,7 +1224,8 @@
 		/* Do I even know about this type of extension? */
 		if(!(ext_parsers[pfkey_ext->sadb_ext_type])) {
 			DEBUGGING(
-				"pfkey_msg_parse: ext type %d unknown, ignoring.\n", 
+				"pfkey_msg_parse: "
+				"ext type %d unknown, ignoring.\n", 
 				pfkey_ext->sadb_ext_type);
 			goto next_ext;
 		}
@@ -1169,7 +1234,8 @@
 		if(!(extensions_bitmaps[dir][EXT_BITS_PERM][pfkey_msg->sadb_msg_type] &
 		     1<<pfkey_ext->sadb_ext_type)) {
 			DEBUGGING(
-				"pfkey_msg_parse: ext type %d not permitted, exts_perm_in=%08x, 1<<type=%08x\n", 
+				"pfkey_msg_parse: "
+				"ext type %d not permitted, exts_perm_in=%08x, 1<<type=%08x\n", 
 				pfkey_ext->sadb_ext_type, 
 				extensions_bitmaps[dir][EXT_BITS_PERM][pfkey_msg->sadb_msg_type],
 				1<<pfkey_ext->sadb_ext_type);
@@ -1177,19 +1243,22 @@
 		}
 
 		DEBUGGING(
-			"pfkey_msg_parse: About to parse extension %d %p with parser %p.\n",
+			"pfkey_msg_parse: "
+			"About to parse extension %d %p with parser %p.\n",
 			pfkey_ext->sadb_ext_type,
 			pfkey_ext,
 			ext_parsers[pfkey_ext->sadb_ext_type]);
 		/* Parse the extension */
 		if((error = ext_parsers[pfkey_ext->sadb_ext_type](pfkey_ext))) {
 			DEBUGGING(
-				"pfkey_msg_parse: extension parsing for type %d failed with error %d.\n",
+				"pfkey_msg_parse: "
+				"extension parsing for type %d failed with error %d.\n",
 				pfkey_ext->sadb_ext_type, error); 
 			SENDERR(-error);
 		}
 		DEBUGGING(
-			"pfkey_msg_parse: Extension %d parsed.\n",
+			"pfkey_msg_parse: "
+			"Extension %d parsed.\n",
 			pfkey_ext->sadb_ext_type);
 		
 		/* Mark that we have seen this extension and remember the header location */
@@ -1210,7 +1279,8 @@
 
 	if(remain) {
 		DEBUGGING(
-			"pfkey_msg_parse: unexpected remainder of %d.\n", 
+			"pfkey_msg_parse: "
+			"unexpected remainder of %d.\n", 
 			remain);
 		/* why is there still something remaining? */
 		SENDERR(EINVAL);
@@ -1218,8 +1288,8 @@
 
 	/* check required extensions */
 	DEBUGGING(
-		"pfkey_msg_parse: extensions "
-		"permitted=%08x, seen=%08x, required=%08x.\n",
+		"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]);
@@ -1227,14 +1297,15 @@
 	/* don't check further if it is an error return message since it
 	   may not have a body */
 	if(pfkey_msg->sadb_msg_errno) {
-		return error;
+		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(
-			"pfkey_msg_parse: required extensions missing:%08x.\n",
+			"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]));
@@ -1257,9 +1328,9 @@
 		SENDERR(EINVAL);
 	}
 	
-	if((pfkey_msg->sadb_msg_type == SADB_ADD) ||
-	   (pfkey_msg->sadb_msg_type == SADB_UPDATE)) {
-
+	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) {
@@ -1272,8 +1343,8 @@
 		}
 		
 		/* check AH and ESP */
-		if(((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_satype ==
-		   SADB_SATYPE_AH) {
+		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)) {
@@ -1290,10 +1361,8 @@
 					((struct sadb_sa*)(extensions[SADB_EXT_SA]))->sadb_sa_encrypt);
 				SENDERR(EINVAL);
 			}
-		}
-		
-		if(((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_satype ==
-		   SADB_SATYPE_ESP) {
+			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)) {
@@ -1313,10 +1382,8 @@
 					"ESP handed encNULL+authNONE, illegal combination.\n");
 				SENDERR(EINVAL);
 			}
-		}
-
-		if(((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_satype ==
-		   SADB_X_SATYPE_COMP) {
+			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)) {
@@ -1327,7 +1394,25 @@
 					((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(
+					"pfkey_msg_parse: "
+					"COMP handed auth=%d, must be zero.\n",
+					((struct sadb_sa*)(extensions[SADB_EXT_SA]))->sadb_sa_auth);
+				SENDERR(EINVAL);
+			}
+			break;
+		default:
+		}
+		if(ntohl(((struct sadb_sa*)(extensions[SADB_EXT_SA]))->sadb_sa_spi) <= 255) {
+			DEBUGGING(
+				"pfkey_msg_parse: "
+				"spi=%08x must be > 255.\n",
+				ntohl(((struct sadb_sa*)(extensions[SADB_EXT_SA]))->sadb_sa_spi));
+			SENDERR(EINVAL);
 		}
+	default:	
 	}
 errlab:
 
@@ -1336,6 +1421,27 @@
 
 /*
  * $Log: pfkey_v2_parse.c,v $
+ * Revision 1.35  2001/05/03 19:44:51  rgb
+ * Standardise on SENDERR() macro.
+ *
+ * Revision 1.34  2001/03/16 07:41:51  rgb
+ * Put freeswan.h include before pluto includes.
+ *
+ * Revision 1.33  2001/02/27 07:13:51  rgb
+ * Added satype2name() function.
+ * Added text to default satype_tbl entry.
+ * Added satype2name() conversions for most satype debug output.
+ *
+ * Revision 1.32  2001/02/26 20:01:09  rgb
+ * Added internal IP protocol 61 for magic SAs.
+ * Ditch unused sadb_satype2proto[], replaced by satype2proto().
+ * Re-formatted debug output (split lines, consistent spacing).
+ * Removed acquire, register and expire requirements for a known satype.
+ * Changed message type checking to a switch structure.
+ * Verify expected NULL auth for IPCOMP.
+ * Enforced spi > 0x100 requirement, now that pass uses a magic SA for
+ * appropriate message types.
+ *
  * Revision 1.31  2000/12/01 07:09:00  rgb
  * Added ipcomp sanity check to require encalgo is set.
  *
diff -bruN freeswan-1.9.orig/lib/pfkeyv2.h freeswan-1.9/lib/pfkeyv2.h
--- freeswan-1.9.orig/lib/pfkeyv2.h	Thu Feb  8 13:51:05 2001
+++ freeswan-1.9/lib/pfkeyv2.h	Wed May 16 10:57:20 2001
@@ -1,5 +1,5 @@
 /*
- * RCSID $Id: pfkeyv2.h,v 1.14 2001/02/08 18:51:05 rgb Exp $
+ * RCSID $Id: pfkeyv2.h,v 1.15 2001/02/26 20:00:43 rgb Exp $
  */
 
 /*
@@ -231,7 +231,8 @@
 #define SADB_SATYPE_MIP       8
 #define SADB_X_SATYPE_IPIP    9
 #define SADB_X_SATYPE_COMP    10
-#define SADB_SATYPE_MAX       10
+#define SADB_X_SATYPE_INT     11
+#define SADB_SATYPE_MAX       11
 
 #define SADB_SASTATE_LARVAL   0
 #define SADB_SASTATE_MATURE   1
@@ -280,6 +281,9 @@
 
 /*
  * $Log: pfkeyv2.h,v $
+ * 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.
  *
diff -bruN freeswan-1.9.orig/lib/satoa.c freeswan-1.9/lib/satoa.c
--- freeswan-1.9.orig/lib/satoa.c	Sat Sep 16 02:43:47 2000
+++ freeswan-1.9/lib/satoa.c	Mon Jun  4 12:58:45 2001
@@ -1,6 +1,6 @@
 /*
  * convert from binary form of SA ID to ASCII
- * Copyright (C) 1998, 1999  Henry Spencer.
+ * Copyright (C) 1998, 1999, 2001  Henry Spencer.
  * 
  * This library is free software; you can redistribute it and/or modify it
  * under the terms of the GNU Library General Public License as published by
@@ -12,7 +12,7 @@
  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
  * License for more details.
  *
- * RCSID $Id: satoa.c,v 1.9 2000/09/16 06:43:47 henry Exp $
+ * RCSID $Id: satoa.c,v 1.11 2001/06/01 16:44:48 henry Exp $
  */
 #include "internal.h"
 #include "freeswan.h"
@@ -25,6 +25,7 @@
 	{ SA_ESP,	"esp" },
 	{ SA_IPIP,	"tun" },
 	{ SA_COMP,	"comp" },
+	{ SA_INT,	"int" },
 	{ 0,		NULL }
 };
 
@@ -38,7 +39,7 @@
 char *dst;			/* need not be valid if dstlen is 0 */
 size_t dstlen;
 {
-	size_t len;
+	size_t len = 0;		/* 0 means not handled yet */
 	int base;
 	struct typename *tn;
 	char buf[30+ADDRTOA_BUF];
@@ -66,7 +67,24 @@
 					sa.dst.s_addr == PASSTHROUGHDST) {
 		strcpy(buf, PASSTHROUGHNAME);
 		len = strlen(buf);
-	} else {
+	} else if (sa.proto == SA_INT && sa.dst.s_addr == 0) {
+		char *p;
+
+		switch (ntohl(sa.spi)) {
+		case SPI_PASS:	p = "%pass";	break;
+		case SPI_DROP:	p = "%drop";	break;
+		case SPI_REJECT:	p = "%reject";	break;
+		case SPI_HOLD:	p = "%hold";	break;
+		case SPI_TRAP:	p = "%trap";	break;
+		default:	p = NULL;	break;
+		}
+		if (p != NULL) {
+			strcpy(buf, p);
+			len = strlen(buf);
+		}
+	}
+
+	if (len == 0) {
 		strcpy(buf, tn->name);
 		len = strlen(buf);
 		len += ultoa(ntohl(sa.spi), base, buf+len, sizeof(buf)-len);
diff -bruN freeswan-1.9.orig/lib/satot.c freeswan-1.9/lib/satot.c
--- freeswan-1.9.orig/lib/satot.c	Fri Sep 15 13:02:52 2000
+++ freeswan-1.9/lib/satot.c	Wed May 16 10:57:20 2001
@@ -1,6 +1,6 @@
 /*
  * convert from binary form of SA ID to text
- * Copyright (C) 2000  Henry Spencer.
+ * 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
@@ -12,7 +12,7 @@
  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
  * License for more details.
  *
- * RCSID $Id: satot.c,v 1.4 2000/09/15 17:02:52 henry Exp $
+ * RCSID $Id: satot.c,v 1.7 2001/02/27 19:30:16 henry Exp $
  */
 #include "internal.h"
 #include "freeswan.h"
@@ -25,6 +25,7 @@
 	{ SA_ESP,	"esp" },
 	{ SA_IPIP,	"tun" },
 	{ SA_COMP,	"comp" },
+	{ SA_INT,	"int" },
 	{ 0,		NULL }
 };
 
@@ -38,11 +39,14 @@
 char *dst;			/* need not be valid if dstlen is 0 */
 size_t dstlen;
 {
-	size_t len;
+	size_t len = 0;		/* 0 means "not recognized yet" */
 	int base;
 	int showversion;	/* use delimiter to show IP version? */
 	struct typename *tn;
-	char buf[3+1+ULTOT_BUF+ADDRTOT_BUF];
+	char *p;
+	char *pre;
+	char buf[10+1+ULTOT_BUF+ADDRTOT_BUF];
+	char unk[10];
 
 	switch (format) {
 	case 0:
@@ -66,21 +70,46 @@
 		break;
 	}
 
+	pre = NULL;
 	for (tn = typenames; tn->name != NULL; tn++)
-		if (sa->proto == tn->type)
-			break;
-	if (tn->name == NULL)
-		return 0;
+		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(tn->name, PASSTHROUGHTYPE) == 0 &&
+	if (strcmp(pre, PASSTHROUGHTYPE) == 0 &&
 					sa->spi == PASSTHROUGHSPI &&
 					isunspecaddr(&sa->dst)) {
 		strcpy(buf, (addrtypeof(&sa->dst) == AF_INET) ?
 							PASSTHROUGH4NAME :
 							PASSTHROUGH6NAME);
 		len = strlen(buf);
-	} else {
-		strcpy(buf, tn->name);
+	}
+	
+	if (sa->proto == SA_INT && addrtypeof(&sa->dst) == AF_INET &&
+						isunspecaddr(&sa->dst)) {
+		switch (ntohl(sa->spi)) {
+		case SPI_PASS:	p = "%pass";	break;
+		case SPI_DROP:	p = "%drop";	break;
+		case SPI_REJECT:	p = "%reject";	break;
+		case SPI_HOLD:	p = "%hold";	break;
+		case SPI_TRAP:	p = "%trap";	break;
+		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) ? '.' :
diff -bruN freeswan-1.9.orig/lib/ttosa.3 freeswan-1.9/lib/ttosa.3
--- freeswan-1.9.orig/lib/ttosa.3	Fri Sep 15 13:02:52 2000
+++ freeswan-1.9/lib/ttosa.3	Wed May 16 10:57:20 2001
@@ -1,5 +1,5 @@
-.TH IPSEC_TTOSA 3 "15 Sept 2000"
-.\" RCSID $Id: ttosa.3,v 1.4 2000/09/15 17:02:52 henry Exp $
+.TH IPSEC_TTOSA 3 "27 Feb 2001"
+.\" RCSID $Id: ttosa.3,v 1.8 2001/02/27 19:43:24 henry Exp $
 .SH NAME
 ipsec ttosa, satot \- convert IPSEC Security Association IDs to and from text
 .br
@@ -51,8 +51,9 @@
 .BR ah ,
 .BR esp ,
 .BR tun ,
+.BR comp ,
 or
-.BR comp ),
+.BR int ),
 a single character indicating the address family
 .RB ( .
 for IPv4,
@@ -89,6 +90,22 @@
 .IR satot ,
 so the internal representation is never visible.
 .PP
+Similarly, the SA specifiers
+.BR %pass ,
+.BR %drop ,
+.BR %reject ,
+.BR %hold ,
+and
+.B %trap
+signify special ``magic'' SAs used to indicate that packets should be
+passed, dropped, rejected (dropped with ICMP notification),
+held,
+and trapped (sent up to
+.IR ipsec_pluto (8))
+respectively.
+These forms too are known to both routines,
+so the internal representation of the magic SAs should never be visible.
+.PP
 The
 .B <freeswan.h>
 header file supplies the
@@ -116,6 +133,34 @@
 and
 .BR IPPROTO_COMP .
 .PP
+.B <freeswan.h>
+also defines
+.BR SA_INT
+to have the value
+.BR 61
+(reserved by IANA for ``any host internal protocol'')
+and
+.BR SPI_PASS ,
+.BR SPI_DROP ,
+.BR SPI_REJECT ,
+.BR SPI_HOLD ,
+and
+.B SPI_TRAP
+to have the values 256-260 (in \fIhost\fR byte order) respectively.
+These are used in constructing the magic SAs
+(which always have address
+.BR 0.0.0.0 ).
+.PP
+If
+.I satot
+encounters an unknown protocol code, e.g. 77,
+it yields output using a prefix
+showing the code numerically, e.g. ``unk77''.
+This form is
+.I not
+recognized by
+.IR ttosa .
+.PP
 The
 .I srclen
 parameter of
@@ -215,7 +260,7 @@
 Fatal errors in
 .I satot
 are:
-unknown format; unknown protocol code.
+unknown format.
 .SH HISTORY
 Written for the FreeS/WAN project by Henry Spencer.
 .SH BUGS
diff -bruN freeswan-1.9.orig/lib/ttosa.c freeswan-1.9/lib/ttosa.c
--- freeswan-1.9.orig/lib/ttosa.c	Fri Sep 15 15:20:33 2000
+++ freeswan-1.9/lib/ttosa.c	Wed May 16 10:57:20 2001
@@ -1,6 +1,6 @@
 /*
  * convert from text form of SA ID to binary
- * Copyright (C) 2000  Henry Spencer.
+ * 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
@@ -12,7 +12,7 @@
  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
  * License for more details.
  *
- * RCSID $Id: ttosa.c,v 1.6 2000/09/15 19:20:33 henry Exp $
+ * RCSID $Id: ttosa.c,v 1.8 2001/02/27 19:28:32 henry Exp $
  */
 #include "internal.h"
 #include "freeswan.h"
@@ -26,9 +26,25 @@
 	{ "esp",	3,	SA_ESP	},
 	{ "tun",	3,	SA_IPIP },
 	{ "comp",	4,	SA_COMP },
+	{ "int",	3,	SA_INT	},
 	{ NULL,		0,	0,	}
 };
 
+static struct magic {
+	char *name;
+	char *really;
+} magic[] = {
+	{ PASSTHROUGHNAME,	PASSTHROUGH4IS		},
+	{ PASSTHROUGH4NAME,	PASSTHROUGH4IS		},
+	{ PASSTHROUGH6NAME,	PASSTHROUGH6IS		},
+	{ "%pass",		"int256@0.0.0.0"	},
+	{ "%drop",		"int257@0.0.0.0"	},
+	{ "%reject",		"int258@0.0.0.0"	},
+	{ "%hold",		"int259@0.0.0.0"	},
+	{ "%trap",		"int260@0.0.0.0"	},
+	{ NULL,			NULL			}
+};
+
 /*
  - ttosa - convert text "ah507@10.0.0.1" to SA identifier
  */
@@ -45,13 +61,9 @@
 	struct satype *sat;
 	unsigned long ul;
 	const char *oops;
+	struct magic *mp;
+	size_t nlen;
 #	define	MINLEN	5	/* ah0@0 is as short as it can get */
-	static char ptname[] = PASSTHROUGHNAME;
-#	define	PTNLEN	(sizeof(ptname)-1)	/* -1 for NUL */
-	static char pt4name[] = PASSTHROUGH4NAME;
-#	define	PT4NLEN	(sizeof(pt4name)-1)	/* -1 for NUL */
-	static char pt6name[] = PASSTHROUGH6NAME;
-#	define	PT6NLEN	(sizeof(pt6name)-1)	/* -1 for NUL */
 	int af;
 	int base;
 
@@ -61,14 +73,15 @@
 		return "empty string";
 	if (srclen < MINLEN)
 		return "string too short to be SA identifier";
-	if (srclen == PTNLEN && memcmp(src, ptname, PTNLEN) == 0) {
-		src = PASSTHROUGH4IS;
-		srclen = strlen(src);
-	} else if (srclen == PT4NLEN && memcmp(src, pt4name, PT4NLEN) == 0) {
-		src = PASSTHROUGH4IS;
-		srclen = strlen(src);
-	} else if (srclen == PT6NLEN && memcmp(src, pt6name, PT6NLEN) == 0) {
-		src = PASSTHROUGH6IS;
+	if (*src == '%') {
+		for (mp = magic; mp->name != NULL; mp++) {
+			nlen = strlen(mp->name);
+			if (srclen == nlen && memcmp(src, mp->name, nlen) == 0)
+				break;
+		}
+		if (mp->name == NULL)
+			return "unknown % keyword";
+		src = mp->really;
 		srclen = strlen(src);
 	}
 
@@ -174,6 +187,7 @@
 
 struct rtab {
 	int format;
+#		define	FUDGE	0x1000
 	char *input;
 	char *output;			/* NULL means error expected */
 } rtab[] = {
@@ -205,6 +219,19 @@
 	0, "esp7x7@1.2.3.4",		NULL,
 	0, "esp77@1.0x2.3.4",		NULL,
 	0, PASSTHROUGHNAME,		PASSTHROUGH4NAME,
+	0, PASSTHROUGH6NAME,		PASSTHROUGH6NAME,
+	0, "%pass",			"%pass",
+	0, "int256@0.0.0.0",		"%pass",
+	0, "%drop",			"%drop",
+	0, "int257@0.0.0.0",		"%drop",
+	0, "%reject",			"%reject",
+	0, "int258@0.0.0.0",		"%reject",
+	0, "%hold",			"%hold",
+	0, "int259@0.0.0.0",		"%hold",
+	0, "%trap",			"%trap",
+	0, "int260@0.0.0.0",		"%trap",
+	0, "int261@0.0.0.0",		"int.105@0.0.0.0",
+	FUDGE, "esp9@1.2.3.4",		"unk77.9@1.2.3.4",
 	0, NULL,			NULL
 };
 
@@ -232,7 +259,9 @@
 								r->input);
 			status = 1;
 		} else {
-			n = satot(&sa, r->format, buf, sizeof(buf));
+			if (r->format&FUDGE)
+				sa.proto = 77;
+			n = satot(&sa, (char)r->format, buf, sizeof(buf));
 			if (n > sizeof(buf)) {
 				printf("`%s' satot failed:  need %ld\n",
 							r->input, (long)n);
diff -bruN freeswan-1.9.orig/libdes/Makefile freeswan-1.9/libdes/Makefile
--- freeswan-1.9.orig/libdes/Makefile	Tue Oct 10 22:12:45 2000
+++ freeswan-1.9/libdes/Makefile	Wed May 16 10:57:20 2001
@@ -59,10 +59,10 @@
 #DES_ENC=asm/dx86-sol.o	asm/yx86-sol.o	# solaris format x86 
 #DES_ENC=asm/dx86bsdi.o	asm/yx86basi.o	# bsdi format x86 
 
-LIBDIR=/usr/local/lib
-BINDIR=/usr/local/bin
-INCDIR=/usr/local/include
-MANDIR=/usr/local/man
+LIBDIR=/usr/lib
+BINDIR=/usr/bin
+INCDIR=/usr/include
+MANDIR=/usr/man
 MAN1=1
 MAN3=3
 SHELL=/bin/sh
diff -bruN freeswan-1.9.orig/pluto/CHANGES freeswan-1.9/pluto/CHANGES
--- freeswan-1.9.orig/pluto/CHANGES	Wed Jan 31 20:54:09 2001
+++ freeswan-1.9/pluto/CHANGES	Mon Jun  4 12:59:59 2001
@@ -1,7 +1,83 @@
 Changes to Pluto
 ================
 
+Changes since 1.9 release by D. Hugh Redelmeier <hugh@mimosa.com>
+
+- refined the code for DODGE_DH_MISSING_ZERO_BUG to ensure
+  Responder never drops a negotiation.
+
+- added and exploited builddiag(), a routine make it easier to add
+  intermediate context to diagnostics.
+
+- For purposes of IPv4, Pluto will now only consider interfaces that
+  are "up".  It has always ignored those configured with address
+  0.0.0.0, thus ignoring "down" interfaces in most cases.
+
+- add a list of interface pairs to --status output.
+
+- replace signal(2) calls with sigaction(2) calls: glibc has further
+  broken the semantics of signal(2).  We want slow system calls
+  to be interruptable and not be restarted.
+
+- improved error message for lack of preshared key by showing
+  IDs that were used in lookup.  Collateral tidying.
+
+- documented complex logic of routing and erouting in routing.txt
+
+- When a connection is --routed, a route is installed to direct
+  outbound packets destined for the peer's client to go to the ipsec
+  interface implicit in the connection.  This is not allowed for Road
+  Warrior connections -- they are strictly inbound.  For Opportunistic
+  connections, a new default root is installed that points to the
+  ipsec interface.  Note that the route does not take into account the
+  source address.  In addition, a TRAP shunt eroute is installed to
+  catch any traffic sent on the not-yet-initiated connection.
+
+- When an outbound packet is trapped by the TRAP shunt eroute,
+  Pluto attempts to initiate the corresponding connection.
+  If the attempt fails because an Opportunistic connection was used
+  and no gateway information was found, a PASS shunt eroute is
+  installed (with no provision for automatic removal).
+
+- if negotiation fails at a later point, a shunt eroute is installed.
+  The kind of shunt is a policy decision.  It is specified as part of
+  the connection.  (Untested; can not be specified in ipsec.conf.)
+
+- When an inbound negotiation doesn't match a specific connection,
+  and there is an Opportunistic connection, Pluto will try to respond
+  using that connection.
+
+- Every 2 minutes (SHUNT_SCAN_INTERVAL seconds), Pluto scans for
+
+  + PASS eroutes that it installed that haven't been used recently.
+    These will be deleted.
+
+  + HOLD eroutes for which Pluto hasn't received a PFKEY_ACQUIRE message.
+    For any it finds, it will attempt an opportunistic initiate.
+
+- We no longer allow Phase 1 negotiations that we initiate to switch
+  which connection is being used based on the Peer's Phase 1 ID.
+  The fact that we used to do so was probably a bug.
+
+- When Pluto as the Responder receives the Peer's Phase 1 ID, it is
+  now willing to use a connection with a different ID and private
+  RSA key for our end.  Nothing has committed us to the current guess.
+
+- Changes in internal data structures to aid in better tracking of
+  history of attempted and successful communication.  Needed for
+  effective Opportunism.
+  + struct host_pair represents information about pairs of hosts.
+  + "Orientation" is done as soon as possible rather than as late
+    as possible.
+  + an arbitrary number of Quick Mode negotiations may now queue
+    for the completion of a Main Mode negotiation.  Formerly,
+    a negotiation could only use a previously completed Keying Channel.
+
+
 Changes since 1.8 release by D. Hugh Redelmeier <hugh@mimosa.com>
+
+- [Svenning Soerensen] correct check requiring OAKLEY_LIFE_TYPE
+  attribute before OAKLEY_LIFE_DURATION.
 
 - Improved whack diagnostics for various cases of failure to connect
   with Pluto.
diff -bruN freeswan-1.9.orig/pluto/Makefile freeswan-1.9/pluto/Makefile
--- freeswan-1.9.orig/pluto/Makefile	Wed Oct 25 19:58:15 2000
+++ freeswan-1.9/pluto/Makefile	Mon Jun  4 13:02:07 2001
@@ -12,7 +12,7 @@
 # or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 # for more details.
 #
-# RCSID $Id: Makefile,v 1.75 2000/10/25 23:58:15 henry Exp $
+# RCSID $Id: Makefile,v 1.76 2001/03/13 09:22:01 dhr Exp $
 
 SHELL = /bin/sh
 
@@ -31,17 +31,32 @@
 FREESWANLIB=$(FREESWANLIBDIR)/libfreeswan.a
 LIBDESLITE=$(FREESWANLIBDIR)/libdes.a
 
+ifeq "$(USEOPENSSL)" "1"
+OPENSSLDEFS=-DOPENSSL
+
+OPENSSLOBJS=openssl.o xmap.o xmap_file.o xmap_dir.o xmap_db.o xmap_ldap.o \
+	x_sobj.o
+
+LDAPLIBS=-L$(LDAPROOT)/lib -lldap -llber -Wl,-rpath $(LDAPROOT)/lib
+LDAPDEFS=-DHAVE_LDAP
+
+DBROOT=/usr
+DBINCS=-I$(DBROOT)/include
+DBLIBS=-L$(DBROOT)/lib -ldb
+DBDEFS=-DHAVE_DB -DHAVE_DB185
+endif # USEOPENSSL = 1
+
 KLIPSD=../klips/net/ipsec
 
 INSTALL=install
 
 # -O on Linux makes gcc coredump when compiling sha1.c
 # -Wundef is nice but RHL5.2 compiler doesn't support it
-CFLAGS = -g -Wall -W -Wmissing-prototypes -Wpointer-arith -Wbad-function-cast \
-	-Wcast-qual -Wmissing-declarations -Wwrite-strings -Wstrict-prototypes
+CFLAGS = -g -Wall -Wmissing-prototypes -Wpointer-arith -Wbad-function-cast \
+	-Wcast-qual -Wmissing-declarations -Wwrite-strings
 
 # where to find klips headers and FreeS/WAN headers
-HDRDIRS = -I$(KLIPSD) $(FREESWANINCLS)
+HDRDIRS = -I$(KLIPSD) $(FREESWANINCLS) $(OPENSSLINCLS) $(LDAPINCS) $(DBINCS)
 
 # On non-LINUX systems, these one of these may be needed (see endian.h)
 # BYTE_ORDER = -DBIG_ENDIAN=4321 -DLITTLE_ENDIAN=1234 -DBYTE_ORDER=BIG_ENDIAN
@@ -76,22 +91,31 @@
 
 CPPFLAGS = $(HDRDIRS) $(BYTE_ORDER) \
 	-DPLUTO -DKLIPS -DDODGE_DH_MISSING_ZERO_BUG \
-	-DDEBUG -DGCC_LINT
+	-DDEBUG -DGCC_LINT $(OPENSSLDEFS) $(LDAPDEFS) $(DBDEFS)
 
 ALLFLAGS = $(CPPFLAGS) $(CFLAGS)
 
 # libefence is a free memory allocation debugger
 # Solaris 2 needs -lsocket -lnsl
-LIBSPLUTO = -lgmp -lresolv # -lefence
+LIBSPLUTO = -lgmp -lresolv $(OPENSSLLIBS) $(LDAPLIBS) $(DBLIBS)  # -lefence
 
 LDFLAGS =
 
 # Solaris needs -lsocket -lnsl
 LIBSWHACK =
 
+LIBSD2H   = $(OPENSSLLIBS) $(DBLIBS)
+
 BINNAMEPLUTO = pluto
 BINNAMEWHACK = whack
 
+# Comment this out if you don't have Berkeley DB available, which,
+# if you're running Linux is a bit strange...
+#ifeq ($(USEOPENSSL),1)
+ifeq "$(USEOPENSSL)" "1"
+BINNAMED2H   = dir2hash
+endif
+
 RM = /bin/rm
 RMFLAGS = -f
 
@@ -100,12 +124,12 @@
 
 # files for a (source) distribution
 
-DISTMISC = CHANGES TODO ipsec.secrets Makefile \
+DISTMISC = CHANGES TODO ipsec.secrets Makefile routing.txt \
 	 pluto.8 ipsec.secrets.5
 
 DISTGCRYPT = \
 	gcryptfix.c gcryptfix.h \
-	dsa.c dsa.h \
+        g10_dsa.c g10_dsa.h \
 	elgamal.c elgamal.h \
 	primegen.c \
 	smallprime.c
@@ -142,23 +166,30 @@
 
 # start of support for DSS/DSA.  Not currently used.
 # OBJSGCRYPT =  gcryptfix.o dsa.o elgamal.o primegen.o smallprime.o
-OBJSGCRYPT =
+OBJSGCRYPT = gcryptfix.o g10_dsa.o elgamal.o primegen.o smallprime.o
 
 OBJSPLUTO = connections.o constants.o cookie.o crypto.o defs.o log.o \
 	state.o main.o server.o timer.o id.o ipsec_doi.o kernel.o \
 	kernel_comm.o demux.o packet.o preshared.o dnskey.o rnd.o spdb.o \
-	sha1.o md5.o $(OBJSGCRYPT) $(LIBDESLITE) $(FREESWANLIB)
+	sha1.o md5.o $(OBJSGCRYPT) $(LIBDESLITE) $(FREESWANLIB) \
+	$(OPENSSLOBJS) $(LIBGMP)
 
 OBJSWHACK = whack.o $(FREESWANLIB)
 
-all: $(BINNAMEPLUTO) $(BINNAMEWHACK)
+#ifeq ($(USEOPENSSL),1)
+ifeq "$(USEOPENSSL)" "1"
+OBJSD2H = dir2hash.o
+endif
+
+all: $(BINNAMEPLUTO) $(BINNAMEWHACK) $(BINNAMED2H)
 
 install: all
-	$(INSTALL) $(BINNAMEPLUTO) $(BINNAMEWHACK) $(BINDIR)
-	$(INSTALL) pluto.8 $(PMANDIR)/ipsec_pluto.8
-	../utils/manlink $(PMANDIR) ipsec_pluto.8
-	$(INSTALL) ipsec.secrets.5 $(FMANDIR)
-	../utils/manlink $(FMANDIR) ipsec.secrets.5
+	$(INSTALL) $(BINNAMEPLUTO) $(BINNAMEWHACK) $(BINNAMED2H) \
+		$(PREFIX)/$(BINDIR)
+	$(INSTALL) pluto.8 $(PREFIX)/$(PMANDIR)/ipsec_pluto.8
+	../utils/manlink $(PREFIX)/$(PMANDIR) ipsec_pluto.8
+	$(INSTALL) ipsec.secrets.5 $(PREFIX)/$(FMANDIR)
+	../utils/manlink $(PREFIX)/$(FMANDIR) ipsec.secrets.5
 
 $(BINNAMEPLUTO): $(OBJSPLUTO)
 	$(CC) -o $(BINNAMEPLUTO) $(LDFLAGS) $(OBJSPLUTO) $(LIBSPLUTO)
@@ -166,6 +197,9 @@
 $(BINNAMEWHACK): $(OBJSWHACK)
 	$(CC) -o $(BINNAMEWHACK) $(OBJSWHACK) $(LIBSWHACK)
 
+$(BINNAMED2H): $(OBJSD2H)
+	$(CC) -o $(BINNAMED2H) $(OBJSD2H) $(LIBSD2H)
+
 distlist:
 	@echo $(DIST)
 
@@ -185,8 +219,10 @@
 realclean: clean
 
 clean:
-	$(RM) $(RMFLAGS) $(OBJSPLUTO) *.core core *~ a.out ktrace.out
-	$(RM) $(RMFLAGS) $(BINNAMEPLUTO) $(OBJSWHACK) $(BINNAMEWHACK)
+	$(RM) $(RMFLAGS) $(OBJSPLUTO) $(OBJSD2H) \
+		*.core core *~ a.out ktrace.out
+	$(RM) $(RMFLAGS) $(BINNAMEPLUTO) $(OBJSWHACK) $(BINNAMEWHACK) \
+		$(BINNAMED2H)
 
 .c.o:
 	$(CC) $(COPTS) $(ALLFLAGS) -c $<
@@ -198,6 +234,7 @@
 $(LIBDESLITE):
 	cd $(FREESWANLIBDIR) ; $(MAKE) libdes.a
 
+
 # Gather dependencies caused by explicit #includes within .c files
 #
 # Each .c is assumed to compile into a .o with the corresponding name.
@@ -221,9 +258,6 @@
 defs.o: defs.c
 demux.o: demux.c
 dnskey.o: dnskey.c
-dsa.o: dsa.c
-elgamal.o: elgamal.c
-gcryptfix.o: gcryptfix.c
 id.o: id.c
 ipsec_doi.o: ipsec_doi.c
 kernel.o: kernel.c
@@ -233,11 +267,9 @@
 md5.o: md5.c
 packet.o: packet.c
 preshared.o: preshared.c
-primegen.o: primegen.c
 rnd.o: rnd.c
 server.o: server.c
 sha1.o: sha1.c
-smallprime.o: smallprime.c
 spdb.o: spdb.c
 state.o: state.c
 timer.o: timer.c
@@ -259,6 +291,7 @@
 connections.o: dnskey.h
 connections.o: whack.h
 constants.o: constants.h
+constants.o: defs.h
 constants.o: packet.h
 cookie.o: constants.h
 cookie.o: defs.h
@@ -301,23 +334,6 @@
 dnskey.o: dnskey.h
 dnskey.o: packet.h
 dnskey.o: timer.h
-dsa.o: constants.h
-dsa.o: defs.h
-dsa.o: log.h
-dsa.o: rnd.h
-dsa.o: gcryptfix.h
-dsa.o: dsa.h
-elgamal.o: constants.h
-elgamal.o: defs.h
-elgamal.o: log.h
-elgamal.o: rnd.h
-elgamal.o: gcryptfix.h
-elgamal.o: elgamal.h
-gcryptfix.o: constants.h
-gcryptfix.o: defs.h
-gcryptfix.o: log.h
-gcryptfix.o: rnd.h
-gcryptfix.o: gcryptfix.h
 id.o: constants.h
 id.o: defs.h
 id.o: id.h
@@ -408,11 +424,6 @@
 preshared.o: dnskey.h
 preshared.o: log.h
 preshared.o: whack.h
-primegen.o: constants.h
-primegen.o: defs.h
-primegen.o: log.h
-primegen.o: rnd.h
-primegen.o: gcryptfix.h
 rnd.o: sha1.h
 rnd.o: constants.h
 rnd.o: defs.h
@@ -434,9 +445,6 @@
 server.o: whack.h
 sha1.o: sha1.h
 sha1.o: endian.h
-smallprime.o: constants.h
-smallprime.o: defs.h
-smallprime.o: gcryptfix.h
 spdb.o: constants.h
 spdb.o: defs.h
 spdb.o: id.h
diff -bruN freeswan-1.9.orig/pluto/connections.c freeswan-1.9/pluto/connections.c
--- freeswan-1.9.orig/pluto/connections.c	Sun Jan 28 16:03:02 2001
+++ freeswan-1.9/pluto/connections.c	Wed Jun  6 16:37:02 2001
@@ -11,7 +11,7 @@
  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  * for more details.
  *
- * RCSID $Id: connections.c,v 1.82 2001/01/28 21:03:02 dhr Exp $
+ * RCSID $Id: connections.c,v 1.103 2001/06/02 06:42:22 dhr Exp $
  */
 
 #include <string.h>
@@ -21,6 +21,7 @@
 #include <unistd.h>
 #include <netinet/in.h>
 #include <sys/socket.h>
+#include <sys/stat.h>
 #include <netinet/in.h>
 #include <arpa/inet.h>
 
@@ -36,35 +37,45 @@
 #include "timer.h"
 #include "ipsec_doi.h"	/* needs demux.h and state.h */
 #include "server.h"
-#include "kernel.h"	/* for no_klips */
+#include "kernel.h"
 #include "log.h"
 #include "preshared.h"
 #include "dnskey.h"	/* needs preshared.h */
 #include "whack.h"
 
+#ifdef OPENSSL
+#include "openssl.h"
+#include "xmap.h"
+#endif
+static void flush_pending_by_connection(struct connection *c); /* forward */
+
 static struct connection *connections = NULL;
 
-/* host_pair: a nexus of information about a pair of hosts.
+/* struct host_pair: a nexus of information about a pair of hosts.
  * A host is an IP address, UDP port pair.  This is a debatable choice:
  * - should port be considered (no choice of port in standard)?
  * - should ID be considered (hard because not always known)?
  * - should IP address matter on our end (we don't know our end)?
- * Since connections are not all oriented, the host identifiers
- * (ip_address values) are placed in a canonical order.
+ * Only oriented connections are registered.
+ * Unoriented connections are kept on the unoriented_connections
+ * linked list (using hp_next).  For them, host_pair is NULL.
  */
 
 struct host_pair {
     struct {
 	ip_address addr;
 	u_int16_t port;	/* host order */
-    } a, b;
+    } me, him;
     bool initial_connection_sent;
     struct connection *connections;	/* connections with this pair */
+    struct pending *pending;   /* awaiting Keying Channel */
     struct host_pair *next;
 };
 
 static struct host_pair *host_pairs = NULL;
 
+static struct connection *unoriented_connections = NULL;
+
 /* check to see that Ids of peers match */
 bool
 same_peer_ids(const struct connection *c, const struct connection *d
@@ -74,58 +85,20 @@
 	&& same_id(his_id == NULL? &c->that.id : his_id, &d->that.id);
 }
 
-/* Arbitrary canonicalization of host pair.
- * Because it is arbitrary, we don't need to compare in host order.
- */
-static void
-canonical_host_pair(struct host_pair *hp
-, const ip_address *xaddr, u_int16_t xport
-, const ip_address *yaddr, u_int16_t yport)
-{
-    int ac;
-
-    passert(sameaddrtype(xaddr, yaddr));
-    ac = addrcmp(xaddr, yaddr);
-
-    if (ac < 0
-    || (ac == 0 && xport <= yport))
-    {
-	hp->a.addr = *xaddr;
-	hp->a.port = xport;
-	hp->b.addr = *yaddr;
-	hp->b.port = yport;
-    }
-    else
-    {
-	hp->a.addr = *yaddr;
-	hp->a.port = yport;
-	hp->b.addr = *xaddr;
-	hp->b.port = xport;
-    }
-
-    return;
-}
-
 static struct host_pair *
-find_host_pair(const ip_address *xaddr, u_int16_t xport
-, const ip_address *yaddr, u_int16_t yport)
+find_host_pair(const ip_address *myaddr, u_int16_t myport
+, const ip_address *hisaddr, u_int16_t hisport)
 {
-    struct host_pair hp;
     struct host_pair *p, *prev;
-    ip_address any;
 
-    if (yaddr == NULL)
-    {
-	(void) anyaddr(addrtypeof(xaddr), &any);
-	yaddr = &any;
-    }
-
-    canonical_host_pair(&hp, xaddr, xport, yaddr, yport);
+    /* default hisaddr to an appropriate any */
+    if (hisaddr == NULL)
+       hisaddr = aftoinfo(addrtypeof(myaddr))->any;
 
     for (prev = NULL, p = host_pairs; p != NULL; prev = p, p = p->next)
     {
-	if (sameaddr(&p->a.addr, &hp.a.addr) && p->a.port == hp.a.port
-	&& sameaddr(&p->b.addr, &hp.b.addr) && p->b.port == hp.b.port)
+        if (sameaddr(&p->me.addr, myaddr) && p->me.port == myport
+        && sameaddr(&p->him.addr, hisaddr) && p->him.port == hisport)
 	{
 	    if (prev != NULL)
 	    {
@@ -139,11 +112,12 @@
     return p;
 }
 
+/* find head of list of connections with this pair of hosts */
 static struct connection *
-find_host_pair_connections(const ip_address *xaddr, u_int16_t xport
-, const ip_address *yaddr, u_int16_t yport)
+find_host_pair_connections(const ip_address *myaddr, u_int16_t myport
+, const ip_address *hisaddr, u_int16_t hisport)
 {
-    struct host_pair *hp = find_host_pair(xaddr, xport, yaddr, yport);
+    struct host_pair *hp = find_host_pair(myaddr, myport, hisaddr, hisport);
 
     return hp == NULL? NULL : hp->connections;
 }
@@ -151,22 +125,38 @@
 static void
 connect_to_host_pair(struct connection *c)
 {
+    if (oriented(*c))
+    {
     struct host_pair *hp = find_host_pair(&c->this.host_addr, c->this.host_port
 	, &c->that.host_addr, c->that.host_port);
 
     if (hp == NULL)
     {
+	  /* no suitable host_pair -- build one */
 	hp = alloc_thing(struct host_pair, "host_pair");
-	canonical_host_pair(hp, &c->this.host_addr, c->this.host_port
-	    , &c->that.host_addr, c->that.host_port);
+	  hp->me.addr = c->this.host_addr;
+	  hp->me.port = c->this.host_port;
+	  hp->him.addr = c->that.host_addr;
+	  hp->him.port = c->that.host_port;
 	hp->initial_connection_sent = FALSE;
 	hp->connections = NULL;
+	  hp->pending = NULL;
 	hp->next = host_pairs;
 	host_pairs = hp;
     }
     c->host_pair = hp;
     c->hp_next = hp->connections;
     hp->connections = c;
+    }
+    else
+    {
+	/* since this connection isn't oriented, we place it
+	* in the unoriented_connections list instead.
+	*/
+	c->host_pair = NULL;
+	c->hp_next = unoriented_connections;
+	unoriented_connections = c;
+    }
 }
 
 /* figure out if Opportunism is possible: are there any connections
@@ -194,43 +184,41 @@
 	    struct connection *c = find_host_pair_connections(&p->addr
 		, pluto_port, (ip_address *)NULL, pluto_port);
 
-	    for (; c != NULL; c = c->next)
-	    {
-		if (c->rw_state == rwcs_permanent && HasWildcardClient(c))
-		{
-		    passert(HasWildcardIP(*c));
+	    for (; c != NULL; c = c->hp_next)
+		if (c->kind == CK_TEMPLATE && HasWildcardClient(c))
 		    return definitely_some_oppo = possibly_some_oppo = TRUE;
 		}
-	    }
-	}
 	definitely_some_oppo = possibly_some_oppo = FALSE;
     }
     return definitely_some_oppo;
 }
 
 /* find a connection by name.
- * move the winner (if any) to the front.
- * If none is found, and wfd is not NULL_FD, a diagnostic is logged to whack.
+ * If strict, don't accept a CK_INSTANCE.
+ * Move the winner (if any) to the front.
+ * If none is found, and strict, a diagnostic is logged to whack.
  */
 struct connection *
 con_by_name(const char *nm, bool strict)
 {
     struct connection *p, *prev;
 
-    for (prev = NULL, p = connections; ; prev = p, p = p->next)
+    for (prev = NULL, p = connections; ; prev = p, p = p->ac_next)
     {
 	if (p == NULL)
 	{
 	    if (strict)
-		whack_log(RC_UNKNOWN_NAME, "no connection with that name");
+		whack_log(RC_UNKNOWN_NAME
+		    , "no connection named \"%s\"", nm);
 	    break;
 	}
-	if (streq(p->name, nm))
+	if (streq(p->name, nm)
+	&& (!strict || p->kind != CK_INSTANCE))
 	{
 	    if (prev != NULL)
 	    {
-		prev->next = p->next;	/* remove p from list */
-		p->next = connections;	/* and stick it on front */
+		prev->ac_next = p->ac_next;	/* remove p from list */
+		p->ac_next = connections;	/* and stick it on front */
 		connections = p;
 	    }
 	    break;
@@ -240,21 +228,21 @@
 }
 
 void
-unorient_connection(struct connection *c)
+release_connection(struct connection *c)
 {
-    if (c->rw_state == rwcs_instance)
+    if (c->kind == CK_INSTANCE)
     {
 	/* This does everything we need.
-	 * Note that we will be called by delete_connection,
-	 * but rw_state will be rwcs_going_away.
+	 * Note that we will be called recursively by delete_connection,
+	 * but kind will be CK_GOING_AWAY.
 	 */
 	delete_connection(c);
     }
     else
     {
+	flush_pending_by_connection(c);
 	delete_states_by_connection(c);
 	unroute_connection(c);
-	c->interface = NULL;
     }
 }
 
@@ -282,25 +270,44 @@
     /* Must be careful to avoid circularity:
      * we mark c as going away so it won't get deleted recursively.
      */
-    passert(c->rw_state != rwcs_going_away);
-    if (c->rw_state == rwcs_instance)
+    passert(c->kind != CK_GOING_AWAY);
+    if (c->kind == CK_INSTANCE)
     {
-	log("deleting connection \"%s\" with Road Warrior %s"
+	log("deleting connection \"%s\" instance with peer %s"
 	    , c->name, ip_str(&c->that.host_addr));
-	c->rw_state = rwcs_going_away;
+	c->kind = CK_GOING_AWAY;
     }
     else
     {
 	definitely_some_oppo = FALSE;	/* could be more careful */
 	log("deleting connection");
     }
-    unorient_connection(c);	/* won't delete c */
+    release_connection(c);     /* won't delete c */
+
+#ifdef OPENSSL
+    if (c->cert != NULL) X509_free((X509 *)(c->cert));
+    if (c->key != NULL) EVP_PKEY_free((EVP_PKEY *)(c->key));
+    if (c->lu != NULL) sk_XMAP_pop_free(c->lu, XMAP_free);
+    {
+      int i;
+
+      for (i=0; i<MAX_OTHER; i++)
+       if (c->other[i].cert != NULL) {
+         X509_free((X509 *)(c->other[i].cert));
+        }
+    }
+#endif
 
     /* find and delete c from connections list */
-    list_rm(struct connection, next, c, connections);
+    list_rm(struct connection, ac_next, c, connections);
     cur_connection = old_cur_connection;
 
     /* find and delete c from the host pair list */
+    if (c->host_pair == NULL)
+    {
+       list_rm(struct connection, hp_next, c, unoriented_connections);
+    }
+    else
     {
 	struct host_pair *hp = c->host_pair;
 
@@ -311,8 +318,10 @@
 	 * and we haven't even made an initial contact, let's delete
 	 * this guy in case we were created by an attempted DOS attack.
 	 */
-	if (hp->connections == NULL && !hp->initial_connection_sent)
+	if (hp->connections == NULL
+	&& !hp->initial_connection_sent)
 	{
+	    passert(hp->pending == NULL);       /* ??? must deal with this! */
 	    list_rm(struct host_pair, next, hp, host_pairs);
 	    pfree(hp);
 	}
@@ -337,16 +346,103 @@
 }
 
 void
-release_interface(struct iface *i)
+release_dead_interfaces(void)
 {
-    struct connection *c, *n;
+    struct host_pair *hp;
+
+    for (hp = host_pairs; hp != NULL; hp = hp->next)
+    {
+       struct connection **pp
+           , *p;
 
-    passert(i != NULL);
-    for (c = connections; c != NULL; c = n)
+       for (pp = &hp->connections; (p = *pp) != NULL; )
+       {
+           if (p->interface->change == IFN_DELETE)
     {
-	n = c->next;
-	if (c->interface == i)
-	    unorient_connection(c);	/* may delete c */
+               /* this connection's interface is going away:
+                * this connection needs to be relegated to the
+                * unoriented_connections lists
+                */
+               *pp = p->hp_next;       /* advance *pp */
+
+               p->interface = NULL;
+               p->host_pair = NULL;
+               p->hp_next = unoriented_connections;
+               unoriented_connections = p;
+
+               /* do the release last because it leave p dangling */
+               release_connection(p);
+           }
+           else
+           {
+               pp = &p->hp_next;       /* advance pp */
+           }
+       }
+    }
+}
+
+/* adjust orientations of connections to reflect newly added interfaces */
+void
+check_orientations(void)
+{
+    /* try to orient all the unoriented connections */
+    {
+       struct connection *c = unoriented_connections;
+
+       unoriented_connections = NULL;
+
+       while (c != NULL)
+       {
+           struct connection *nxt = c->hp_next;
+
+           (void)orient(c);
+           connect_to_host_pair(c);
+           c = nxt;
+       }
+    }
+
+    /* Check that no oriented connection has become double-oriented.
+     * In other words, the far side must not match one of our new interfaces.
+     */
+    {
+       struct iface *i;
+
+       for (i = interfaces; i != NULL; i = i->next)
+       {
+           if (i->change == IFN_ADD)
+           {
+               struct host_pair *hp;
+
+               for (hp = host_pairs; hp != NULL; hp = hp->next)
+               {
+                   if (sameaddr(&hp->him.addr, &i->addr)
+                   && (!no_klips || hp->him.port == pluto_port))
+                   {
+                       /* bad news: the whole chain of connections
+                        * hanging off this host pair has both sides
+                        * matching an interface.
+                        * We'll get rid of them, using orient and
+                        * connect_to_host_pair.  But we'll be lazy
+                        * and not ditch the host_pair itself (the
+                        * cost of leaving it is slight and cannot
+                        * be induced by a foe).
+                        */
+                       struct connection *c = hp->connections;
+
+                       hp->connections = NULL;
+                       while (c != NULL)
+                       {
+                           struct connection *nxt = c->hp_next;
+
+                           c->interface = NULL;
+                           (void)orient(c);
+                           connect_to_host_pair(c);
+                           c = nxt;
+                       }
+                   }
+               }
+           }
+       }
     }
 }
 
@@ -429,7 +525,7 @@
     /* id, if different from host */
     host_id[0] = '\0';
     if (!(this->id.kind == ID_NONE
-    || ((this->id.kind == ID_IPV4_ADDR || this->id.kind == ID_IPV6_ADDR) && sameaddr(&this->id.ip_addr, &this->host_addr))))
+    || (id_is_ipaddr(&this->id) && sameaddr(&this->id.ip_addr, &this->host_addr))))
     {
 	int len = idtoa(&this->id, host_id+1, sizeof(host_id)-2);
 
@@ -462,12 +558,61 @@
 static void
 unshare_connection_strings(struct connection *c)
 {
+#ifdef OPENSSL
+    void *tempcert, *tempkey;
+    STACK_OF(XMAP) *templu;
+#endif
     c->name = clone_str(c->name, "connection name");
 
     unshare_id_content(&c->this.id);
     c->this.updown = clone_str(c->this.updown, "updown");
     unshare_id_content(&c->that.id);
     c->that.updown = clone_str(c->that.updown, "updown");
+
+#ifdef OPENSSL
+    {
+      int i;
+
+      for (i=0; i<MAX_OTHER; i++)
+        if (c->other[i].cert) {
+          tempcert = c->other[i].cert;
+          c->other[i].cert = X509_dup(tempcert);
+        }
+    }
+
+
+    if (c->cert) {
+      tempcert = c->cert;
+      c->cert = X509_dup(tempcert);
+    }
+/* ******** HOW to use EVP_PKEY *************
+ * #define RSAPrivateKey_dup(rsa) (RSA *)ASN1_dup((int (*)())i2d_RSAPrivateKey,
+ *                (char *(*)())d2i_RSAPrivateKey,(char *)rsa)
+ * /usr/include/openssl/evp.h:621:RSA *  EVP_PKEY_get1_RSA(EVP_PKEY *pkey);
+ *
+ * DEFS:
+ * /usr/include/openssl/evp.h:637:EVP_PKEY *  d2i_PrivateKey(int type,
+ *               EVP_PKEY **a, unsigned char **pp,
+ * /usr/include/openssl/evp.h:641:int  i2d_PrivateKey(EVP_PKEY *a,
+ *               unsigned char **pp);
+ * X509 dup macro:
+ * #define X509_dup(x509) (X509 *)ASN1_dup((int (*)())i2d_X509, \
+ *                 (char *(*)())d2i_X509,(char *)x509)
+ * NEW MACRO:
+ * #define EVP_PKEY_dup(pkey) \
+ *   (EVP_PKEY *)ASN1_dup((int (*)())i2d_PrivateKey, \
+ *   (char *(*)())d2i_AutoPrivateKey,(char *)pkey)
+ */
+
+    if (c->key) {
+      tempkey = c->key;
+      c->key = EVP_PKEY_dup(tempkey);
+    }
+    if (c->lu) {
+      templu = c->lu;
+      c->lu = clone_sk_XMAP(templu);
+    }
+#endif
 }
 
 static void
@@ -537,7 +682,11 @@
 
 	    for (; c != NULL; c = c->hp_next)
 	    {
+#ifndef OPENSSL
 		if ((c->policy ^ wm->policy) & (POLICY_PSK | POLICY_RSASIG))
+#else
+		if ((c->policy ^ wm->policy) & (POLICY_PSK | POLICY_OPENSSL))
+#endif
 		{
 		    loglog(RC_CLASH
 			, "authentication method disagrees with \"%s\", which is also for an unspecified peer"
@@ -553,6 +702,8 @@
 void
 add_connection(const struct whack_message *wm)
 {
+    bool success = TRUE;
+
     if (con_by_name(wm->name, FALSE) != NULL)
     {
 	loglog(RC_DUPNAME, "attempt to redefine connection \"%s\"", wm->name);
@@ -577,6 +728,15 @@
 	c->sa_rekey_fuzz = wm->sa_rekey_fuzz;
 	c->sa_keying_tries = wm->sa_keying_tries;
 
+	c->block_cypher = wm->block_cypher;
+
+#ifdef OPENSSL
+	c->this.id.key_id.len = 0;
+	c->that.id.key_id.len = 0;
+	c->this.id.der_asn1_dn.len = 0;
+	c->that.id.der_asn1_dn.len = 0;
+#endif
+
 	c->addr_family = wm->addr_family;
 	c->tunnel_addr_family = wm->tunnel_addr_family;
 
@@ -587,7 +747,7 @@
 	default_end(&c->that, &c->this.host_addr);
 
 	/* force any wildcard host IP address to that end */
-	if (isanyaddr(&wm->left.host_addr))
+	if (isanyaddr(&c->this.host_addr))
 	{
 	    struct end t = c->this;
 
@@ -595,16 +755,45 @@
 	    c->that = t;
 	}
 
+#ifdef OPENSSL
+	{
+	    int i;
+
+	    for(i=0; i<MAX_OTHER; i++) {
+	      c->other[i].cert = NULL;
+	      c->other[i].type = 0;
+	    }
+	}
+	load_cert_and_key(wm->whack_certfile, wm->whack_keyfile,
+	    (X509 **)&(c->cert), (EVP_PKEY **)&(c->key));
+	c->cert_options = parse_options(wm->whack_certopts);
+
+#if 0 /* to be removed? */
+	/* ID_DER_ASN1_DN cannot be done with path=db or path=dir */
+	if (! check_idtype_and_path(c, wm->whack_certpath)) {
+	  success = FALSE;
+	}
+#endif
+
+       if (! make_lookups((STACK_OF(XMAP) **)(&(c->lu)),
+         wm->whack_certpath) ) {
+         success = FALSE;
+       }
+       strncpy(c->path, wm->whack_certpath, PATH_NAME_LIMIT);
+#endif
+
+
+
 	/* set internal fields */
-	c->next = connections;
+	c->ac_next = connections;
 	connections = c;
 	c->interface = NULL;
-	c->routed = FALSE;
+	c->routing = RT_UNROUTED;
 	c->newest_isakmp_sa = SOS_NOBODY;
 	c->newest_ipsec_sa = SOS_NOBODY;
 	c->eroute_owner = SOS_NOBODY;
 
-	c->rw_state = rwcs_permanent;
+	c->kind = isanyaddr(&c->that.host_addr)? CK_TEMPLATE : CK_PERMANENT;
 
 #ifdef DEBUG
 	c->extra_debugging = wm->debugging;
@@ -614,11 +803,13 @@
 
 	unshare_connection_strings(c);
 
+	(void)orient(c);
 	connect_to_host_pair(c);
 
 	possibly_some_oppo = TRUE;	/* could be more careful about this */
 
-	/* log all about this connection */
+	/* log all about this connection, if sucessful */
+	if (success) {
 	log("added connection description \"%s\"", c->name);
 	DBG(DBG_CONTROL,
 	    char lhs[SUBNETTOT_BUF + ADDRTOT_BUF + IDTOA_BUF + ADDRTOT_BUF];
@@ -651,6 +842,15 @@
 		, (unsigned long) c->sa_keying_tries
 		, bitnamesof(sa_policy_bit_names, c->policy));
 	);
+	} else {
+	  loglog(RC_LOG_SERIOUS,
+	    "Adding connection description \"%s\" failed.",
+	    c->name);
+	  loglog(RC_LOG_SERIOUS,
+	    "Deleting connection description \"%s\".",
+	    c->name);
+	  delete_connection(c);
+	}
     }
 }
 
@@ -668,7 +868,7 @@
 {
     struct connection *d = clone_thing(*c, "temporary connection");
 
-    passert(c->rw_state == rwcs_permanent);
+    passert(c->kind == CK_TEMPLATE);
     if (his_id != NULL)
     {
 	passert(d->that.id.kind == ID_NONE || same_id(&d->that.id, his_id));
@@ -676,10 +876,9 @@
     }
     unshare_connection_strings(d);
 
-    d->rw_state = rwcs_instance;
+    d->kind = CK_INSTANCE;
 
     passert(oriented(*d));
-    passert(HasWildcardIP(*d));
     d->that.host_addr = *him;
     default_end(&d->that, &d->this.host_addr);
 
@@ -690,9 +889,9 @@
     default_end(&d->this, &d->that.host_addr);
 
     /* set internal fields */
-    d->next = connections;
+    d->ac_next = connections;
     connections = d;
-    d->routed = FALSE;
+    d->routing = RT_UNROUTED;
     d->newest_isakmp_sa = SOS_NOBODY;
     d->newest_ipsec_sa = SOS_NOBODY;
     d->eroute_owner = SOS_NOBODY;
@@ -772,21 +971,22 @@
  *   + that subnet contains peer_client (or peer is peer_client)
  *   + don't care about peer (we don't know), but not NO_IP
  *   + don't care about Phase 1 IDs (we don't know)
+ *   + require that the connection HAS_IPSEC_POLICY (duh: to serve clients)
  * Give preference to the first one that has an SA (either phase).
  */
-struct connection *
-find_opportunistic_connection(const ip_address *our_client, const ip_address *peer_client)
+static struct connection *
+find_connection_for_clients(const ip_address *our_client, const ip_address *peer_client)
 {
     struct connection *c = connections
 	, *best = NULL;
 
     passert(!isanyaddr(our_client) && !isanyaddr(peer_client));
 
-    for (c = connections; c != NULL; c = c->next)
-    {
-	if (oriented(*c) || orient(c, FALSE))
+    for (c = connections; c != NULL; c = c->ac_next)
 	{
-	    if (addrinsubnet(our_client, &c->this.client)
+       if (HAS_IPSEC_POLICY(c->policy)
+       && oriented(*c)
+       && addrinsubnet(our_client, &c->this.client)
 	    && addrinsubnet(peer_client, &c->that.client))
 	    {
 		best = c;
@@ -795,17 +995,17 @@
 		    break;
 	    }
 	}
-    }
     return best;
 }
 
 /* Find and instantiate a connection for an outgoing Opportunistic connection.
  * We've already discovered its gateway.
+ * We look for a the connection such that:
  *   + this is one of our interfaces
  *   + this subnet contains our_client (or we are our_client)
- *     (we will specialize the client)
- *   + that subnet is specified and is NO_IP/32 (we will fill in)
- *   + that peer is NO_IP (we will fill in)
+ *     (we will specialize the client).  We prefer the smallest such subnet.
+ *   + HasWildcardClient (that subnet is as NO_IP/32).
+ *   + that peer is NO_IP
  *   + don't care about Phase 1 IDs (probably should be default)
  * We could look for a connection that already had the desired peer
  * (rather than NO_IP) specified, but it doesn't seem worth the
@@ -816,9 +1016,13 @@
 , const ip_address *our_client, const ip_address *peer_client)
 {
     struct iface *p;
+    struct connection *best = NULL;
 
     passert(!isanyaddr(our_client) && !isanyaddr(peer_client));
 
+    /* We don't know his ID yet, so gw id must be an ipaddr */
+    passert(id_is_ipaddr(&gw->gw_id));
+
     /* for each of our addresses... */
     for (p = interfaces; p != NULL; p = p->next)
     {
@@ -829,28 +1033,22 @@
 	struct connection *c = find_host_pair_connections(&p->addr
 	    , pluto_port, (ip_address *)NULL, pluto_port);
 
-	for (; c != NULL; c = c->next)
-	{
-	    if (!oriented(*c))
-		(void)orient(c, TRUE);	/* needed by rw_instantiate */
-
-	    if (addrinsubnet(our_client, &c->this.client)
-	    && HasWildcardClient(c))
-	    {
-		/* success: instantiate.
-		 * We don't know his ID yet.
-		 */
-		return oppo_instantiate(c, &gw->gw, NULL, gw, our_client
-		    , peer_client);
-	    }
-	}
+       for (; c != NULL; c = c->hp_next)
+           if (c->kind == CK_TEMPLATE
+           && addrinsubnet(our_client, &c->this.client)
+           && HasWildcardClient(c)
+           && HAS_IPSEC_POLICY(c->policy)
+           && (best == NULL || !subnetinsubnet(&best->this.client, &c->this.client)))
+               best = c;
     }
-    return NULL;	/* no luck */
+    return best == NULL? NULL
+       : oppo_instantiate(best, &gw->gw_id.ip_addr, NULL, gw
+           , our_client, peer_client);
 }
 
 
 bool
-orient(struct connection *c, bool must)
+orient(struct connection *c)
 {
     if (!oriented(*c))
     {
@@ -871,10 +1069,11 @@
 		    {
 			if (c->interface == p)
 			    loglog(RC_LOG_SERIOUS
-				, "both sides of \"%s\" are our interfaces!"
-				, c->name);
+                               , "both sides of \"%s\" are our interface %s!"
+                               , c->name, p->rname);
 			else
-			    loglog(RC_LOG_SERIOUS, "two interfaces match \"%s\"", c->name);
+			    loglog(RC_LOG_SERIOUS, "two interfaces match \"%s\" (%s, %s)"
+                               , c->name, c->interface->rname, p->rname);
 			c->interface = NULL;	/* withdraw orientation */
 			return FALSE;
 		    }
@@ -886,7 +1085,11 @@
 		&& (!no_klips || c->that.host_port == pluto_port)))
 		    break;
 
-		/* swap ends and try again */
+		/* swap ends and try again.
+		 * It is a little tricky to see that this loop will stop.
+		 * Only continue if the far side matches.
+		 * If both sides match, there is an error-out.
+		 */
 		{
 		    struct end t = c->this;
 
@@ -895,14 +1098,8 @@
 		}
 	    }
 	}
-	if (!oriented(*c))
-	{
-	    if (must)
-		loglog(RC_LOG_SERIOUS, "cannot find interface for connection \"%s\"", c->name);
-	    return FALSE;
-	}
     }
-    return TRUE;
+    return oriented(*c);
 }
 
 void
@@ -913,13 +1110,13 @@
     if (c != NULL)
     {
 	SET_CUR_CONNECTION(c);
-	if (!orient(c, TRUE))
+	if (!oriented(*c))
 	{
-	    loglog(RC_ORIENT, "could not orient connection");
+		loglog(RC_ORIENT, "we have no ipsecN interface for either end of this connection");
 	}
-	else if (HasWildcardIP(*c))
+	else if (c->kind != CK_PERMANENT)
 	{
-	    loglog(RC_NOPEERIP, "cannot initiate connection without peer IP");
+		loglog(RC_NOPEERIP, "cannot initiate connection without knowing peer IP address");
 	}
 	else
 	{
@@ -928,11 +1125,7 @@
 	     * This is a fudge, but not yet important.
 	     * If we are to proceed asynchronously, whackfd will be NULL_FD.
 	     */
-	    ipsecdoi_initiate(whackfd
-		, c
-		, (c->policy>>POLICY_IPSEC_SHIFT) != 0
-		, c->policy
-		, 1);
+	    ipsecdoi_initiate(whackfd, c, c->policy, 1);
 	    whackfd = NULL_FD;	/* protect from close */
 	}
 	UNSET_CUR_CONNECTION();
@@ -944,12 +1137,12 @@
 /* knowing clients (single IP addresses), try to build an SA */
 void
 initiate_opportunistic(const ip_address *our_client
-, const ip_address *peer_client, int whackfd)
+, const ip_address *peer_client, bool held, int whackfd)
 {
     struct connection *c;
 
     /* What connection shall we use?
-     * First try for an existing one.
+     * First try for one that explicitly handles the clients.
      */
     DBG(DBG_CONTROL,
 	{
@@ -961,34 +1154,76 @@
 	    DBG_log("attempt opportunistic from %s to %s", ours, his);
 	});
 
-    c = find_opportunistic_connection(our_client, peer_client);
+    c = find_connection_for_clients(our_client, peer_client);
     if (c != NULL)
     {
+	/* We've found a connection that can serve.
+	 * Do we have to initiate it?
+	 * Not if there is currently an IPSEC SA.
+	 * But if there is an IPSEC SA, then KLIPS would not
+	 * have generated the acquire.  So we assume that there isn't one.
+	 * This may be redundant if a non-opportunistic
+	 * negotiation is already being attempted.
+	 */
+
 	/* We will only request an IPsec SA if policy isn't empty
 	 * (ignoring Main Mode items).
 	 * This is a fudge, but not yet important.
 	 * If we are to proceed asynchronously, whackfd will be NULL_FD.
 	 */
-	ipsecdoi_initiate(whackfd
-	    , c
-	    , (c->policy>>POLICY_IPSEC_SHIFT) != 0
-	    , c->policy
-	    , 1);
+
+	passert(HAS_IPSEC_POLICY(c->policy));
+
+	if (held)
+	{
+	    /* what should we do on failure? */
+	    (void) assign_hold(c, our_client, peer_client);
+
+	    switch (c->routing){
+	    case RT_UNROUTED:
+	        c->routing = RT_UNROUTED_HOLD;
+	        break;
+	    case RT_ROUTED_PROSPECTIVE:
+	        c->routing = RT_ROUTED_HOLD;
+	        break;
+	    default:
+	        passert(FALSE);
+	    }
+	}
+	ipsecdoi_initiate(whackfd, c, c->policy, 1);
 	whackfd = NULL_FD;	/* protect from close */
     }
     else
     {
-	/* try to find peer via DNS query */
-	err_t ugh = discover_gateway(peer_client);
+       /* No connection explicitly handles the clients.
+        * So we don't even know the peer:
+        * try to discover peer via DNS query
+        */
+       struct gw_info *gw;
+       err_t ugh = discover_gateway(peer_client, (const struct id *) NULL, &gw);
 
 	if (ugh != NULL)
 	{
-	    loglog(RC_OPPOFAILURE, "failure discovering gateway: %s", ugh);
+           char pcb[ADDRTOT_BUF];
+
+           addrtot(peer_client, 0, pcb, sizeof(pcb));
+           loglog(RC_OPPOFAILURE, "failure discovering gateway for %s: %s"
+               , pcb, ugh);
+
+           if (held)
+           {
+               /* Replace HOLD with PASS.
+                * The type of replacement *ought* to be
+                * specified by policy.
+                */
+               (void) replace_bare_shunt(our_client, peer_client
+                   , SPI_PASS  /* fail into PASS */
+                   , TRUE, "replace HOLD with PASS [no SG discoverd]");
+           }
 	}
 	else
 	{
-	    /* note: new gw_info is at front of gateways list */
-	    c = build_outgoing_opportunistic_connection(gateways, our_client
+	    c = build_outgoing_opportunistic_connection(gw, our_client
 		, peer_client);
 	    if (c == NULL)
 	    {
@@ -997,27 +1232,36 @@
 		    , pb[ADDRTOT_BUF];
 
 		addrtot(our_client, 0, ocb, sizeof(ocb));
-		addrtot(peer_client, 0, pcb, sizeof(ocb));
-		addrtot(&gateways->gw, 0, pb, sizeof(pb));
+		addrtot(peer_client, 0, pcb, sizeof(pcb));
+                passert(id_is_ipaddr(&gw->gw_id));
+                addrtot(&gw->gw_id.ip_addr, 0, pb, sizeof(pb));
 		loglog(RC_OPPOFAILURE
 		    , "no suitable connection for opportunism"
 		      " between %s and %s with %s as peer"
 		    , ocb, pcb, pb);
+
+                if (held)
+                {
+                    /* Replace HOLD with PASS.
+                     * The type of replacement *ought* to be
+                     * specified by policy.
+                     */
+                    (void) replace_bare_shunt(our_client, peer_client
+                        , SPI_PASS      /* fail into PASS */
+                        , TRUE, "replace HOLD with PASS [no suitable connection]");
+                }
 	    }
 	    else
 	    {
-		/* We will only request an IPsec SA if policy isn't empty
-		 * (ignoring Main Mode items).
-		 * This is a fudge, but not yet important.
-		 * If we are to proceed asynchronously, whackfd will be NULL_FD.
+                /* If we are to proceed asynchronously, whackfd will be NULL_FD.
 		 */
 		passert(c->gw_info != NULL);
+               passert(HAS_IPSEC_POLICY(c->policy));
+               passert(c->routing == RT_UNROUTED);
+               if (held)
+                   c->routing = RT_UNROUTED_HOLD;
 		c->gw_info->last_tried_time = now();
-		ipsecdoi_initiate(whackfd
-		    , c
-		    , (c->policy>>POLICY_IPSEC_SHIFT) != 0
-		    , c->policy
-		    , 1);
+		ipsecdoi_initiate(whackfd, c, c->policy, 1);
 		whackfd = NULL_FD;	/* protect from close */
 	    }
 	}
@@ -1035,7 +1279,7 @@
 
     for (c = con_by_name(nm, TRUE); c != NULL; c = n)
     {
-	n = c->next;	/* grab this before c might disappear */
+	n = c->ac_next;	/* grab this before c might disappear */
 	if (streq(c->name, nm))
 	{
 	    SET_CUR_CONNECTION(c);
@@ -1052,47 +1296,47 @@
  * not process a packet output by an eroute.
  */
 #ifdef NEVER
-bool
-check_nexthop(const struct connection *c)
-{
-    struct connection *d;
-
-    if (addrinsubnet(&c->this.host_nexthop, &c->that.client))
-    {
-	loglog(RC_LOG_SERIOUS, "cannot perform routing for connection \"%s\""
-	    " because nexthop is within peer's client network",
-	    c->name);
-	return FALSE;
-    }
-
-    for (d = connections; d != NULL; d = d->next)
-    {
-	if (d->routed)
-	{
-	    if (addrinsubnet(&c->this.host_nexthop, &d->that.client))
-	    {
-		loglog(RC_LOG_SERIOUS, "cannot do routing for connection \"%s\"
-		    " because nexthop is contained in"
-		    " existing routing for connection \"%s\"",
-		    c->name, d->name);
-		return FALSE;
-	    }
-	    if (addrinsubnet(&d->this.host_nexthop, &c->that.client))
-	    {
-		loglog(RC_LOG_SERIOUS, "cannot do routing for connection \"%s\"
-		    " because it contains nexthop of"
-		    " existing routing for connection \"%s\"",
-		    c->name, d->name);
-		return FALSE;
-	    }
-	}
-    }
-    return TRUE;
-}
+//bool
+//check_nexthop(const struct connection *c)
+//{
+//    struct connection *d;
+//
+//    if (addrinsubnet(&c->this.host_nexthop, &c->that.client))
+//    {
+//	loglog(RC_LOG_SERIOUS, "cannot perform routing for connection \"%s\""
+//	    " because nexthop is within peer's client network",
+//	    c->name);
+//	return FALSE;
+//    }
+//
+//    for (d = connections; d != NULL; d = d->next)
+//    {
+//	if (d->routed)
+//	{
+//	    if (addrinsubnet(&c->this.host_nexthop, &d->that.client))
+//	    {
+//		loglog(RC_LOG_SERIOUS, "cannot do routing for connection \"%s\"
+//		    " because nexthop is contained in"
+//		    " existing routing for connection \"%s\"",
+//		    c->name, d->name);
+//		return FALSE;
+//	    }
+//	    if (addrinsubnet(&d->this.host_nexthop, &c->that.client))
+//	    {
+//		loglog(RC_LOG_SERIOUS, "cannot do routing for connection \"%s\"
+//		    " because it contains nexthop of"
+//		    " existing routing for connection \"%s\"",
+//		    c->name, d->name);
+//		return FALSE;
+//	    }
+//	}
+//    }
+//    return TRUE;
+//}
 #endif /* NEVER */
 
 /* an ISAKMP SA has been established.
- * Note the serial number, and unorient any connections with
+ * Note the serial number, and release any connections with
  * the same peer ID but different peer IP address.
  */
 bool uniqueIDs = FALSE;	/* --uniqueids? */
@@ -1111,74 +1355,179 @@
 
 	for (d = connections; d != NULL; )
 	{
-	    struct connection *next = d->next;	/* might move underneath us */
+	    struct connection *next = d->ac_next;	/* might move underneath us */
 
-	    if (same_id(&c->that.id, &d->that.id)
-	    && !sameaddr(&c->that.host_addr, &d->that.host_addr)
-	    && !HasWildcardIP(*d))
+           if (d->kind != CK_TEMPLATE
+           && same_id(&c->that.id, &d->that.id)
+           && !sameaddr(&c->that.host_addr, &d->that.host_addr))
 	    {
-		unorient_connection(d);
+		release_connection(d);
 	    }
 	    d = next;
 	}
-	
     }
 }
 
-/* Find a connection that owns the route to a connection's peer's client.
- * Preference is given to one that has an eroute too.
- * If eroute is true, our client must match too (as for eroutes).
+/* Find the connection to connection c's peer's client with the
+ * largest value of .routing.  All other things being equal,
+ * preference is given to c.  If none is routed, return NULL.
+ *
+ * If erop is non-null, set *erop to a connection sharing both
+ * our client subnet and peer's client subnet with the largest value
+ * of .routing.  If none is erouted, set *erop to NULL.
+ *
+ * The return value is used to find other connections sharing a route.
+ * *erop is used to find other connections sharing an eroute.
  */
 struct connection *
-route_owner(struct connection *c, bool eroute)
+route_owner(struct connection *c, struct connection **erop)
 {
-    struct connection
-	*d,
-	*best = NULL;
+    struct connection *d
+       , *bestro = c
+       , *bestero = c;
+    const ip_subnet *cc = EffectivePeerClient(c);
 
     passert(oriented(*c));
 
-    if (c->routed && c->eroute_owner != SOS_NOBODY)
-	return c;
-
-    for (d = connections; d != NULL; d = d->next)
+    for (d = connections; d != NULL; d = d->ac_next)
     {
-	if (d->routed)
+       if (d->routing != RT_UNROUTED   /* quick filter */
+       && samesubnet(cc, EffectivePeerClient(d)))
 	{
 	    passert(oriented(*d));
-	    if (samesubnet(&c->that.client, &d->that.client)
-	    && (!eroute || samesubnet(&c->this.client, &d->this.client)))
+           if (d->routing > bestro->routing)
+               bestro = d;
+           if (d->routing > bestero->routing
+           && samesubnet(&c->this.client, &d->this.client))
+               bestero = d;
+       }
+    }
+    DBG(DBG_CONTROL,
 	    {
-		if (d->eroute_owner != SOS_NOBODY)
-		    return d;	/* definite winner */
+           err_t m = builddiag("route owner of \"%s\" %s %s:"
+               , c->name
+               , enum_name(&connection_kind_names, c->kind)
+               , enum_name(&routing_story, c->routing));
 
-		best = d;	/* winner if no better comes along */
-	    }
+           if (!routed(bestro->routing))
+               m = builddiag("%s NULL", m);
+           else if (bestro == c)
+               m = builddiag("%s self", m);
+           else
+               m = builddiag("%s \"%s\" %s %s", m
+                   , bestro->name
+                   , enum_name(&connection_kind_names, bestro->kind)
+                   , enum_name(&routing_story, bestro->routing));
+
+           if (erop != NULL)
+	    {
+               m = builddiag("%s; eroute owner:", m);
+               if (!erouted(bestero->routing))
+                   m = builddiag("%s NULL", m);
+               else if (bestero == c)
+                   m = builddiag("%s self", m);
+               else
+                   m = builddiag("%s \"%s\" %s %s", m
+                       , bestero->name
+                       , enum_name(&connection_kind_names, bestero->kind)
+                       , enum_name(&routing_story, bestero->routing));
 	}
+
+           DBG_log("%s", m);
+       });
+    if (erop != NULL)
+       *erop = erouted(bestero->routing)? bestero : NULL;
+    return routed(bestro->routing)? bestro : NULL;
+}
+
+/* Find a connection that owns the shunt eroute between subnets.
+ * There ought to be only one.
+ * This might get to be a bottleneck -- try hashing if it does.
+ */
+struct connection *
+shunt_owner(const ip_subnet *ours, const ip_subnet *his)
+{
+    struct connection *c;
+
+    for (c = connections; c != NULL; c = c->ac_next)
+    {
+       if (shunt_erouted(c->routing)
+       && samesubnet(ours, &c->this.client)
+       && samesubnet(his, &c->that.client))
+           break;
     }
-    return best;
+    return c;
 }
 
+/* Find some connection with this pair of hosts.
+ * We don't know enough to chose amongst those available.
+ * ??? no longer usefully different from find_host_pair_connections
+ */
 struct connection *
 find_host_connection(const ip_address *me, u_int16_t my_port
 , const ip_address *him, u_int16_t his_port)
 {
-    struct connection *c = find_host_pair_connections(me, my_port, him, his_port);
-
-    if (c != NULL && !oriented(*c))
-	(void)orient(c, FALSE);
-    return c;
+    return find_host_pair_connections(me, my_port, him, his_port);
 }
 
-/* given an up-until-now satisfactory connection, find the best
- * connection now that we've got the Id Payload from the peer.
+/* given an up-until-now satisfactory connection, find the best connection
+ * now that we just got the Phase 1 Id Payload from the peer.
+ *
+ * Comments in the code describe the (tricky!) matching criteria.
+ * Although this routine could handle the initiator case,
+ * it isn't currently called in this case.
+ * This routine won't do anything interesting for Opportunistic Connections;
+ * it's not clear that anything useful could be done.
+ *
+ * In RFC 2409 "The Internet Key Exchange (IKE)",
+ * in 5.1 "IKE Phase 1 Authenticated With Signatures", describing Main
+ * Mode:
+ *
+ *         Initiator                          Responder
+ *        -----------                        -----------
+ *         HDR, SA                     -->
+ *                                     <--    HDR, SA
+ *         HDR, KE, Ni                 -->
+ *                                     <--    HDR, KE, Nr
+ *         HDR*, IDii, [ CERT, ] SIG_I -->
+ *                                     <--    HDR*, IDir, [ CERT, ] SIG_R
+ *
+ * In 5.4 "Phase 1 Authenticated With a Pre-Shared Key":
+ *
+ *               HDR, SA             -->
+ *                                   <--    HDR, SA
+ *               HDR, KE, Ni         -->
+ *                                   <--    HDR, KE, Nr
+ *               HDR*, IDii, HASH_I  -->
+ *                                   <--    HDR*, IDir, HASH_R
+ *
+ * refine_host_connection could be called in two case:
+ *
+ * - the Responder receives the IDii payload:
+ *   + [PSK] after using PSK to decode this message
+ *   + before sending its IDir payload
+ *   + before using its ID in HASH_R computation
+ *   + [DSig] before using its private key to sign SIG_R
+ *   + before using the Initiator's ID in HASH_I calculation
+ *   + [DSig] before using the Initiator's public key to check SIG_I
  *
- * We can only accept connections with compatible authentication.
- * The authentication method has been committed to.
- * The authentication materials are a slightly different matter.
- * We are committed to all authentication materials EXCEPT
- * in the case of RSA Sig authentication when we are the Responder.
- * In that case, the Initiator's public key is still open.
+ * - the Initiator receives the IDir payload:
+ *   + [PSK] after using PSK to encode previous message and decode this message
+ *   + after sending its IDii payload
+ *   + after using its ID in HASH_I computation
+ *   + [DSig] after using its private key to sign SIG_I
+ *   + before using the Responder's ID to compute HASH_R
+ *   + [DSig] before using Responder's public key to check SIG_R
+ *
+ * refine_host_connection can choose a different connection, as long as
+ * nothing already used is changed.
+ *
+ * In the Initiator case, the particular connection might have been
+ * specified by whatever provoked Pluto to initiate.  For example:
+ *	whack --initiate connection-name
+ * The advantages of switching connections when we're the Initiator seem
+ * less important than the disadvantages, so after FreeS/WAN 1.9, we
+ * don't do this.
  */
 struct connection *
 refine_host_connection(const struct state *st, const struct id *peer_id
@@ -1189,39 +1538,64 @@
     struct connection *d;
     lset_t auth_policy;
     const chunk_t *psk;
-    const struct RSA_public_key *his_RSA_pub;
-    const struct RSA_private_key *my_RSA_pri;
+    const struct RSA_private_key *my_RSA_pri = NULL;
     bool rw;
 
     if (same_id(&c->that.id, peer_id))
-	return c;
+	return c;       /* peer ID matches current connection -- look no further */
 
     switch (auth)
     {
     case OAKLEY_PRESHARED_KEY:
 	auth_policy = POLICY_PSK;
 	psk = get_preshared_secret(c);
+	/* It should be virtually impossible to fail to find PSK:
+	 * we just used it to decode the current message!
+	 */
 	if (psk == NULL)
 	    return NULL;	/* cannot determine PSK! */
 	break;
+
     case OAKLEY_RSA_SIG:
+#ifndef OPENSSL
 	auth_policy = POLICY_RSASIG;
+#else
+   case OAKLEY_RSA_ENC:
+   case OAKLEY_RSA_ENC_REV:
+	auth_policy = POLICY_OPENSSL;
+#endif
+	if (initiator)
+	{
+           /* at this point, we've committed to our RSA private key:
+            * we used it in our previous message.
+            */
 	my_RSA_pri = get_RSA_private_key(c);
 	if (my_RSA_pri == NULL)
 	    return NULL;	/* cannot determine my RSA private key! */
-	if (initiator)
-	{
-	    his_RSA_pub = get_his_RSA_public_key(c);
-	    if (his_RSA_pub == NULL)
-		return NULL;	/* cannot determine his RSA public key! */
 	}
 	break;
+#ifdef OPENSSL
+    case OAKLEY_DSS_SIG:
+    case OAKLEY_ELGAMAL_ENC:
+    case OAKLEY_ELGAMAL_ENC_REV:
+	auth_policy = POLICY_OPENSSL;
+	/* Not implemented yet */
+	break;
+#endif
     default:
 	passert(FALSE);
     }
+
     /* The current connection won't do: search for one that will.
      * First search for one with the same pair of hosts.
      * If that fails, search for one with a Road Warrior peer.
+     * We need to match:
+     * - peer_id (slightly complicated by instantiation)
+     * - if PSK auth, the key must not change (we used it to decode message)
+     * - policy-as-used must be acceptable to new connection
+     * - if initiator, also:
+     *   + our ID must not change (we sent it in previous message)
+     *   + our RSA key must not change (we used in in previous message)
      */
     d = c->host_pair->connections;
     for (rw = FALSE; ; rw = TRUE)
@@ -1230,22 +1604,40 @@
 
 	for (; d != NULL; d = d->hp_next)
 	{
-	    bool exact;
+	    bool exact = same_id(peer_id, &d->that.id); /* exact peer ID match? */
 
-	    if (!oriented(*d))
-		(void)orient(d, FALSE);
+#ifdef OPENSSL
+           /* fetch d's other cert, when applicable. */
+             if (auth_policy == POLICY_OPENSSL) {
+               bool r;
+               switch(auth) {
+                 case OAKLEY_RSA_SIG:
+                 case OAKLEY_RSA_ENC:
+                 case OAKLEY_RSA_ENC_REV:
+                   r = have_othercert(d, EVP_PKEY_RSA);
+                   break;
 
-	    if (!same_id(&c->this.id, &d->this.id))
+                  case OAKLEY_DSS_SIG:
+                 case OAKLEY_ELGAMAL_ENC:
+                 case OAKLEY_ELGAMAL_ENC_REV:
+                   r = have_othercert(d, EVP_PKEY_DSA);
+                   break;
+               default:
+                   passert(FALSE);
+               } /* END switch */
+             }
+#endif
+           /* check if peer_id matches, exactly or after instantiation */
+           if (!exact && !(rw && d->that.id.kind == ID_NONE))
 		continue;
 
-	    exact = same_id(peer_id, &d->that.id);
-
-	    if (exact || (rw && d->that.id.kind == ID_NONE))
-	    {
-		/* check whether authentication would work the same */
+           /* if initiator, our ID must match exactly */
+           if (initiator && !same_id(&c->this.id, &d->this.id))
+		continue;
 
-		if (!((d->policy & auth_policy) != 0
-		|| (d->policy & POLICY_ISAKMP_MASK) == 0))
+           /* authentication used must fit policy of this connection */
+           if (!((d->policy & auth_policy) != LEMPTY
+           || (d->policy & POLICY_ID_AUTH_MASK) == LEMPTY))
 		    continue;	/* our auth isn't OK for this connection */
 
 		switch (auth)
@@ -1263,25 +1655,27 @@
 				continue;	/* different secret */
 		    }
 		    break;
-		case OAKLEY_RSA_SIG:
-		    if (my_RSA_pri != get_RSA_private_key(d))
-			continue;	/* different private key */
 
-		    if (initiator)
-		    {
-			/* his public key has been used for authentication
-			 * so we must be sure that any connection we
-			 * select will use the same public key.
+           case OAKLEY_RSA_SIG:
+#ifdef OPENSSL
+           case OAKLEY_RSA_ENC:
+           case OAKLEY_RSA_ENC_REV:
+#endif
+               /* We must at least be able to find our private key.
+                * If we initiated, it must match the one we
+                * used in the SIG_I payload that we sent previously.
 			 */
-			const struct RSA_public_key *hnk = exact
-			    ? get_his_RSA_public_key(d) : get_RSA_public_key(peer_id);
-
-			passert(exact || d->gw_info == NULL);
+               {
+                   const struct RSA_private_key *pri
+                       = get_RSA_private_key(d);
 
-			if (!same_RSA_public_key(his_RSA_pub, hnk))
-			    continue;	/* different public key */
+                   if (pri == NULL
+                   || (initiator
+                       && !same_RSA_public_key(&my_RSA_pri->pub, &pri->pub)))
+                       continue;
 		    }
 		    break;
+
 		default:
 		    passert(FALSE);
 		}
@@ -1291,7 +1685,6 @@
 
 		best_found = d;	/* passed tests, but peer_id was wildcarded */
 	    }
-	}
 	if (rw)
 	    return best_found;	/* been around twice already */
 
@@ -1342,20 +1735,17 @@
 
     for (d = hp->connections; d != NULL; d = d->hp_next)
     {
-	if (!oriented(*d))
-	    (void)orient(d, FALSE);
-
 	if (!same_peer_ids(c, d, peer_id))
 	    continue;
 
 	if (oppo)
 	{
 	    /* Opportunistic case:
-	     * our_client must be inside the abstract client
-	     * and we must have a Wildcard Client.
+             * our_net must be inside d->this.client
+             * and d must have a Wildcard that.client.
 	     */
-	    if (!addrinsubnet(&d->this.host_addr, our_net)
-	    || !HasWildcardClient(c))
+            if (!subnetinsubnet(our_net, &d->this.client)
+            || !HasWildcardClient(d))
 		continue;
 	}
 	else
@@ -1387,7 +1777,7 @@
 	}
 
 	/* we've run the gauntlet -- success */
-	if (d->routed)
+	if (routed(d->routing))
 	    return d;
 
 	if (unrouted == NULL)
@@ -1412,7 +1802,7 @@
 	&& samesubnet(&c->that.client, peer_net))
 	{
 	    passert(oriented(*c));
-	    if (c->routed)
+	    if (routed(c->routing))
 		return c;
 
 	    unrouted = c;
@@ -1439,9 +1829,7 @@
 	    /* RW match with actual peer_id? */
 	    d = fc_try(FALSE, c, hp, NULL, our_net, peer_net);
 
-	    if (d == NULL
-	    && (c->that.id.kind == ID_IPV4_ADDR || c->that.id.kind == ID_IPV6_ADDR)
-	    && sameaddr(&c->that.id.ip_addr, &c->that.host_addr))
+	    if (d == NULL && his_id_was_instantiated(c))
 	    {
 		/* RW match with abstract peer_id?
 		 * Note that later instantiation will result in the same peer_id.
@@ -1470,11 +1858,10 @@
 {
     struct connection *c;
 
-    for (c = connections; c != NULL; c = c->next)
+    for (c = connections; c != NULL; c = c->ac_next)
     {
-	const char *routed = c->routed? "; routed" : "";
 	const char *ifn = oriented(*c)? c->interface->rname : "";
-	const char *instance = c->rw_state == rwcs_instance? " instance" : "";
+	const char *instance = c->kind == CK_INSTANCE? " instance" : "";
 
 	/* show topology */
 	{
@@ -1511,12 +1898,12 @@
 	    , (unsigned long) c->sa_keying_tries);
 
 	whack_log(RC_COMMENT
-	    , "\"%s\"%s:   policy: %s; interface: %s%s"
+	    , "\"%s\"%s:   policy: %s; interface: %s; %s"
 	    , c->name
 	    , instance
 	    , bitnamesof(sa_policy_bit_names, c->policy)
 	    , ifn
-	    , routed);
+            , enum_name(&routing_story, c->routing));
 
 	whack_log(RC_COMMENT
 	    , "\"%s\"%s:   newest ISAKMP SA: #%ld; newest IPsec SA: #%ld; eroute owner: #%lu"
@@ -1544,3 +1931,198 @@
     }
     return FALSE;
 }
+
+/* peer client, but for wildcard, subrange containing all */
+const ip_subnet *
+EffectivePeerClient(const struct connection *c)
+{
+    return c->kind == CK_TEMPLATE && HasWildcardClient(c)
+       ? aftoinfo(subnettypeof(&c->that.client))->all
+       : &c->that.client;
+}
+
+/* struct pending, the structure representing Quick Mode
+ * negotiations delayed until a Keying Channel has been negotiated.
+ * Essentially, a pending call to quick_outI1.
+ */
+
+struct pending {
+    int whack_sock;
+    struct state *isakmp_sa;
+    struct connection *connection;
+    lset_t policy;
+    unsigned long try;
+
+    struct pending *next;
+};
+
+/* queue a Quick Mode negotiation pending completion of a suitable Main Mode */
+void
+add_pending(int whack_sock
+, struct state *isakmp_sa
+, struct connection *c
+, lset_t policy
+, unsigned long try)
+{
+    struct pending *p = alloc_thing(struct pending, "struct pending");
+
+    DBG(DBG_CONTROL, DBG_log("Queuing pending Quick Mode with %s \"%s\""
+       , ip_str(&c->that.host_addr)
+       , c->name));
+    p->whack_sock = whack_sock;
+    p->isakmp_sa = isakmp_sa;
+    p->connection = c;
+    p->policy = policy;
+    p->try = try;
+    p->next = c->host_pair->pending;
+    c->host_pair->pending = p;
+}
+
+/* Release all the whacks awaiting the completion of this state.
+ * This is accomplished by closing all the whack socket file descriptors.
+ * We go to a lot of trouble to tell each whack, but to not tell it twice.
+ */
+void
+release_pending_whacks(struct state *st, err_t story)
+{
+    struct pending *p;
+    struct stat stst;
+
+    if (st->st_whack_sock == NULL_FD || fstat(st->st_whack_sock, &stst) != 0)
+       zero (&stst);   /* resulting st_dev/st_ino ought to be distinct */
+
+    release_whack(st);
+
+    for (p = st->st_connection->host_pair->pending; p != NULL; p = p->next)
+    {
+       if (p->isakmp_sa == st && p->whack_sock != NULL_FD)
+       {
+           struct stat pst;
+
+           if (fstat(p->whack_sock, &pst) == 0
+           && (stst.st_dev != pst.st_dev || stst.st_ino != pst.st_ino))
+           {
+               passert(whack_log_fd == NULL_FD);
+               whack_log_fd = p->whack_sock;
+               whack_log(RC_COMMENT
+                   , "%s for ISAKMP SA, but releasing whack for pending IPSEC SA"
+                   , story);
+               whack_log_fd = NULL_FD;
+           }
+           close(p->whack_sock);
+           p->whack_sock = NULL_FD;
+       }
+    }
+}
+
+static void
+delete_pending(struct pending **pp)
+{
+    struct pending *p = *pp;
+
+    *pp = p->next;
+    if (p->connection != NULL)
+       connection_discard(p->connection);
+    if (p->whack_sock != NULL_FD)
+       close(p->whack_sock);
+    pfree(p);
+}
+
+void
+unpend(struct state *st)
+{
+    struct pending **pp
+       , *p;
+
+    for (pp = &st->st_connection->host_pair->pending; (p = *pp) != NULL; )
+    {
+       if (p->isakmp_sa == st)
+       {
+           DBG(DBG_CONTROL, DBG_log("unqueuing pending Quick Mode with %s \"%s\""
+               , ip_str(&p->connection->that.host_addr)
+               , p->connection->name));
+           (void) quick_outI1(p->whack_sock, st, p->connection, p->policy
+               , p->try);
+           p->whack_sock = NULL_FD;    /* ownership transferred */
+           p->connection = NULL;       /* ownership transferred */
+           delete_pending(pp);
+       }
+       else
+       {
+           pp = &p->next;
+       }
+    }
+}
+
+/* a Main Mode negotiation has been replaced; update any pending */
+void
+update_pending(struct state *os, struct state *ns)
+{
+    struct pending *p;
+
+    for (p = os->st_connection->host_pair->pending; p != NULL; p = p->next)
+       if (p->isakmp_sa == os)
+           p->isakmp_sa = ns;
+}
+
+/* a Main Mode negotiation has failed; discard any pending */
+void
+flush_pending_by_state(struct state *st)
+{
+    struct pending **pp
+       , *p;
+
+    for (pp = &st->st_connection->host_pair->pending; (p = *pp) != NULL; )
+    {
+       if (p->isakmp_sa == st)
+           delete_pending(pp);
+       else
+           pp = &p->next;
+    }
+}
+
+/* a connection has been deleted; discard any related pending */
+static void
+flush_pending_by_connection(struct connection *c)
+{
+    if (c->host_pair != NULL)
+    {
+       struct pending **pp
+           , *p;
+
+       for (pp = &c->host_pair->pending; (p = *pp) != NULL; )
+       {
+           if (p->connection == c)
+           {
+               p->connection = NULL;   /* prevent delete_pending from releasing */
+               delete_pending(pp);
+           }
+           else
+           {
+               pp = &p->next;
+           }
+       }
+    }
+}
+
+/* Delete a connection if it is an instance and it is no longer in use.
+ * We must be careful to avoid circularity:
+ * we don't touch it if it is CK_GOING_AWAY.
+ */
+void
+connection_discard(struct connection *c)
+{
+    if (c->kind == CK_INSTANCE)
+    {
+       /* see if it is being used by a pending */
+       struct pending *p;
+
+       for (p = c->host_pair->pending; p != NULL; p = p->next)
+           if (p->connection == c)
+               return; /* in use, so we're done */
+
+       if (!states_use_connection(c))
+           delete_connection(c);
+    }
+}
+
diff -bruN freeswan-1.9.orig/pluto/connections.h freeswan-1.9/pluto/connections.h
--- freeswan-1.9.orig/pluto/connections.h	Sun Jan 28 16:03:02 2001
+++ freeswan-1.9/pluto/connections.h	Wed Jun  6 16:13:22 2001
@@ -11,9 +11,13 @@
  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  * for more details.
  *
- * RCSID $Id: connections.h,v 1.43 2001/01/28 21:03:02 dhr Exp $
+ * RCSID $Id: connections.h,v 1.54 2001/05/28 19:18:17 dhr Exp $
  */
 
+#ifdef OPENSSL
+#include "openssl_defs.h"
+#endif
+
 /* There are two kinds of connections:
  * - ISAKMP connections, between hosts (for IKE communication)
  * - IPsec connections, between clients (for secure IP communication)
@@ -54,13 +58,16 @@
  *   gateway can get traffic for a specific (client) subnet.
  *   Furthermore, if the routing isn't in place, packets will
  *   be sent in the clear.
- *   "routed" indicates whether the routing has been done for
- *   this connection.
+ *   "routing" indicates whether the routing has been done for
+ *   this connection.  Note that several connections may claim
+ *   the same routing, as long as they agree about where the
+ *   packets are to be sent.
  * - With the current KLIPS, only one outbound IPsec SA bundle can be
  *   used for a particular client.  This is due to a limitation
  *   of using only routing for selection.  So only one IPsec state (SA)
  *   may "own" the eroute.  "eroute_owner" is the serial number of
- *   this state, or SOS_NOBODY if there is none.
+ *   this state, SOS_NOBODY if there is none.  "routing" indicates
+ *   what kind of erouting has been done for this connection, if any.
  *
  * Operations on Connections:
  *
@@ -70,14 +77,27 @@
  * - find a connection (by IP addresses of hosts)
  *   [response to peer request; finding ISAKMP connection for IPsec connection]
  *
- * When a connection is referenced by a state object, it must have
- * the IP addresses of the hosts filled in.  Some connections are
- * missing one or the other IP addresses (essentially "wildcarded",
- * denoted by a value of 0.0.0.0).  When one must be filled in (to allow
- * it to be used by a state object), a new connection is derived from
- * the old one.  It is deleted when no longer in use.
+ * Some connections are templates, missing the address of the peer
+ * (represented by INADDR_ANY).  These are always arranged so that the
+ * missing end is "that" (there can only be one missing end).  These can
+ * be instantiated (turned into real connections) by Pluto in one of two
+ * different ways: Road Warrior Instantiation or Opportunistic
+ * Instantiation.  A template connection is marked for Opportunistic
+ * Instantiation by specifying the peer client as 0.0.0.0/32 (or the IPV6
+ * equivalent).  Otherwise, it is suitable for Road Warrior Instantiation.
+ *
+ * Instantiation creates a new temporary connection, with the missing
+ * details filled in.  The resulting template lasts only as long as there
+ * is a stat that uses it.
  */
 
+#ifdef OPENSSL
+struct other_st {
+  u_int32_t type; /* type of certificate in 'cert': EVP_PKEY_RSA or EVP_PKEY_DSA */
+  void *cert;
+};
+#endif
+
 struct end {
     struct id id;
     ip_address
@@ -92,6 +112,20 @@
 
 struct connection {
     char *name;
+#ifdef OPENSSL
+    /* The declaration of these as void is truly horrific - they 
+     * should be X509 and EVP_PKEY pointers. Unfortunately, if this
+     * is declared, the MD5 header files from OpenSSL conflict with those
+     * in the KLIPS source. Hence we cast these pointers to the right
+     * type at the time of use. It's disgusting, but I can't think of
+     * another way -- ND 
+     */
+    void *cert, *key, *lu;
+    struct other_st other[MAX_OTHER];
+    u_char path[PATH_NAME_LIMIT];
+    u_int32_t cert_options;
+#endif
+    lset_t block_cypher;
     lset_t policy;
     time_t sa_ike_life_seconds;
     time_t sa_ipsec_life_seconds;
@@ -104,20 +138,15 @@
 
     /* internal fields: */
 
+    enum connection_kind kind;
     const struct iface *interface;	/* filled in iff oriented */
-    bool routed;	/* is routing in place for peer's client? */
+    enum routing_t routing;    /* level of routing in place */
+
     so_serial_t	/* state object serial number */
 	newest_isakmp_sa,
 	newest_ipsec_sa,
 	eroute_owner;
 
-    enum rwcs {
-	rwcs_permanent,	/* normal connection */
-	rwcs_instance,	/* instance created for a particular attempt */
-	rwcs_going_away	/* being deleted -- don't delete again */
-    };
-    enum rwcs rw_state;
-
 #ifdef DEBUG
     unsigned int extra_debugging;
 #endif
@@ -129,13 +158,13 @@
     struct gw_info *gw_info;
 
     struct host_pair *host_pair;
-    struct connection *hp_next;
+    struct connection *hp_next;		/* host pair list link */
 
-    struct connection *next;
+    struct connection *ac_next;		/* all connections list link */
 };
 
 #define oriented(c) ((c).interface != NULL)
-extern bool orient(struct connection *c, bool must);
+extern bool orient(struct connection *c);
 
 extern bool same_peer_ids(const struct connection *c
     , const struct connection *d, const struct id *his_id);
@@ -147,27 +176,33 @@
 extern void add_connection(const struct whack_message *wm);
 extern void initiate_connection(const char *name, int whackfd);
 extern void initiate_opportunistic(const ip_address *our_client
-    , const ip_address *peer_client, int whackfd);
+    , const ip_address *peer_client, bool held, int whackfd);
 extern void terminate_connection(const char *nm);
-extern void unorient_connection(struct connection *c);
+extern void release_connection(struct connection *c);
 extern void delete_connection(struct connection *c);
 extern void delete_every_connection(void);
-extern void release_interface(struct iface *i);
-extern struct connection *route_owner(struct connection *c, bool eroute);
+extern void release_dead_interfaces(void);
+extern void check_orientations(void);
+extern struct connection *route_owner(struct connection *c
+    , struct connection **erop);
+extern struct connection *shunt_owner(const ip_subnet *ours
+    , const ip_subnet *his);
+
 
 extern bool uniqueIDs;	/* --uniqueids? */
 extern void ISAKMP_SA_established(struct connection *c, so_serial_t serial);
 
-/* for Road Warrior (and Opportunism) */
-#define HasWildcardIP(c) (isanyaddr(&(c).that.host_addr))
-
-bool HasWildcardClient(const struct connection *c);
+#define his_id_was_instantiated(c) ((c)->kind == CK_INSTANCE \
+    && id_is_ipaddr(&(c)->that.id) \
+    && sameaddr(&(c)->that.id.ip_addr, &(c)->that.host_addr))
+
+/* for Opportunism */
+extern bool HasWildcardClient(const struct connection *c);
+extern const ip_subnet *EffectivePeerClient(const struct connection *c);
 
 struct state;	/* forward declaration of tag (defined in state.h) */
 extern struct connection
     *con_by_name(const char *nm, bool strict),
-    *find_opportunistic_connection(const ip_address *our_client
-	, const ip_address *peer_client),
     *find_host_connection(const ip_address *me, u_int16_t my_port
 	, const ip_address *him, u_int16_t his_port),
     *refine_host_connection(const struct state *st, const struct id *id
@@ -191,5 +226,27 @@
 	, const ip_address *our_client, const ip_address *peer_client),
     *build_outgoing_opportunistic_connection(struct gw_info *gw
 	, const ip_address *our_client, const ip_address *peer_client);
+
+
+/* operations on "pending", the structure representing Quick Mode
+ * negotiations delayed until a Keying Channel has been negotiated.
+ */
+
+struct pending;        /* forward declaration (opaque outside connections.c) */
+extern void add_pending(int whack_sock
+    , struct state *isakmp_sa
+    , struct connection *c
+    , lset_t policy
+    , unsigned long try);
+
+extern void release_pending_whacks(struct state *st, err_t story);
+extern void unpend(struct state *st);
+extern void update_pending(struct state *os, struct state *ns);
+extern void flush_pending_by_state(struct state *st);
+
+extern void connection_discard(struct connection *c);
+
+/* print connection status */
+
 
 extern void show_connections_status(void);
diff -bruN freeswan-1.9.orig/pluto/constants.c freeswan-1.9/pluto/constants.c
--- freeswan-1.9.orig/pluto/constants.c	Sun Jan 28 16:03:02 2001
+++ freeswan-1.9/pluto/constants.c	Wed Jun  6 16:38:34 2001
@@ -11,7 +11,7 @@
  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  * for more details.
  *
- * RCSID $Id: constants.c,v 1.40 2001/01/28 21:03:02 dhr Exp $
+ * RCSID $Id: constants.c,v 1.47 2001/05/29 18:39:56 dhr Exp $
  */
 
 /*
@@ -27,6 +27,7 @@
 #include <freeswan.h>
 
 #include "constants.h"
+#include "defs.h"
 #include "packet.h"
 
 struct enum_names {
@@ -52,6 +53,7 @@
 static const char *const timer_event_name[] = {
 	"EVENT_NULL",
 	"EVENT_REINIT_SECRET",
+	"EVENT_SHUNT_SCAN",
 	"EVENT_SO_DISCARD",
 	"EVENT_RETRANSMIT",
 	"EVENT_SA_REPLACE",
@@ -134,6 +136,33 @@
 	"got encrypted Informational Message",	/* STATE_INFO_PROTECTED */
     };
 
+/* kind of struct connection */
+
+static const char *const connection_kind_name[] = {
+    "CK_TEMPLATE",     /* abstract connection, with wildcard */
+    "CK_PERMANENT",    /* normal connection */
+    "CK_INSTANCE",     /* instance of template, created for a particular attempt */
+    "CK_GOING_AWAY"    /* instance being deleted -- don't delete again */
+};
+
+
+enum_names connection_kind_names =
+    { CK_TEMPLATE, CK_GOING_AWAY, connection_kind_name, NULL };
+
+/* routing status names */
+
+static const char *const routing_story_strings[] = {
+    "unrouted",        /* RT_UNROUTED: unrouted */
+    "unrouted HOLD",   /* RT_UNROUTED_HOLD: unrouted, but HOLD eroute installed */
+    "trap erouted",    /* RT_ROUTED_PROSPECTIVE: routed, and TRAP eroute installed */
+    "routed HOLD",     /* RT_ROUTED_HOLD: routed, and HOLD eroute installed */
+    "fail erouted",    /* RT_ROUTED_FAILURE: routed, and failure-context shunt eroute installed */
+    "erouted", /* RT_ROUTED_TUNNEL: routed, and erouted to an IPSEC SA group */
+    };
+
+enum_names routing_story =
+    { RT_UNROUTED, RT_ROUTED_TUNNEL, routing_story_strings, NULL};
+
 /* Payload types (draft-ietf-ipsec-isakmp-09.txt section 3.1) */
 
 const char *const payload_name[] = {
@@ -283,18 +312,45 @@
 enum_names ident_names =
     { ID_IPV4_ADDR, ID_KEY_ID, ident_name, NULL };
 
+#ifdef OPENSSL
+/* Certificate type values */
+static const char *const cert_name[] = {
+       "CERT_TYPE_NONE",
+       "CERT_TYPE_PKCS7",
+       "CERT_TYPE_PGP",
+       "CERT_TYPE_DNSKEY",
+       "CERT_TYPE_X509_SIG",
+       "CERT_TYPE_X509_KEX",
+       "CERT_TYPE_KERBEROS",
+       "CERT_TYPE_CRL",
+       "CERT_TYPE_ARL",
+       "CERT_TYPE_SPKI",
+       "CERT_TYPE_X509_ATTR",
+    };
+
+enum_names cert_names =
+    { CERT_TYPE_NONE, CERT_TYPE_X509_ATTR, cert_name, NULL };
+#endif
+
+
 /* Goal BITs for establishing an SA
  * Note: we drop the POLICY_ prefix so that logs are more concise.
  */
 
 const char *const sa_policy_bit_names[] = {
 	"PSK",
+#ifndef OPENSSL
 	"RSASIG",
+#else
+	"OPENSSL",
+#endif
 	"ENCRYPT",
 	"AUTHENTICATE",
 	"COMPRESS",
 	"TUNNEL",
 	"PFS",
+	"PASS",
+	"DROP",
 	NULL
     };
 
@@ -607,6 +663,10 @@
 
 enum_names af_names = { AF_INET, AF_INET, af_inet_name, &af_names6 };
 
+static ip_address ipv4_any, ipv6_any;
+static ip_subnet ipv4_wildcard, ipv6_wildcard;
+static ip_subnet ipv4_all, ipv6_all;
+
 struct af_info af_inet4_info = {
 	AF_INET,
 	"AF_INET",
@@ -614,6 +674,7 @@
 	sizeof(struct sockaddr_in),
 	32,
 	ID_IPV4_ADDR, ID_IPV4_ADDR_SUBNET, ID_IPV4_ADDR_RANGE,
+	&ipv4_any, &ipv4_wildcard, &ipv4_all,
     };
 
 struct af_info af_inet6_info = {
@@ -623,6 +684,7 @@
 	sizeof(struct sockaddr_in6),
 	128,
 	ID_IPV6_ADDR, ID_IPV6_ADDR_SUBNET, ID_IPV6_ADDR_RANGE,
+	&ipv6_any, &ipv6_wildcard, &ipv6_all,
     };
 
 const struct af_info *
@@ -732,6 +794,26 @@
 	p = buf;
     }
     return p;
+}
+
+void init_constants(void)
+{
+    err_t ugh;
+
+    ugh = anyaddr(AF_INET, &ipv4_any);
+    passert(ugh == NULL);
+    ugh = anyaddr(AF_INET, &ipv6_any);
+    passert(ugh == NULL);
+
+    ugh = rangetosubnet(&ipv4_any, &ipv4_any, &ipv4_wildcard);
+    passert(ugh == NULL);
+    ugh = rangetosubnet(&ipv6_any, &ipv6_any, &ipv6_wildcard);
+    passert(ugh == NULL);
+
+    ugh = initsubnet(&ipv4_any, 0, '0', &ipv4_all);
+    passert(ugh == NULL);
+    ugh = initsubnet(&ipv6_any, 0, '0', &ipv6_all);
+    passert(ugh == NULL);
 }
 
 /* construct a string to name the bits on in a set
diff -bruN freeswan-1.9.orig/pluto/constants.h freeswan-1.9/pluto/constants.h
--- freeswan-1.9.orig/pluto/constants.h	Sun Jan 28 16:03:03 2001
+++ freeswan-1.9/pluto/constants.h	Wed Jun  6 16:34:55 2001
@@ -12,9 +12,11 @@
  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  * for more details.
  *
- * RCSID $Id: constants.h,v 1.58 2001/01/28 21:03:03 dhr Exp $
+ * RCSID $Id: constants.h,v 1.68 2001/05/29 18:39:56 dhr Exp $
  */
 
+extern void init_constants(void);
+
 /*
  * NOTE:For debugging purposes, constants.c has tables to map numbers back to names.
  * Any changes here should be reflected there.
@@ -47,7 +49,8 @@
 typedef unsigned long lset_t;
 #define LEMPTY 0UL
 #define LELEM(opt) (1UL << (opt))
-#define LRANGE(lwb, upb) (LELEM(upb) + LELEM(upb) - LELEM(lwb))
+#define LRANGE(lwb, upb) LRANGES(LELEM(lwb), LELEM(upb))
+#define LRANGES(first, last) (last - first + last)
 #define LALLIN(set, probe)	(((set) & (probe)) == (probe))
 
 /* Control and lock pathnames */
@@ -158,12 +161,15 @@
 
 extern enum_names timer_event_names;
 
-#define EVENT_NULL				0 /* non-event */
-#define EVENT_REINIT_SECRET			1 /* Refresh cookie secret */
-#define EVENT_SO_DISCARD			2 /* discard unfinished state object */
-#define EVENT_RETRANSMIT			3 /* Retransmit packet */
-#define EVENT_SA_REPLACE			4 /* SA replacement event */
-#define EVENT_SA_EXPIRE				5 /* SA expiration event */
+enum event_type {
+    EVENT_NULL,        /* non-event */
+    EVENT_REINIT_SECRET,       /* Refresh cookie secret */
+    EVENT_SHUNT_SCAN,  /* scan shunt eroutes known to kernel */
+    EVENT_SO_DISCARD,  /* discard unfinished state object */
+    EVENT_RETRANSMIT,  /* Retransmit packet */
+    EVENT_SA_REPLACE,  /* SA replacement event */
+    EVENT_SA_EXPIRE    /* SA expiration event */
+};
 
 #define EVENT_REINIT_SECRET_DELAY		3600 /* 1 hour */
 #define EVENT_RETRANSMIT_DELAY_0		10   /* 10 seconds */
@@ -265,25 +271,37 @@
 extern enum_names state_names;
 extern const char *const state_story[];
 
-#define STATE_MAIN_R0       1
-#define STATE_MAIN_I1       2
-#define STATE_MAIN_R1       3
-#define STATE_MAIN_I2       4
-#define STATE_MAIN_R2       5
-#define STATE_MAIN_I3       6
-#define STATE_MAIN_R3       7
-#define STATE_MAIN_I4       8
-
-#define STATE_QUICK_R0      9
-#define STATE_QUICK_I1      10
-#define STATE_QUICK_R1      11
-#define STATE_QUICK_I2      12
-#define STATE_QUICK_R2      13
+enum state_kind {
+    STATE_UNDEFINED,   /* 0 -- most likely accident */
+
+    /*  Opportunism states: see "Opportunistic Encryption" 2.2 */
+
+    OPPO_ACQUIRE,      /* got an ACQUIRE message for this pair */
+    OPPO_GW_DISCOVERED,        /* got TXT specifying gateway */
 
-#define STATE_INFO           14
-#define STATE_INFO_PROTECTED 15
+    /* IKE states */
+
+    STATE_MAIN_R0,
+    STATE_MAIN_I1,
+    STATE_MAIN_R1,
+    STATE_MAIN_I2,
+    STATE_MAIN_R2,
+    STATE_MAIN_I3,
+    STATE_MAIN_R3,
+    STATE_MAIN_I4,
+
+    STATE_QUICK_R0,
+    STATE_QUICK_I1,
+    STATE_QUICK_R1,
+    STATE_QUICK_I2,
+    STATE_QUICK_R2,
 
-#define STATE_ROOF          16
+    STATE_INFO,
+    STATE_INFO_PROTECTED
+};
+
+#define STATE_IKE_FLOOR        STATE_MAIN_R0
+#define STATE_IKE_ROOF (STATE_INFO_PROTECTED + 1)
 
 #define IS_PHASE1(s) (STATE_MAIN_R0 <= (s) && (s) <= STATE_MAIN_I4)
 #define IS_QUICK(s) (STATE_QUICK_R0 <= (s) && (s) <= STATE_QUICK_R2)
@@ -291,6 +309,37 @@
 #define IS_IPSEC_SA_ESTABLISHED(s) ((s) == STATE_QUICK_I2 || (s) == STATE_QUICK_R2)
 #define IS_ONLY_INBOUND_IPSEC_SA_ESTABLISHED(s) ((s) == STATE_QUICK_R1)
 
+/* kind of struct connection */
+
+extern enum_names connection_kind_names;
+
+enum connection_kind {
+    CK_TEMPLATE,       /* abstract connection, with wildcard */
+    CK_PERMANENT,      /* normal connection */
+    CK_INSTANCE,       /* instance of template, created for a particular attempt */
+    CK_GOING_AWAY      /* instance being deleted -- don't delete again */
+};
+
+
+/* routing status.
+ * Note: routing ignores source address, but erouting does not!
+ */
+
+extern enum_names routing_story;
+
+enum routing_t {
+    RT_UNROUTED,       /* unrouted */
+    RT_UNROUTED_HOLD,  /* unrouted, but HOLD shunt installed */
+    RT_ROUTED_PROSPECTIVE,     /* routed, and TRAP shunt installed */
+    RT_ROUTED_HOLD,    /* routed, and HOLD shunt installed */
+    RT_ROUTED_FAILURE, /* routed, and failure-context shunt installed */
+    RT_ROUTED_TUNNEL   /* routed, and erouted to an IPSEC SA group */
+};
+
+#define routed(rs) ((rs) > RT_UNROUTED_HOLD)
+#define erouted(rs) ((rs) != RT_UNROUTED)
+#define shunt_erouted(rs) (erouted(rs) && (rs) != RT_ROUTED_TUNNEL)
+
 /* Payload types
  * RFC2408 Internet Security Association and Key Management Protocol (ISAKMP)
  * section 3.1
@@ -460,27 +509,77 @@
 #define ID_DER_ASN1_GN              10
 #define ID_KEY_ID                   11
 
+#ifdef OPENSSL
+#define CERT_OPTION_SEND           0x01
+#define CERT_OPTION_PKCS7          0x02
+#define CERT_OPTION_PK             0x04
+#define CERT_OPTION_REV            0x08
+#define CERT_OPTION_STRICT         0x10
+#define CERT_OPTION_DSS_SHA        0x20
+#define CERT_OPTION_DSS_ALT        0x40
+
+extern enum_names cert_names;
+
+#define CERT_TYPE_NONE              0
+#define CERT_TYPE_PKCS7             1
+#define CERT_TYPE_PGP               2
+#define CERT_TYPE_DNSKEY            3
+#define CERT_TYPE_X509_SIG          4
+#define CERT_TYPE_X509_KEX          5
+#define CERT_TYPE_KERBEROS          6
+#define CERT_TYPE_CRL               7
+#define CERT_TYPE_ARL               8
+#define CERT_TYPE_SPKI              9
+#define CERT_TYPE_X509_ATTR        10
+#endif
+
 /* Policies for establishing an SA
  *
- * These are used to specify attributes (eg. encryption) and techniques for
- * (eg PFS) required of an SA.  POLICY_PSK and POLICY_RSASIG are for
- * ISAKMP SAs; the rest are about IPsec SAs
+ * These are used to specify attributes (eg. encryption) and techniques
+ * (eg PFS) for an SA.
  */
 
 extern const char *const sa_policy_bit_names[];
 
+/* ISAKMP auth techniques */
 #define POLICY_PSK           LELEM(0)
+#ifndef OPENSSL
 #define POLICY_RSASIG        LELEM(1)
+#else
+#define POLICY_OPENSSL        LELEM(1)
+#endif
 
-#define POLICY_ENCRYPT       LELEM(2)
-#define POLICY_AUTHENTICATE  LELEM(3)
+#define POLICY_ISAKMP_SHIFT    0       /* log2(POLICY_PSK) */
+#ifndef OPENSSL
+#define POLICY_ID_AUTH_MASK    LRANGES(POLICY_PSK, POLICY_RSASIG)
+#else
+#define POLICY_ID_AUTH_MASK    LRANGES(POLICY_PSK, POLICY_OPENSSL)
+#endif
+#define POLICY_ISAKMP_MASK     POLICY_ID_AUTH_MASK     /* all so far */
+
+/* Quick Mode (IPSEC) attributes */
+#define POLICY_ENCRYPT       LELEM(2)  /* must be first of IPSEC policies */
+#define POLICY_AUTHENTICATE  LELEM(3)  /* must be second */
 #define POLICY_COMPRESS      LELEM(4)
 #define POLICY_TUNNEL        LELEM(5)
 #define POLICY_PFS           LELEM(6)
 
-#define POLICY_ISAKMP_SHIFT	0	/* log2(POLICY_PSK) */
-#define POLICY_ISAKMP_MASK	(POLICY_PSK | POLICY_RSASIG)
 #define POLICY_IPSEC_SHIFT	2	/* log2(POLICY_ENCRYPT) */
+#define POLICY_IPSEC_MASK      LRANGES(POLICY_ENCRYPT, POLICY_PFS)
+
+/* opportunistic attributes: what to do with a packet without a tunnel */
+#define POLICY_PASS     LELEM(7)
+#define POLICY_DROP     LELEM(8)
+/* PASS | DROP is construed as REJECT */
+
+#define POLICY_OPPO_SHIFT      7       /* log2(POLICY_PASS) */
+#define POLICY_OPPO_MASK       (POLICY_PASS | POLICY_DROP)
+
+
+/* Any IPsec policy?  If not, a connection description
+ * is only for ISAKMP SA, not IPSEC SA.  (A pun, I admit.)
+ */
+#define HAS_IPSEC_POLICY(p) (((p) & POLICY_IPSEC_MASK) != 0)
 
 /* Oakley transform attributes
  * draft-ietf-ipsec-ike-01.txt appendix A
@@ -532,6 +631,15 @@
 /* SA Lifetime Type attribute
  * RFC2407 The Internet IP security Domain of Interpretation for ISAKMP 4.5
  * Default time specified in 4.5
+ *
+ * There are two defaults for IPSEC SA lifetime, SA_LIFE_DURATION_DEFAULT,
+ * and PLUTO_SA_LIFE_DURATION_DEFAULT.
+ * SA_LIFE_DURATION_DEFAULT is specified in RFC2407 "The Internet IP
+ * Security Domain of Interpretation for ISAKMP" 4.5.  It applies when
+ * an ISAKMP negotiation does not explicitly specify a life duration.
+ * PLUTO_SA_LIFE_DURATION_DEFAULT is specified in pluto(8).  It applies
+ * when a connection description does not specify --ipseclifetime.
+ * The value of SA_LIFE_DURATION_MAXIMUM is our local policy.
  */
 
 extern enum_names sa_lifetime_names;
@@ -539,8 +647,9 @@
 #define SA_LIFE_TYPE_SECONDS   1
 #define SA_LIFE_TYPE_KBYTES    2
 
-#define SA_LIFE_DURATION_DEFAULT    28800 /* Eight hours */
-#define SA_LIFE_DURATION_MAXIMUM    86400 /* One day */
+#define SA_LIFE_DURATION_DEFAULT    28800 /* eight hours (RFC2407 4.5) */
+#define PLUTO_SA_LIFE_DURATION_DEFAULT    28800 /* eight hours (pluto(8)) */
+#define SA_LIFE_DURATION_MAXIMUM    86400 /* one day */
 
 #define SA_REPLACEMENT_MARGIN_DEFAULT	    540	  /* (IPSEC & IKE) nine minutes */
 #define SA_REPLACEMENT_FUZZ_DEFAULT	    100	  /* (IPSEC & IKE) 100% of MARGIN */
@@ -548,6 +657,12 @@
 
 #define SA_LIFE_DURATION_K_DEFAULT  0xFFFFFFFFlu
 
+/* DES support */
+#define ALL_BLOCK_CYPHER 1
+#define DES_BLOCK_CYPHER 2
+#define DES3_BLOCK_CYPHER 3
+#define FORCE_ENCRYPT_CYPHER_DEFAULT ALL_BLOCK_CYPHER
+
 /* Encapsulation Mode attribute */
 
 extern enum_names enc_mode_names;
@@ -568,14 +683,18 @@
 
 /* Oakley Lifetime Type attribute
  * draft-ietf-ipsec-ike-01.txt appendix A
+ * As far as I can see, there is not specification for
+ * OAKLEY_ISAKMP_SA_LIFETIME_DEFAULT.  This could lead to interop problems!
+ * For no particular reason, we chose one hour.
+ * The value of OAKLEY_ISAKMP_SA_LIFETIME_MAXIMUM is our local policy.
  */
 extern enum_names oakley_lifetime_names;
 
 #define OAKLEY_LIFE_SECONDS   1
 #define OAKLEY_LIFE_KILOBYTES 2
 
-#define OAKLEY_ISAKMP_SA_LIFETIME_DEFAULT 3600    /* One hour */
-#define OAKLEY_ISAKMP_SA_LIFETIME_MAXIMUM 28800   /* 8 hours */
+#define OAKLEY_ISAKMP_SA_LIFETIME_DEFAULT 3600    /* one hour */
+#define OAKLEY_ISAKMP_SA_LIFETIME_MAXIMUM 28800   /* eight hours */
 
 /* Oakley PRF attribute (none defined)
  * draft-ietf-ipsec-ike-01.txt appendix A
@@ -744,6 +863,9 @@
     size_t sa_sz;
     int mask_cnt;
     u_int8_t id_addr, id_subnet, id_range;
+    const ip_address *any;
+    const ip_subnet *wildcard; /* 0.0.0.0/32 or IPv6 equivalent */
+    const ip_subnet *all;      /* 0.0.0.0/0 or IPv6 equivalent */
 };
 
 extern const struct af_info
diff -bruN freeswan-1.9.orig/pluto/cookie.c freeswan-1.9/pluto/cookie.c
--- freeswan-1.9.orig/pluto/cookie.c	Wed Oct 25 20:58:05 2000
+++ freeswan-1.9/pluto/cookie.c	Wed May 16 10:57:20 2001
@@ -12,7 +12,7 @@
  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  * for more details.
  *
- * RCSID $Id: cookie.c,v 1.13 2000/10/26 00:58:05 dhr Exp $
+ * RCSID $Id: cookie.c,v 1.14 2001/03/13 09:22:03 dhr Exp $
  */
 
 #include <stdio.h>
@@ -20,6 +20,8 @@
 #include <sys/types.h>
 #include <sys/socket.h>
 #include <netinet/in.h>
+
+#include <freeswan.h>
 
 #include "constants.h"
 #include "defs.h"
diff -bruN freeswan-1.9.orig/pluto/crypto.h freeswan-1.9/pluto/crypto.h
--- freeswan-1.9.orig/pluto/crypto.h	Sun Dec 12 19:40:50 1999
+++ freeswan-1.9/pluto/crypto.h	Wed May 16 10:57:20 2001
@@ -56,7 +56,11 @@
 /* unification of cryptographic hashing mechanisms */
 
 union hash_ctx {
+#ifndef OPENSSL
 	MD5_CTX ctx_md5;
+#else
+	PLUTO_MD5_CTX ctx_md5;
+#endif
 	SHA1_CTX ctx_sha1;
     };
 
diff -bruN freeswan-1.9.orig/pluto/defs.c freeswan-1.9/pluto/defs.c
--- freeswan-1.9.orig/pluto/defs.c	Wed Oct 25 18:05:02 2000
+++ freeswan-1.9/pluto/defs.c	Wed May 16 10:57:20 2001
@@ -11,7 +11,7 @@
  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  * for more details.
  *
- * RCSID $Id: defs.c,v 1.17 2000/10/25 22:05:02 dhr Exp $
+ * RCSID $Id: defs.c,v 1.18 2001/03/13 09:22:03 dhr Exp $
  */
 
 #include <stdlib.h>
@@ -19,9 +19,13 @@
 #include <stdio.h>
 #include <sys/types.h>
 
+#include <freeswan.h>
+
 #include "constants.h"
 #include "defs.h"
 #include "log.h"
+#include "id.h"
+#include "connections.h" /* needs id.h */
 #include "whack.h"	/* for RC_LOG_SERIOUS */
 
 const chunk_t empty_chunk = { NULL, 0 };
diff -bruN freeswan-1.9.orig/pluto/defs.h freeswan-1.9/pluto/defs.h
--- freeswan-1.9.orig/pluto/defs.h	Wed Oct 25 18:05:02 2000
+++ freeswan-1.9/pluto/defs.h	Thu Jun  7 12:09:54 2001
@@ -12,7 +12,7 @@
  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  * for more details.
  *
- * RCSID $Id: defs.h,v 1.24 2000/10/25 22:05:02 dhr Exp $
+ * RCSID $Id: defs.h,v 1.26 2001/05/08 05:37:21 dhr Exp $
  */
 
 /* GCC magic! */
@@ -38,7 +38,7 @@
  */
 typedef unsigned long so_serial_t;
 #define SOS_NOBODY  0	/* null serial number */
-
+#define SOS_FIRST	1	/* first normal serial number */
 
 /* memory allocation */
 
@@ -59,6 +59,19 @@
 #define pfreeany(p) { if ((p) != NULL) pfree(p); }
 #define replace(p, q) { pfreeany(p); (p) = (q); }
 
+#ifdef OPENSSL
+#include <des.h>
+
+typedef union _keysched_u {
+  struct _des3_ks { des_key_schedule ks[3]; } des3_ks;
+  des_key_schedule des_ks;
+
+#ifdef NOTYET
+  /* Other ciphers, eg CAST, RC5, etc... */
+#endif
+
+} keysched;
+#endif
 
 /* chunk is a simple pointer-and-size abstraction */
 
@@ -83,6 +96,9 @@
 extern void exit_pluto(int /*status*/) NEVER_RETURNS;
 
 
+/* zero all bytes */
+#define zero(x) memset((x), '\0', sizeof(*(x)))
+
 /* are all bytes 0? */
 extern bool all_zero(const unsigned char *m, size_t len);
 
@@ -105,3 +121,31 @@
 
 /* pad_up(n, m) is the amount to add to n to make it a multiple of m */
 #define pad_up(n, m) (((m) - 1) - (((n) + (m) - 1) % (m)))
+
+/* writemem_short adds support to write to unaligned memory (arm). */
+#ifdef __arm__
+#define writemem_u_int16_t(addr, offset, n) do {\
+  u_int16_t temp16 = htons((n)); \
+  (addr)[(offset)] = temp16 & 0xff; \
+  (addr)[(offset)+1] = temp16 >> 8; \
+} while (0)
+#else
+#define writemem_u_int16_t(addr, offset, n) do {\
+  *((u_int16_t *)(&((addr)[(offset)]))) = htons((n)); \
+} while (0)
+#endif
+
+/* readmem_short adds support to read from unaligned memory (arm). */
+#ifdef __arm__
+#define readmem_u_int16_t(addr, offset, var) do {\
+  u_int16_t temp16 = 0; \
+  temp16 += *((u_int8_t *)(&((addr)[(offset)]))) << 8; \
+  temp16 += *((u_int8_t *)(&((addr)[(offset)+1]))); \
+  (var) = temp16; \
+} while (0)
+#else
+#define readmem_u_int16_t(addr, offset, var) do {\
+  u_int16_t temp16 = ntohs(*((u_int16_t *)(&((addr)[(offset)])))); \
+  (var) = temp16; \
+} while (0)
+#endif
diff -bruN freeswan-1.9.orig/pluto/demux.c freeswan-1.9/pluto/demux.c
--- freeswan-1.9.orig/pluto/demux.c	Wed Jan 24 18:09:33 2001
+++ freeswan-1.9/pluto/demux.c	Tue Jun 12 10:58:26 2001
@@ -12,7 +12,7 @@
  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  * for more details.
  *
- * RCSID $Id: demux.c,v 1.95 2001/01/24 23:09:33 dhr Exp $
+ * RCSID $Id: demux.c,v 1.104 2001/05/28 19:18:18 dhr Exp $
  */
 
 /* Ordering Constraints on Payloads
@@ -139,6 +139,10 @@
 #include "whack.h"	/* requires connections.h */
 #include "server.h"
 
+#ifdef OPENSSL
+#include "openssl.h"
+#endif
+
 /* This file does basic header checking and demux of
  * incoming packets.
  */
@@ -153,12 +157,12 @@
  */
 
 struct state_microcode {
-    int state;
+    enum state_kind state;
     lset_t flags;
     lset_t req_payloads;	/* required payloads (allows just one) */
     lset_t opt_payloads;	/* optional payloads (any mumber) */
     u_int8_t first_out_payload;	/* if not ISAKMP_NEXT_NONE, payload to start with */
-    u_int8_t timeout_event;
+    enum event_type timeout_event;
     state_transition_fn *processor;
 };
 
@@ -190,13 +194,14 @@
 
 /* state_microcode_table is a table of all state_microcode tuples.
  * It must be in order of state (the first element).
- * After initialization, state_microcode_index[s] points to the
+ * After initialization, ike_microcode_index[s] points to the
  * first entry in state_microcode_table for state s.
  * Remember that each state name in Main or Quick Mode describes
  * what has happened in the past, not what this message is.
  */
 
-static const struct state_microcode *state_microcode_index[STATE_ROOF];
+static const struct state_microcode
+    *ike_microcode_index[STATE_IKE_ROOF - STATE_IKE_FLOOR];
 
 static const struct state_microcode state_microcode_table[] = {
 #define PT(n) ISAKMP_NEXT_##n
@@ -241,11 +246,19 @@
 
     { STATE_MAIN_R1, SMF_PKE_AUTH
     , P(KE) | P(ID) | P(NONCE), P(VID) | P(HASH), PT(KE)
+#ifndef OPENSSL
     , EVENT_RETRANSMIT, unexpected /* ??? not yet implemented */ },
+#else
+    , EVENT_RETRANSMIT, main_inI2_outR2_pk },
+#endif
 
     { STATE_MAIN_R1, SMF_RPKE_AUTH
     , P(NONCE) | P(KE) | P(ID), P(VID) | P(HASH) | P(CERT), PT(NONCE)
+#ifndef OPENSSL
     , EVENT_RETRANSMIT, unexpected /* ??? not yet implemented */ },
+#else
+    , EVENT_RETRANSMIT, main_inI2_outR2_rpk },
+#endif
 
     /* for states from here on, output message must be encrypted */
 
@@ -263,11 +276,20 @@
 
     { STATE_MAIN_I2, SMF_PKE_AUTH | SMF_INITIATOR | SMF_OUTPUT_ENCRYPTED
     , P(KE) | P(ID) | P(NONCE), P(VID), PT(HASH)
+#ifndef OPENSSL
     , EVENT_RETRANSMIT, unexpected /* ??? not yet implemented */ },
+#else
+    , EVENT_RETRANSMIT, main_inR2_outI3_pk /* ??? not yet implemented */ },
+#endif
 
-    { STATE_MAIN_I2, SMF_ALL_AUTH | SMF_INITIATOR | SMF_OUTPUT_ENCRYPTED
-    ,  P(NONCE) | P(KE) | P(ID), P(VID), PT(HASH)
+    { STATE_MAIN_I2, SMF_RPKE_AUTH | SMF_INITIATOR | SMF_OUTPUT_ENCRYPTED
+/*   ,  P(NONCE) | P(KE) | P(ID), P(VID), PT(HASH) */
+    ,  P(NONCE) | P(KE) | P(ID), P(VID) | P(CERT), PT(HASH)
+#ifndef OPENSSL
     , EVENT_RETRANSMIT, unexpected /* ??? not yet implemented */ },
+#else
+    , EVENT_RETRANSMIT, main_inR2_outI3_rpk /* ??? not yet implemented */ },
+#endif
 
     /* for states from here on, input message must be encrypted */
 
@@ -282,11 +304,19 @@
 
     { STATE_MAIN_R2, SMF_DS_AUTH | SMF_FIRST_ENCRYPTED_INPUT | SMF_ENCRYPTED
     , P(ID) | P(SIG), P(VID) | P(CERT), PT(ID)
+#ifndef OPENSSL
     , EVENT_SA_REPLACE, main_inI3_outR3 },
+#else
+    , EVENT_SA_REPLACE, main_inI3_outR3_whichds},
+#endif
 
     { STATE_MAIN_R2, SMF_PKE_AUTH | SMF_RPKE_AUTH | SMF_FIRST_ENCRYPTED_INPUT | SMF_ENCRYPTED
     , P(HASH), P(VID), PT(HASH)
+#ifndef OPENSSL
     , EVENT_SA_REPLACE, unexpected /* ??? not yet implemented */ },
+#else
+    , EVENT_SA_REPLACE, main_inI3_outR3_pk},
+#endif
 
     /* STATE_MAIN_I3: R3 --> done
      * SMF_PSK_AUTH: HDR*, IDr1, HASH_R --> done
@@ -300,11 +330,20 @@
 
     { STATE_MAIN_I3, SMF_DS_AUTH | SMF_INITIATOR | SMF_FIRST_ENCRYPTED_INPUT | SMF_ENCRYPTED
     , P(ID) | P(SIG), P(VID) | P(CERT), PT(NONE)
+#ifndef OPENSSL
     , EVENT_SA_REPLACE, main_inR3 },
+#else
+    , EVENT_SA_REPLACE, main_inR3_whichds },
+#endif
 
     { STATE_MAIN_I3, SMF_PKE_AUTH | SMF_RPKE_AUTH | SMF_INITIATOR | SMF_FIRST_ENCRYPTED_INPUT | SMF_ENCRYPTED
     , P(HASH), P(VID), PT(NONE)
+#ifndef OPENSSL
     , EVENT_SA_REPLACE, unexpected /* ??? not yet implemented */ },
+#else
+    , EVENT_SA_REPLACE, main_inR3_pk },
+#endif
+
 
     /* STATE_MAIN_R3: can only get here due to packet loss */
     { STATE_MAIN_R3, SMF_ALL_AUTH | SMF_ENCRYPTED | SMF_RETRANSMIT_ON_DUPLICATE, LEMPTY, LEMPTY
@@ -378,8 +417,8 @@
 void
 init_demux(void)
 {
-    /* fill state_microcode_index:
-     * make state_microcode_index[s] point to first entry in
+    /* fill ike_microcode_index:
+     * make ike_microcode_index[s] point to first entry in
      * state_microcode_table for state s (backward scan makes this easier).
      * Check that table is in order -- catch coding errors.
      * For what it's worth, this routine is idempotent.
@@ -388,8 +427,8 @@
 
     for (t = &state_microcode_table[elemsof(state_microcode_table) - 1];;)
     {
-	passert(0 < t->state && t->state < STATE_ROOF);
-	state_microcode_index[t->state] = t;
+        passert(STATE_IKE_FLOOR <= t->state && t->state < STATE_IKE_ROOF);
+        ike_microcode_index[t->state - STATE_IKE_FLOOR] = t;
 	if (t == state_microcode_table)
 	    break;
 	t--;
@@ -467,7 +506,7 @@
 
     /* initialize md */
     md.iface = ifp;
-    md.from_state = 0;		/* not yet valid */
+    md.from_state = STATE_UNDEFINED;           /* not yet valid */
     md.st = NULL;
     md.note = NOTHING_WRONG;
     md.raw_packet.ptr = NULL;
@@ -499,9 +538,9 @@
 	} from;
 	int from_len = sizeof(from);
 	err_t from_ugh = NULL;
-	static const char undisclosed[] = "undisclosed source";
+        static const char undisclosed[] = "unknown source";
 
-	memset(&from.sa, 0x00, sizeof(from.sa));
+	zero(&from.sa);
 	packet_len = recvfrom(ifp->fd, bigbuffer, sizeof(bigbuffer), 0
 	    , &from.sa, &from_len);
 
@@ -564,7 +603,7 @@
 	    }
 	    else if (from_ugh != NULL)
 	    {
-		log_errno((e, "recvfrom() on %s failed in comm_handle; source sockaddr misformed: %s"
+		log_errno((e, "recvfrom() on %s failed in comm_handle (Pluto cannot decode source sockaddr in rejection: %s)"
 		    , ifp->rname, from_ugh));
 	    }
 	    else
@@ -600,7 +639,7 @@
 		struct cmsghdr *cm;
 		char fromstr[INET6_ADDRSTRLEN + sizeof(" port 65536")];
 
-		memset(&from.sa, 0x00, sizeof(from.sa));
+		zero(&from.sa);
 		from_len = sizeof(from);
 
 		emh.msg_name = &from.sa;	/* ??? filled in? */
@@ -1053,8 +1092,7 @@
      * Look up the appropriate microcode based on state and
      * possibly Oakley Auth type.
      */
-    passert(STATE_MAIN_R0 <= md.from_state && md.from_state <= STATE_INFO_PROTECTED);
-    smc = state_microcode_index[md.from_state];
+    smc = ike_microcode_index[md.from_state - STATE_IKE_FLOOR];
 
     if (md.st != NULL)
     {
@@ -1197,9 +1235,9 @@
 
     /* Digest the message.
      * Padding must be removed to make hashing work.
-     * Padding comes from encryption (so this code must be after decryption)
-     * and from the requirement that messages must be "aligned" (padded
-     * to a multiple of 4 octets).
+     * Padding comes from encryption (so this code must be after decryption).
+     * Padding rules are described before the definition of
+     * struct isakmp_hdr in packet.h.
      */
     {
 	struct payload_digest *pd = md.digest;
@@ -1241,6 +1279,9 @@
 	    {
 		lset_t s = LELEM(np);
 
+                loglog(RC_LOG_SERIOUS, "parsing: (%s)",
+                   enum_show(&payload_names, np));
+
 		if (0 == (s & (needed | smc->opt_payloads
 		| LELEM(ISAKMP_NEXT_N) | LELEM(ISAKMP_NEXT_D))))
 		{
@@ -1253,6 +1294,267 @@
 		needed &= ~s;
 	    }
 
+#ifdef OPENSSL
+            {
+              /* This code really shouldn't be here - it should be in */
+              /* the ipsec_doi code section with all the other protocol */
+              /* spec. Unfortunately, the "syntax checking" of the payload */
+              /* is done here, and the "semantic checking" of the payload */
+              /* is over in ipsec_doi. Since the fields of the ID payload */
+              /* are encrypted, and the ipsec_doi code checks those fields */
+              /* before processing the ID payload, we must ensure that the */
+              /* payload is decrypted and stored in the identification */
+              /* structure *before* the main mode routines process it. So */
+              /* the code is here. */
+ 
+              if ((IS_PHASE1(md.from_state)) && (md.st)) {
+                if ((md.st->st_oakley.auth == OAKLEY_RSA_ENC) || 
+                    (md.st->st_oakley.auth == OAKLEY_ELGAMAL_ENC)) {
+                  if ((sd == &isakmp_identification_desc) ||
+                      (sd == &isakmp_nonce_desc)) {
+                    /* We need to decrypt this packet */
+                    char cpl[65], ppl[65];
+                    u_int16_t paylen;
+                    chunk_t ch;
+ 
+                    /* see macro in defs.h */
+                    readmem_u_int16_t(md.message_pbs.cur, 2, paylen);
+
+                    clonetochunk(ch, &(md.message_pbs.cur[4]), paylen-4, 
+                      "Ciphertext payload");
+ 
+                    /* Make a copy chunk of the payload after the generic */
+                    /* header, which should be the ciphertext of */
+                    /* the ID payload */
+                    if (sd == &isakmp_identification_desc) {
+                      snprintf(cpl, sizeof(cpl)-1, "ID payload (ciphertext): ");
+                      snprintf(ppl, sizeof(ppl)-1, "ID payload (plaintext): ");
+                    } else if (sd == &isakmp_nonce_desc) {
+                      snprintf(cpl, sizeof(cpl)-1,
+                               "Nonce payload (ciphertext): ");
+                      snprintf(ppl, sizeof(ppl)-1,
+                               "Nonce payload (plaintext): ");
+                    } else {
+                      snprintf(cpl, sizeof(cpl)-1,
+                               "Unknown payload (ciphertext): ");
+                      snprintf(ppl, sizeof(ppl)-1,
+                               "Unknown payload (plaintext): ");
+                    }
+ 
+                    if (!valid_ciphertext_length(paylen - 4, md.st->st_connection)) {
+                      log("Ciphertext length not a multiple of key modulus length for %s", cpl );
+                      free_md(&md);
+                      return;
+                    }
+
+                    DBG(DBG_RAW,
+                    DBG_dump_chunk(cpl, ch);
+                    );
+
+                    if (! privkey_decrypt_chunk( &ch, md.st )) {
+                      log("Ciphertext for %s could not be decrypted.", cpl );
+                      free_md(&md);
+                      return;
+                    }
+
+                    if ((ch.len == 0) || (ch.len > paylen)) {
+                      /* Error - the decryption has failed */
+                      log("Decryption failure - malformed payload in packet");
+                      free_md(&md);
+                      return;
+                    }
+
+                    DBG(DBG_RAW,
+                    DBG_dump_chunk(ppl, ch);
+                    );
+
+/*  ** a nice data dumper **
+ * {
+ * 	int *ptr = (int *) md.message_pbs.cur;
+ * 	int length = md.message_pbs.roof -  md.message_pbs.cur;
+ * 	int i;
+ * 	DBG_log("before memcopy: ---------------------- length %d", length);
+ * 	for (i=0; i<length/4; i+=4) {
+ * 		DBG_log("%4d: %08x %08x %08x %08x ", i*4, ntohl(ptr[0]), 
+ * 			ntohl(ptr[1]), ntohl(ptr[2]), ntohl(ptr[3]));
+ * 		ptr += 4;
+ * 	}
+ * }
+ */
+
+                    /* Now restructure the message_pbs block, so that the */ 
+                    /* plaintext is now stored in the ID/nonce payload space */
+                    /* Adjust the length first */
+                    /* see macro in defs.h */
+                    writemem_u_int16_t(md.message_pbs.cur, 2, (ch.len + 4));
+
+                    /* Now copy the plaintext */
+                    memcpy(&(md.message_pbs.cur[4]), ch.ptr, ch.len);
+                    /* Clear the source plaintext */
+                    memset(ch.ptr, 0, ch.len);
+
+                    /* Shift down all subsequent payloads */
+                    memmove(&(md.message_pbs.cur[ch.len+4]),
+                            &(md.message_pbs.cur[paylen]),
+                            md.message_pbs.roof - &(md.message_pbs.cur[paylen]));
+
+                    /* Adjust the size of root downwards */
+                    md.message_pbs.roof -= paylen - ch.len - 4;
+                    freeanychunk(ch);
+
+                  }
+                } else if ((md.st->st_oakley.auth == OAKLEY_RSA_ENC_REV) ||
+			   (md.st->st_oakley.auth == OAKLEY_ELGAMAL_ENC_REV)) {
+                  if ((sd == &isakmp_identification_desc) ||
+                      (sd == &isakmp_nonce_desc) ||
+                      (sd == &isakmp_keyex_desc) ||
+                      (sd == &isakmp_ipsec_certificate_desc)) {
+                    if (sd == &isakmp_nonce_desc) {
+                      /* Nonce is public key encrypted */
+                      u_int16_t paylen;
+                      chunk_t ch;
+ 
+                      /* see macro in defs.h */
+                      readmem_u_int16_t(md.message_pbs.cur, 2, paylen);
+
+                      clonetochunk(ch, &(md.message_pbs.cur[4]), paylen-4, 
+                        "Ciphertext payload");
+
+                      if (!valid_ciphertext_length(paylen - 4, 
+                        md.st->st_connection)) {
+                        log("Ciphertext length not a multiple of key modulus length for nonce" );
+                        free_md(&md);
+                        return;
+                      }
+
+                      DBG(DBG_PARSING | DBG_CRYPT, 
+                      DBG_dump_chunk("Nonce payload (ciphertext)", ch);
+                      );
+
+                      if (! privkey_decrypt_chunk( &ch, md.st )) {
+                        log("Ciphertext for %s could not be decrypted.",
+                          "Nonce payload (ciphertext)");
+                        free_md(&md);
+                        return;
+                      }
+
+                      if ((ch.len == 0) || (ch.len > paylen)) {
+                        /* Error - the decryption has failed */
+                        log("Decryption failure - malformed payload in packet");
+                        free_md(&md);
+                        return;
+                      }
+                      DBG(DBG_PARSING | DBG_CRYPT, 
+                      DBG_dump_chunk("Nonce payload (plaintext)", ch);
+                      );
+
+		      if ((md.st->st_state == STATE_MAIN_I1) ||
+			  (md.st->st_state == STATE_MAIN_I2) ||
+			  (md.st->st_state == STATE_MAIN_I3) ||
+			  (md.st->st_state == STATE_MAIN_I4)) {
+			if (derive_symmetric_key(md.st, ch,
+						 md.st->st_rcookie,
+						 COOKIE_SIZE,
+						 &md.st->st_ks_r,
+						 &md.st->st_ne_r) < 0) {
+			  log("Unable to derive symmetric key");
+			  free(&md);
+			  return;
+			}
+			memset(&md.st->st_ne_r_iv, 0, MAX_DIGEST_LEN);
+			DBG(DBG_PARSING,
+			DBG_dump_chunk("Received Ke_r:", md.st->st_ne_r);
+			);
+		      } else {
+			if (derive_symmetric_key(md.st, ch,
+						 md.st->st_icookie,
+						 COOKIE_SIZE,
+						 &md.st->st_ks_i,
+						 &md.st->st_ne_i) < 0) {
+			  log("Unable to derive symmetric key");
+			  free(&md);
+			  return;
+			}
+			memset(&md.st->st_ne_i_iv, 0, MAX_DIGEST_LEN);
+			DBG(DBG_PARSING,
+			DBG_dump_chunk("Received Ke_i:", md.st->st_ne_i);
+			);
+		      }
+
+                      /* Now restructure the message_pbs block, so that the */
+                      /* plaintext is now stored in the payload space */
+                      /* Adjust the length first */
+                      /* see macro in defs.h */ 
+                      writemem_u_int16_t(md.message_pbs.cur, 2, (ch.len + 4));
+
+                      /* Now copy the plaintext */
+                      memcpy(&(md.message_pbs.cur[4]), ch.ptr, ch.len);
+                      /* Clear the source plaintext */
+                      memset(ch.ptr, 0, ch.len);
+                      /* Shift down all subsequent payloads */
+                      memmove(&(md.message_pbs.cur[ch.len+4]),
+                              &(md.message_pbs.cur[paylen]),
+                              md.message_pbs.roof - &(md.message_pbs.cur[paylen]));
+		      /* Adjust the size of roof downwards */
+                      md.message_pbs.roof -= paylen - ch.len - 4;
+
+		      /* Discard the plaintext chunk */
+		      memset(ch.ptr, 0, ch.len);
+		      freeanychunk(ch);
+		    } else {
+                      u_int16_t paylen;
+                      chunk_t ch, pch;
+ 
+                      /* see macro in defs.h */
+                      readmem_u_int16_t(md.message_pbs.cur, 2, paylen);
+
+                      DBG(DBG_CRYPT, 
+		      DBG_log("Encrypted payload length = %d", paylen);
+                      );
+                      clonetochunk(ch, &(md.message_pbs.cur[4]), paylen-4, "Ciphertext payload");
+		      setchunk(pch, NULL, 0);
+		      if ((md.st->st_state == STATE_MAIN_I1) ||
+			  (md.st->st_state == STATE_MAIN_I2) ||
+			  (md.st->st_state == STATE_MAIN_I3) ||
+			  (md.st->st_state == STATE_MAIN_I4)) {
+			if (! decrypt_payload(md.st, &md.st->st_ks_r,
+					      md.st->st_ne_r_iv,
+					      ch, &pch) ) {
+			  log("Unable to decrypt responder payload");
+			  free(&md);
+			  return;
+			}
+		      } else {
+			if (!decrypt_payload(md.st, &md.st->st_ks_i,
+					     md.st->st_ne_i_iv,
+					     ch, &pch) ) {
+			  log("Unable to decrypt initiator payload");
+			  free(&md);
+			  return;
+			}
+		      }
+                      /* see macro in defs.h */ 
+                      writemem_u_int16_t(md.message_pbs.cur, 2, (pch.len + 4));
+
+                      /* Now copy the plaintext */
+                      memcpy(&(md.message_pbs.cur[4]), pch.ptr, pch.len);
+                      /* Shift down all subsequent payloads */
+                      memmove(&(md.message_pbs.cur[pch.len+4]),
+                              &(md.message_pbs.cur[paylen]),
+                              md.message_pbs.roof - &(md.message_pbs.cur[paylen]));
+		      /* Adjust the size of roof downwards */
+                      md.message_pbs.roof -= paylen - pch.len - 4;
+
+		      freeanychunk(ch);
+		      memset(pch.ptr, 0, pch.len);
+		      freeanychunk(pch);
+		    }
+		  } /* Otherwise, let everything else pass */
+		} /* end if (revised PK mode ) */
+	      } /* end if Phase 1 */
+	    } /* end OPENSSL handling */
+#endif /* OPENSSL */
+                                                                             
 	    if (!in_struct(&pd->payload, sd, &md.message_pbs, &pd->pbs))
 	    {
 		loglog(RC_LOG_SERIOUS, "%smalformed payload in packet", excuse);
@@ -1456,8 +1758,9 @@
 	    case STF_IGNORE:
 		break;
 	    case STF_NO_REPLY:
-	    case STF_REPLY:
 	    case STF_UNPEND_QUICK:
+            case STF_REPLY:
+            case STF_REPLY_UNPEND_QUICK:
 		/* Delete previous retransmission event.
 		 * New event will be scheduled below.
 		 */
@@ -1484,7 +1787,7 @@
 		freeanychunk(md.st->st_tpacket);
 
 		/* if requested, send the new reply packet */
-		if (result == STF_REPLY)
+		if (result == STF_REPLY || result == STF_REPLY_UNPEND_QUICK)
 		{
 		    close_output_pbs(&md.reply);   /* good form, but actually a no-op */
 
@@ -1502,7 +1805,7 @@
 		/* Schedule for whatever timeout is specified */
 		{
 		    time_t delay;
-		    int kind = smc->timeout_event;
+		    enum event_type kind = smc->timeout_event;
 
 		    switch (kind)
 		    {
@@ -1596,15 +1899,18 @@
 			, state_story[md.st->st_state - STATE_MAIN_R0]);
 		}
 
-		if (result == STF_UNPEND_QUICK && md.st->st_pending_quick)
+		if (result == STF_UNPEND_QUICK
+                || result == STF_REPLY_UNPEND_QUICK)
 		{
-		    struct connection *c = md.st->st_connection;
-
-		    DBG(DBG_CONTROL, DBG_log("Doing Quick Mode with %s \"%s\""
-			, ip_str(&c->that.host_addr), c->name));
-		    (void) quick_outI1(dup_any(md.st->st_whack_sock)
-			, md.st, c, md.st->st_policy, 1);
-		    md.st->st_pending_quick = FALSE;
+                   /* Initiate any Quick Mode negotiations that
+                    * were waiting to piggyback on this Keying Channel.
+                    *
+                    * ??? there is a potential race condition
+                    * if we are the responder: the initial Phase 2
+                    * message might outrun the final Phase 1 message.
+                    * I think that retransmission will recover.
+                    */
+                   unpend(md.st);
 		}
 
 		if (IS_ISAKMP_SA_ESTABLISHED(md.st->st_state)
@@ -1634,14 +1940,6 @@
 		delete_state(md.st);
 		md.st = NULL;
 		break;
-
-	    case STF_DROP_DOOMED_EXCHANGE:
-		loglog(RC_LOG_SERIOUS, "dropping exchange to avoid Pluto 1.0 bug"
-		    " handling DH shared secret with leading zero byte");
-		delete_event(md.st);
-		delete_state(md.st);
-		md.st = NULL;
-		break;
 #endif
 
 	    default:	/* a shortcut to STF_FAIL, setting md.note */
@@ -1666,3 +1964,294 @@
     }
     free_md(&md);
 }
+
+#ifdef OPENSSL
+int
+derive_symmetric_key( struct state *st, const chunk_t nonce,
+		      const u_char *seedptr, const size_t seedlen,
+		      keysched *ks,
+		      chunk_t *key )
+{
+  struct hmac_ctx ctx;
+  chunk_t k, kk, kchain;
+  chunk_t ne;
+  char nestr[8];
+  int needed_len;
+
+  DBG(DBG_PARSING, 
+	  DBG_dump_chunk("Deriving symmetric key from: ", nonce);
+	  DBG_dump("Initial Cookie:", seedptr, seedlen);
+	);
+  switch(st->st_oakley.encrypt) {
+    /* We really shouldn't deal with DES, */
+    /* uncomment this if you must have it */
+  case OAKLEY_DES_CBC:
+    needed_len = DES_CBC_BLOCK_SIZE;
+    break;
+#ifdef NOTYET
+  case OAKLEY_IDEA_CBC:
+    needed_len = IDEA_CBC_KEY_LEN;
+    break;
+  case OAKLEY_BLOWFISH_CBC:
+    needed_len = BLOWFISH_CBC_KEY_LEN;
+    break;
+  case OAKLEY_RC5_R16_B64_CBC:
+    needed_len = RC5_CBC_KEY_LEN;
+    break;
+#endif
+  case OAKLEY_3DES_CBC:
+    needed_len = DES_CBC_BLOCK_SIZE * 3;
+    break;
+#ifdef NOTYET
+  case OAKLEY_CAST_CBC:
+    needed_len = CAST_CBC_KEY_LEN;
+    break;
+#endif
+  default:
+    log("Unknown block cipher ID for symmetric cipher");
+    return -1;
+  }
+
+  /* Generate initial decryption key material */
+  /* key = prf(Nonce-X, Cookie-X); X={I,R} */
+  ne.ptr = NULL;
+  hmac_init_chunk(&ctx, st->st_oakley.hasher, nonce);
+  hmac_update(&ctx, seedptr, seedlen);
+  hmac_final_chunk(ne, nestr, &ctx);
+  clonetochunk(*key, ne.ptr, ne.len, "Initial key material");
+
+  if (key->len < needed_len) {
+    freeanychunk(*key);
+    kchain.ptr = alloc_bytes(1, "initial zero octet");
+    kchain.len = 1;
+    memset(kchain.ptr, 0, kchain.len);
+    while (key->len < needed_len) {
+      kk.ptr = NULL;
+      hmac_init_chunk(&ctx, st->st_oakley.hasher, ne);
+      hmac_update_chunk(&ctx, kchain);
+      hmac_final_chunk(kk, "extra key material", &ctx);
+      clonereplacechunk(kchain, kk.ptr, kk.len, "chain key material");
+      /* Now append kk to key */
+      if (! key->ptr ) {
+	clonetochunk(*key, kk.ptr, kk.len, "initial extra key material");
+      } else {
+	k.ptr = alloc_bytes(key->len + kk.len, "appended key material");
+	k.len = key->len + kk.len;
+	memcpy(k.ptr, key->ptr, key->len);
+	memcpy(&(k.ptr[key->len]), kk.ptr, kk.len);
+	freeanychunk(*key);
+	key->len = k.len;
+	key->ptr = k.ptr;
+      }
+      freeanychunk(kk);
+    }
+    freeanychunk(kchain);
+  }
+
+  switch(st->st_oakley.encrypt) {
+    /* We really shouldn't deal with DES, */
+    /* uncomment this if you must have it */
+  case OAKLEY_DES_CBC:
+    (void)des_set_key((des_cblock *)key->ptr, ks->des_ks);
+    break;
+#ifdef NOTYET
+  case OAKLEY_IDEA_CBC:
+    break;
+  case OAKLEY_BLOWFISH_CBC:
+    break;
+  case OAKLEY_RC5_R16_B64_CBC:
+    break;
+#endif
+  case OAKLEY_3DES_CBC:
+    (void)des_set_key((des_cblock *)key->ptr + 0, ks->des3_ks.ks[0]);
+    (void)des_set_key((des_cblock *)key->ptr + 1, ks->des3_ks.ks[1]);
+    (void)des_set_key((des_cblock *)key->ptr + 2, ks->des3_ks.ks[2]);
+    break;
+#ifdef NOTYET
+  case OAKLEY_CAST_CBC:
+    break;
+#endif
+  }
+
+  return 0;
+}
+
+bool
+encrypt_payload( struct state *st, keysched *ks, u_char *iv,
+		 chunk_t inp, chunk_t *out )
+{
+  chunk_t temp;
+  int blocklen;
+  u_char pv;
+
+  switch(st->st_oakley.encrypt) {
+  case OAKLEY_DES_CBC:
+    blocklen = DES_CBC_BLOCK_SIZE;
+    break;
+#ifdef NOTYET
+  case OAKLEY_IDEA_CBC:
+    break;
+  case OAKLEY_BLOWFISH_CBC:
+    break;
+  case OAKLEY_RC5_R16_B64_CBC:
+    break;
+#endif
+  case OAKLEY_3DES_CBC:
+    blocklen = DES_CBC_BLOCK_SIZE;
+    break;
+#ifdef NOTYET
+  case OAKLEY_CAST_CBC:
+    break;
+#endif
+  }
+
+  /* Pad the input up to a block size multiple */
+  if (inp.len % blocklen == 0) { /* Add a full block for padding */
+    pv = (u_char)blocklen;
+    temp.len = inp.len + (size_t)pv;
+  } else {
+    pv = (u_char)(blocklen - 1  - ((inp.len + blocklen - 1) % blocklen));
+    temp.len = inp.len + (size_t)pv;
+  }
+
+  temp.ptr = alloc_bytes(temp.len, "padded plaintext");
+  memset(temp.ptr, 0, temp.len);
+  clonetochunk(*out, temp.ptr, temp.len, "ciphertext");
+  memcpy(temp.ptr, inp.ptr, inp.len);
+  temp.ptr[temp.len-1] = pv;
+  
+  DBG(DBG_PARSING | DBG_CRYPT,
+	  DBG_dump_chunk("Plaintext:", temp);
+	  DBG_dump("Old IV: ", iv, blocklen);
+	);
+
+  switch(st->st_oakley.encrypt) {
+  case OAKLEY_DES_CBC:
+    des_ncbc_encrypt((des_cblock *)temp.ptr, (des_cblock *)out->ptr,
+		     temp.len, ks->des_ks, (des_cblock *)iv, TRUE);
+    break;
+#ifdef NOTYET
+  case OAKLEY_IDEA_CBC:
+    break;
+  case OAKLEY_BLOWFISH_CBC:
+    break;
+  case OAKLEY_RC5_R16_B64_CBC:
+    break;
+#endif
+  case OAKLEY_3DES_CBC:
+    des_ede3_cbc_encrypt((des_cblock *)temp.ptr, (des_cblock *)out->ptr,
+			 temp.len,
+			 ks->des3_ks.ks[0],
+			 ks->des3_ks.ks[1],
+			 ks->des3_ks.ks[2],
+			 (des_cblock *)iv, TRUE);
+    break;
+#ifdef NOTYET
+  case OAKLEY_CAST_CBC:
+    break;
+#endif
+  }
+
+  DBG(DBG_PARSING | DBG_CRYPT,
+	DBG_dump_chunk("Ciphertext: ", *out);
+	DBG_dump("New IV: ", iv, blocklen);
+	);
+  freeanychunk(temp);
+  return TRUE;
+}
+
+bool
+decrypt_payload( struct state *st, keysched *ks, u_char *iv,
+		 chunk_t inp, chunk_t *out )
+{
+  chunk_t temp;
+  int blocklen;
+
+  switch(st->st_oakley.encrypt) {
+  case OAKLEY_DES_CBC:
+    blocklen = DES_CBC_BLOCK_SIZE;
+    break;
+#ifdef NOTYET
+  case OAKLEY_IDEA_CBC:
+    break;
+  case OAKLEY_BLOWFISH_CBC:
+    break;
+  case OAKLEY_RC5_R16_B64_CBC:
+    break;
+#endif
+  case OAKLEY_3DES_CBC:
+    blocklen = DES_CBC_BLOCK_SIZE;
+    break;
+#ifdef NOTYET
+  case OAKLEY_CAST_CBC:
+    break;
+#endif
+  }
+
+  if (inp.len % blocklen != 0) {
+    log("Ciphertext is not a multiple of block length");
+    return FALSE;
+  }
+
+  DBG(DBG_PARSING | DBG_CRYPT,
+	DBG_dump_chunk("Ciphertext: ", inp);
+	DBG_dump("Old IV: ", iv, blocklen);
+	);
+
+  temp.ptr = alloc_bytes(inp.len, "temporary plaintext");
+  temp.len = inp.len;
+  memset(temp.ptr, 0, temp.len);
+
+  switch(st->st_oakley.encrypt) {
+  case OAKLEY_DES_CBC:
+    des_ncbc_encrypt((des_cblock *)inp.ptr, (des_cblock *)temp.ptr,
+		     inp.len, ks->des_ks, (des_cblock *)iv, FALSE);
+    break;
+#ifdef NOTYET
+  case OAKLEY_IDEA_CBC:
+    break;
+  case OAKLEY_BLOWFISH_CBC:
+    break;
+  case OAKLEY_RC5_R16_B64_CBC:
+    break;
+#endif
+  case OAKLEY_3DES_CBC:
+    des_ede3_cbc_encrypt((des_cblock *)inp.ptr, (des_cblock *)temp.ptr,
+			 inp.len,
+			 ks->des3_ks.ks[0],
+			 ks->des3_ks.ks[1],
+			 ks->des3_ks.ks[2],
+			 (des_cblock *)iv, FALSE);
+    break;
+#ifdef NOTYET
+  case OAKLEY_CAST_CBC:
+    break;
+#endif
+  }
+
+  /* Strip padding from plaintext */
+  if ((temp.ptr[temp.len-1] < (u_char)1) ||
+      (temp.ptr[temp.len-1] > (u_char)blocklen) ||
+      (temp.ptr[temp.len-1] > temp.len)) {
+    /* Impossible padding value */
+    log("Impossible plaintext padding value: %d", temp.ptr[temp.len-1]);
+    memset(temp.ptr, 0, temp.len);
+    freeanychunk(temp);
+    return FALSE;
+  }
+
+  out->len = temp.len - (size_t)(temp.ptr[temp.len-1]);
+  out->ptr = alloc_bytes(inp.len, "plaintext");
+  memcpy(out->ptr, temp.ptr, out->len);
+
+  DBG(DBG_PARSING | DBG_CRYPT,
+	DBG_dump_chunk("Plaintext: ", *out);
+	DBG_dump("New IV: ", iv, blocklen);
+	);
+
+  memset(temp.ptr, 0, temp.len);
+  freeanychunk(temp);
+  return TRUE;
+}
+
+#endif
diff -bruN freeswan-1.9.orig/pluto/demux.h freeswan-1.9/pluto/demux.h
--- freeswan-1.9.orig/pluto/demux.h	Tue Sep 12 02:59:26 2000
+++ freeswan-1.9/pluto/demux.h	Tue Jun  5 14:50:00 2001
@@ -11,7 +11,7 @@
  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  * for more details.
  *
- * RCSID $Id: demux.h,v 1.15 2000/09/12 06:59:26 dhr Exp $
+ * RCSID $Id: demux.h,v 1.18 2001/05/05 02:51:38 dhr Exp $
  */
 
 struct state;	/* forward declaration of tag */
@@ -48,7 +48,7 @@
     pb_stream message_pbs;	/* message to be processed */
     struct isakmp_hdr hdr;	/* message's header */
     bool encrypted;	/* was it encrypted? */
-    int from_state;	/* state we started in */
+    enum state_kind from_state;        /* state we started in */
     struct state *st;	/* current state object */
     pb_stream reply;	/* room for reply */
     pb_stream rbody;	/* room for reply body (after header) */
@@ -66,14 +66,26 @@
 typedef enum {
     STF_IGNORE,	/* don't respond */
     STF_NO_REPLY,	/* success, but no reply to send */
+    STF_UNPEND_QUICK,  /* phase 1 success: initiate any phase 2 */
     STF_REPLY,	/* success, so send reply */
-    STF_UNPEND_QUICK,	/* phase 1 success; initiate any phase 2 */
+    STF_REPLY_UNPEND_QUICK,	/* reply; phase 1 success: initiate any phase 2 */
     STF_INTERNAL_ERROR,	/* discard everything, we failed */
 #ifdef DODGE_DH_MISSING_ZERO_BUG
-    STF_DROP_DOOMED_EXCHANGE,	/* we're responder -- don't respond */
     STF_REPLACE_DOOMED_EXCHANGE,	/* we're initiator -- reinitiate */
 #endif
     STF_FAIL	/* discard everything, something failed.  notification_t added. */
 } stf_status;
 
 typedef stf_status state_transition_fn(struct msg_digest *md);
+
+#ifdef OPENSSL
+extern int derive_symmetric_key( struct state *st, const chunk_t nonce,
+				 const u_char *seedptr,
+				 const size_t seedlen,
+				 keysched *ks,
+				 chunk_t *key );
+extern bool encrypt_payload( struct state *st, keysched *ks, u_char *iv,
+			   chunk_t inp, chunk_t *out );
+extern bool decrypt_payload( struct state *st, keysched *ks, u_char *iv,
+			     chunk_t inp, chunk_t *out );
+#endif /* OPENSSL */
diff -bruN freeswan-1.9.orig/pluto/dir2hash.c freeswan-1.9/pluto/dir2hash.c
--- freeswan-1.9.orig/pluto/dir2hash.c	Wed Dec 31 19:00:00 1969
+++ freeswan-1.9/pluto/dir2hash.c	Wed May 16 10:57:20 2001
@@ -0,0 +1,1071 @@
+/*
+ * Convert an XMAP hash directory to a Berkeley DB hash file
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <getopt.h>
+#include <string.h>
+#include <dirent.h>
+#include <errno.h>
+#include <netinet/in.h>
+#include <ctype.h>
+
+#ifdef HAVE_DB185
+#include <db_185.h>
+#else
+#include <db.h>
+#endif
+
+#include <openssl/pem.h>
+#include <openssl/bio.h>
+#include <openssl/sha.h>
+#include <openssl/x509.h>
+#include <openssl/x509v3.h>
+
+#define VERSION_SIZE 4
+static unsigned char version_data[] = { '\00', '\00', '\00', '\01' };
+
+#define TAGLEN 4
+
+#define UID_PREFIX "uid-"
+
+#define X509_TYPE 0
+#define X509_CRL_TYPE 1
+
+typedef struct _cert_st {
+  u_int8_t type;
+  union _inf {
+    X509 *x;
+    X509_CRL *c;
+  } info;
+  unsigned char *d;
+  size_t dlen;
+  unsigned char digest[SHA_DIGEST_LENGTH];
+  struct _cert_st *next;
+} CERT;
+
+typedef struct _xname_list_st {
+  unsigned char digest[SHA_DIGEST_LENGTH];
+  struct _xname_list_st *next;
+} XNAME_LIST;
+
+typedef struct _xname_st {
+  unsigned char *d;
+  size_t dlen;
+  int lcount;
+  XNAME_LIST *list;
+  struct _xname_st *next;
+} XNAME;
+
+static const char *hashout = "certhash.db";
+
+void *nalloc( size_t s );
+void dump( unsigned char *p, size_t l, const char *name );
+void free_xname_list_node( XNAME_LIST *node );
+void free_xname_node( XNAME *node );
+void free_xnames( XNAME **nl );
+XNAME *alloc_xname_node( const unsigned char *n, const size_t s );
+int add_unique_xname( XNAME **nl, X509_NAME *name,
+		      const unsigned char *digest );
+int add_unique_xname( XNAME **nl, X509_NAME *name,
+		      const unsigned char *digest );
+void add_unique_dns(XNAME **nl, X509 *x, const unsigned char *digest );
+void add_unique_ip(XNAME **nl, X509 *x, const unsigned char *digest );
+int isCA( X509 *x );
+void free_cert_node( CERT *c );
+int add_unique_xinf( CERT **cl, XNAME **xl,
+		     XNAME **cal, XNAME **dnl, XNAME **ipl,
+		     unsigned int type, void *x );
+void putcerts(DB *db, int start, int end, char *argv[],
+	      CERT **cl, XNAME **xl, XNAME **cal, XNAME **dnl, XNAME **ipl);
+void free_cert_list( CERT **cl );
+void putcrls(DB *db, int start, int end, char *argv[], CERT **cl, XNAME **xl);
+int add_unique_uid(XNAME **ul, X509 *x, const char *uid);
+void putuids(DB *db, int start, int end, char *argv[], XNAME **ul);
+
+void *
+nalloc( size_t s )
+{
+  void *t = malloc(s);
+
+  if (!t) {
+    fprintf(stderr, "cannot allocate %d bytes\n", s);
+    exit(-1);
+  }
+  return t;
+}
+
+void
+dump( unsigned char *p, size_t l, const char *name )
+{
+  int i;
+
+  printf("%s: (length %d)\n", name, l);
+  for(i=0; i<l; i++) {
+    printf("%02X", p[i]);
+    if (i < l-1) putchar((i % 16 == 15) ? '\n' : ':');
+  }
+  printf("\n");
+}
+
+void
+free_xname_list_node( XNAME_LIST *node )
+{
+  free(node);
+}
+
+void
+free_xname_node( XNAME *node )
+{
+  XNAME_LIST *xl, *p;
+
+  if (node->d) free(node->d);
+  for(xl=node->list; xl;) {
+    p = xl->next;
+    free_xname_list_node(xl);
+    xl = p;
+  }
+  free(node);
+}
+
+void
+free_xnames( XNAME **nl )
+{
+  XNAME *l, *p;
+
+  if (!nl) return;
+  for(l = *nl; l; ) {
+    p = l->next;
+    free_xname_node(l);
+    l = p;
+  }
+  *nl = NULL;
+}
+
+XNAME *
+alloc_xname_node( const unsigned char *n, const size_t s )
+{
+  /* Create an empty list for name store in n */
+  XNAME *ret;
+
+  ret = nalloc(sizeof(XNAME));
+  ret->lcount = 0;
+  ret->list = NULL;
+  ret->dlen = s;
+  ret->d = nalloc(s);
+  memcpy(ret->d, n, s);
+  ret->next = NULL;
+
+  return ret;
+}
+
+int
+add_unique_xname( XNAME **nl, X509_NAME *name,
+		  const unsigned char *digest )
+{
+  unsigned char *d, *dum;
+  size_t dlen;
+  XNAME *p;
+  int found, res = 1;
+
+  /* Create DER form of name */
+
+  if (name == NULL) {
+    dlen = 1;
+    d = nalloc(dlen);
+    d[0] = '\0';
+  } else {
+    dlen = i2d_X509_NAME(name, NULL);
+    d = nalloc(dlen); dum = d;
+    i2d_X509_NAME(name, &dum);
+  }
+
+  /* Search nl for name */
+  for (p=*nl, found = 0; ((!found) && (p));
+       (!found) ? p=p->next : p)
+    if ((dlen == p->dlen) && (memcmp(d, p->d, dlen) == 0)) found = 1;
+
+  if (found) {
+    XNAME_LIST *pp;
+
+    /* add digest to list of names if not already there */
+    for(pp = p->list, found = 0; ((!found) && (pp));
+	(!found) ? pp=pp->next : pp)
+      if (memcmp(pp->digest, digest, SHA_DIGEST_LENGTH) == 0) found = 1;
+    
+    if (!found) {
+      XNAME_LIST *n = nalloc(sizeof(XNAME_LIST));
+      n->next = p->list;
+      memcpy(n->digest, digest, SHA_DIGEST_LENGTH);
+      p->list = n;
+      p->lcount++;
+    } else
+      res = 0;
+  } else {
+    p = alloc_xname_node(d, dlen);
+    p->list = nalloc(sizeof(XNAME_LIST));
+    p->list->next = NULL;
+    memcpy(p->list->digest, digest, SHA_DIGEST_LENGTH);
+    p->lcount = 1;
+    p->next = *nl;
+    *nl = p;
+  }
+  free(d);
+  return res;
+}
+
+void
+add_unique_dns(XNAME **nl, X509 *x, const unsigned char *digest )
+{
+  unsigned char *d;
+  size_t dlen;
+  XNAME *p;
+  int found, res = 1;
+  int i, loc;
+  u_char *pp;
+  STACK_OF(GENERAL_NAME) *nsk = NULL;
+  X509_EXTENSION *ext;
+  GENERAL_NAME *gn;
+
+  if ((loc = X509_get_ext_by_NID(x, NID_subject_alt_name, -1)) < 0) return;
+  if ((ext = X509_get_ext(x, loc)) == NULL) return;
+  pp = ext->value->data;
+  d2i_GENERAL_NAMES(&nsk, &pp, ext->value->length);
+  if (!nsk) return;
+  for(i=0; i<sk_GENERAL_NAME_num(nsk); i++) {
+    gn = sk_GENERAL_NAME_value(nsk, i);
+
+    if (gn->type == GEN_DNS) {
+      dlen = gn->d.ia5->length;
+      d = nalloc(dlen);
+      memcpy(d, gn->d.ia5->data, dlen);
+
+      for (p=*nl, found = 0; ((!found) && (p));
+	   (!found) ? p=p->next : p)
+	if ((dlen == p->dlen) && (memcmp(d, p->d, dlen) == 0)) found = 1;
+
+      if (found) {
+	XNAME_LIST *pp;
+	
+	/* add digest to list of names if not already there */
+	for(pp = p->list, found = 0; ((!found) && (pp));
+	    (!found) ? pp=pp->next : pp)
+	  if (memcmp(pp->digest, digest, SHA_DIGEST_LENGTH) == 0) found = 1;
+	
+	if (!found) {
+	  XNAME_LIST *n = nalloc(sizeof(XNAME_LIST));
+	  n->next = p->list;
+	  memcpy(n->digest, digest, SHA_DIGEST_LENGTH);
+	  p->list = n;
+	  p->lcount++;
+	} else
+	  res = 0;
+      } else {
+	p = alloc_xname_node(d, dlen);
+	p->list = nalloc(sizeof(XNAME_LIST));
+	p->list->next = NULL;
+	memcpy(p->list->digest, digest, SHA_DIGEST_LENGTH);
+	p->lcount = 1;
+	p->next = *nl;
+	*nl = p;
+      }
+      free(d);
+    }
+  }
+  sk_GENERAL_NAME_free(nsk);
+}
+
+void
+add_unique_ip(XNAME **nl, X509 *x, const unsigned char *digest )
+{
+  unsigned char *d;
+  size_t dlen;
+  XNAME *p;
+  int found, res = 1;
+  int i, loc;
+  u_char *pp;
+  STACK_OF(GENERAL_NAME) *nsk = NULL;
+  X509_EXTENSION *ext;
+  GENERAL_NAME *gn;
+
+  if ((loc = X509_get_ext_by_NID(x, NID_subject_alt_name, -1)) < 0) return;
+  if ((ext = X509_get_ext(x, loc)) == NULL) return;
+  pp = ext->value->data;
+  d2i_GENERAL_NAMES(&nsk, &pp, ext->value->length);
+  if (!nsk) return;
+  for(i=0; i<sk_GENERAL_NAME_num(nsk); i++) {
+    gn = sk_GENERAL_NAME_value(nsk, i);
+
+    if (gn->type == GEN_IPADD) {
+      dlen = gn->d.ip->length;
+      d = nalloc(dlen);
+      memcpy(d, gn->d.ip->data, dlen);
+
+      for (p=*nl, found = 0; ((!found) && (p));
+	   (!found) ? p=p->next : p)
+	if ((dlen == p->dlen) && (memcmp(d, p->d, dlen) == 0)) found = 1;
+
+      if (found) {
+	XNAME_LIST *pp;
+	
+	/* add digest to list of names if not already there */
+	for(pp = p->list, found = 0; ((!found) && (pp));
+	    (!found) ? pp=pp->next : pp)
+	  if (memcmp(pp->digest, digest, SHA_DIGEST_LENGTH) == 0) found = 1;
+	
+	if (!found) {
+	  XNAME_LIST *n = nalloc(sizeof(XNAME_LIST));
+	  n->next = p->list;
+	  memcpy(n->digest, digest, SHA_DIGEST_LENGTH);
+	  p->list = n;
+	  p->lcount++;
+	} else
+	  res = 0;
+      } else {
+	p = alloc_xname_node(d, dlen);
+	p->list = nalloc(sizeof(XNAME_LIST));
+	p->list->next = NULL;
+	memcpy(p->list->digest, digest, SHA_DIGEST_LENGTH);
+	p->lcount = 1;
+	p->next = *nl;
+	*nl = p;
+      }
+      free(d);
+    }
+  }
+  sk_GENERAL_NAME_free(nsk);
+}
+
+int
+isCA( X509 *x )
+{
+  X509_EXTENSION *ext;
+  BASIC_CONSTRAINTS *p = NULL;
+  int loc;
+  
+  loc = X509_get_ext_by_NID(x, NID_basic_constraints, -1);
+  if (loc >= 0) {
+    ext = X509_get_ext(x, loc);
+    if (ext) {
+      p = X509V3_EXT_d2i(ext);
+      if (! p->ca) {
+	BASIC_CONSTRAINTS_free(p);
+	return 0;
+      } else {
+	BASIC_CONSTRAINTS_free(p);
+	return 1; /* This is a CA certificate */
+      }
+    } else
+      return 0;
+  } else
+    return 0;
+}
+
+void
+free_cert_node( CERT *c )
+{
+  if (c->d) free(c->d);
+  c->d = NULL;
+  switch(c->type) {
+    case X509_TYPE: if (c->info.x) X509_free(c->info.x); break;
+    case X509_CRL_TYPE: if (c->info.c) X509_CRL_free(c->info.c); break;
+  }
+  c->info.x = NULL;
+  memset(c->digest, 0, SHA_DIGEST_LENGTH);
+  c->next = NULL;
+  free(c);
+}
+
+int
+add_unique_xinf( CERT **cl, XNAME **xl,
+		 XNAME **cal, XNAME **dnl, XNAME **ipl,
+		 unsigned int type, void *x )
+{
+  int f;
+  CERT *p, *node;
+  unsigned char *dum;
+
+  if (!cl) return 0;
+
+  node = nalloc(sizeof(CERT));
+  node->next = NULL;
+  node->type = type;
+  switch(type) {
+  case X509_TYPE:
+    node->info.x = (X509 *)x;
+    node->dlen = i2d_X509((X509 *)x, NULL);
+    node->d = nalloc(node->dlen);
+    dum = node->d;
+    i2d_X509( (X509 *)x, &dum );
+    break;
+  case X509_CRL_TYPE:
+    node->info.c = (X509_CRL *)x;
+    node->dlen = i2d_X509_CRL((X509_CRL *)x, NULL);
+    node->d = nalloc(node->dlen);
+    dum = node->d;
+    i2d_X509_CRL( (X509_CRL *)x, &dum );
+    break;
+  default:
+    fprintf(stderr, "Unknown info type: %d\n", type);
+    free(node);
+    return 0;
+  }
+
+  SHA1(node->d, node->dlen, node->digest);
+
+  for(p=*cl, f=0; (!f) && (p); p=p->next)
+    if (memcmp(p->digest, node->digest, SHA_DIGEST_LENGTH) == 0) f=1;
+    /* found a duplicate */
+
+  if (!f) {
+    /* insert at head of list */
+    node->next = *cl;
+    *cl = node;
+    switch(type) {
+    case X509_TYPE:
+      add_unique_xname(xl, X509_get_subject_name((X509 *)x), node->digest);
+      if (isCA(x)) add_unique_xname(cal, NULL, node->digest);
+      add_unique_dns(dnl, (X509 *)x, node->digest);
+      add_unique_ip(ipl, (X509 *)x, node->digest);
+      break;
+    case X509_CRL_TYPE:
+      add_unique_xname(xl, X509_CRL_get_issuer((X509_CRL *)x), node->digest);
+      break;
+    }
+    return 1;
+  } else
+    return 0;
+}
+
+void
+free_cert_list( CERT **cl )
+{
+  CERT *c;
+
+  if (!cl) return;
+
+  for(c=*cl; c;) {
+    CERT *p = c->next;
+
+    free_cert_node(c);
+    c = p;
+  }
+  *cl = NULL;
+}
+
+static char dirname[PATH_MAX+1];
+static int
+select_files(const struct dirent *de)
+{
+  struct stat st;
+  char path[PATH_MAX+1];
+
+  snprintf(path, sizeof(path), "%s/%s", dirname, de->d_name);
+  if (lstat(path, &st) == 0) {
+    if (S_ISREG(st.st_mode))
+      return 1;
+    else
+      return 0;
+  } else {
+    perror("stat");
+    return 0;
+  }
+}
+
+static int
+select_uid_files(const struct dirent *de)
+{
+  struct stat st;
+  char path[PATH_MAX+1];
+
+  if (strncasecmp(UID_PREFIX, de->d_name, strlen(UID_PREFIX)) != 0) return 0;
+  snprintf(path, sizeof(path), "%s/%s", dirname, de->d_name);
+  if (lstat(path, &st) == 0) {
+    if ((S_ISREG(st.st_mode)) || (S_ISLNK(st.st_mode)))
+      return 1;
+    else
+      return 0;
+  } else {
+    perror("stat");
+    return 0;
+  }
+}
+
+void
+putcerts(DB *db, int start, int end, char *argv[],
+	 CERT **cl, XNAME **xl, XNAME **cal, XNAME **dnl, XNAME **ipl)
+{
+  int i, j, n;
+  struct dirent **namelist = NULL;
+  char path[PATH_MAX+1];
+
+  for(i=start; i<end; i++) {
+    printf("Dumping certs from directory \"%s\"\n", argv[i]);
+    snprintf(dirname, sizeof(dirname)-1, "%s", argv[i]);
+    if ((n = scandir(argv[i], &namelist, select_files, alphasort)) >= 0) {
+      for(j=0; j<n; j++) {
+	BIO *b;
+
+	printf("File: %s\n", namelist[j]->d_name);
+	snprintf(path, sizeof(path), "%s/%s", argv[i], namelist[j]->d_name);
+	if ((b = BIO_new_file(path, "r")) != NULL) {
+	  X509 *x;
+
+	  if (!(x = PEM_read_bio_X509(b, NULL, NULL, NULL))) {
+	    BIO_ctrl(b, BIO_CTRL_RESET, 0, NULL);
+	    x = d2i_X509_bio(b, NULL);
+	  }
+	  if ((x) && (!add_unique_xinf(cl, xl, cal, dnl, ipl, X509_TYPE, x)))
+	    X509_free(x);
+	  BIO_free(b);
+	}
+      }
+      free(namelist);
+    } else
+      perror("scandir");
+  }
+}
+
+void
+putcrls(DB *db, int start, int end, char *argv[], CERT **cl, XNAME **xl)
+{
+  int i, j, n;
+  struct dirent **namelist = NULL;
+  char path[PATH_MAX+1];
+
+  for(i=start; i<end; i++) {
+    printf("Dumping CRLs from directory \"%s\"\n", argv[i]);
+    snprintf(dirname, sizeof(dirname)-1, "%s", argv[i]);
+    if ((n = scandir(argv[i], &namelist, select_files, alphasort)) >= 0) {
+      for(j=0; j<n; j++) {
+	BIO *b;
+
+	printf("File: %s\n", namelist[j]->d_name);
+	snprintf(path, sizeof(path), "%s/%s", argv[i], namelist[j]->d_name);
+	if ((b = BIO_new_file(path, "r")) != NULL) {
+	  X509_CRL *c;
+
+	  if (!(c = PEM_read_bio_X509_CRL(b, NULL, NULL, NULL))) {
+	    BIO_ctrl(b, BIO_CTRL_RESET, 0, NULL);
+	    c = d2i_X509_CRL_bio(b, NULL);
+	  }
+	  if ((c) &&
+	      (!add_unique_xinf(cl, xl, NULL, NULL, NULL,X509_CRL_TYPE, c)))
+	    X509_CRL_free(c);
+
+	  BIO_free(b);
+	}
+      }
+      free(namelist);
+    } else
+      perror("scandir");
+  }
+}
+
+int
+add_unique_uid(XNAME **ul, X509 *x, const char *uid)
+{
+  int found;
+  XNAME *p;
+  unsigned char digest[SHA_DIGEST_LENGTH], *d, *dum;
+  size_t dlen;
+
+  if (!x || !ul) return 0;
+
+  dlen = i2d_X509(x, NULL);
+  d = nalloc(dlen);
+  dum = d;
+  i2d_X509( x, &dum );
+
+  SHA1(d, dlen, digest);
+  free(d);
+
+  printf("Adding user id \"%s\"\n", uid);
+  for(found=0, p=*ul; ((!found) && (p)); 
+      (!found) ? p=p->next : p)
+    if ((strlen(uid) == p->dlen) && (memcmp(p->d, uid, p->dlen) == 0))
+      found = 1;
+
+  if (found) {
+    XNAME_LIST *pp;
+    
+    for(pp = p->list, found = 0; ((!found) && (pp));
+	pp=(!found) ? pp->next : pp)
+      if (memcmp(pp->digest, digest, SHA_DIGEST_LENGTH) == 0) found = 1;
+    
+    if (!found) {
+      XNAME_LIST *n = nalloc(sizeof(XNAME_LIST));
+      n->next = p->list;
+      memcpy(n->digest, digest, SHA_DIGEST_LENGTH);
+      p->list = n;
+      p->lcount++;
+    } else
+      return 0;
+  } else {
+    p = alloc_xname_node(uid, strlen(uid));
+    p->list = nalloc(sizeof(XNAME_LIST));
+    p->list->next = NULL;
+    memcpy(p->list->digest, digest, SHA_DIGEST_LENGTH);
+    p->lcount = 1;
+    p->next = *ul;
+    *ul = p;
+    return 1;
+  }
+  return 0;
+}
+
+static int
+isuidchar( char c )
+{
+  if (isalnum(c)) return 1;
+  if (c == '_') return 1;
+  return 0;
+}
+
+void
+putuids(DB *db, int start, int end, char *argv[], XNAME **ul)
+{
+  int i, j, n;
+  struct dirent **namelist = NULL;
+  char path[PATH_MAX+1];
+
+  for(i=start; i<end; i++) {
+    printf("Dumping uids from directory \"%s\"\n", argv[i]);
+    snprintf(dirname, sizeof(dirname)-1, "%s", argv[i]);
+    if ((n = scandir(argv[i], &namelist, select_uid_files, alphasort)) >= 0) {
+      for(j=0; j<n; j++) {
+	BIO *b;
+	char *n, *nn;
+
+	printf("File: %s\n", namelist[j]->d_name);
+	snprintf(path, sizeof(path), "%s/%s", argv[i], namelist[j]->d_name);
+	if ((b = BIO_new_file(path, "r")) != NULL) {
+	  X509 *x;
+
+	  if (!(x = PEM_read_bio_X509(b, NULL, NULL, NULL))) {
+	    BIO_ctrl(b, BIO_CTRL_RESET, 0, NULL);
+	    x = d2i_X509_bio(b, NULL);
+	  }
+
+	  n = nn = strdup(&(namelist[j]->d_name[strlen(UID_PREFIX)]));
+	  while ((*nn) && (isuidchar(*nn))) nn++;
+	  *nn = '\0';
+	  if ((x) && (!add_unique_uid(ul, x, n))) X509_free(x);
+
+	  BIO_free(b);
+	}
+      }
+      free(namelist);
+    } else
+      perror("scandir");
+  }
+}
+
+int
+main( int argc, char *argv[] )
+{
+  int c;
+  DB *db;
+  CERT *clist = NULL, *crlist = NULL;
+  XNAME *xlist = NULL, *nlist = NULL, *xcrlist = NULL, *calist = NULL;
+  XNAME *dnlist = NULL, *iplist = NULL;
+
+  while(1) {
+    int option_index = 0;
+    static struct option long_options[] = {
+      { "output", 1, 0, 0 },
+      { 0, 0, 0, 0 }
+    };
+
+    c = getopt_long(argc, argv, "o:",
+		    long_options, &option_index);
+    if (c == -1) break;
+
+    switch(c) {
+    case 0:
+      if (strcasecmp(long_options[option_index].name, "output") == 0)
+	hashout = optarg;
+      break;
+    case 'o':
+      hashout = optarg;
+      break;
+    case '?':
+      break;
+    default:
+      printf("?? getopt returned character code 0%o ??\n", c);
+    }
+  }
+
+  X509V3_add_standard_extensions();
+
+  if ((db = dbopen(hashout, O_CREAT | O_TRUNC | O_RDWR, 0644, DB_HASH, NULL)) == NULL) {
+    perror("dbopen");
+  } else {
+    DBT k, v;
+    CERT *c;
+    XNAME *x;
+    unsigned char *kk, *vv;
+
+    memset(&k, 0, sizeof(DBT));
+    memset(&v, 0, sizeof(DBT));
+    k.data = strdup("\xFF\xFF\xFF\xFFversion");
+    k.size = strlen("version") + TAGLEN;
+    v.data = version_data;
+    v.size = VERSION_SIZE;
+
+    if (db->put(db, &k, &v, 0) != 0) perror("dbput");
+    db->sync(db, 0);
+    free(k.data);
+
+    putcerts(db, optind, argc, argv,
+	     &clist, &xlist,
+	     &calist, &dnlist, &iplist);
+    putcrls(db, optind, argc, argv, &crlist, &xcrlist);
+    putuids(db, optind, argc, argv, &nlist);
+
+    for(c=clist; c; c=c->next) {
+      k.size = SHA_DIGEST_LENGTH+TAGLEN;
+      k.data = nalloc(k.size);
+      v.size = c->dlen;
+      v.data = nalloc(v.size);
+
+      kk = k.data;
+      vv = v.data;
+      memset(kk, 0, TAGLEN);
+      memcpy(&kk[TAGLEN], c->digest, SHA_DIGEST_LENGTH);
+      memcpy(vv, c->d, c->dlen);
+
+      if (db->put(db, &k, &v, 0) != 0) perror("dbput");
+      free(k.data);
+      free(v.data);
+    }
+    free_cert_list(&clist);
+
+    for(x=xlist; x; x=x->next) {
+      u_int32_t cnt;
+      int i;
+      XNAME_LIST *p;
+
+      k.size = x->dlen + TAGLEN;
+      k.data = nalloc(k.size);
+      v.size = TAGLEN + x->lcount * SHA_DIGEST_LENGTH;
+      v.data = nalloc(v.size);
+      kk = k.data;
+      vv = v.data;
+
+      memset(kk, 0, TAGLEN-1); kk[TAGLEN-1] = '\01';
+      memcpy(&kk[TAGLEN], x->d, x->dlen);
+      cnt = htonl(x->lcount);
+      memcpy(vv, (unsigned char *)&cnt, TAGLEN);
+      for(i=0, p=x->list; i<x->lcount; i++, p=p->next)
+	memcpy(&vv[TAGLEN + i*SHA_DIGEST_LENGTH],
+	       p->digest, SHA_DIGEST_LENGTH);
+      if (db->put(db, &k, &v, 0) < 0) perror("dbput");
+      free(k.data);
+      free(v.data);
+    }
+    free_xnames(&xlist);
+
+    for(x=calist; x; x=x->next) {
+      u_int32_t cnt;
+      int i;
+      XNAME_LIST *p;
+
+      k.size = TAGLEN;
+      k.data = nalloc(k.size);
+      v.size = TAGLEN + x->lcount * SHA_DIGEST_LENGTH;
+      v.data = nalloc(v.size);
+      kk = k.data;
+      vv = v.data;
+
+      memset(kk, 0, TAGLEN-1); kk[TAGLEN-1] = '\05';
+      cnt = htonl(x->lcount);
+      memcpy(vv, (unsigned char *)&cnt, TAGLEN);
+      for(i=0, p=x->list; i<x->lcount; i++, p=p->next)
+	memcpy(&vv[TAGLEN + i*SHA_DIGEST_LENGTH],
+	       p->digest, SHA_DIGEST_LENGTH);
+      if (db->put(db, &k, &v, 0) != 0) perror("dbput");
+      free(k.data);
+      free(v.data);
+    }
+    free_xnames(&calist);
+
+    for(x=dnlist; x; x=x->next) {
+      u_int32_t cnt;
+      int i;
+      XNAME_LIST *p;
+
+      k.size = x->dlen + TAGLEN;
+      k.data = nalloc(k.size);
+      v.size = TAGLEN + x->lcount * SHA_DIGEST_LENGTH;
+      v.data = nalloc(v.size);
+      kk = k.data;
+      vv = v.data;
+
+      memset(kk, 0, TAGLEN-1); kk[TAGLEN-1] = '\06';
+      memcpy(&kk[TAGLEN], x->d, x->dlen);
+      cnt = htonl(x->lcount);
+      memcpy(vv, (unsigned char *)&cnt, TAGLEN);
+      for(i=0, p=x->list; i<x->lcount; i++, p=p->next)
+	memcpy(&vv[TAGLEN + i*SHA_DIGEST_LENGTH],
+	       p->digest, SHA_DIGEST_LENGTH);
+      if (db->put(db, &k, &v, 0) != 0) perror("dbput");
+      free(k.data);
+      free(v.data);
+    }
+    free_xnames(&dnlist);
+
+    for(x=iplist; x; x=x->next) {
+      u_int32_t cnt;
+      int i;
+      XNAME_LIST *p;
+
+      k.size = x->dlen + TAGLEN;
+      k.data = nalloc(k.size);
+      v.size = TAGLEN + x->lcount * SHA_DIGEST_LENGTH;
+      v.data = nalloc(v.size);
+      kk = k.data;
+      vv = v.data;
+
+      memset(kk, 0, TAGLEN-1); kk[TAGLEN-1] = '\07';
+      memcpy(&kk[TAGLEN], x->d, x->dlen);
+      cnt = htonl(x->lcount);
+      memcpy(vv, (unsigned char *)&cnt, TAGLEN);
+      for(i=0, p=x->list; i<x->lcount; i++, p=p->next)
+	memcpy(&vv[TAGLEN + i*SHA_DIGEST_LENGTH],
+	       p->digest, SHA_DIGEST_LENGTH);
+      if (db->put(db, &k, &v, 0) != 0) perror("dbput");
+      free(k.data);
+      free(v.data);
+    }
+    free_xnames(&iplist);
+
+    for(c=crlist; c; c=c->next) {
+      k.size = SHA_DIGEST_LENGTH+TAGLEN;
+      k.data = nalloc(k.size);
+      v.size = c->dlen;
+      v.data = nalloc(v.size);
+
+      kk = k.data;
+      vv = v.data;
+      memset(kk, 0, TAGLEN-1); kk[TAGLEN-1] = '\04';
+      memcpy(&kk[TAGLEN], c->digest, SHA_DIGEST_LENGTH);
+      memcpy(vv, c->d, c->dlen);
+
+      if (db->put(db, &k, &v, 0) != 0) perror("dbput");
+      free(k.data);
+      free(v.data);
+    }
+    free_cert_list(&crlist);
+
+    for(x=xcrlist; x; x=x->next) {
+      u_int32_t cnt;
+      int i;
+      XNAME_LIST *p;
+
+      k.size = x->dlen + TAGLEN;
+      k.data = nalloc(k.size);
+      v.size = TAGLEN + x->lcount * SHA_DIGEST_LENGTH;
+      v.data = nalloc(v.size);
+      kk = k.data;
+      vv = v.data;
+
+      memset(kk, 0, TAGLEN-1); kk[TAGLEN-1] = '\02';
+      memcpy(&kk[TAGLEN], x->d, x->dlen);
+      cnt = htonl(x->lcount);
+      memcpy(vv, (unsigned char *)&cnt, TAGLEN);
+      for(i=0, p=x->list; i<x->lcount; i++, p=p->next)
+	memcpy(&vv[TAGLEN + i*SHA_DIGEST_LENGTH],
+	       p->digest, SHA_DIGEST_LENGTH);
+      if (db->put(db, &k, &v, 0) != 0) perror("dbput");
+      free(k.data);
+      free(v.data);
+    }
+    free_xnames(&xcrlist);
+
+    for(x=nlist; x; x=x->next) {
+      u_int32_t cnt;
+      int i;
+      XNAME_LIST *p;
+
+      k.size = x->dlen + TAGLEN;
+      k.data = nalloc(k.size);
+      v.size = TAGLEN + x->lcount * SHA_DIGEST_LENGTH;
+      v.data = nalloc(v.size);
+      kk = k.data;
+      vv = v.data;
+
+      memset(kk, 0, TAGLEN-1); kk[TAGLEN-1] = '\03';
+      memcpy(&kk[TAGLEN], x->d, x->dlen);
+      cnt = htonl(x->lcount);
+      memcpy(vv, (unsigned char *)&cnt, TAGLEN);
+      for(i=0, p=x->list; i<x->lcount; i++, p=p->next)
+	memcpy(&vv[TAGLEN + i*SHA_DIGEST_LENGTH],
+	       p->digest, SHA_DIGEST_LENGTH);
+      if (db->put(db, &k, &v, 0) != 0) perror("dbput");
+      free(k.data);
+      free(v.data);
+    }
+    free_xnames(&nlist);
+    db->close(db);
+  }
+
+  printf("Dumping keys from DB file\n");
+  if ((db = dbopen(hashout, 0, 0, DB_HASH, NULL)) == NULL) {
+    perror("db_open");
+  } else {
+    DBT k, v;
+    int i;
+
+    memset(&k, 0, sizeof(k));
+    memset(&v, 0, sizeof(v));
+    while (db->seq(db, &k, &v, R_NEXT) == 0) {
+      if (k.size < TAGLEN)
+	fprintf(stderr, "Error: key value too short\n");
+      else {
+	unsigned char *kk = k.data, *vv = v.data, *p;
+	u_int32_t c1, c2;
+	X509_NAME *xn;
+	
+	switch(kk[TAGLEN-1]) {
+	case 0:
+	  printf("X509 Certificate\n");
+	  dump(&kk[TAGLEN], k.size-TAGLEN, "SHA-DIGEST");
+	  printf("Data Length %d\n", v.size);
+	  break;
+	case 1:
+	  printf("X509 Subject Name\n");
+	  p = &kk[TAGLEN];
+	  if ((xn = d2i_X509_NAME(NULL, &p, k.size-TAGLEN)) != NULL) {
+	    char buf[256];
+	    
+	    X509_NAME_oneline(xn, buf, sizeof(buf));
+	    printf("%s:\n", buf);
+	    X509_NAME_free(xn);
+	    memcpy((unsigned char *)(&c1), v.data, TAGLEN);
+	    c2 = ntohl(c1);
+	    if (v.size != TAGLEN + (SHA_DIGEST_LENGTH * c2)) {
+	      fprintf(stderr, "X509 name length error\n");
+	    } else {
+	      for(i=0; i<c2; i++)
+		dump( &vv[TAGLEN + i*SHA_DIGEST_LENGTH],
+		      SHA_DIGEST_LENGTH, "SHA-DIGEST");
+	    }
+	    printf("\n");
+	  }
+	  break;
+	case 0x02:
+	  printf("X509 CRL Issuer Name\n");
+	  p = &kk[TAGLEN];
+	  if ((xn = d2i_X509_NAME(NULL, &p, k.size-TAGLEN)) != NULL) {
+	    char buf[256];
+	    
+	    X509_NAME_oneline(xn, buf, sizeof(buf));
+	    printf("%s:\n", buf);
+	    X509_NAME_free(xn);
+	    memcpy((unsigned char *)(&c1), v.data, TAGLEN);
+	    c2 = ntohl(c1);
+	    if (v.size != TAGLEN + (SHA_DIGEST_LENGTH * c2)) {
+	      fprintf(stderr, "X509 name length error\n");
+	    } else {
+	      for(i=0; i<c2; i++)
+		dump( &vv[TAGLEN + i*SHA_DIGEST_LENGTH],
+		      SHA_DIGEST_LENGTH, "SHA-DIGEST");
+	    }
+	    printf("\n");
+	  }
+	  break;
+	case 0x03:
+	  printf("UID: ");
+	  for(i=TAGLEN; i<k.size; i++)
+	    printf("%c", isprint(kk[i]) ? kk[i] : '?');
+	  printf("\n");
+	  memcpy((unsigned char *)(&c1), v.data, TAGLEN);
+	  c2 = ntohl(c1);
+	  if (v.size != TAGLEN + (SHA_DIGEST_LENGTH * c2)) {
+	    fprintf(stderr, "X509 name length error\n");
+	  } else {
+	    for(i=0; i<c2; i++)
+	      dump( &vv[TAGLEN + i*SHA_DIGEST_LENGTH],
+		    SHA_DIGEST_LENGTH, "SHA-DIGEST");
+	  }
+	  printf("\n");
+	  break;
+	case 0x04:
+	  printf("X509 Certificate Revocation List\n");
+	  dump(&kk[TAGLEN], k.size-TAGLEN, "SHA-DIGEST");
+	  printf("Data Length %d\n", v.size);
+	  break;
+	case 0x05:
+	  printf("CA Certificate:\n");
+	  memcpy((unsigned char *)(&c1), v.data, TAGLEN);
+	  c2 = ntohl(c1);
+	  if (v.size != TAGLEN + (SHA_DIGEST_LENGTH * c2)) {
+	    fprintf(stderr, "X509 name length error\n");
+	  } else {
+	    for(i=0; i<c2; i++)
+	      dump( &vv[TAGLEN + i*SHA_DIGEST_LENGTH],
+		    SHA_DIGEST_LENGTH, "SHA-DIGEST");
+	  }
+	  printf("\n");
+	  break;
+	case 0x06:
+	  printf("DNS: ");
+	  for(i=TAGLEN; i<k.size; i++)
+	    printf("%c", isprint(kk[i]) ? kk[i] : '?');
+	  printf("\n");
+	  memcpy((unsigned char *)(&c1), v.data, TAGLEN);
+	  c2 = ntohl(c1);
+	  if (v.size != TAGLEN + (SHA_DIGEST_LENGTH * c2)) {
+	    fprintf(stderr, "X509 name length error\n");
+	  } else {
+	    for(i=0; i<c2; i++)
+	      dump( &vv[TAGLEN + i*SHA_DIGEST_LENGTH],
+		    SHA_DIGEST_LENGTH, "SHA-DIGEST");
+	  }
+	  printf("\n");
+	  break;
+	case 0x07:
+	  printf("IPv4: ");
+	  for(i=TAGLEN; i<k.size; i++)
+	    printf("%d.", kk[i]);
+	  printf("\n");
+	  memcpy((unsigned char *)(&c1), v.data, TAGLEN);
+	  c2 = ntohl(c1);
+	  if (v.size != TAGLEN + (SHA_DIGEST_LENGTH * c2)) {
+	    fprintf(stderr, "X509 name length error\n");
+	  } else {
+	    for(i=0; i<c2; i++)
+	      dump( &vv[TAGLEN + i*SHA_DIGEST_LENGTH],
+		    SHA_DIGEST_LENGTH, "SHA-DIGEST");
+	  }
+	  printf("\n");
+	  break;
+	case 0xFF:
+	  printf("Metainfo: ");
+	  for(i=TAGLEN; i<k.size; i++)
+	    printf("%c", isprint(kk[i]) ? kk[i] : '?');
+	  printf(":- ");
+	  dump(v.data, v.size, "Value");
+	  printf("\n");
+	  break;
+	default:
+	  fprintf(stderr, "Error in type field: %02X\n", kk[TAGLEN-1]);
+	  break;
+	}
+      }
+    }
+    db->close(db);
+  }
+  printf("Done\n");
+
+  X509V3_EXT_cleanup();
+  return 0;
+}
+
+
diff -bruN freeswan-1.9.orig/pluto/dnskey.c freeswan-1.9/pluto/dnskey.c
--- freeswan-1.9.orig/pluto/dnskey.c	Sun Jan 28 16:03:03 2001
+++ freeswan-1.9/pluto/dnskey.c	Thu Jun  7 12:12:25 2001
@@ -11,7 +11,7 @@
  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  * for more details.
  *
- * RCSID $Id: dnskey.c,v 1.18 2001/01/28 21:03:03 dhr Exp $
+ * RCSID $Id: dnskey.c,v 1.24 2001/04/09 19:48:40 dhr Exp $
  */
 
 #include <stdlib.h>
@@ -39,7 +39,8 @@
  * so we build some of our own :-(
  */
 
-static err_t do_dns_query(const struct id *id, int type, const char *typename);	/* forward */
+static err_t do_dns_query(const struct id *id, const struct id *peerid
+    , int type, const char *typename); /* forward */
 
 /* Support deprecated interface to allow for older releases of the resolver.
  * Fake new interface!
@@ -255,6 +256,14 @@
     return NULL;
 }
 
+static err_t
+eat_name_helpfully(pb_stream *pbs, const char *context)
+{
+    err_t ugh = eat_name(pbs);
+
+    return ugh == NULL? ugh
+       : builddiag("malformed name within DNS record of %s: %s", context, ugh);}
+
 /* non-variable part of 4.1.2 Question Section entry:
  *                                 1  1  1  1  1  1
  *   0  1  2  3  4  5  6  7  8  9  0  1  2  3  4  5
@@ -512,7 +521,7 @@
     return NULL;
 }
 
-/* info relevant for T_TXT */
+/* info relevant for T_TXT X-IPsec-Server */
 
 #define our_TXT_attr_string "X-IPsec-Server"
 static const char our_TXT_attr[] = our_TXT_attr_string;
@@ -530,11 +539,67 @@
 };
 
 static err_t
-accumulate_txt_rr(u_char *rdata, size_t rdlen, struct txt_tbl *tt)
+decode_iii(u_char **pp, const struct id *client_id, struct id *gw_id)
+{
+    u_char *p = *pp + strspn(*pp, " \t");
+    u_char *e = p + strcspn(p, " \t");
+    u_char under = *e;
+
+    if (p == e)
+       return "TXT " our_TXT_attr_string " badly formed (no gateway specified)";
+
+    *e = '\0';
+    if (*p == '@')
+    {
+       /* gateway specification in this record is @FQDN */
+       err_t ugh = atoid(p, gw_id);
+
+       if (ugh != NULL)
+           return builddiag("malformed FQDN in TXT " our_TXT_attr_string ": %s"
+               , ugh);
+    }
+    else
+    {
+       /* gateway specification is numeric */
+       ip_address ip;
+       err_t ugh = tnatoaddr(p, e-p
+           , strchr(p, ':') == NULL? AF_INET : AF_INET6
+           , &ip);
+
+       if (ugh != NULL)
+           return builddiag("malformed IP address in TXT " our_TXT_attr_string ": %s"
+               , ugh);
+
+       if (isanyaddr(&ip))
+           return "gateway address must not be 0.0.0.0 or 0::0";
+
+       iptoid(&ip, gw_id);
+    }
+
+    *e = under;
+    *pp = e + strspn(e, " \t");
+
+    DBG(DBG_CONTROL,
+       {
+           char cidb[IDTOA_BUF];
+           char pidb[IDTOA_BUF];
+
+           idtoa(client_id, cidb, sizeof(cidb));
+           idtoa(gw_id, pidb, sizeof(cidb));
+           DBG_log("decoding TXT %s record for %s: security gateway %s"
+               , our_TXT_attr, cidb, pidb);
+       });
+    return NULL;
+}
+
+static err_t
+accumulate_txt_rr(u_char *rdata, size_t rdlen, struct txt_tbl *tt
+, const struct id *client_id, const struct id *peer_id)
 {
     u_char str[2049];	/* space for unpacked RDATA */
     u_char *p = str;
     unsigned long pref = 0;
+    struct id sgw_id;
 
     {
 	err_t ugh = unpack_txt_rdata(str, sizeof(str), rdata, rdlen);
@@ -552,8 +617,10 @@
     p += sizeof(our_TXT_attr) - 1;	/* ignore our attribute name */
     p += strspn(p, " \t");	/* ignore leading whitespace */
 
-    /* decode optional '(' pref ')' */
-    if (*p == '(')
+    /* decode '(' pref ')' */
+    if (*p != '(')
+       return "X-IPsec-Server missing '('";
+
     {
 	char *e;
 
@@ -569,24 +636,57 @@
 
 	p++;
 	p += strspn(p, " \t");
+
+       if (pref > 0xFFFF)
+           return "X-IPsec-Server priority larger than 0xFFFF";
     }
 
     /* time for '=' */
 
-    if (*p == '=')
-    {
+    if (*p != '=')
+       return "X-IPsec-Server priority missing '='";
 
 	p++;
 	p += strspn(p, " \t");
 
+    /* Decode iii (Security Gateway ID).
+     * For simplicity, we don't save the decoded ID because
+     * we'd have to allocate memory for the strings in the id.
+     * (There are ways to excuse ourselves, but they are too tricky
+     * by half: the only time the ID would get used, it would only
+     * be an IP address.)
+     */
+    {
+       u_char *q = p;  /* so p isn't updated */
+       err_t ugh = decode_iii(&q, client_id, &sgw_id);
+
+       if (ugh != NULL)
+           return ugh;
+
+	if (peer_id == NULL)
+	{
+           /* we're looking for a gateway spec with an IP address */
+           if (!id_is_ipaddr(&sgw_id))
+               return NULL;    /* we cannot use this record, but it isn't wrong */
+	}
+	else
+	{
+	    /* we're looking for a gatway spec that confirms what we were told */
+           if (!same_id(peer_id, &sgw_id))
+               return NULL;    /* we cannot use this record, but it isn't wrong */
+	}
+    }
+
 	if (tt->count == 0)
 	    tt->pref = pref;
+ 
 	if (tt->pref > pref)
 	{
 	    /* earlier accumulation trumped by this one */
 	    tt->count = 0;
 	    tt->pref = pref;
 	}
+ 
 	if (tt->pref == pref
 	&& tt->count < (int)elemsof(tt->rr))
 	{
@@ -597,7 +697,7 @@
 	    i->rdlen = rdlen;
 	    i->offset = p - str;
 	}
-    }
+
     return NULL;
 }
 
@@ -610,10 +710,13 @@
  * Entries must not be freed without first clearing out references
  * from struct connection objects.
  */
-struct gw_info *gateways = NULL;
+static struct gw_info *gateways = NULL;
 
-/* process TXT record of remote client to discover its Security Gatway.
- * Format of body (what we get): a.b.c.d kkk
+/* process TXT X-IPsec-Server record of remote client to discover its
+ * Security Gatway.
+ * Format of body (the part we get): iii kkk
+ * where iii is @FQDN or dotted-decimal IPv4 address or colon-hex IPv6 address
+ * and kkk is an optional RSA public signing key in base 64.
  * Side effect: result is added at front of gateways list.
  * NOTE: we've got to be very wary of anything we find -- bad guys
  * might have prepared it.
@@ -628,7 +731,7 @@
     u_char *p;
     err_t ugh;
 
-    memset(&gi, 0, sizeof(gi));
+    zero(&gi);
 
     gi.client_id = *id;	/* will need to unshare_id_content */
 
@@ -638,58 +741,24 @@
 
     p = str + rri->offset;
 
-    /* decode a.b.c.d (or IPv6 equivalent) */
-    {
-	u_char *e = p + strcspn(p, " \t");
-	u_char under;
-
-	if (p == e)
-	    return "TXT " our_TXT_attr_string " badly formed (no separator)";
+    /* decode iii */
 
-	under = *e;
-	*e = '\0';
-	ugh = tnatoaddr(p, e-p
-	    , strchr(p, ':') == NULL? AF_INET : AF_INET6
-	    , &gi.gw);
-	*e = under;
+    ugh = decode_iii(&p, id, &gi.gw_id);
 	if (ugh != NULL)
-	    return ugh;	/* ??? more context would be nice */
-
-	if (isanyaddr(&gi.gw))
-	    return "gateway address must not be 0.0.0.0 or 0::0";
-
-	DBG(DBG_CONTROL,
-	    {
-		char cidb[IDTOA_BUF];
-
-		idtoa(id, cidb, sizeof(cidb));
-		DBG_log("decoding TXT %s record for %s: server %s"
-		    , our_TXT_attr, cidb, ip_str(&gi.gw));
-	    });
+       return ugh;
 
-	p = e + strspn(e, " \t");
-    }
+    if (!id_is_ipaddr(&gi.gw_id))
+       return "IP address for security gateway not specified in TXT record";
 
-    /* decode key */
+    /* decode optional key */
 
-    if (*p == '@')
+    if (*p == '\0')
     {
-	/* kkk is @hhh form */
-	struct id hhh;	/* id from TXT record -- not necessarily the host */
-	const struct RSA_public_key *pk;
-
-	/* decode the @dns.  It is *very* convenient that the '@' is there.
-	 * ??? the name will be searched in our domains!
-	 *     What is the best cure?  Trailling "." screws up numeric form.
-	 */
-	ugh = atoid(p, &hhh);
-	if (ugh != NULL)
-	    return ugh;
-
-	/* look for a key for hhh.
+        /* kkk is missing: go for gateway's KEY record (Gateway id is iii).
 	 * Beware: this is recursive!
 	 */
-	pk = get_RSA_public_key(&hhh);
+	const struct RSA_public_key *pk = get_RSA_public_key(&gi.gw_id);
+
 	if (pk == NULL)
 	    return "no RSA public key found";
 
@@ -701,18 +770,17 @@
     else
     {
 	/* kkk is base 64 encoding of key */
-	passert(p - str >= 2);	/* must be room for "0s" prefix */
-	*--p = 's';	    /* add "0s" prefix */
-	*--p = '0';
-	ugh = atobytes(p, 0, kb, sizeof(kb), &kbc.len);
+        ugh = ttodata(p, 0, 64, kb, sizeof(kb), &kbc.len);
+
 	if (ugh != NULL)
-	    return ugh;	/* ??? more context would be nice */
+	  return builddiag("malformed key data: %s", ugh);
+
 	passert(kbc.len < sizeof(kb));
 
 	kbc.ptr = kb;
 	ugh = unpack_RSA_public_key(&gi.gw_key, &kbc);
 	if (ugh != NULL)
-	    return ugh;	/* ??? more context would be nice */
+	  return builddiag("invalid key data: %s", ugh);
     }
 
     /* we're home free!  Allocate everything and add to gateways list. */
@@ -726,7 +794,8 @@
 }
 
 static err_t
-process_dns_answer(const struct id *id, u_char ans[], int anslen, int type)
+process_dns_answer(const struct id *id, const struct id *sgw_id
+, u_char ans[], int anslen, int type)
 {
     int r;	/* all-purpose return value holder */
     u_int16_t c;	/* number of current RR in current answer section */
@@ -734,7 +803,7 @@
     pb_stream pbs;
     struct qr_header qr_header;
     chunk_t key;	/* info relevant to T_KEY */
-    struct txt_tbl txt_tbl;	/* info relevant to T_TXT */
+    struct txt_tbl txt_tbl;	/* info relevant to T_TXT X-IPsec-Server */
 
     setchunk(key, NULL, 0);	/* empty */
     txt_tbl.count = 0;	/* empty */
@@ -794,7 +863,7 @@
     {
 	struct qs_fixed qsf;
 
-	ugh = eat_name(&pbs);
+	ugh = eat_name_helpfully(&pbs, "Query Section");
 	if (ugh != NULL)
 	    return ugh;
 
@@ -819,7 +888,7 @@
 
 	/* ??? do we need to match the name? */
 
-	ugh = eat_name(&pbs);
+	ugh = eat_name_helpfully(&pbs, "Answer Section");
 	if (ugh != NULL)
 	    return ugh;
 
@@ -841,7 +910,7 @@
 		ugh = process_key_rr(pbs.cur, tail, &key);
 		break;
 	    case T_TXT:
-		ugh = accumulate_txt_rr(pbs.cur, tail, &txt_tbl);
+                ugh = accumulate_txt_rr(pbs.cur, tail, &txt_tbl, id, sgw_id);
 		break;
 	    default:
 		passert(FALSE);
@@ -859,7 +928,7 @@
 	struct rr_fixed rrf;
 	size_t tail;
 
-	ugh = eat_name(&pbs);
+	ugh = eat_name_helpfully(&pbs, "Authority Section");
 	if (ugh != NULL)
 	    return ugh;
 
@@ -883,7 +952,7 @@
 	struct rr_fixed rrf;
 	size_t tail;
 
-	ugh = eat_name(&pbs);
+	ugh = eat_name_helpfully(&pbs, "Additional Section");
 	if (ugh != NULL)
 	    return ugh;
 
@@ -919,6 +988,7 @@
 
 	/* Note: quality of rand() matters hardly at all in this case */
 	return process_ipsec_server_rr(id, &txt_tbl.rr[rand() % txt_tbl.count]);
+	break;
 
     default:
 	passert(FALSE);
@@ -926,11 +996,22 @@
     return NULL;
 }
 
-/* look up a TXT or KEY record
+/* Look up a TXT X-IPsec-Server or KEY record.
+ * Three kinds of queries are supported:
+ * For KEY record, the result is a new entry in the public key table.
+ * For TXT records, the result is a new gateway entry.
+ * If sgw_id is null, only pay attention to TXT records that specify an
+ * IP address for the gatway: we need this in the initiation case.
+ * If sgw_id is non-null, only pay attention to TXT records that specify
+ * this id as the security gatway; this is useful to the Responder
+ * for confirming claims of gateways.
  * Beware: this can be recursive.
  */
 static err_t
-do_dns_query(const struct id *id, int type, const char *typename)
+do_dns_query(const struct id *id       /* domain to query */
+, const struct id *sgw_id      /* if non-null, any accepted gw_info must match */
+, int type     /* T_TXT or T_KEY, selecting rr type of interest */
+, const char *typename)        /* string for type */
 {
     err_t ugh;
     u_char name_buf[NS_MAXDNAME + 1];
@@ -952,53 +1033,74 @@
 	 * That might be better, but older resolvers don't.
 	 * See resolver(3), if you have it.
 	 */
-	return hstrerror(h_errno);
+	return builddiag("failure querying DNS for %s of %s: %s"
+           , typename, name_buf, hstrerror(h_errno));
     }
 
     if (anslen > (int) sizeof(ans))
-	return "(internal error) answer too long for buffer";
+       return "(INTERNAL ERROR) answer too long for buffer";
+
+    ugh = process_dns_answer(id, sgw_id, ans, anslen, type);
+    if (ugh != NULL)
+       return builddiag("failure processing %s record of DNS answer for %s: %s"
+           , typename, name_buf, ugh);
 
-    return process_dns_answer(id, ans, anslen, type);
+    return NULL;
 }
 
-/* look up KEY record, if any, for a suitable RSA key */
+/* look up DNS KEY RR, if any, for id to find a suitable RSA key */
 err_t
 fetch_public_key(const struct id *id)
 {
-    return do_dns_query(id, T_KEY, "KEY");
+    return do_dns_query(id, (struct id *)NULL, T_KEY, "KEY");
 }
 
-/* look up TXT record, if any.
+/* look up TXT X-IPsec-Server record, if any.
  * Will tell us GW IP address and public RSA key.
- * On success, the result will be the first entry in the gateways list.
+ * On success, the result will be assigned to *gwp.
  * Note: the key is being ascribed to the gateway by the client.
  *   The gateway may not agree!  So we cannot trust it in other
  *   contexts.
  */
 err_t
-discover_gateway(const ip_address *peer_client)
+discover_gateway(const ip_address *peer_client
+, const struct id *putative_sgw
+, struct gw_info **gwp)
 {
     struct id id;
-    struct gw_info
-	**pp,
-	*p;
+    struct gw_info **pp
+       , *p;
+    err_t ugh = NULL;
 
-    memset(&id, 0, sizeof(id));
-    id.kind = aftoinfo(addrtypeof(peer_client))->id_addr;
-    id.ip_addr = *peer_client;
+    iptoid(peer_client, &id);
 
-    for (pp = &gateways; (p = *pp) != NULL; pp = &p->next)
+    for (pp = &gateways; ; pp = &p->next)
     {
-	if (same_id(&id, &p->client_id))
+       p = *pp;
+       if (p == NULL)
+       {
+           /* not in table: do a DNS query.
+            * On success, will leave result at front of gateways.
+            */
+           ugh = do_dns_query(&id, putative_sgw, T_TXT, "TXT");
+           break;
+       }
+       if (same_id(&id, &p->client_id)
+       && (putative_sgw == NULL? id_is_ipaddr(&p->gw_id) : same_id(putative_sgw, &p->gw_id)))
 	{
 	    /* We found one from a previous attempt.
-	     * Move it to front of gateways list; return.
+	     * Move it to front of gateways list.
 	     */
 	    *pp = p->next;
 	    p->next = gateways;
 	    gateways = p;
-	    return NULL;
+	    break;
 	}
     }
-    return do_dns_query(&id, T_TXT, "TXT");
+
+    /* if successful and requested, set *gwp from front of gateways */
+    if (ugh == NULL && gwp != NULL)
+       *gwp = gateways;
+
+    return ugh;
 }
diff -bruN freeswan-1.9.orig/pluto/dnskey.h freeswan-1.9/pluto/dnskey.h
--- freeswan-1.9.orig/pluto/dnskey.h	Sun Jan 28 16:03:03 2001
+++ freeswan-1.9/pluto/dnskey.h	Tue Jun  5 15:48:15 2001
@@ -11,7 +11,7 @@
  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  * for more details.
  *
- * RCSID $Id: dnskey.h,v 1.9 2001/01/28 21:03:03 dhr Exp $
+ * RCSID $Id: dnskey.h,v 1.12 2001/02/26 23:21:30 dhr Exp $
  */
 
 extern err_t fetch_public_key(const struct id *id);
@@ -22,13 +22,14 @@
 	, last_tried_time
 	, last_worked_time;
 #define NO_TIME ((time_t) -2)	/* time_t value meaning "not_yet" */
-    struct id client_id;	/* of peer */
-    ip_address gw;	/* peer */
+    struct id client_id;       /* id of client of peer */
+    struct id gw_id;   /* id of peer (if id_is_ipaddr, .ip_addr is address) */
     struct RSA_public_key gw_key;
     struct gw_info *next;
 };
 
-extern struct gw_info *gateways;	/* list of discovered gateways */
-
-/* find a new gateway; add it to front of list */
-extern err_t discover_gateway(const ip_address *peer_client);
+/* find a new gateway */
+extern err_t
+    discover_gateway(const ip_address *peer_client
+       , const struct id *putative_sgw
+       , struct gw_info **gwp);
diff -bruN freeswan-1.9.orig/pluto/dsa.c freeswan-1.9/pluto/dsa.c
--- freeswan-1.9.orig/pluto/dsa.c	Mon Nov  1 16:52:39 1999
+++ freeswan-1.9/pluto/dsa.c	Wed Dec 31 19:00:00 1969
@@ -1,476 +0,0 @@
-/* dsa.c  -  DSA signature scheme
- *	Copyright (C) 1998 Free Software Foundation, Inc.
- *
- * This file is part of GnuPG.
- *
- * GnuPG 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.
- *
- * GnuPG 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.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#ifdef PLUTO
-#include <gmp.h>
-#include <freeswan.h>
-#include "constants.h"
-#include "defs.h"
-#include "log.h"
-#include "rnd.h"
-#include "gcryptfix.h"
-#else /*! PLUTO */
-/* #include <config.h> */
-#endif /* !PLUTO */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#ifndef PLUTO
-/* #include <assert.h> */
-/* #include "util.h" */
-/* #include "mpi.h" */
-/* #include "cipher.h" */
-#endif
-
-#include "dsa.h"
-
-typedef struct {
-    MPI p;	    /* prime */
-    MPI q;	    /* group order */
-    MPI g;	    /* group generator */
-    MPI y;	    /* g^x mod p */
-} DSA_public_key;
-
-
-typedef struct {
-    MPI p;	    /* prime */
-    MPI q;	    /* group order */
-    MPI g;	    /* group generator */
-    MPI y;	    /* g^x mod p */
-    MPI x;	    /* secret exponent */
-} DSA_secret_key;
-
-
-static MPI gen_k( MPI q );
-static void test_keys( DSA_secret_key *sk, unsigned qbits );
-static int  check_secret_key( DSA_secret_key *sk );
-static void generate( DSA_secret_key *sk, unsigned nbits, MPI **ret_factors );
-static void sign(MPI r, MPI s, MPI input, DSA_secret_key *skey);
-static int  verify(MPI r, MPI s, MPI input, DSA_public_key *pkey);
-
-static void
-progress( int c )
-{
-    fputc( c, stderr );
-}
-
-
-/****************
- * Generate a random secret exponent k less than q
- */
-static MPI
-gen_k( MPI q )
-{
-    MPI k = mpi_alloc_secure( mpi_get_nlimbs(q) );
-    unsigned int nbits = mpi_get_nbits(q);
-    unsigned int nbytes = (nbits+7)/8;
-    char *rndbuf = NULL;
-
-    if( DBG_CIPHER )
-	log_debug("choosing a random k ");
-    for(;;) {
-	if( DBG_CIPHER )
-	    progress('.');
-
-	if( !rndbuf || nbits < 32 ) {
-	    m_free(rndbuf);
-	    rndbuf = get_random_bits( nbits, 1, 1 );
-	}
-	else { /* change only some of the higher bits */
-	    /* we could imporove this by directly requesting more memory
-	     * at the first call to get_random_bits() and use this the here
-	     * maybe it is easier to do this directly in random.c */
-	    char *pp = get_random_bits( 32, 1, 1 );
-	    memcpy( rndbuf,pp, 4 );
-	    m_free(pp);
-	}
-	mpi_set_buffer( k, rndbuf, nbytes, 0 );
-	if( mpi_test_bit( k, nbits-1 ) )
-	    mpi_set_highbit( k, nbits-1 );
-	else {
-	    mpi_set_highbit( k, nbits-1 );
-	    mpi_clear_bit( k, nbits-1 );
-	}
-
-	if( !(mpi_cmp( k, q ) < 0) ) {	/* check: k < q */
-	    if( DBG_CIPHER )
-		progress('+');
-	    continue; /* no  */
-	}
-	if( !(mpi_cmp_ui( k, 0 ) > 0) ) { /* check: k > 0 */
-	    if( DBG_CIPHER )
-		progress('-');
-	    continue; /* no */
-	}
-	break;	/* okay */
-    }
-    m_free(rndbuf);
-    if( DBG_CIPHER )
-	progress('\n');
-
-    return k;
-}
-
-
-static void
-test_keys( DSA_secret_key *sk, unsigned qbits )
-{
-    DSA_public_key pk;
-    MPI test = mpi_alloc( qbits / BITS_PER_MPI_LIMB );
-    MPI out1_a = mpi_alloc( qbits / BITS_PER_MPI_LIMB );
-    MPI out1_b = mpi_alloc( qbits / BITS_PER_MPI_LIMB );
-
-    pk.p = sk->p;
-    pk.q = sk->q;
-    pk.g = sk->g;
-    pk.y = sk->y;
-    /*mpi_set_bytes( test, qbits, get_random_byte, 0 );*/
-    {	char *p = get_random_bits( qbits, 0, 0 );
-	mpi_set_buffer( test, p, (qbits+7)/8, 0 );
-	m_free(p);
-    }
-
-    sign( out1_a, out1_b, test, sk );
-    if( !verify( out1_a, out1_b, test, &pk ) )
-	log_fatal("DSA:: sign, verify failed\n");
-
-    mpi_free( test );
-    mpi_free( out1_a );
-    mpi_free( out1_b );
-}
-
-
-
-/****************
- * Generate a DSA key pair with a key of size NBITS
- * Returns: 2 structures filled with all needed values
- *	    and an array with the n-1 factors of (p-1)
- */
-static void
-generate( DSA_secret_key *sk, unsigned nbits, MPI **ret_factors )
-{
-    MPI p;    /* the prime */
-    MPI q;    /* the 160 bit prime factor */
-    MPI g;    /* the generator */
-    MPI y;    /* g^x mod p */
-    MPI x;    /* the secret exponent */
-    MPI h, e;  /* helper */
-    unsigned qbits;
-    byte *rndbuf;
-
-    assert( nbits >= 512 && nbits <= 1024 );
-
-    qbits = 160;
-    p = generate_elg_prime( 1, nbits, qbits, NULL, ret_factors );
-    /* get q out of factors */
-    q = mpi_copy((*ret_factors)[0]);
-    if( mpi_get_nbits(q) != qbits )
-	BUG();
-
-    /* find a generator g (h and e are helpers)*/
-    /* e = (p-1)/q */
-    e = mpi_alloc( mpi_get_nlimbs(p) );
-    mpi_sub_ui( e, p, 1 );
-    mpi_fdiv_q( e, e, q );
-    g = mpi_alloc( mpi_get_nlimbs(p) );
-    h = mpi_alloc_set_ui( 1 ); /* we start with 2 */
-    do {
-	mpi_add_ui( h, h, 1 );
-	/* g = h^e mod p */
-	mpi_powm( g, h, e, p );
-    } while( !mpi_cmp_ui( g, 1 ) );  /* continue until g != 1 */
-
-    /* select a random number which has these properties:
-     *	 0 < x < q-1
-     * This must be a very good random number because this
-     * is the secret part. */
-    if( DBG_CIPHER )
-	log_debug("choosing a random x ");
-    assert( qbits >= 160 );
-    x = mpi_alloc_secure( mpi_get_nlimbs(q) );
-    mpi_sub_ui( h, q, 1 );  /* put q-1 into h */
-    rndbuf = NULL;
-    do {
-	if( DBG_CIPHER )
-	    progress('.');
-	if( !rndbuf )
-	    rndbuf = get_random_bits( qbits, 2, 1 );
-	else { /* change only some of the higher bits (= 2 bytes)*/
-	    char *r = get_random_bits( 16, 2, 1 );
-	    memcpy(rndbuf, r, 16/8 );
-	    m_free(r);
-	}
-	mpi_set_buffer( x, rndbuf, (qbits+7)/8, 0 );
-	mpi_clear_highbit( x, qbits+1 );
-    } while( !( mpi_cmp_ui( x, 0 )>0 && mpi_cmp( x, h )<0 ) );
-    m_free(rndbuf);
-    mpi_free( e );
-    mpi_free( h );
-
-    /* y = g^x mod p */
-    y = mpi_alloc( mpi_get_nlimbs(p) );
-    mpi_powm( y, g, x, p );
-
-    if( DBG_CIPHER ) {
-	progress('\n');
-	log_mpidump("dsa  p= ", p );
-	log_mpidump("dsa  q= ", q );
-	log_mpidump("dsa  g= ", g );
-	log_mpidump("dsa  y= ", y );
-	log_mpidump("dsa  x= ", x );
-    }
-
-    /* copy the stuff to the key structures */
-    sk->p = p;
-    sk->q = q;
-    sk->g = g;
-    sk->y = y;
-    sk->x = x;
-
-    /* now we can test our keys (this should never fail!) */
-    test_keys( sk, qbits );
-}
-
-
-
-/****************
- * Test whether the secret key is valid.
- * Returns: if this is a valid key.
- */
-static int
-check_secret_key( DSA_secret_key *sk )
-{
-    int rc;
-    MPI y = mpi_alloc( mpi_get_nlimbs(sk->y) );
-
-    mpi_powm( y, sk->g, sk->x, sk->p );
-    rc = !mpi_cmp( y, sk->y );
-    mpi_free( y );
-    return rc;
-}
-
-
-
-/****************
- * Make a DSA signature from HASH and put it into r and s.
- */
-
-static void
-sign(MPI r, MPI s, MPI hash, DSA_secret_key *skey )
-{
-    MPI k;
-    MPI kinv;
-    MPI tmp;
-
-    /* select a random k with 0 < k < q */
-    k = gen_k( skey->q );
-
-    /* r = (a^k mod p) mod q */
-    mpi_powm( r, skey->g, k, skey->p );
-    mpi_fdiv_r( r, r, skey->q );
-
-    /* kinv = k^(-1) mod q */
-    kinv = mpi_alloc( mpi_get_nlimbs(k) );
-    mpi_invm(kinv, k, skey->q );
-
-    /* s = (kinv * ( hash + x * r)) mod q */
-    tmp = mpi_alloc( mpi_get_nlimbs(skey->p) );
-    mpi_mul( tmp, skey->x, r );
-    mpi_add( tmp, tmp, hash );
-    mpi_mulm( s , kinv, tmp, skey->q );
-
-    mpi_free(k);
-    mpi_free(kinv);
-    mpi_free(tmp);
-}
-
-
-/****************
- * Returns true if the signature composed from R and S is valid.
- */
-static int
-verify(MPI r, MPI s, MPI hash, DSA_public_key *pkey )
-{
-    int rc;
-    MPI w, u1, u2, v;
-    MPI base[3];
-    MPI exp[3];
-
-
-    if( !(mpi_cmp_ui( r, 0 ) > 0 && mpi_cmp( r, pkey->q ) < 0) )
-	return 0; /* assertion	0 < r < q  failed */
-    if( !(mpi_cmp_ui( s, 0 ) > 0 && mpi_cmp( s, pkey->q ) < 0) )
-	return 0; /* assertion	0 < s < q  failed */
-
-    w  = mpi_alloc( mpi_get_nlimbs(pkey->q) );
-    u1 = mpi_alloc( mpi_get_nlimbs(pkey->q) );
-    u2 = mpi_alloc( mpi_get_nlimbs(pkey->q) );
-    v  = mpi_alloc( mpi_get_nlimbs(pkey->p) );
-
-    /* w = s^(-1) mod q */
-    mpi_invm( w, s, pkey->q );
-
-    /* u1 = (hash * w) mod q */
-    mpi_mulm( u1, hash, w, pkey->q );
-
-    /* u2 = r * w mod q  */
-    mpi_mulm( u2, r, w, pkey->q );
-
-    /* v =  g^u1 * y^u2 mod p mod q */
-    base[0] = pkey->g; exp[0] = u1;
-    base[1] = pkey->y; exp[1] = u2;
-    base[2] = NULL;    exp[2] = NULL;
-    mpi_mulpowm( v, base, exp, pkey->p );
-    mpi_fdiv_r( v, v, pkey->q );
-
-    rc = !mpi_cmp( v, r );
-
-    mpi_free(w);
-    mpi_free(u1);
-    mpi_free(u2);
-    mpi_free(v);
-    return rc;
-}
-
-
-/*********************************************
- **************  interface  ******************
- *********************************************/
-
-int
-dsa_generate( int algo, unsigned nbits, MPI *skey, MPI **retfactors )
-{
-    DSA_secret_key sk;
-
-    if( algo != PUBKEY_ALGO_DSA )
-	return G10ERR_PUBKEY_ALGO;
-
-    generate( &sk, nbits, retfactors );
-    skey[0] = sk.p;
-    skey[1] = sk.q;
-    skey[2] = sk.g;
-    skey[3] = sk.y;
-    skey[4] = sk.x;
-    return 0;
-}
-
-
-int
-dsa_check_secret_key( int algo, MPI *skey )
-{
-    DSA_secret_key sk;
-
-    if( algo != PUBKEY_ALGO_DSA )
-	return G10ERR_PUBKEY_ALGO;
-    if( !skey[0] || !skey[1] || !skey[2] || !skey[3] || !skey[4] )
-	return G10ERR_BAD_MPI;
-
-    sk.p = skey[0];
-    sk.q = skey[1];
-    sk.g = skey[2];
-    sk.y = skey[3];
-    sk.x = skey[4];
-    if( !check_secret_key( &sk ) )
-	return G10ERR_BAD_SECKEY;
-
-    return 0;
-}
-
-
-
-int
-dsa_sign( int algo, MPI *resarr, MPI data, MPI *skey )
-{
-    DSA_secret_key sk;
-
-    if( algo != PUBKEY_ALGO_DSA )
-	return G10ERR_PUBKEY_ALGO;
-    if( !data || !skey[0] || !skey[1] || !skey[2] || !skey[3] || !skey[4] )
-	return G10ERR_BAD_MPI;
-
-    sk.p = skey[0];
-    sk.q = skey[1];
-    sk.g = skey[2];
-    sk.y = skey[3];
-    sk.x = skey[4];
-    resarr[0] = mpi_alloc( mpi_get_nlimbs( sk.p ) );
-    resarr[1] = mpi_alloc( mpi_get_nlimbs( sk.p ) );
-    sign( resarr[0], resarr[1], data, &sk );
-    return 0;
-}
-
-int
-dsa_verify( int algo, MPI hash, MPI *data, MPI *pkey,
-		    int (*cmp)(void *, MPI) UNUSED, void *opaquev UNUSED)
-{
-    DSA_public_key pk;
-
-    if( algo != PUBKEY_ALGO_DSA )
-	return G10ERR_PUBKEY_ALGO;
-    if( !data[0] || !data[1] || !hash
-	|| !pkey[0] || !pkey[1] || !pkey[2] || !pkey[3] )
-	return G10ERR_BAD_MPI;
-
-    pk.p = pkey[0];
-    pk.q = pkey[1];
-    pk.g = pkey[2];
-    pk.y = pkey[3];
-    if( !verify( data[0], data[1], hash, &pk ) )
-	return G10ERR_BAD_SIGN;
-    return 0;
-}
-
-
-
-unsigned
-dsa_get_nbits( int algo, MPI *pkey )
-{
-    if( algo != PUBKEY_ALGO_DSA )
-	return 0;
-    return mpi_get_nbits( pkey[0] );
-}
-
-
-/****************
- * Return some information about the algorithm.  We need algo here to
- * distinguish different flavors of the algorithm.
- * Returns: A pointer to string describing the algorithm or NULL if
- *	    the ALGO is invalid.
- * Usage: Bit 0 set : allows signing
- *	      1 set : allows encryption
- */
-const char *
-dsa_get_info( int algo, int *npkey, int *nskey, int *nenc, int *nsig,
-							 int *use )
-{
-    *npkey = 4;
-    *nskey = 5;
-    *nenc = 0;
-    *nsig = 2;
-
-    switch( algo ) {
-      case PUBKEY_ALGO_DSA:   *use = PUBKEY_USAGE_SIG; return "DSA";
-      default: *use = 0; return NULL;
-    }
-}
-
-
diff -bruN freeswan-1.9.orig/pluto/dsa.h freeswan-1.9/pluto/dsa.h
--- freeswan-1.9.orig/pluto/dsa.h	Mon Nov  1 16:48:08 1999
+++ freeswan-1.9/pluto/dsa.h	Wed Dec 31 19:00:00 1969
@@ -1,32 +0,0 @@
-/* dsa.h  -  DSA signature scheme
- *	Copyright (C) 1998 Free Software Foundation, Inc.
- *
- * This file is part of GnuPG.
- *
- * GnuPG 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.
- *
- * GnuPG 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.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-#ifndef G10_DSA_H
-#define G10_DSA_H
-
-int dsa_generate( int algo, unsigned nbits, MPI *skey, MPI **retfactors );
-int dsa_check_secret_key( int algo, MPI *skey );
-int dsa_sign( int algo, MPI *resarr, MPI data, MPI *skey );
-int dsa_verify( int algo, MPI hash, MPI *data, MPI *pkey,
-		    int (*cmp)(void *, MPI), void *opaquev );
-unsigned dsa_get_nbits( int algo, MPI *pkey );
-const char *dsa_get_info( int algo, int *npkey, int *nskey,
-				    int *nenc, int *nsig, int *use );
-
-#endif /*G10_DSA_H*/
diff -bruN freeswan-1.9.orig/pluto/g10_dsa.c freeswan-1.9/pluto/g10_dsa.c
--- freeswan-1.9.orig/pluto/g10_dsa.c	Wed Dec 31 19:00:00 1969
+++ freeswan-1.9/pluto/g10_dsa.c	Wed May 16 10:57:20 2001
@@ -0,0 +1,476 @@
+/* g10_dsa.c  -  DSA signature scheme
+ *	Copyright (C) 1998 Free Software Foundation, Inc.
+ *
+ * This file is part of GnuPG.
+ *
+ * GnuPG 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.
+ *
+ * GnuPG 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#ifdef PLUTO
+#include <gmp.h>
+#include <freeswan.h>
+#include "constants.h"
+#include "defs.h"
+#include "log.h"
+#include "rnd.h"
+#include "gcryptfix.h"
+#else /*! PLUTO */
+/* #include <config.h> */
+#endif /* !PLUTO */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifndef PLUTO
+/* #include <assert.h> */
+/* #include "util.h" */
+/* #include "mpi.h" */
+/* #include "cipher.h" */
+#endif
+
+#include "g10_dsa.h"
+
+typedef struct {
+    MPI p;	    /* prime */
+    MPI q;	    /* group order */
+    MPI g;	    /* group generator */
+    MPI y;	    /* g^x mod p */
+} DSA_public_key;
+
+
+typedef struct {
+    MPI p;	    /* prime */
+    MPI q;	    /* group order */
+    MPI g;	    /* group generator */
+    MPI y;	    /* g^x mod p */
+    MPI x;	    /* secret exponent */
+} DSA_secret_key;
+
+
+static MPI gen_k( MPI q );
+static void test_keys( DSA_secret_key *sk, unsigned qbits );
+static int  check_secret_key( DSA_secret_key *sk );
+static void generate( DSA_secret_key *sk, unsigned nbits, MPI **ret_factors );
+static void sign(MPI r, MPI s, MPI input, DSA_secret_key *skey);
+static int  verify(MPI r, MPI s, MPI input, DSA_public_key *pkey);
+
+static void
+progress( int c )
+{
+    fputc( c, stderr );
+}
+
+
+/****************
+ * Generate a random secret exponent k less than q
+ */
+static MPI
+gen_k( MPI q )
+{
+    MPI k = mpi_alloc_secure( mpi_get_nlimbs(q) );
+    unsigned int nbits = mpi_get_nbits(q);
+    unsigned int nbytes = (nbits+7)/8;
+    char *rndbuf = NULL;
+
+    if( DBG_CIPHER )
+	log_debug("choosing a random k ");
+    for(;;) {
+	if( DBG_CIPHER )
+	    progress('.');
+
+	if( !rndbuf || nbits < 32 ) {
+	    m_free(rndbuf);
+	    rndbuf = get_random_bits( nbits, 1, 1 );
+	}
+	else { /* change only some of the higher bits */
+	    /* we could imporove this by directly requesting more memory
+	     * at the first call to get_random_bits() and use this the here
+	     * maybe it is easier to do this directly in random.c */
+	    char *pp = get_random_bits( 32, 1, 1 );
+	    memcpy( rndbuf,pp, 4 );
+	    m_free(pp);
+	}
+	mpi_set_buffer( k, rndbuf, nbytes, 0 );
+	if( mpi_test_bit( k, nbits-1 ) )
+	    mpi_set_highbit( k, nbits-1 );
+	else {
+	    mpi_set_highbit( k, nbits-1 );
+	    mpi_clear_bit( k, nbits-1 );
+	}
+
+	if( !(mpi_cmp( k, q ) < 0) ) {	/* check: k < q */
+	    if( DBG_CIPHER )
+		progress('+');
+	    continue; /* no  */
+	}
+	if( !(mpi_cmp_ui( k, 0 ) > 0) ) { /* check: k > 0 */
+	    if( DBG_CIPHER )
+		progress('-');
+	    continue; /* no */
+	}
+	break;	/* okay */
+    }
+    m_free(rndbuf);
+    if( DBG_CIPHER )
+	progress('\n');
+
+    return k;
+}
+
+
+static void
+test_keys( DSA_secret_key *sk, unsigned qbits )
+{
+    DSA_public_key pk;
+    MPI test = mpi_alloc( qbits / BITS_PER_MPI_LIMB );
+    MPI out1_a = mpi_alloc( qbits / BITS_PER_MPI_LIMB );
+    MPI out1_b = mpi_alloc( qbits / BITS_PER_MPI_LIMB );
+
+    pk.p = sk->p;
+    pk.q = sk->q;
+    pk.g = sk->g;
+    pk.y = sk->y;
+    /*mpi_set_bytes( test, qbits, get_random_byte, 0 );*/
+    {	char *p = get_random_bits( qbits, 0, 0 );
+	mpi_set_buffer( test, p, (qbits+7)/8, 0 );
+	m_free(p);
+    }
+
+    sign( out1_a, out1_b, test, sk );
+    if( !verify( out1_a, out1_b, test, &pk ) )
+	log_fatal("DSA:: sign, verify failed\n");
+
+    mpi_free( test );
+    mpi_free( out1_a );
+    mpi_free( out1_b );
+}
+
+
+
+/****************
+ * Generate a DSA key pair with a key of size NBITS
+ * Returns: 2 structures filled with all needed values
+ *	    and an array with the n-1 factors of (p-1)
+ */
+static void
+generate( DSA_secret_key *sk, unsigned nbits, MPI **ret_factors )
+{
+    MPI p;    /* the prime */
+    MPI q;    /* the 160 bit prime factor */
+    MPI g;    /* the generator */
+    MPI y;    /* g^x mod p */
+    MPI x;    /* the secret exponent */
+    MPI h, e;  /* helper */
+    unsigned qbits;
+    byte *rndbuf;
+
+    assert( nbits >= 512 && nbits <= 1024 );
+
+    qbits = 160;
+    p = generate_elg_prime( 1, nbits, qbits, NULL, ret_factors );
+    /* get q out of factors */
+    q = mpi_copy((*ret_factors)[0]);
+    if( mpi_get_nbits(q) != qbits )
+	BUG();
+
+    /* find a generator g (h and e are helpers)*/
+    /* e = (p-1)/q */
+    e = mpi_alloc( mpi_get_nlimbs(p) );
+    mpi_sub_ui( e, p, 1 );
+    mpi_fdiv_q( e, e, q );
+    g = mpi_alloc( mpi_get_nlimbs(p) );
+    h = mpi_alloc_set_ui( 1 ); /* we start with 2 */
+    do {
+	mpi_add_ui( h, h, 1 );
+	/* g = h^e mod p */
+	mpi_powm( g, h, e, p );
+    } while( !mpi_cmp_ui( g, 1 ) );  /* continue until g != 1 */
+
+    /* select a random number which has these properties:
+     *	 0 < x < q-1
+     * This must be a very good random number because this
+     * is the secret part. */
+    if( DBG_CIPHER )
+	log_debug("choosing a random x ");
+    assert( qbits >= 160 );
+    x = mpi_alloc_secure( mpi_get_nlimbs(q) );
+    mpi_sub_ui( h, q, 1 );  /* put q-1 into h */
+    rndbuf = NULL;
+    do {
+	if( DBG_CIPHER )
+	    progress('.');
+	if( !rndbuf )
+	    rndbuf = get_random_bits( qbits, 2, 1 );
+	else { /* change only some of the higher bits (= 2 bytes)*/
+	    char *r = get_random_bits( 16, 2, 1 );
+	    memcpy(rndbuf, r, 16/8 );
+	    m_free(r);
+	}
+	mpi_set_buffer( x, rndbuf, (qbits+7)/8, 0 );
+	mpi_clear_highbit( x, qbits+1 );
+    } while( !( mpi_cmp_ui( x, 0 )>0 && mpi_cmp( x, h )<0 ) );
+    m_free(rndbuf);
+    mpi_free( e );
+    mpi_free( h );
+
+    /* y = g^x mod p */
+    y = mpi_alloc( mpi_get_nlimbs(p) );
+    mpi_powm( y, g, x, p );
+
+    if( DBG_CIPHER ) {
+	progress('\n');
+	log_mpidump("dsa  p= ", p );
+	log_mpidump("dsa  q= ", q );
+	log_mpidump("dsa  g= ", g );
+	log_mpidump("dsa  y= ", y );
+	log_mpidump("dsa  x= ", x );
+    }
+
+    /* copy the stuff to the key structures */
+    sk->p = p;
+    sk->q = q;
+    sk->g = g;
+    sk->y = y;
+    sk->x = x;
+
+    /* now we can test our keys (this should never fail!) */
+    test_keys( sk, qbits );
+}
+
+
+
+/****************
+ * Test whether the secret key is valid.
+ * Returns: if this is a valid key.
+ */
+static int
+check_secret_key( DSA_secret_key *sk )
+{
+    int rc;
+    MPI y = mpi_alloc( mpi_get_nlimbs(sk->y) );
+
+    mpi_powm( y, sk->g, sk->x, sk->p );
+    rc = !mpi_cmp( y, sk->y );
+    mpi_free( y );
+    return rc;
+}
+
+
+
+/****************
+ * Make a DSA signature from HASH and put it into r and s.
+ */
+
+static void
+sign(MPI r, MPI s, MPI hash, DSA_secret_key *skey )
+{
+    MPI k;
+    MPI kinv;
+    MPI tmp;
+
+    /* select a random k with 0 < k < q */
+    k = gen_k( skey->q );
+
+    /* r = (a^k mod p) mod q */
+    mpi_powm( r, skey->g, k, skey->p );
+    mpi_fdiv_r( r, r, skey->q );
+
+    /* kinv = k^(-1) mod q */
+    kinv = mpi_alloc( mpi_get_nlimbs(k) );
+    mpi_invm(kinv, k, skey->q );
+
+    /* s = (kinv * ( hash + x * r)) mod q */
+    tmp = mpi_alloc( mpi_get_nlimbs(skey->p) );
+    mpi_mul( tmp, skey->x, r );
+    mpi_add( tmp, tmp, hash );
+    mpi_mulm( s , kinv, tmp, skey->q );
+
+    mpi_free(k);
+    mpi_free(kinv);
+    mpi_free(tmp);
+}
+
+
+/****************
+ * Returns true if the signature composed from R and S is valid.
+ */
+static int
+verify(MPI r, MPI s, MPI hash, DSA_public_key *pkey )
+{
+    int rc;
+    MPI w, u1, u2, v;
+    MPI base[3];
+    MPI exp[3];
+
+
+    if( !(mpi_cmp_ui( r, 0 ) > 0 && mpi_cmp( r, pkey->q ) < 0) )
+	return 0; /* assertion	0 < r < q  failed */
+    if( !(mpi_cmp_ui( s, 0 ) > 0 && mpi_cmp( s, pkey->q ) < 0) )
+	return 0; /* assertion	0 < s < q  failed */
+
+    w  = mpi_alloc( mpi_get_nlimbs(pkey->q) );
+    u1 = mpi_alloc( mpi_get_nlimbs(pkey->q) );
+    u2 = mpi_alloc( mpi_get_nlimbs(pkey->q) );
+    v  = mpi_alloc( mpi_get_nlimbs(pkey->p) );
+
+    /* w = s^(-1) mod q */
+    mpi_invm( w, s, pkey->q );
+
+    /* u1 = (hash * w) mod q */
+    mpi_mulm( u1, hash, w, pkey->q );
+
+    /* u2 = r * w mod q  */
+    mpi_mulm( u2, r, w, pkey->q );
+
+    /* v =  g^u1 * y^u2 mod p mod q */
+    base[0] = pkey->g; exp[0] = u1;
+    base[1] = pkey->y; exp[1] = u2;
+    base[2] = NULL;    exp[2] = NULL;
+    mpi_mulpowm( v, base, exp, pkey->p );
+    mpi_fdiv_r( v, v, pkey->q );
+
+    rc = !mpi_cmp( v, r );
+
+    mpi_free(w);
+    mpi_free(u1);
+    mpi_free(u2);
+    mpi_free(v);
+    return rc;
+}
+
+
+/*********************************************
+ **************  interface  ******************
+ *********************************************/
+
+int
+dsa_generate( int algo, unsigned nbits, MPI *skey, MPI **retfactors )
+{
+    DSA_secret_key sk;
+
+    if( algo != PUBKEY_ALGO_DSA )
+	return G10ERR_PUBKEY_ALGO;
+
+    generate( &sk, nbits, retfactors );
+    skey[0] = sk.p;
+    skey[1] = sk.q;
+    skey[2] = sk.g;
+    skey[3] = sk.y;
+    skey[4] = sk.x;
+    return 0;
+}
+
+
+int
+dsa_check_secret_key( int algo, MPI *skey )
+{
+    DSA_secret_key sk;
+
+    if( algo != PUBKEY_ALGO_DSA )
+	return G10ERR_PUBKEY_ALGO;
+    if( !skey[0] || !skey[1] || !skey[2] || !skey[3] || !skey[4] )
+	return G10ERR_BAD_MPI;
+
+    sk.p = skey[0];
+    sk.q = skey[1];
+    sk.g = skey[2];
+    sk.y = skey[3];
+    sk.x = skey[4];
+    if( !check_secret_key( &sk ) )
+	return G10ERR_BAD_SECKEY;
+
+    return 0;
+}
+
+
+
+int
+dsa_sign( int algo, MPI *resarr, MPI data, MPI *skey )
+{
+    DSA_secret_key sk;
+
+    if( algo != PUBKEY_ALGO_DSA )
+	return G10ERR_PUBKEY_ALGO;
+    if( !data || !skey[0] || !skey[1] || !skey[2] || !skey[3] || !skey[4] )
+	return G10ERR_BAD_MPI;
+
+    sk.p = skey[0];
+    sk.q = skey[1];
+    sk.g = skey[2];
+    sk.y = skey[3];
+    sk.x = skey[4];
+    resarr[0] = mpi_alloc( mpi_get_nlimbs( sk.p ) );
+    resarr[1] = mpi_alloc( mpi_get_nlimbs( sk.p ) );
+    sign( resarr[0], resarr[1], data, &sk );
+    return 0;
+}
+
+int
+dsa_verify( int algo, MPI hash, MPI *data, MPI *pkey,
+		    int (*cmp)(void *, MPI) UNUSED, void *opaquev UNUSED)
+{
+    DSA_public_key pk;
+
+    if( algo != PUBKEY_ALGO_DSA )
+	return G10ERR_PUBKEY_ALGO;
+    if( !data[0] || !data[1] || !hash
+	|| !pkey[0] || !pkey[1] || !pkey[2] || !pkey[3] )
+	return G10ERR_BAD_MPI;
+
+    pk.p = pkey[0];
+    pk.q = pkey[1];
+    pk.g = pkey[2];
+    pk.y = pkey[3];
+    if( !verify( data[0], data[1], hash, &pk ) )
+	return G10ERR_BAD_SIGN;
+    return 0;
+}
+
+
+
+unsigned
+dsa_get_nbits( int algo, MPI *pkey )
+{
+    if( algo != PUBKEY_ALGO_DSA )
+	return 0;
+    return mpi_get_nbits( pkey[0] );
+}
+
+
+/****************
+ * Return some information about the algorithm.  We need algo here to
+ * distinguish different flavors of the algorithm.
+ * Returns: A pointer to string describing the algorithm or NULL if
+ *	    the ALGO is invalid.
+ * Usage: Bit 0 set : allows signing
+ *	      1 set : allows encryption
+ */
+const char *
+dsa_get_info( int algo, int *npkey, int *nskey, int *nenc, int *nsig,
+							 int *use )
+{
+    *npkey = 4;
+    *nskey = 5;
+    *nenc = 0;
+    *nsig = 2;
+
+    switch( algo ) {
+      case PUBKEY_ALGO_DSA:   *use = PUBKEY_USAGE_SIG; return "DSA";
+      default: *use = 0; return NULL;
+    }
+}
+
+
diff -bruN freeswan-1.9.orig/pluto/g10_dsa.h freeswan-1.9/pluto/g10_dsa.h
--- freeswan-1.9.orig/pluto/g10_dsa.h	Wed Dec 31 19:00:00 1969
+++ freeswan-1.9/pluto/g10_dsa.h	Wed May 16 10:57:20 2001
@@ -0,0 +1,32 @@
+/* dsa.h  -  DSA signature scheme
+ *	Copyright (C) 1998 Free Software Foundation, Inc.
+ *
+ * This file is part of GnuPG.
+ *
+ * GnuPG 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.
+ *
+ * GnuPG 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+#ifndef G10_DSA_H
+#define G10_DSA_H
+
+int dsa_generate( int algo, unsigned nbits, MPI *skey, MPI **retfactors );
+int dsa_check_secret_key( int algo, MPI *skey );
+int dsa_sign( int algo, MPI *resarr, MPI data, MPI *skey );
+int dsa_verify( int algo, MPI hash, MPI *data, MPI *pkey,
+		    int (*cmp)(void *, MPI), void *opaquev );
+unsigned dsa_get_nbits( int algo, MPI *pkey );
+const char *dsa_get_info( int algo, int *npkey, int *nskey,
+				    int *nenc, int *nsig, int *use );
+
+#endif /*G10_DSA_H*/
diff -bruN freeswan-1.9.orig/pluto/id.c freeswan-1.9/pluto/id.c
--- freeswan-1.9.orig/pluto/id.c	Wed Oct  4 20:12:10 2000
+++ freeswan-1.9/pluto/id.c	Wed Jun  6 16:40:59 2001
@@ -11,36 +11,45 @@
  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  * for more details.
  *
- * RCSID $Id: id.c,v 1.11 2000/10/05 00:12:10 dhr Exp $
+ * RCSID $Id: id.c,v 1.15 2001/04/12 23:34:14 dhr Exp $
  */
 
 #include <stdlib.h>
 #include <string.h>
+#include <ctype.h>
 #include <sys/socket.h>
 #include <netinet/in.h>
 #include <arpa/inet.h>
 
+#ifdef OPENSSL
+#include <openssl/x509.h>	/* needed by DER handling */
+#endif
+
 #include <freeswan.h>
 
 #include "constants.h"
 #include "defs.h"
 #include "id.h"
+#include "log.h"
 #include "connections.h"	/* needs id.h */
 #include "packet.h"
 
 const struct id empty_id;	/* all zeros and NULLs */
 
-/* convert textual form of id into a (temporary) struct id */
-
+/* Convert textual form of id into a (temporary) struct id.
+ * Note that if the id is to be kept, unshare_id_content will be necessary.
+ */
 err_t
 atoid(char *src, struct id *id)
 {
     err_t ugh = NULL;
+#ifdef OPENSSL
+    char *nptr, *kptr;
+    char s[4];
+    u_int i;
+#endif
 
-    memset(id, 0, sizeof(*id));
-    id->name.ptr = NULL;
-    id->next = NULL;
-
+    *id = empty_id;
     if (strchr(src, '@') == NULL)
     {
 	/* !!! this test is not sufficient for distinguishing address families.
@@ -56,11 +65,70 @@
     {
 	if (*src == '@')
 	{
+#ifdef OPENSSL
+          /* if there is a second specifier (#) on the line
+           * we interprete this as ID_KEY_ID
+           */
+          if (*(src+1) == '#')
+          {
+            id->key_id.ptr = NULL;
+
+            id->kind = ID_KEY_ID;
+            id->name.ptr = src+2;
+            id->key_id.ptr = alloc_bytes(strlen(id->name.ptr)/2, "keyid-ptr");
+            id->key_id.len = strlen(id->name.ptr)/2;
+            nptr = id->name.ptr;
+            kptr = id->key_id.ptr;
+
+            for (i=0; i<  strlen(id->name.ptr)/2; i++, kptr++)
+            {
+              snprintf(s, 3, "%s", nptr);
+              *kptr = strtol(s, NULL, 16);
+              nptr+=2;
+            }
+            DBG(DBG_PARSING,
+            DBG_dump("Key-ID: ", id->key_id.ptr, id->key_id.len);
+            );
+          }
+          else if (*(src+1) == '~')
+          {
+            /* if there is a second specifier (~) on the line
+             * we interprete this as
+             *   ID_DER_ASN1_DN -> Distinguished Name
+             * in ASN1 (Subject-Field in X.509)
+             */
+            id->kind = ID_DER_ASN1_DN;
+            id->name.ptr = src+2;
+            id->der_asn1_dn.ptr = alloc_bytes(strlen(id->name.ptr)/2, "der_asn1_dn-ptr");
+            id->der_asn1_dn.len = strlen(id->name.ptr)/2;
+            nptr = id->name.ptr;
+            kptr = id->der_asn1_dn.ptr;
+
+            for (i=0; i<  strlen(id->name.ptr)/2; i++, kptr++)
+            {
+              snprintf(s, 3, "%s", nptr);
+              *kptr = strtol(s, NULL, 16);
+              nptr+=2;
+            }
+
+            DBG(DBG_PARSING,
+            DBG_dump("DER ASN1 DN: ", id->der_asn1_dn.ptr,
+              id->der_asn1_dn.len);
+            );
+
+            /* Check DN */
+            ugh = check_der_asn1_dn(id);
+
+          }
+          else
+          {
 	    id->kind = ID_FQDN;
 	    id->name.ptr = src+1;	/* discard @ */
 	}
+	}
 	else
 	{
+#endif /* OPENSSL */
 	    /* We leave in @, as per DOI 4.6.2.4
 	     * (but DNS wants . instead).
 	     */
@@ -72,39 +140,75 @@
     return ugh;
 }
 
+void
+iptoid(const ip_address *ip, struct id *id)
+{
+    *id = empty_id;
+
+    switch (addrtypeof(ip))
+    {
+    case AF_INET:
+	id->kind = ID_IPV4_ADDR;
+	break;
+    case AF_INET6:
+	id->kind = ID_IPV6_ADDR;
+	break;
+    default:
+	passert(FALSE);
+    }
+    id->ip_addr = *ip;
+}
+
 int
 idtoa(const struct id *id, char *dst, size_t dstlen)
 {
+    int n;
+
     switch (id->kind)
     {
     case ID_NONE:
-	return snprintf(dst, dstlen, "(none)");
+       n = snprintf(dst, dstlen, "(none)");
+       break;
     case ID_IPV4_ADDR:
     case ID_IPV6_ADDR:
-	return (int)addrtot(&id->ip_addr, 0, dst, dstlen) - 1;
+       n = (int)addrtot(&id->ip_addr, 0, dst, dstlen) - 1;
+       break;
     case ID_FQDN:
-	return snprintf(dst, dstlen, "@%.*s", (int)id->name.len, id->name.ptr);
+       n = snprintf(dst, dstlen, "@%.*s", (int)id->name.len, id->name.ptr);
+       break;
     case ID_USER_FQDN:
-	return snprintf(dst, dstlen, "%.*s", (int)id->name.len, id->name.ptr);
+       n = snprintf(dst, dstlen, "@%.*s", (int)id->name.len, id->name.ptr);
+       break;
+#ifdef OPENSSL
+    case ID_KEY_ID:
+       n = snprintf(dst, dstlen, "@%.*s", (int)id->key_id.len, id->key_id.ptr);
+       break;
+    case ID_DER_ASN1_DN:
+       n = snprintf(dst, dstlen, "@%.*s", (int)id->der_asn1_dn.len,
+       id->der_asn1_dn.ptr);
+       break;
+#endif
     default:
-	return snprintf(dst, dstlen, "unknown id kind %d", id->kind);
+        n = snprintf(dst, dstlen, "unknown id kind %d", id->kind);
+	break;
     }
-}
 
-/* deep-copy a struct id into a new heap object
- * This is needed if the result of atoid is to be kept.
+    /* "Sanitize" string so that log isn't endangered:
+     * replace unprintable characters with '?'.
  */
+    if (n > 0)
+    {
+       for ( ; *dst != '\0'; dst++)
+           if (!isprint(*dst))
+               *dst = '?';
+    }
 
-struct id *
-clone_id(const struct id *src)
-{
-    struct id *dst = clone_thing(*src, "keep id");
-
-    unshare_id_content(dst);
-    dst->next = NULL;
-    return dst;
+    return n;
 }
 
+/* Make private copy of string in struct id.
+ * This is needed if the result of atoid is to be kept.
+ */
 void
 unshare_id_content(struct id *id)
 {
@@ -112,8 +216,20 @@
     {
     case ID_FQDN:
     case ID_USER_FQDN:
-	id->name.ptr = clone_bytes(id->name.ptr, id->name.len, "keep id name");
+#ifdef OPENSSL
+    case ID_KEY_ID:
+#endif
+	id->name.ptr = clone_bytes(id->name.ptr, id->name.len, 
+		"keep id name");
+	break;
+#ifdef OPENSSL
+    case ID_DER_ASN1_DN:
+	id->name.ptr = clone_bytes(id->name.ptr, id->name.len, 
+		"keep id name");
+	id->der_asn1_dn.ptr = clone_bytes(id->der_asn1_dn.ptr, 
+		id->der_asn1_dn.len, "keep der_asn1_dn id");
 	break;
+#endif
     case ID_NONE:
     case ID_IPV4_ADDR:
     case ID_IPV6_ADDR:
@@ -140,6 +256,16 @@
     case ID_USER_FQDN:
 	pfree(id->name.ptr);
 	break;
+#ifdef OPENSSL
+    case ID_KEY_ID:
+	pfree(id->name.ptr);
+	pfree(id->key_id.ptr);
+	break;
+    case ID_DER_ASN1_DN:
+	pfree(id->name.ptr);
+	pfree(id->der_asn1_dn.ptr);
+	break;
+#endif /* OPENSSL */
     case ID_NONE:
     case ID_IPV4_ADDR:
     case ID_IPV6_ADDR:
@@ -166,10 +292,20 @@
 
     case ID_FQDN:
     case ID_USER_FQDN:
+#ifdef OPENSSL
+    case ID_KEY_ID:
 	/* assumption: case should be ignored */
+#endif
 	return a->name.len == b->name.len
 	    && strncasecmp(a->name.ptr, b->name.ptr, a->name.len) == 0;
+#ifdef OPENSSL
+    case ID_DER_ASN1_DN:
+	/* assumption: case should be ignored */
 
+	return (a->der_asn1_dn.len == b->der_asn1_dn.len)
+	    && strncasecmp(a->der_asn1_dn.ptr, 
+	      b->der_asn1_dn.ptr, a->der_asn1_dn.len) == 0;
+#endif /* OPENSSL */
     default:
 	passert(FALSE);
     }
@@ -183,7 +319,7 @@
 void
 build_id_payload(struct isakmp_ipsec_id *hd, chunk_t *tl, struct end *end)
 {
-    memset(hd, '\0', sizeof(*hd));
+    zero(hd);
     hd->isaiid_idtype = end->id.kind;
     switch (end->id.kind)
     {
@@ -201,7 +337,49 @@
 	tl->len = addrbytesptr(&end->host_addr
 	    , (const unsigned char **)&tl->ptr);
 	break;
+#ifdef OPENSSL
+    case ID_KEY_ID:
+	*tl = end->id.key_id;
+	break;
+    case ID_DER_ASN1_DN:
+	*tl = end->id.der_asn1_dn;
+	break;
+#endif /* OPENSSL */
     default:
 	passert(FALSE);
     }
 }
+
+#ifdef OPENSSL
+err_t
+check_der_asn1_dn(struct id *id)
+{
+	err_t ugh = NULL;
+	u_char *temp_ptr;
+
+	X509_NAME *xn = X509_NAME_new();
+	char dnout[256];
+
+	if (xn == NULL) {
+		ugh="Unable to malloc X509_NAME *xn";
+	}
+
+	/* temp_ptr because d2i_X509_NAME will mangle the pointer. */
+	temp_ptr = id->der_asn1_dn.ptr;
+	xn = d2i_X509_NAME(&xn, &(id->der_asn1_dn.ptr),
+		(long)id->der_asn1_dn.len);
+	id->der_asn1_dn.ptr = temp_ptr;
+
+	if (xn != NULL) {
+		DBG(DBG_PARSING,
+		X509_NAME_oneline(xn,dnout,256);
+		DBG_log("Valid DN == %s", dnout);
+		);
+	} else {
+		ugh="Invalid DER string";
+	}
+
+	X509_NAME_free(xn);
+	return ugh;
+}
+#endif
diff -bruN freeswan-1.9.orig/pluto/id.h freeswan-1.9/pluto/id.h
--- freeswan-1.9.orig/pluto/id.h	Wed Oct  4 20:12:10 2000
+++ freeswan-1.9/pluto/id.h	Tue Jun  5 15:56:51 2001
@@ -11,28 +11,35 @@
  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  * for more details.
  *
- * RCSID $Id: id.h,v 1.11 2000/10/05 00:12:10 dhr Exp $
+ * RCSID $Id: id.h,v 1.15 2001/02/26 23:50:11 dhr Exp $
  */
 
 struct id {
     int kind;	/* ID_* value */
     ip_address ip_addr;	/* ID_IPV4_ADDR, ID_IPV6_ADDR */
+#ifdef OPENSSL
+    chunk_t key_id;   /* ID_KEY_ID */
+    chunk_t der_asn1_dn;      /* ID_DER_ASN1_DN */
+#endif
     chunk_t name;	/* ID_FQDN, ID_USER_FQDN (with @) */
-    struct id *next;
 };
 
 extern const struct id empty_id;
 
 extern err_t atoid(char *src, struct id *id);
+extern void iptoid(const ip_address *ip, struct id *id);
 extern int idtoa(const struct id *id, char *dst, size_t dstlen);
 #define IDTOA_BUF 256
 struct end;	/* forward declaration of tag (defined in connections.h) */
-extern struct id *clone_id(const struct id *src);
 extern void unshare_id_content(struct id *id);
 extern void free_id(struct id *id);
 extern void free_id_content(struct id *id);
 extern bool same_id(const struct id *a, const struct id *b);
+#define id_is_ipaddr(id) ((id)->kind == ID_IPV4_ADDR || (id)->kind == ID_IPV6_ADDR)
 
 struct isakmp_ipsec_id;	/* forward declaration of tag (defined in packet.h) */
 extern void
     build_id_payload(struct isakmp_ipsec_id *hd, chunk_t *tl, struct end *end);
+#ifdef OPENSSL
+err_t check_der_asn1_dn(struct id *id);
+#endif
diff -bruN freeswan-1.9.orig/pluto/ipsec_doi.c freeswan-1.9/pluto/ipsec_doi.c
--- freeswan-1.9.orig/pluto/ipsec_doi.c	Sun Jan 28 16:03:04 2001
+++ freeswan-1.9/pluto/ipsec_doi.c	Mon Jun 11 16:44:14 2001
@@ -49,19 +49,63 @@
 #include "md5.h"
 #include "crypto.h" /* requires sha1.h and md5.h */
 
+#ifdef OPENSSL
+#include "openssl.h"
+#endif
+
 /* MAGIC: perform f, a function that returns notification_t
  * and return from the ENCLOSING stf_status returning function if it fails.
  */
 #define RETURN_STF_FAILURE(f) \
     { int r = (f); if (r != NOTHING_WRONG) return STF_FAIL + r; }
 
-/* if we haven't already done so, compute a local DH secret (st->st_sec) and
- * the corresponding public value (g).  This is emitted as a KE payload.
+stf_status send_delete(struct state *p2st, ipsec_spi_t *spi, bool ESP);
+static bool encrypt_message(pb_stream *pbs, struct state *st);
+extern bool build_and_ship_KE(struct state *st, chunk_t *g, 
+	const struct oakley_group_desc *group, pb_stream *outs, u_int8_t np);
+
+/* needed for PGPnet Vendor ID */
+char pgp_vid[] = { 0x4f, 0x70, 0x65, 0x6e,
+		   0x50, 0x47, 0x50, 0x31,
+		   0x30, 0x31, 0x37, 0x31};
+
+/* Compute DH shared secret from our local secret and the peer's public value.
+ * We make the leap that the length should be that of the group
+ * (see quoted passage at start of ACCEPT_KE).
  */
+static void
+compute_dh_shared(struct state *st, const chunk_t g
+, const struct oakley_group_desc *group)
+{
+    MP_INT mp_g, mp_shared;
+
+    passert(st->st_sec_in_use);
+    n_to_mpz(&mp_g, g.ptr, g.len);
+    mpz_init(&mp_shared);
+    mpz_powm(&mp_shared, &mp_g, &st->st_sec, group->modulus);
+    mpz_clear(&mp_g);
+    freeanychunk(st->st_shared);       /* happens in odd error cases */
+    st->st_shared = mpz_to_n(&mp_shared, group->bytes);
+    mpz_clear(&mp_shared);
+#ifdef DODGE_DH_MISSING_ZERO_BUG
+    if (st->st_shared.ptr[0] == 0)
+	loglog(RC_LOG_SERIOUS, "shared DH secret has leading zero -- triggers Pluto 1.0 bug");
+#endif
+    DBG_cond_dump_chunk(DBG_CRYPT, "DH shared secret:\n", st->st_shared);
+}
+
+#ifdef OPENSSL
 static bool
-build_and_ship_KE(struct state *st, chunk_t *g
-    , const struct oakley_group_desc *group, pb_stream *outs, u_int8_t np)
+build_and_ship_KE_rpk(struct state *st, bool init,
+                    chunk_t *g,
+                    const struct oakley_group_desc *group, pb_stream *outs,
+                    u_int8_t np)
 {
+  keysched *ks;
+  u_char *iv;
+  chunk_t op;
+  bool res;
+
     if (!st->st_sec_in_use)
     {
 	u_char tmp[LOCALSECRETSIZE];
@@ -73,50 +117,123 @@
 
 	mpz_init(&mp_g);
 	mpz_powm(&mp_g, &groupgenerator, &st->st_sec, group->modulus);
+      freeanychunk(*g);       /* happens in odd error cases */
 	*g = mpz_to_n(&mp_g, group->bytes);
 	mpz_clear(&mp_g);
 #ifdef DODGE_DH_MISSING_ZERO_BUG
 	if (g->ptr[0] == 0)
 	{
 	    /* generate a new secret to avoid this situation */
-	    loglog(RC_LOG_SERIOUS, "regenerating DH private secret to avoid Pluto 1.0 bug"
+          log("regenerating DH private secret to avoid Pluto 1.0 bug"
 		" handling public value with leading zero");
 	    mpz_clear(&st->st_sec);
 	    st->st_sec_in_use = FALSE;
-	    freeanychunk(*g);
+          return build_and_ship_KE_rpk(st, init, g, group, outs, np);
+      }
+       /* if we're the responder, we can compute the shared secret
+        * to see if it would turn out OK.
+        */
+       if (g == &st->st_gr)
+       {
+           compute_dh_shared(st, st->st_gi
+               , IS_PHASE1(st->st_state)
+                   ? st->st_oakley.group : st->st_pfs_group);
+           if (st->st_shared.ptr[0] == 0)
+           {
+               /* generate a new secret to avoid this situation */
+               loglog(RC_LOG_SERIOUS, "regenerating DH private secret to avoid Pluto 1.0 bug"
+                   " handling shared secret with leading zero");
+               freeanychunk(st->st_shared);
+               mpz_clear(&st->st_sec);
+               st->st_sec_in_use = FALSE;
 	    return build_and_ship_KE(st, g, group, outs, np);
 	}
+       }
 #endif
 
 	DBG(DBG_CRYPT,
 	    DBG_dump("Local DH secret:\n", tmp, LOCALSECRETSIZE);
-	    DBG_dump_chunk("Public DH value sent:\n", *g));
+      DBG_dump_chunk("Public DH value sent:\n", *g);
+      );
     }
-    return out_generic_chunk(np, &isakmp_keyex_desc, outs, *g, "keyex value");
+    /* Encrypt the chunk */
+    if (init) {
+      ks = &st->st_ks_i;
+      iv = st->st_ne_i_iv;
+    } else {
+      ks = &st->st_ks_r;
+      iv = st->st_ne_r_iv;
+    }
+    setchunk(op, NULL, 0);
+    if (!encrypt_payload( st, ks, iv, *g, &op )) return FALSE;
+    res = out_generic_chunk(np, &isakmp_keyex_desc, outs, op,
+                          "encrypted keyex value");
+    freeanychunk(op);
+    return res;
 }
+#endif
 
-/* Compute DH shared secret from our local secret and the peer's public value.
- * We make the leap that the length should be that of the group
- * (see quoted passage at start of ACCEPT_KE).
+/* if we haven't already done so, compute a local DH secret (st->st_sec) and
+ * the corresponding public value (g).  This is emitted as a KE payload.
+ * KLUDGE: if DODGE_DH_MISSING_ZERO_BUG and we're the responder,
+ * this routine computes the shared secret to see if it would
+ * have a leading zero.  If so, we try again.
  */
-static void
-compute_dh_shared(struct state *st, const chunk_t g
-    , const struct oakley_group_desc *group)
+extern bool
+build_and_ship_KE(struct state *st, chunk_t *g
+, const struct oakley_group_desc *group, pb_stream *outs, u_int8_t np)
 {
-    MP_INT mp_g, mp_shared;
+    if (!st->st_sec_in_use)
+    {
+	u_char tmp[LOCALSECRETSIZE];
+	MP_INT mp_g;
 
-    passert(st->st_sec_in_use);
-    n_to_mpz(&mp_g, g.ptr, g.len);
-    mpz_init(&mp_shared);
-    mpz_powm(&mp_shared, &mp_g, &st->st_sec, group->modulus);
+	get_rnd_bytes(tmp, LOCALSECRETSIZE);
+	st->st_sec_in_use = TRUE;
+	n_to_mpz(&st->st_sec, tmp, LOCALSECRETSIZE);
+
+	mpz_init(&mp_g);
+	mpz_powm(&mp_g, &groupgenerator, &st->st_sec, group->modulus);
+	freeanychunk(*g);       /* happens in odd error cases */
+	*g = mpz_to_n(&mp_g, group->bytes);
     mpz_clear(&mp_g);
-    st->st_shared = mpz_to_n(&mp_shared, group->bytes);
-    mpz_clear(&mp_shared);
 #ifdef DODGE_DH_MISSING_ZERO_BUG
+	if (g->ptr[0] == 0)
+	{
+	    /* generate a new secret to avoid this situation */
+	    loglog(RC_LOG_SERIOUS, "regenerating DH private secret to avoid Pluto 1.0 bug"
+		" handling public value with leading zero");
+	    mpz_clear(&st->st_sec);
+	    st->st_sec_in_use = FALSE;
+	    return build_and_ship_KE(st, g, group, outs, np);
+	}
+       /* if we're the responder, we can compute the shared secret
+        * to see if it would turn out OK.
+        */
+       if (g == &st->st_gr)
+       {
+           compute_dh_shared(st, st->st_gi
+               , IS_PHASE1(st->st_state)
+                   ? st->st_oakley.group : st->st_pfs_group);
     if (st->st_shared.ptr[0] == 0)
-	loglog(RC_LOG_SERIOUS, "shared DH secret has leading zero -- triggers Pluto 1.0 bug");
+           {
+               /* generate a new secret to avoid this situation */
+               loglog(RC_LOG_SERIOUS, "regenerating DH private secret to avoid Pluto 1.0 bug"
+                   " handling shared secret with leading zero");
+               freeanychunk(st->st_shared);
+               mpz_clear(&st->st_sec);
+               st->st_sec_in_use = FALSE;
+               return build_and_ship_KE(st, g, group, outs, np);
+           }
+       }
 #endif
-    DBG_cond_dump_chunk(DBG_CRYPT, "DH shared secret:\n", st->st_shared);
+
+	DBG(DBG_CRYPT,
+	DBG_dump("Local DH secret:\n", tmp, LOCALSECRETSIZE);
+	DBG_dump_chunk("Public DH value sent:\n", *g);
+	);
+    }
+    return out_generic_chunk(np, &isakmp_keyex_desc, outs, *g, "keyex value");
 }
 
 /* accept_ke
@@ -131,7 +248,8 @@
  *     values to interoperate with old Plutos.  This should change some day.
  */
 static notification_t
-accept_KE(chunk_t *dest, const char *val_name, const struct oakley_group_desc *gr
+accept_KE(chunk_t *dest, const char *val_name
+, const struct oakley_group_desc *gr
 , pb_stream *pbs)
 {
     if (pbs_left(pbs) != gr->bytes)
@@ -155,7 +273,8 @@
  * Extends ACCEPT_PFS to check whether KE is allowed or required.
  */
 static notification_t
-accept_PFS_KE(struct msg_digest *md, chunk_t *dest, const char *val_name, const char *msg_name)
+accept_PFS_KE(struct msg_digest *md, chunk_t *dest
+, const char *val_name, const char *msg_name)
 {
     struct state *st = md->st;
     struct payload_digest *const ke_pd = md->chain[ISAKMP_NEXT_KE];
@@ -187,13 +306,31 @@
 }
 
 static bool
-build_and_ship_nonce(chunk_t *n, pb_stream *outs, u_int8_t np, const char *name)
+build_and_ship_nonce(chunk_t *n, pb_stream *outs, u_int8_t np
+, const char *name)
 {
     setchunk(*n, alloc_bytes(DEFAULT_NONCE_SIZE, name), DEFAULT_NONCE_SIZE);
     get_rnd_bytes(n->ptr, DEFAULT_NONCE_SIZE);
     return out_generic_chunk(np, &isakmp_nonce_desc, outs, *n, name);
 }
 
+#ifdef OPENSSL
+static bool
+build_and_ship_nonce_pk(struct state *st, chunk_t *n, pb_stream *outs, u_int8_t np, const char *name)
+{
+    chunk_t c;
+
+    setchunk(*n, alloc_bytes(DEFAULT_NONCE_SIZE, name), DEFAULT_NONCE_SIZE);
+    get_rnd_bytes(n->ptr, DEFAULT_NONCE_SIZE);
+    c.len = n->len;
+    c.ptr = clone_bytes(n->ptr, c.len, name);
+    if (! pubkey_encrypt_chunk(&c, st)) {
+      return FALSE;
+    }
+    return out_generic_chunk(np, &isakmp_nonce_desc, outs, c, name);
+}
+#endif
+
 /*
  * Send a notification to the peer. We could make a decision on
  * whether to send the notification, based on the type and the
@@ -256,11 +393,128 @@
 //	    show_sa(&sa)));
 //    else
 //    {
-//	DBG(DBG_CONTROL, DBG_log("transmitted %d bytes", ntohl(isa->isa_length)));
+//	DBG(DBG_CONTROL, 
+//	DBG_log("transmitted %d bytes", ntohl(isa->isa_length));
+//	);
 //    }
 //}
 #endif /* not currently used */
 
+
+stf_status
+send_delete(struct state *p2st, ipsec_spi_t *spi, bool ESP)
+{
+     
+     pb_stream reply_pbs;
+     pb_stream r_hdr_pbs;
+     msgid_t	msgid;
+     u_char 	old_new_iv[MAX_DIGEST_LEN];
+     u_char 	old_iv[MAX_DIGEST_LEN];         
+     u_char buffer[8192];
+     struct state *p1st;
+     
+     u_char spilen = sizeof(ipsec_spi_t);
+     u_char
+ 	*r_hashval,	/* where in reply to jam hash value */
+ 	*r_hash_start;	/* start of what is to be hashed */
+     
+     memset(buffer, '\0', sizeof(buffer));
+     init_pbs(&reply_pbs, buffer, sizeof(buffer), "delete msg");
+ 
+     /* find the related P1-State to the calling P2-state */
+     p1st = find_state(p2st->st_icookie, p2st->st_rcookie, 
+     			&(p2st->st_connection->that.host_addr), 0);
+     if (p1st == NULL) 
+     {
+ 	DBG_log("no phase 1 state where one should be");
+	return STF_INTERNAL_ERROR;
+     }
+ 
+     msgid = generate_msgid(p1st);
+
+     /* HDR* */
+     {
+ 	struct isakmp_hdr hdr;
+ 
+ 	hdr.isa_version = ISAKMP_MAJOR_VERSION << ISA_MAJ_SHIFT | ISAKMP_MINOR_VERSION;
+ 	hdr.isa_np = ISAKMP_NEXT_HASH;
+ 	hdr.isa_xchg = ISAKMP_XCHG_INFO;
+ 	hdr.isa_msgid = msgid;
+ 	hdr.isa_flags = ISAKMP_FLAG_ENCRYPTION;
+ 	memcpy(hdr.isa_icookie, p1st->st_icookie, COOKIE_SIZE);
+ 	memcpy(hdr.isa_rcookie, p1st->st_rcookie, COOKIE_SIZE);
+ 	if (!out_struct(&hdr, &isakmp_hdr_desc, &reply_pbs, &r_hdr_pbs))
+ 	    return STF_INTERNAL_ERROR;
+     }
+ 
+     /* HASH -- space to be filled later */
+     {
+ 	pb_stream hash_pbs;
+ 
+ 	if (!out_generic(ISAKMP_NEXT_D, &isakmp_hash_desc, &r_hdr_pbs, &hash_pbs))
+     	    return STF_INTERNAL_ERROR;
+ 	r_hashval = hash_pbs.cur;	/* remember where to plant value */
+ 	if (!out_zero(p1st->st_oakley.hasher->hash_digest_len, &hash_pbs, "HASH(1)"))
+ 	    return STF_INTERNAL_ERROR;
+ 	close_output_pbs(&hash_pbs);
+ 	r_hash_start = r_hdr_pbs.cur;	/* hash from after HASH(1) */
+     }
+ 
+     /* DELETE PAYLOAD */
+     {
+ 	pb_stream del_pbs;
+ 	struct isakmp_delete isad;
+ 	
+        isad.isad_doi = ISAKMP_DOI_IPSEC;
+ 	isad.isad_np = ISAKMP_NEXT_NONE;
+ 	isad.isad_spisize = spilen;
+        if (ESP) isad.isad_protoid = PROTO_IPSEC_ESP;
+        else isad.isad_protoid = PROTO_IPSEC_AH;
+ 	isad.isad_nospi = 0x0001;
+         if (!out_struct(&isad, &isakmp_delete_desc, &r_hdr_pbs, &del_pbs))
+ 	    return STF_INTERNAL_ERROR;
+ 	if (!out_raw(spi, spilen, &del_pbs, "delete payload"))
+ 	    return STF_INTERNAL_ERROR;;
+         close_output_pbs(&del_pbs);
+     }
+     
+     {
+         struct hmac_ctx ctx;
+ 	hmac_init_chunk(&ctx, p1st->st_oakley.hasher, p1st->st_skeyid_a);
+         hmac_update(&ctx, (u_char *) &msgid, sizeof(msgid_t));
+         hmac_update(&ctx, r_hash_start, r_hdr_pbs.cur-r_hash_start);
+ 	hmac_final(r_hashval, &ctx);
+ 
+         DBG(DBG_CRYPT,
+     	    DBG_log("HASH(1) computed:");
+ 	    DBG_dump("", r_hashval, ctx.hmac_digest_len));
+     }
+ 
+     /* save old IV (this prevents from copying a whole new state object 
+      * for NOTIFICATION / DELETE messages we don't need to maintain a state
+      * because there are no retransmissions...
+      */
+      
+     memcpy(old_new_iv, p1st->st_new_iv, p1st->st_new_iv_len);
+     memcpy(old_iv, p1st->st_iv, p1st->st_iv_len);
+     init_phase2_iv(p1st, &msgid);
+ 
+     if(!encrypt_message(&r_hdr_pbs, p1st)) passert(FALSE);
+     
+     clonetochunk(p1st->st_tpacket, reply_pbs.start, pbs_offset(&reply_pbs)
+ 	, "reply packet for main_outI1");
+ 
+     send_packet(p1st, "delete notify");
+     
+     /* get back old IV for this state */
+     memcpy(p1st->st_new_iv, old_new_iv, p1st->st_new_iv_len);
+     memcpy(p1st->st_iv, old_iv, p1st->st_iv_len);    
+     
+     return STF_IGNORE; 
+}
+ 
+
+
 /* The whole message must be a multiple of 4 octets.
  * I'm not sure where this is spelled out, but look at
  * rfc2408 3.6 Transform Payload.
@@ -280,12 +534,11 @@
  * --> HDR;SA
  */
 static stf_status
-main_outI1(
-	int whack_sock,
-	struct connection *c,
-	bool pending_quick,
-	lset_t policy,
-	unsigned long try)
+main_outI1(int whack_sock
+, struct connection *c
+, struct state *predecessor
+, lset_t policy
+, unsigned long try)
 {
     u_char space[8192];	/* NOTE: we assume 8192 is big enough to build the packet */
     pb_stream reply;	/* not actually a reply, but you know what I mean */
@@ -293,14 +546,17 @@
 
     struct state *st;
 
+    DBG(DBG_PARSING,
+    DBG_log("in main_outI1");
+    );
+
     /* set up new state */
     cur_state = st = new_state();
     st->st_connection = c;
 #ifdef DEBUG
     extra_debugging(c);
 #endif
-    st->st_pending_quick = pending_quick;
-    st->st_policy = policy;
+    st->st_policy = policy & ~POLICY_IPSEC_MASK;
     st->st_whack_sock = whack_sock;
     st->st_try = try;
     st->st_state = STATE_MAIN_I1;
@@ -309,6 +565,9 @@
 
     insert_state(st);	/* needs cookies, connection, and msgid (0) */
 
+    if (HAS_IPSEC_POLICY(policy))
+       add_pending(dup_any(whack_sock), st, c, policy, 1);
+
     log("initiating Main Mode");
 
     /* set up reply */
@@ -318,7 +577,7 @@
     {
 	struct isakmp_hdr hdr;
 
-	memset(&hdr, '\0', sizeof(hdr));	/* default to 0 */
+	zero(&hdr);     /* default to 0 */
 	hdr.isa_version = ISAKMP_MAJOR_VERSION << ISA_MAJ_SHIFT | ISAKMP_MINOR_VERSION;
 	hdr.isa_np = ISAKMP_NEXT_SA;
 	hdr.isa_xchg = ISAKMP_XCHG_IDPROT;
@@ -335,7 +594,7 @@
     /* SA out */
     {
 	u_char *sa_start = rbody.cur;
-	lset_t auth_policy = policy & POLICY_ISAKMP_MASK;
+	lset_t auth_policy = policy & POLICY_ID_AUTH_MASK;
 
 	if (auth_policy == LEMPTY)
 	{
@@ -345,7 +604,11 @@
 
 	    if (get_RSA_private_key(c) != NULL
 	    && get_his_RSA_public_key(c) != NULL)
+#ifndef OPENSSL
 		auth_policy |= POLICY_RSASIG;
+#else
+		auth_policy |= POLICY_OPENSSL;
+#endif
 	    /* Not clear what we should do if neither is possible.
 	     * Perhaps we should not have entered negotiations at all.
 	     */
@@ -356,6 +619,23 @@
 		return STF_INTERNAL_ERROR;
 	    }
 	}
+
+#ifdef OPENSSL
+if (use_openssl(c)) 
+{
+	loglog(RC_LOG_SERIOUS, "Using OPENSSL sadb.");
+	if (!out_sa(&rbody
+	, &oakley_sadb2[auth_policy >> POLICY_ISAKMP_SHIFT]
+	, st, TRUE, ISAKMP_NEXT_NONE))
+	{
+	    cur_state = NULL;
+	    return STF_INTERNAL_ERROR;
+	}
+}
+else
+{
+#endif /* OPENSSL */
+	loglog(RC_LOG_SERIOUS, "Using standard sadb.");
 	if (!out_sa(&rbody
 	, &oakley_sadb[auth_policy >> POLICY_ISAKMP_SHIFT]
 	, st, TRUE, ISAKMP_NEXT_NONE))
@@ -363,6 +643,10 @@
 	    cur_state = NULL;
 	    return STF_INTERNAL_ERROR;
 	}
+#ifdef OPENSSL
+}
+#endif /* ! OPENSSL */
+
 
 	/* save initiator SA for later HASH */
 	passert(st->st_p1isa.ptr == NULL);	/* no leak!  (MUST be first time) */
@@ -384,35 +668,47 @@
     delete_event(st);
     event_schedule(EVENT_RETRANSMIT, EVENT_RETRANSMIT_DELAY_0, st);
 
+    if (predecessor != NULL)
+    {
+       update_pending(predecessor, st);
+       whack_log(RC_NEW_STATE + STATE_MAIN_I1
+           , "%s: initiate, replacing #%lu"
+           , enum_name(&state_names, st->st_state)
+           , predecessor->st_serialno);
+    }
+    else
+    {
     whack_log(RC_NEW_STATE + STATE_MAIN_I1
 	, "%s: initiate", enum_name(&state_names, st->st_state));
+    }
     cur_state = NULL;
     return STF_NO_REPLY;
 }
 
 void
-ipsecdoi_initiate(
-	int whack_sock,
-	struct connection *c,
-	bool pending_quick,
-	lset_t policy,
-	unsigned long try)
+ipsecdoi_initiate(int whack_sock
+, struct connection *c
+, lset_t policy
+, unsigned long try)
 {
     /* If there's already an ISAKMP SA established, use that and
      * go directly to Quick Mode.
      * Note: there is no way to initiate with a Road Warrior.
-     * XXX If an ISAKMP SA is *being* established, we foolishly
-     * XXX try to establish another one, in parallel.  We could
-     * XXX issue an event to wait for it to finish and then try
-     * XXX to establish it.
      */
-    struct state *st = find_isakmp_sa(c);
+    struct state *st = find_phase1_state(c);
 
     if (st == NULL)
     {
-	(void) main_outI1(whack_sock, c, pending_quick, policy, try);
+	(void) main_outI1(whack_sock, c, NULL, policy, try);
+    }
+    else if (HAS_IPSEC_POLICY(policy))
+    {
+       if (!IS_ISAKMP_SA_ESTABLISHED(st->st_state))
+       {
+           /* leave our Phase 2 negotiation pending */
+           add_pending(whack_sock, st, c, policy, try);
     }
-    else if (pending_quick)
+	else
     {
 	/* ??? we assume that peer_nexthop_sin isn't important:
 	 * we already have it from when we negotiated the ISAKMP SA!
@@ -420,6 +716,7 @@
 	 */
 	(void) quick_outI1(whack_sock, st, c, policy, try);
     }
+    }
     else if (whack_sock != NULL_FD)
     {
 	close(whack_sock);
@@ -443,8 +740,8 @@
 
     if (IS_PHASE1(st->st_state))
     {
-	(void) main_outI1(whack_sock, st->st_connection, st->st_pending_quick
-	    , policy, try);
+	passert(!HAS_IPSEC_POLICY(policy));
+        (void) main_outI1(whack_sock, st->st_connection, st, policy, try);
     }
     else
     {
@@ -472,7 +769,8 @@
 	    if (st->st_ipcomp.attrs.encapsulation == ENCAPSULATION_MODE_TUNNEL)
 		policy |= POLICY_TUNNEL;
 	}
-	ipsecdoi_initiate(whack_sock, st->st_connection, TRUE, policy, try);
+        passert(HAS_IPSEC_POLICY(policy));
+        ipsecdoi_initiate(whack_sock, st->st_connection, policy, try);
     }
 }
 
@@ -522,6 +820,57 @@
     return TRUE;
 }
 
+#ifdef OPENSSL
+#if 0
+static const chunk_t
+chunk_concat( const chunk_t c1, const chunk_t c2 )
+{
+    chunk_t cc;
+
+    cc.len = c1.len + c2.len;
+    if ((cc.ptr = malloc(cc.len)) != NULL) {
+      memcpy(cc.ptr, c1.ptr, c1.len);
+      memcpy(&(cc.ptr[c1.len]), c2.ptr, c2.len);
+    }
+    return cc;
+}
+#endif
+
+static bool
+skeyid_pke(struct state *st)
+{
+    /* This routine lifted straight from Kai Martius' patches */
+    /* and updated to use chunks */
+    struct hmac_ctx ctx;
+    union hash_ctx ictx;
+    const struct hash_desc *h = st->st_oakley.hasher;
+    u_char *nonce;
+    u_int16_t nonce_len;
+    chunk_t noncechunk, cky_i, cky_r;
+
+    nonce_len = h->hash_digest_len;
+    nonce=alloc_bytes(nonce_len, "nonce in skeyid_pke()");
+
+    h->hash_init(&ictx);
+    h->hash_update(&ictx, st->st_ni.ptr, st->st_ni.len);
+    h->hash_update(&ictx, st->st_nr.ptr, st->st_nr.len);
+    h->hash_final(nonce, &ictx);
+
+    setchunk(noncechunk, nonce, nonce_len);
+    setchunk(cky_i, st->st_icookie, COOKIE_SIZE);
+    setchunk(cky_r, st->st_rcookie, COOKIE_SIZE);
+
+    hmac_init_chunk(&ctx, h, noncechunk);
+    hmac_update_chunk(&ctx, cky_i);
+    hmac_update_chunk(&ctx, cky_r);
+    hmac_final_chunk(st->st_skeyid, "st_skeyid in skeyid_pke()", &ctx);
+
+    free(nonce);
+
+    return TRUE;
+}
+#endif
+
 /* Generate the SKEYID_* and new IV
  * See draft-ietf-ipsec-ike-01.txt 4.1
  */
@@ -542,13 +891,21 @@
 	    break;
 
 	case OAKLEY_DSS_SIG:
-	    /* XXX */
+#ifdef OPENSSL
+          if (!skeyid_digisig(st))
+              return FALSE;
+          break;
+#endif
 
 	case OAKLEY_RSA_ENC:
 	case OAKLEY_RSA_ENC_REV:
 	case OAKLEY_ELGAMAL_ENC:
 	case OAKLEY_ELGAMAL_ENC_REV:
-	    /* XXX */
+#ifdef OPENSSL
+          if (!skeyid_pke(st))
+              return FALSE;
+          break;
+#endif
 
 	default:
 	    exit_log("generate_skeyids_iv(): unsupported authentication method %s",
@@ -737,7 +1094,7 @@
     return ctx.hmac_digest_len;
 }
 
-#if 0	/* only needed for DSS */
+#ifdef OPENSSL
 static void
 main_mode_sha1(struct state *st, u_char *hash_val, size_t *hash_len
 , bool hashi, bool hashus)
@@ -945,6 +1302,13 @@
     switch (st->st_oakley.auth)
     {
     case OAKLEY_PRESHARED_KEY:
+#ifdef OPENSSL
+     case OAKLEY_RSA_ENC:
+     case OAKLEY_RSA_ENC_REV:
+     case OAKLEY_DSS_SIG:
+     case OAKLEY_ELGAMAL_ENC:
+     case OAKLEY_ELGAMAL_ENC_REV:
+#endif
 	{
 	    pb_stream *const hash_pbs = &md->chain[ISAKMP_NEXT_HASH]->pbs;
 
@@ -1038,7 +1402,10 @@
 
     DBG_cond_dump(DBG_CRYPT | DBG_RAW, "encrypting:\n", enc_start, enc_len);
 
-    /* pad up to multiple of encryption blocksize */
+    /* Pad up to multiple of encryption blocksize.
+     * See the description associated with the definition of
+     * struct isakmp_hdr in packet.h.
+     */
     {
 	size_t padding = pad_up(enc_len, e->blocksize);
 
@@ -1141,6 +1508,7 @@
     pb_stream id_pbs;
     ip_address ta;
     const unsigned char *tbp;
+    size_t tal;
 
     id.isaiid_np = np;
     id.isaiid_idtype = aftoinfo(subnettypeof(net))->id_subnet;
@@ -1151,11 +1519,13 @@
 	return FALSE;
 
     networkof(net, &ta);
-    if (!out_raw(tbp, addrbytesptr(&ta, &tbp), &id_pbs, "client network"))
+    tal = addrbytesptr(&ta, &tbp);
+    if (!out_raw(tbp, tal, &id_pbs, "client network"))
 	return FALSE;
 
     maskof(net, &ta);
-    if (!out_raw(tbp, addrbytesptr(&ta, &tbp), &id_pbs, "client mask"))
+    tal = addrbytesptr(&ta, &tbp);
+    if (!out_raw(tbp, tal, &id_pbs, "client mask"))
 	return FALSE;
 
     close_output_pbs(&id_pbs);
@@ -1163,12 +1533,11 @@
 }
 
 stf_status
-quick_outI1(
-	int whack_sock,
-	struct state *isakmp_sa,
-	struct connection *c,
-	lset_t policy,
-	unsigned long try)
+quick_outI1(int whack_sock
+, struct state *isakmp_sa
+, struct connection *c
+, lset_t policy
+, unsigned long try)
 {
     struct state *st = duplicate_state(isakmp_sa);
     u_char space[8192];	/* NOTE: we assume 8192 is big enough to build the packet */
@@ -1198,6 +1567,10 @@
 
     log("initiating Quick Mode %s", bitnamesof(sa_policy_bit_names, policy));
 
+    DBG(DBG_PARSING,
+    DBG_log("starting quick_outI1");
+    );
+
     /* set up reply */
     init_pbs(&reply, space, sizeof(space), "reply packet");
 
@@ -1294,11 +1667,18 @@
     whack_log(RC_NEW_STATE + STATE_QUICK_I1
 	, "%s: initiate", enum_name(&state_names, st->st_state));
     cur_state = NULL;
+
+    DBG(DBG_PARSING,
+    DBG_log("finished quick_outI1");
+    );
+
     return STF_NO_REPLY;
 }
 
 /* Decode the ID payload of Phase 1 (main_inI3_outR3 and main_inR3)
  * Note: we may change connections as a result.
+ * We must be called before SIG or HASH are decoded since we
+ * may change the peer's RSA key or ID.
  */
 static bool
 decode_peer_id(struct msg_digest *md, bool initiator)
@@ -1308,6 +1688,15 @@
     pb_stream *const id_pbs = &id_pld->pbs;
     struct isakmp_id *const id = &id_pld->payload.id;
     struct id peer;
+    const u_int max_len = 512;
+
+#ifdef OPENSSL
+    u_char key_id[max_len];
+    u_int i, len;
+
+    peer.key_id.len = 0;
+    peer.der_asn1_dn.len = 0;
+#endif
 
     /* I think that RFC2407 (IPSEC DOI) 4.6.2 is confused.
      * It talks about the protocol ID and Port fields of the ID
@@ -1328,6 +1717,7 @@
 	return FALSE;
     }
 
+
     /* XXX Check for valid ID types? */
     peer.kind = id->isaid_idtype;
 
@@ -1361,8 +1751,8 @@
     case ID_FQDN:
 	if (memchr(id_pbs->cur, '\0', pbs_left(id_pbs)) != NULL)
 	{
-	    loglog(RC_LOG_SERIOUS, "Phase 1 ID Payload of type %s contains a NUL"
-		, enum_show(&ident_names, peer.kind));
+	  loglog(RC_LOG_SERIOUS, "Phase 1 ID Payload of type %s contains a NULL"
+	    ,enum_show(&ident_names, peer.kind));
 	    return FALSE;
 	}
 
@@ -1371,6 +1761,76 @@
 	setchunk(peer.name, id_pbs->cur, pbs_left(id_pbs));
 	break;
 
+#ifdef OPENSSL
+    case ID_KEY_ID:
+	if (!(id->isaid_doi_specific_a == 0 && id->isaid_doi_specific_b == 0))
+	{
+	log("protocol/port in Phase 1 ID Payload must be 0/0"
+			" but are %d/%d"
+			, id->isaid_doi_specific_a, id->isaid_doi_specific_b);
+		return FALSE;
+	}
+
+	len = pbs_left(id_pbs);
+
+	/* we need double size for ASCII representation of key id */
+	if (2*len > max_len)
+	{
+		log("too large key id");
+		return FALSE;
+	}
+
+	DBG(DBG_PARSING,
+	DBG_dump("Received Key ID:", id_pbs->cur, pbs_left(id_pbs));
+	);
+
+	/* hold the binary representation of KEY_ID */
+	/* possible memory hole? */
+	peer.key_id.ptr = alloc_bytes(len, "key_id");
+	peer.key_id.len = len;
+	memcpy(peer.key_id.ptr, id_pbs->cur, len);
+
+	for (i=0; i<len; i++, id_pbs->cur++)
+		sprintf(&key_id[i*2], "%02x", *(id_pbs->cur));
+
+	peer.name.ptr = alloc_bytes(2*len, "name");
+	peer.name.len = 2*len;
+	memcpy(peer.name.ptr, key_id, peer.name.len);
+	break;  
+
+    case ID_DER_ASN1_DN:
+	if (!(id->isaid_doi_specific_a == 0 && id->isaid_doi_specific_b == 0))
+	{
+	log("protocol/port in Phase 1 ID Payload must be 0/0"
+			" but are %d/%d", id->isaid_doi_specific_a, 
+			id->isaid_doi_specific_b);
+		return FALSE;
+	}
+	len = pbs_left(id_pbs);
+
+	if (len > max_len)
+	{
+		log("too large DER ASN1 DN");
+		return FALSE;
+	}
+
+	if (id_pbs->cur == NULL) {
+		loglog(RC_LOG_SERIOUS, 
+			"ID_DER_ASN1_DN received, but is 0 length.");
+		return FALSE;
+	}
+
+	peer.der_asn1_dn.ptr = alloc_bytes(len,"der asn1 dn");
+	peer.der_asn1_dn.len = len;
+	memcpy(peer.der_asn1_dn.ptr, id_pbs->cur, len);
+
+	DBG(DBG_PARSING,
+	DBG_dump_chunk("Received peer.id (processed ID_DER_ASN1_DN):", 
+		peer.der_asn1_dn);       
+	);
+	break; 
+#endif OPENSSL
+
     default:
 	/* XXX Could send notification back */
 	loglog(RC_LOG_SERIOUS, "Unacceptable identity type (%s) in Phase 1 ID Payload"
@@ -1382,6 +1842,7 @@
     st->st_peeridentity_protocol = id->isaid_doi_specific_a;
     st->st_peeridentity_port = id->isaid_doi_specific_b;
 
+#if 0 /* Commented out because DER_AS1_DN creates LOTS of output here. */
     DBG(DBG_PARSING,
 	{
 	    char buf[IDTOA_BUF];
@@ -1391,15 +1852,34 @@
 		enum_show(&ident_names, id->isaid_idtype),
 		buf);
 	});
+#endif
 
-    /* now that we've decoded the ID payload, let's see if we
+    /* Now that we've decoded the ID payload, let's see if we
      * need to switch connections.
+     * We must not switch horses if we initiated:
+     * - if the initiation was explicit, we'd be ignoring user's intent
+     * - if opportunistic, we'll lose our HOLD info
      */
+    if (initiator)
+    {
+       if (!same_id(&st->st_connection->that.id, &peer))
+       {
+           char expect[IDTOA_BUF]
+               , found[IDTOA_BUF];
+
+           idtoa(&st->st_connection->that.id, expect, sizeof(expect));
+           idtoa(&peer, found, sizeof(found));
+           loglog(RC_LOG_SERIOUS
+               , "we require peer to have ID '%s', but peer declares '%s'"
+               , expect, found);
+           return FALSE;
+       }
+    }
+    else
     {
 	struct connection *c = st->st_connection;
-	struct connection *r;
+	struct connection *r = refine_host_connection(st, &peer, initiator);
 
-	r = refine_host_connection(st, &peer, initiator);
 	if (r == NULL)
 	{
 	    char buf[IDTOA_BUF];
@@ -1414,29 +1894,47 @@
 
 	    DBG(DBG_CONTROL
 		, DBG_log("switched from \"%s\" to \"%s\"", c->name, r->name));
-	    if (HasWildcardIP(*r))
+	    if (r->kind == CK_TEMPLATE)
 	    {
 		/* instantiate it, filling in peer's ID */
 		r = rw_instantiate(r, &c->that.host_addr, &peer);
 	    }
+
 	    st->st_connection = r;	/* kill reference to c */
 	    SET_CUR_CONNECTION(r);
 	    connection_discard(c);
+
+      }
+#ifdef OPENSSL
+      /* if we have a binary key_id, set it now into conn */
+      if (peer.key_id.len)
+      {
+              r->that.id.key_id.ptr = clone_bytes(peer.key_id.ptr,
+                      peer.key_id.len, "KEY-ID");
+              r->that.id.key_id.len = peer.key_id.len;
+      }
+
+      /* if we have a binary der_asn1_dn, set it now into conn */
+      if (peer.der_asn1_dn.len)
+      {
+              r->that.id.der_asn1_dn.ptr = clone_bytes(peer.der_asn1_dn.ptr,
+                      peer.der_asn1_dn.len, "ID_DER_ASN1_DN");
+              r->that.id.der_asn1_dn.len = peer.der_asn1_dn.len;
 	}
+#endif /* OPENSSL */
     }
 
     return TRUE;
 }
 
-/* Decode the variable part of an ID packet in (during Quick Mode).
+/* Decode the variable part of an ID packet (during Quick Mode).
  * This is designed for packets that identify clients, not peers.
  */
 static bool
-decode_net_id(
-    struct isakmp_ipsec_id *id,
-    pb_stream *id_pbs,
-    ip_subnet *net,
-    const char *which)
+decode_net_id(struct isakmp_ipsec_id *id
+, pb_stream *id_pbs
+, ip_subnet *net
+, const char *which)
 {
     const struct af_info *afi = NULL;
 
@@ -1606,12 +2104,12 @@
 
 /* like decode, but checks that what is received matches what was sent */
 static bool
-check_net_id(
-    struct isakmp_ipsec_id *id,
-    pb_stream *id_pbs,
-    u_int8_t *protoid, u_int16_t *port,
-    ip_subnet *net,
-    const char *which)
+check_net_id(struct isakmp_ipsec_id *id
+, pb_stream *id_pbs
+, u_int8_t *protoid
+, u_int16_t *port
+, ip_subnet *net
+, const char *which)
 {
     ip_subnet net_temp;
 
@@ -1633,10 +2131,9 @@
  * specifies how this is to be done.
  */
 static void
-compute_proto_keymat(
-    struct state *st,
-    u_int8_t protoid,
-    struct ipsec_proto_info *pi)
+compute_proto_keymat(struct state *st
+, u_int8_t protoid
+, struct ipsec_proto_info *pi)
 {
     size_t needed_len; /* bytes of keying material needed */
 
@@ -1795,6 +2292,10 @@
 
     pb_stream r_sa_pbs;
 
+    DBG(DBG_PARSING,
+    DBG_log("in main_inI1_outR1");
+    );
+
     if (c == NULL)
     {
 	/* see if a wildcarded connection can be found */
@@ -1824,7 +2325,7 @@
     extra_debugging(c);
 #endif
     st->st_try = 0;	/* not our job to try again from start */
-    st->st_policy = c->policy;	/* only as accurate as connection */
+    st->st_policy = c->policy & ~POLICY_IPSEC_MASK;    /* only as accurate as connection */
 
     memcpy(st->st_icookie, md->hdr.isa_icookie, COOKIE_SIZE);
     get_cookie(ISAKMP_RESPONDER, st->st_rcookie, COOKIE_SIZE, &md->sender);
@@ -1835,9 +2336,9 @@
     st->st_situation = SIT_IDENTITY_ONLY; /* We only support this */
     st->st_state = STATE_MAIN_R1;
 
-    if (c->rw_state == rwcs_instance)
+    if (c->kind == CK_INSTANCE)
     {
-	log("responding to Main Mode from Road Warrior %s"
+	log("responding to Main Mode from unknown peer %s"
 	    , ip_str(&c->that.host_addr));
     }
     else
@@ -1874,11 +2375,16 @@
     /* SA body in and out */
     RETURN_STF_FAILURE(parse_isakmp_sa_body(&sa_pd->pbs, &sa_pd->payload.sa, &r_sa_pbs
 	    , FALSE, st));
+
     close_message(&md->rbody);
 
     /* save initiator SA for HASH */
     clonereplacechunk(st->st_p1isa, sa_pd->pbs.start, pbs_room(&sa_pd->pbs), "sa in main_inI1_outR1()");
 
+    DBG(DBG_PARSING,
+    DBG_log("finished main_inI1_outR1");
+    );
+
     return STF_REPLY;
 }
 
@@ -1896,21 +2402,37 @@
 main_inR1_outI2(struct msg_digest *md)
 {
     struct state *const st = md->st;
+#ifdef OPENSSL
+  u_int8_t np;
+#endif
+
+  DBG(DBG_PARSING,
+  DBG_log("in main_inR1_outI2");
+  );
 
     /* verify echoed SA */
     {
 	struct payload_digest *const sapd = md->chain[ISAKMP_NEXT_SA];
 
-	RETURN_STF_FAILURE(parse_isakmp_sa_body(&sapd->pbs
-	    , &sapd->payload.sa, NULL, TRUE, st));
+    RETURN_STF_FAILURE(parse_isakmp_sa_body(&sapd->pbs, 
+      &sapd->payload.sa, NULL, TRUE, st));
     }
 
+  /* 
+   * Here, we have to decide if the outgoing packet is going to be created 
+   * for the classic RSASIG, or the OPENSSL functions.
+   */
+#ifdef OPENSSL
+  if (!use_openssl(st->st_connection)) 
+  {
+#endif
     /**************** build output packet HDR;KE;Ni ****************/
 
     /* HDR out.
      * We can't leave this to comm_handle() because the isa_np
      * depends on the type of Auth (eventually).
      */
+
     {
 	struct isakmp_hdr r_hdr = md->hdr;
 
@@ -1920,14 +2442,214 @@
     }
 
     /* KE out */
-    if (!build_and_ship_KE(st, &st->st_gi, st->st_oakley.group
-    , &md->rbody, ISAKMP_NEXT_NONCE))
+    if (!build_and_ship_KE(st, &st->st_gi, st->st_oakley.group, 
+      &md->rbody, ISAKMP_NEXT_NONCE))
 	return STF_INTERNAL_ERROR;
 
     /* Ni out */
     if (!build_and_ship_nonce(&st->st_ni, &md->rbody, ISAKMP_NEXT_NONE, "Ni"))
 	return STF_INTERNAL_ERROR;
 
+#ifdef OPENSSL
+  }
+  else /* use_openssl == TRUE */
+  {
+    DBG(DBG_PARSING, 
+    DBG_log("main_inR1_outI2: auth chosen is %s",
+      enum_show(&oakley_auth_names, st->st_oakley.auth));
+    );
+
+    if ((st->st_oakley.auth == OAKLEY_RSA_ENC_REV) ||
+      (st->st_oakley.auth == OAKLEY_ELGAMAL_ENC_REV)) {
+      struct isakmp_hdr r_hdr = md->hdr;
+
+      /* HDR out */
+      r_hdr.isa_np = ISAKMP_NEXT_NONCE;
+      if (!out_struct(&r_hdr, &isakmp_hdr_desc, &md->reply, &md->rbody))
+        return STF_INTERNAL_ERROR;
+      
+      if (!build_and_ship_nonce_pk(st, &st->st_ni, &md->rbody,
+        ISAKMP_NEXT_KE, "<Ni_b>PubKey_r"))
+        return STF_INTERNAL_ERROR;
+
+      if (derive_symmetric_key(st, st->st_ni,
+        st->st_icookie, COOKIE_SIZE,
+        &st->st_ks_i,
+        &st->st_ne_i) < 0) {
+	log("error while deriving symmetric key in revised mode");
+	return STF_INTERNAL_ERROR;
+      }
+      memset(st->st_ne_i_iv, 0, MAX_DIGEST_LEN);
+      DBG(DBG_PARSING,
+      DBG_dump_chunk("Generated Ke_i:", st->st_ne_i);
+      );
+
+      /* KE out */
+      if (!build_and_ship_KE_rpk(st, TRUE, &st->st_gi, st->st_oakley.group,
+        &md->rbody, ISAKMP_NEXT_ID))
+        return STF_INTERNAL_ERROR;
+
+      /* <IDi1_b>Ke_i,[<cert>Ke_i] out */
+      {
+        chunk_t ch, out;
+
+        /*
+         * Switch for different ID types to send
+         */
+	if (st->st_connection->this.id.kind == ID_DER_ASN1_DN) {
+          ch.len = st->st_connection->this.id.der_asn1_dn.len + 4;
+          ch.ptr = alloc_bytes(ch.len, "encrypted der_asn1_dn identity");
+          ch.ptr[0] = (u_int8_t)st->st_connection->this.id.kind;
+          memset(&(ch.ptr[1]), 0, 1);
+          memset(&(ch.ptr[2]), 0, 2);
+          memcpy(&(ch.ptr[4]), 
+            st->st_connection->this.id.der_asn1_dn.ptr, 
+            st->st_connection->this.id.der_asn1_dn.len);
+        } else {
+          ch.len = sizeof(st->st_connection->this.id.ip_addr) + 4;
+          ch.ptr = alloc_bytes(ch.len, "encrypted identity");
+          ch.ptr[0] = (u_int8_t)st->st_connection->this.id.kind;
+          memset(&(ch.ptr[1]), 0, 1);
+          memset(&(ch.ptr[2]), 0, 2);
+          memcpy(&(ch.ptr[4]), &(st->st_connection->this.id.ip_addr), 
+            sizeof(st->st_connection->this.id.ip_addr));
+	}
+
+        if (!encrypt_payload(st, &st->st_ks_i, st->st_ne_i_iv,
+          ch, &out))
+          return STF_INTERNAL_ERROR;
+        freeanychunk(ch);
+
+        /* Are we going to send CERT? */
+        if ((st->st_connection->cert_options & CERT_OPTION_SEND) == 0) {
+          if (!out_generic_chunk(ISAKMP_NEXT_NONE, &isakmp_generic_desc,
+            &md->rbody, out, "my identity (ciphertext)")) 
+          {
+            freeanychunk(out);
+            return STF_INTERNAL_ERROR;
+          }
+        } else {
+          if (!out_generic_chunk(ISAKMP_NEXT_CERT, &isakmp_generic_desc,
+            &md->rbody, out, "my identity (ciphertext)")) 
+          {
+            freeanychunk(out);
+            return STF_INTERNAL_ERROR;
+          }
+        }
+
+        /* Well, if we do send CERT, let's start on it from here */
+        if ((st->st_connection->cert_options & CERT_OPTION_SEND) != 0) {
+          chunk_t crt, cx;
+          unsigned long ulen;
+          /* Send the signing certificate */
+
+          ulen = i2d_X509(st->st_connection->cert, NULL);
+          ulen++;
+          if ((cx.ptr = alloc_bytes(ulen, "ASN.1 cert")) == NULL)
+          { 
+            return STF_INTERNAL_ERROR; 
+          }
+          (cx.ptr)[0] = (u_char)(CERT_TYPE_X509_SIG);
+          cx.len = ulen;
+          crt.ptr = &(cx.ptr[1]);
+          crt.len = i2d_X509(st->st_connection->cert, &(crt.ptr));
+
+          DBG(DBG_CRYPT,
+          DBG_log("plaintext Certificate length: %d", cx.len);
+          DBG_dump_chunk("plaintext Certificate", cx);
+          );
+
+          /* encrypt the certificate to send */
+          if (!encrypt_payload(st, &st->st_ks_i, st->st_ne_i_iv,
+            cx, &out))
+          return STF_INTERNAL_ERROR;
+
+          DBG(DBG_CRYPT,
+          DBG_log("cyphertext Certificate length: %d", out.len);
+          DBG_dump_chunk("cyphertext Certificate", out);
+          );
+
+          if (!out_generic_chunk(ISAKMP_NEXT_NONE, 
+            &isakmp_ipsec_certificate_desc,
+            &md->rbody, out, "my certificate (ciphertext)")) 
+          {
+            freeanychunk(out);
+            return STF_INTERNAL_ERROR;
+          }
+        }
+        /* end of sending out cert */
+
+        freeanychunk(out);
+      }
+    } else {
+      struct isakmp_hdr r_hdr = md->hdr;
+      
+      r_hdr.isa_np = ISAKMP_NEXT_KE;
+      if (!out_struct(&r_hdr, &isakmp_hdr_desc, &md->reply, &md->rbody))
+        return STF_INTERNAL_ERROR;
+
+      if ((st->st_oakley.auth == OAKLEY_RSA_ENC) ||
+        (st->st_oakley.auth == OAKLEY_ELGAMAL_ENC))
+        np = ISAKMP_NEXT_ID;
+      else /* Digital Sig or Preshared key */
+        np = ISAKMP_NEXT_NONCE;
+      
+      /* KE out */
+      if (!build_and_ship_KE(st, &st->st_gi, st->st_oakley.group, 
+        &md->rbody, np))
+        return STF_INTERNAL_ERROR;
+      
+      if ((st->st_oakley.auth == OAKLEY_RSA_ENC) ||
+	  (st->st_oakley.auth == OAKLEY_ELGAMAL_ENC)) {
+
+	/* <IDii_b>PubKey_r out */
+	chunk_t ch;
+
+        /* Switch for different ID types to send */
+        if (st->st_connection->this.id.kind == ID_DER_ASN1_DN) {
+          ch.len = st->st_connection->this.id.der_asn1_dn.len + 4;
+          ch.ptr = alloc_bytes(ch.len, "plaintext der_asn1_dn identity");
+          ch.ptr[0] = (u_int8_t)st->st_connection->this.id.kind;
+          memset(&(ch.ptr[1]), 0, 1);
+          memset(&(ch.ptr[2]), 0, 2);
+          memcpy(&(ch.ptr[4]), 
+            st->st_connection->this.id.der_asn1_dn.ptr, 
+            st->st_connection->this.id.der_asn1_dn.len);
+        } else {
+          ch.len = sizeof(st->st_connection->this.id.ip_addr) + 4;
+          ch.ptr = alloc_bytes(ch.len, "my identity (plaintext)");
+          ch.ptr[0] = (u_int8_t)st->st_connection->this.id.kind;
+          memset(&(ch.ptr[1]), 0, 1);
+          memset(&(ch.ptr[2]), 0, 2);
+          memcpy(&(ch.ptr[4]), &(st->st_connection->this.id.ip_addr), 
+            sizeof(st->st_connection->this.id.ip_addr));
+        }
+
+        /* PK encrypt this */
+        if (! pubkey_encrypt_chunk( &ch, st )) {
+          return STF_INTERNAL_ERROR;
+        }
+        if (!out_generic_chunk(ISAKMP_NEXT_NONCE, &isakmp_generic_desc,
+          &md->rbody, ch, "my identity (ciphertext)"))
+        return STF_INTERNAL_ERROR;
+        memset(ch.ptr, 0, ch.len);
+        freeanychunk(ch);
+
+        if (!build_and_ship_nonce_pk(st, &st->st_ni, &md->rbody,
+          ISAKMP_NEXT_NONE, "<Ni_b>PubKey_r"))
+          return STF_INTERNAL_ERROR;
+      } else {
+        DBG(DBG_PARSING,
+        DBG_log("Shipping nonce_i");
+        );
+        if (!build_and_ship_nonce(&st->st_ni, &md->rbody, 
+          ISAKMP_NEXT_NONE, "Ni"))
+          return STF_INTERNAL_ERROR;
+      }
+    }
+  }
+#endif
+
     /* finish message */
     close_message(&md->rbody);
 
@@ -1938,6 +2660,10 @@
 
     st->st_state = STATE_MAIN_I2;
 
+  DBG(DBG_PARSING,
+  DBG_log("finished main_inR1_outI2");
+  );
+
     return STF_REPLY;
 }
 
@@ -1957,6 +2683,10 @@
     struct state *const st = md->st;
     pb_stream *keyex_pbs = &md->chain[ISAKMP_NEXT_KE]->pbs;
 
+    DBG(DBG_PARSING,
+    DBG_log("in main_inI2_outR2");
+    );
+
     /* KE in */
     RETURN_STF_FAILURE(accept_KE(&st->st_gi, "Gi", st->st_oakley.group, keyex_pbs));
 
@@ -1986,8 +2716,9 @@
     compute_dh_shared(st, st->st_gi, st->st_oakley.group);
 #ifdef DODGE_DH_MISSING_ZERO_BUG
     if (st->st_shared.ptr[0] == 0)
-	return STF_DROP_DOOMED_EXCHANGE;
+      return STF_REPLACE_DOOMED_EXCHANGE;
 #endif
+
     if (!generate_skeyids_iv(st))
 	return STF_FAIL + AUTHENTICATION_FAILED;
     update_iv(st);
@@ -1995,210 +2726,1117 @@
     /* Advance state */
     st->st_state = STATE_MAIN_R2;
 
+    DBG(DBG_PARSING,
+    DBG_log("finished main_inI2_outR2");
+    );
+
     return STF_REPLY;
 }
 
-/* STATE_MAIN_I2:
- * SMF_PSK_AUTH: HDR, KE, Nr --> HDR*, IDi1, HASH_I
- * SMF_DS_AUTH: HDR, KE, Nr --> HDR*, IDi1, [ CERT, ] SIG_I
- *
- * The following are not yet implemented.
- * SMF_PKE_AUTH: HDR, KE, <IDr1_b>PubKey_i, <Nr_b>PubKey_i
- *	    --> HDR*, HASH_I
- * SMF_RPKE_AUTH: HDR, <Nr_b>PubKey_i, <KE_b>Ke_r, <IDr1_b>Ke_r
- *	    --> HDR*, HASH_I
+#ifdef OPENSSL
+/* Handle HDR;KE;<IDii_b>PubKey_r;<Ni_b>PubKey_r from Initiator.
+ * Send a HDR;KE;<IDir_b>PubKey_i;<Nr_b>PubKey_i back.
  */
 stf_status
-main_inR2_outI3(struct msg_digest *md)
+main_inI2_outR2_pk(struct msg_digest *md)
 {
     struct state *const st = md->st;
-    pb_stream *const keyex_pbs = &md->chain[ISAKMP_NEXT_KE]->pbs;
-    int auth_payload = st->st_oakley.auth == OAKLEY_PRESHARED_KEY
-	? ISAKMP_NEXT_HASH : ISAKMP_NEXT_SIG;
+    pb_stream *keyex_pbs = &md->chain[ISAKMP_NEXT_KE]->pbs;
+
+    DBG(DBG_PARSING,
+    DBG_log("in main_inI2_outR2_pk");
+    );
 
     /* KE in */
-    RETURN_STF_FAILURE(accept_KE(&st->st_gr, "Gr", st->st_oakley.group, keyex_pbs));
+    RETURN_STF_FAILURE(accept_KE(&st->st_gi, "Gi", 
+      st->st_oakley.group, keyex_pbs));
 
-    /* Nr in */
-    RETURN_STF_FAILURE(accept_nonce(md, &st->st_nr, "Nr"));
+    if (!decode_peer_id(md, FALSE))
+    return STF_FAIL + INVALID_ID_INFORMATION;
 
-    /* done parsing; initialize crypto  */
+    /* Ni_b<PubKey_r> in */
+    RETURN_STF_FAILURE(accept_nonce(md, &st->st_ni, "<Ni_b>PubKey_r"));
 
-    compute_dh_shared(st, st->st_gr, st->st_oakley.group);
-#ifdef DODGE_DH_MISSING_ZERO_BUG
-    if (st->st_shared.ptr[0] == 0)
-	return STF_REPLACE_DOOMED_EXCHANGE;
-#endif
-    if (!generate_skeyids_iv(st))
-	return STF_FAIL + AUTHENTICATION_FAILED;
+    /** build output packet HDR;KE;<IDir_b>_PubKey_i;<Nr_b>PubKey_i*********/
 
-    /*************** build output packet HDR*;IDii;HASH/SIG_I ***************/
-    /* ??? NOTE: this is almost the same as main_inI3_outR3's code */
+    /* HDR out done */
 
-    /* HDR* out done */
+    /* KE out */
+    if (!build_and_ship_KE(st, &st->st_gr, st->st_oakley.group, 
+    &md->rbody, ISAKMP_NEXT_ID))
+	return STF_INTERNAL_ERROR;
 
-    /* IDii out */
     {
-	struct isakmp_ipsec_id id_hd;
-	chunk_t id_b;
-	pb_stream id_pbs;
+      /* <IDir_b>PubKey_i out */
+      chunk_t ch;
 
-	build_id_payload(&id_hd, &id_b, &st->st_connection->this);
-	id_hd.isaiid_np = auth_payload;
-	if (!out_struct(&id_hd, &isakmp_ipsec_identification_desc, &md->rbody, &id_pbs)
-	|| !out_chunk(id_b, &id_pbs, "my identity"))
-	    return STF_INTERNAL_ERROR;
-	close_output_pbs(&id_pbs);
+      if (st->st_connection->this.id.kind == ID_DER_ASN1_DN) {
+        ch.len = st->st_connection->this.id.der_asn1_dn.len + 4;
+        ch.ptr = alloc_bytes(ch.len, "plaintext der_asn1_dn identity");
+        ch.ptr[0] = (u_int8_t)st->st_connection->this.id.kind;
+        memset(&(ch.ptr[1]), 0, 1);
+        memset(&(ch.ptr[2]), 0, 2);
+        memcpy(&(ch.ptr[4]), 
+          st->st_connection->this.id.der_asn1_dn.ptr, 
+          st->st_connection->this.id.der_asn1_dn.len);     
+      } else {
+        ch.len = sizeof(st->st_connection->this.id.ip_addr) + 4;
+        ch.ptr = alloc_bytes(ch.len, "plaintext identity");
+        ch.ptr[0] = (u_int8_t)st->st_connection->this.id.kind;
+        memset(&(ch.ptr[1]), 0, 1);
+        memset(&(ch.ptr[2]), 0, 2);
+        memcpy(&(ch.ptr[4]), &(st->st_connection->this.id.ip_addr),
+          sizeof(st->st_connection->this.id.ip_addr));
     }
 
-    /* HASH_I or SIG_I out */
-    {
-	u_char hash_val[MAX_DIGEST_LEN];
-	size_t hash_len = main_mode_hash(st, hash_val, TRUE, TRUE);
 
-	if (auth_payload == ISAKMP_NEXT_HASH)
-	{
-	    /* HASH_I out */
-	    if (!out_generic_raw(ISAKMP_NEXT_NONE, &isakmp_hash_desc, &md->rbody
-	    , hash_val, hash_len, "HASH_I"))
+      /* PK encrypt this */
+      if (! pubkey_encrypt_chunk( &ch, st )) {
 		return STF_INTERNAL_ERROR;
 	}
-	else
-	{
-	    /* SIG_I out */
-	    u_char sig_val[RSA_MAX_OCTETS];
-	    size_t sig_len = RSA_sign_hash(st->st_connection
-		, sig_val, hash_val, hash_len);
-
-	    if (sig_len == 0)
-	    {
-		loglog(RC_LOG_SERIOUS, "unable to locate my private key for RSA Signature");
-		return STF_FAIL + AUTHENTICATION_FAILED;
+      if (!out_generic_chunk(ISAKMP_NEXT_NONCE, &isakmp_generic_desc, &md->rbody, ch, "my identity (ciphertext)"))
+	return STF_INTERNAL_ERROR;
+      memset(ch.ptr, 0, ch.len);
+      freeanychunk(ch);
 	    }
 
-	    if (!out_generic_raw(ISAKMP_NEXT_NONE, &isakmp_signature_desc
-	    , &md->rbody, sig_val, sig_len, "SIG_I"))
+    /* Nr out */
+    if (!build_and_ship_nonce_pk(st, &st->st_nr, &md->rbody, ISAKMP_NEXT_NONE, "<Nr_b>PubKey_i"))
 		return STF_INTERNAL_ERROR;
-	}
-    }
 
-    /* encrypt message, except for fixed part of header */
+    /* finish message */
+    close_message(&md->rbody);
 
-    /* st_new_iv was computed by generate_skeyids_iv */
-    if (!encrypt_message(&md->rbody, st))
-	return STF_INTERNAL_ERROR;	/* ??? we may be partly committed */
+    /* next message will be encrypted, but not this one.
+     * We could defer this calculation.
+     */
+#ifndef DODGE_DH_MISSING_ZERO_BUG
+    compute_dh_shared(st, st->st_gi, st->st_oakley.group);
+#endif
+    if (!generate_skeyids_iv(st))
+	return STF_FAIL + AUTHENTICATION_FAILED;
+    update_iv(st);
 
     /* Advance state */
-    st->st_state = STATE_MAIN_I3;
+    st->st_state = STATE_MAIN_R2;
+
+    DBG(DBG_PARSING,
+    DBG_log("finished main_inI2_outR2_pk");
+    );
 
     return STF_REPLY;
 }
+#endif /* OPENSSL */
 
-/* STATE_MAIN_R2:
- * PSK_AUTH: HDR*, IDi1, HASH_I --> HDR*, IDr1, HASH_R
- * DS_AUTH: HDR*, IDi1, [ CERT, ] SIG_I --> HDR*, IDr1, [ CERT, ] SIG_R
- * PKE_AUTH, RPKE_AUTH: HDR*, HASH_I --> HDR*, HASH_R
+#ifdef OPENSSL
+/* Handle HDR;<Ni_b>Pubkey_r;<KE_b>Ke_i;<IDi1_b>Ke_i[;<cert>Ke_r] from Initiator
+ * Send a HDR;<Nr_b>Pubkey_i;<KE_b>Ke_r;<IDr1_b>Ke_r[;<cert>Ke_r] back.
  */
 stf_status
-main_inI3_outR3(struct msg_digest *md)
+main_inI2_outR2_rpk(struct msg_digest *md)
 {
     struct state *const st = md->st;
-    int auth_payload = st->st_oakley.auth == OAKLEY_PRESHARED_KEY
-	? ISAKMP_NEXT_HASH : ISAKMP_NEXT_SIG;
+    pb_stream *keyex_pbs = &md->chain[ISAKMP_NEXT_KE]->pbs;
 
-    /* input code similar to main_inR3 -- should be factored */
+    DBG(DBG_PARSING,
+    DBG_log("in main_inI2_outR2_rpk");
+    );
+
+    /* Ni_b<PubKey_r> in */
+    RETURN_STF_FAILURE(accept_nonce(md, &st->st_ni, "<Ni_b>PubKey_r"));
+
+    /* KE<Ke_r> in */
+    RETURN_STF_FAILURE(accept_KE(&st->st_gi, "Gi", 
+      st->st_oakley.group, keyex_pbs));
 
-    /* IDii in */
     if (!decode_peer_id(md, FALSE))
 	return STF_FAIL + INVALID_ID_INFORMATION;
 
-    /* HASH_I or SIG_I in */
-    RETURN_STF_FAILURE(check_main_authenticator(md, TRUE));
+    /**************** build output packet ****************/
 
-    /*************** build output packet HDR*;IDir;HASH/SIG_R ***************/
-    /* ??? NOTE: this is almost the same as main_inR2_outI3's code */
+    /* HDR out done */
 
-    /* IDir out */
-    {
-	struct isakmp_ipsec_id id_hd;
-	chunk_t id_b;
-	pb_stream r_id_pbs;
+    /* Nr out */
+    if (!build_and_ship_nonce_pk(st, &st->st_nr, &md->rbody, 
+      ISAKMP_NEXT_KE, "<Nr_b>PubKey_i")) 
+      return STF_INTERNAL_ERROR;
 
-	build_id_payload(&id_hd, &id_b, &st->st_connection->this);
-	id_hd.isaiid_np = auth_payload;
-	if (!out_struct(&id_hd, &isakmp_ipsec_identification_desc, &md->rbody, &r_id_pbs)
-	|| !out_chunk(id_b, &r_id_pbs, "my identity"))
+    if (derive_symmetric_key(st, st->st_nr,
+			     st->st_rcookie, COOKIE_SIZE,
+			     &st->st_ks_r,
+			     &st->st_ne_r) < 0) {
+      log("error while deriving symmetric key in revised mode");
 	    return STF_INTERNAL_ERROR;
-	close_output_pbs(&r_id_pbs);
     }
+    memset(st->st_ne_r_iv, 0, MAX_DIGEST_LEN);
 
-    /* HASH_R or SIG_R out */
-    {
-	u_char hash_val[MAX_DIGEST_LEN];
-	size_t hash_len = main_mode_hash(st, hash_val, FALSE, TRUE);
+    DBG(DBG_PARSING,
+    DBG_dump_chunk("Generated Ke_r:", st->st_ne_r);
+    );
 
-	if (auth_payload == ISAKMP_NEXT_HASH)
-	{
-	    /* HASH_R out */
-	    if (!out_generic_raw(ISAKMP_NEXT_NONE, &isakmp_hash_desc, &md->rbody
-	    , hash_val, hash_len, "HASH_R"))
+    /* KE out */
+    if (!build_and_ship_KE_rpk(st, FALSE, &st->st_gr, st->st_oakley.group
+			       , &md->rbody, ISAKMP_NEXT_ID))
 		return STF_INTERNAL_ERROR;
-	}
-	else
-	{
-	    /* SIG_R out */
-	    u_char sig_val[RSA_MAX_OCTETS];
-	    size_t sig_len = RSA_sign_hash(st->st_connection
-		, sig_val, hash_val, hash_len);
 
-	    if (sig_len == 0)
+    /* <IDr1_b>Ke_r[<cert>Ke_r] out */
 	    {
-		loglog(RC_LOG_SERIOUS, "unable to locate my private key for RSA Signature");
-		return STF_FAIL + AUTHENTICATION_FAILED;
+      chunk_t ch, out;
+
+      if (st->st_connection->this.id.kind == ID_DER_ASN1_DN) {
+        ch.len = st->st_connection->this.id.der_asn1_dn.len + 4;
+        ch.ptr = alloc_bytes(ch.len, "encrypted der_asn1_dn identity");
+        ch.ptr[0] = (u_int8_t)st->st_connection->this.id.kind;
+        memset(&(ch.ptr[1]), 0, 1);
+        memset(&(ch.ptr[2]), 0, 2);
+        memcpy(&(ch.ptr[4]), 
+          st->st_connection->this.id.der_asn1_dn.ptr, 
+          st->st_connection->this.id.der_asn1_dn.len);     
+      } else {
+        ch.len = sizeof(st->st_connection->this.id.ip_addr) + 4;
+        ch.ptr = alloc_bytes(ch.len, "encrypted identity");
+        ch.ptr[0] = (u_int8_t)st->st_connection->this.id.kind;
+        memset(&(ch.ptr[1]), 0, 1);
+        memset(&(ch.ptr[2]), 0, 2);
+        memcpy(&(ch.ptr[4]), &(st->st_connection->this.id.ip_addr),
+          sizeof(st->st_connection->this.id.ip_addr));
 	    }
 
-	    if (!out_generic_raw(ISAKMP_NEXT_NONE, &isakmp_signature_desc
-	    , &md->rbody, sig_val, sig_len, "SIG_R"))
+      if (!encrypt_payload(st, &st->st_ks_r, st->st_ne_r_iv,
+        ch, &out))
 		return STF_INTERNAL_ERROR;
+      freeanychunk(ch);
+
+      /* Are we going to send CERT? */
+      if ((st->st_connection->cert_options & CERT_OPTION_SEND) == 0) {
+        if (!out_generic_chunk(ISAKMP_NEXT_NONE, &isakmp_generic_desc,
+          &md->rbody, out, "my identity (ciphertext)")) 
+        {
+	  freeanychunk(out);
+	  return STF_INTERNAL_ERROR;
+        }
+      } else {
+        if (!out_generic_chunk(ISAKMP_NEXT_CERT, &isakmp_generic_desc,
+          &md->rbody, out, "my identity (ciphertext)")) 
+        {
+	  freeanychunk(out);
+	  return STF_INTERNAL_ERROR;
+        }
+      }
+      freeanychunk(out);
+    }
+
+        /* Well, if we do send CERT, let's start on it from here */
+        if ((st->st_connection->cert_options & CERT_OPTION_SEND) != 0) {
+
+          chunk_t crt, cx, out;
+          unsigned long ulen;
+          /* Send the signing certificate */
+
+          ulen = i2d_X509(st->st_connection->cert, NULL);
+          ulen++;
+          if ((cx.ptr = alloc_bytes(ulen, "ASN.1 cert")) == NULL)
+          { 
+            return STF_INTERNAL_ERROR; 
+          }
+          (cx.ptr)[0] = (u_char)(CERT_TYPE_X509_SIG);
+          cx.len = ulen;
+          crt.ptr = &(cx.ptr[1]);
+          crt.len = i2d_X509(st->st_connection->cert, &(crt.ptr));
+
+          DBG(DBG_CRYPT,
+          DBG_log("plaintext Certificate length: %d", cx.len);
+          DBG_dump_chunk("plaintext Certificate", cx);
+          );
+
+          /* encrypt the certificate to send */
+          if (!encrypt_payload(st, &st->st_ks_r, st->st_ne_r_iv,
+            cx, &out))
+          return STF_INTERNAL_ERROR;
+
+          DBG(DBG_CRYPT,
+          DBG_log("cyphertext Certificate length: %d", out.len);
+          DBG_dump_chunk("cyphertext Certificate", out);
+          );
+
+          if (!out_generic_chunk(ISAKMP_NEXT_NONE, 
+            &isakmp_ipsec_certificate_desc,
+            &md->rbody, out, "my certificate (ciphertext)")) 
+          {
+            freeanychunk(out);
+            return STF_INTERNAL_ERROR;
+          }
+        }
+        /* end of sending out cert */
+    
+    /* finish message */
+    close_message(&md->rbody);
+
+    /* next message will be encrypted, but not this one.
+     * We could defer this calculation.
+     */
+#ifndef DODGE_DH_MISSING_ZERO_BUG
+    compute_dh_shared(st, st->st_gi, st->st_oakley.group);
+#endif
+    if (!generate_skeyids_iv(st))
+	return STF_FAIL + AUTHENTICATION_FAILED;
+    update_iv(st);
+
+    /* Advance state */
+    st->st_state = STATE_MAIN_R2;
+
+    DBG(DBG_PARSING,
+    DBG_log("finished main_inI2_outR2_rpk");
+    );
+
+    return STF_REPLY;
+}
+#endif /* OPENSSL */
+
+
+/* STATE_MAIN_I2:
+ * SMF_PSK_AUTH: HDR, KE, Nr --> HDR*, IDi1, HASH_I
+ * SMF_DS_AUTH: HDR, KE, Nr --> HDR*, IDi1, [ CERT, ] SIG_I
+ *
+ * The following are not yet implemented.
+ * SMF_PKE_AUTH: HDR, KE, <IDr1_b>PubKey_i, <Nr_b>PubKey_i
+ *	    --> HDR*, HASH_I
+ * SMF_RPKE_AUTH: HDR, <Nr_b>PubKey_i, <KE_b>Ke_r, <IDr1_b>Ke_r
+ *	    --> HDR*, HASH_I
+ */
+stf_status
+main_inR2_outI3(struct msg_digest *md)
+{
+    struct state *const st = md->st;
+#ifdef OPENSSL
+    struct connection *c = st->st_connection;
+#endif
+
+    pb_stream *const keyex_pbs = &md->chain[ISAKMP_NEXT_KE]->pbs;
+
+    int auth_payload = st->st_oakley.auth == OAKLEY_PRESHARED_KEY
+	? ISAKMP_NEXT_HASH : ISAKMP_NEXT_SIG;
+
+    DBG(DBG_PARSING,
+    DBG_log("in main_inR2_outI3");
+    );
+
+    /* KE in */
+    RETURN_STF_FAILURE(accept_KE(&st->st_gr, "Gr", 
+		st->st_oakley.group, keyex_pbs));
+
+    /* Nr in */
+    RETURN_STF_FAILURE(accept_nonce(md, &st->st_nr, "Nr"));
+
+    /* done parsing; initialize crypto  */
+
+    compute_dh_shared(st, st->st_gr, st->st_oakley.group);
+#ifdef DODGE_DH_MISSING_ZERO_BUG
+    if (st->st_shared.ptr[0] == 0)
+       return STF_REPLACE_DOOMED_EXCHANGE;
+#endif
+    if (!generate_skeyids_iv(st))
+	return STF_FAIL + AUTHENTICATION_FAILED;
+
+    /*************** build output packet HDR*;IDii;HASH/SIG_I ***************/
+    /* ??? NOTE: this is almost the same as main_inI3_outR3's code */
+
+    /* HDR* out done */
+
+    /* IDii out */
+    {
+	struct isakmp_ipsec_id id_hd;
+	chunk_t id_b;
+	pb_stream id_pbs;
+
+	build_id_payload(&id_hd, &id_b, &st->st_connection->this);
+#ifdef OPENSSL
+if (use_openssl(st->st_connection)) 
+{
+  switch(st->st_oakley.auth) {
+  case OAKLEY_RSA_SIG:
+  case OAKLEY_DSS_SIG:
+    if ((c->cert_options & CERT_OPTION_SEND) == 0)
+      id_hd.isaiid_np = ISAKMP_NEXT_SIG;
+    else
+      id_hd.isaiid_np = ISAKMP_NEXT_CERT;
+    break;
+  case OAKLEY_RSA_ENC:
+  case OAKLEY_RSA_ENC_REV:
+    log("RSA method not supported yet");
+    return STF_INTERNAL_ERROR;
+    break;
+  default:
+    id_hd.isaiid_np = ISAKMP_NEXT_HASH;
+    break;
+  }
+}
+else
+{
+#endif /* OPENSSL */
+	id_hd.isaiid_np = auth_payload;
+#ifdef OPENSSL
+}
+#endif /* OPENSSL */
+
+	if (!out_struct(&id_hd, &isakmp_ipsec_identification_desc, &md->rbody, &id_pbs)
+		|| !out_chunk(id_b, &id_pbs, "my identity")) 
+		return STF_INTERNAL_ERROR;
+	close_output_pbs(&id_pbs);
+    } /* IDii out done */
+
+#ifdef OPENSSL
+if (use_openssl(st->st_connection)) 
+{
+    if (((c->cert_options & CERT_OPTION_SEND) != 0) &&
+  ((st->st_oakley.auth == OAKLEY_RSA_SIG) ||
+   (st->st_oakley.auth == OAKLEY_DSS_SIG))) {
+      u_char *crt, *cx;
+      unsigned long ulen;
+      /* Send the signing certificate */
+
+      ulen = i2d_X509(c->cert, NULL);
+      ulen++;
+      if ((cx = alloc_bytes(ulen, "ASN.1 cert")) == NULL)
+  { return STF_INTERNAL_ERROR; }
+      cx[0] = (u_char)(CERT_TYPE_X509_SIG);
+      crt = &(cx[1]);
+      i2d_X509(c->cert, &crt);
+      if (!out_generic_raw(ISAKMP_NEXT_SIG, &isakmp_ipsec_certificate_desc
+             , &md->rbody, cx, ulen, "CERT_I"))
+  return STF_INTERNAL_ERROR;
+      pfree(cx);
+    }
+
+  /* HASH_I out, OPENSSL */
+  {
+	u_char hash_val[MAX_DIGEST_LEN];
+	size_t hash_len = main_mode_hash(st, hash_val, TRUE, TRUE);
+    u_char *buf;
+    u_int elen;
+    bool ok;
+
+  /* Output the signature/hash as defined by the selected Oakley transform */
+
+  switch (st->st_oakley.auth) {
+  case OAKLEY_RSA_SIG: /* output signed HASH_I */
+    if ((buf = alloc_bytes(EVP_PKEY_size(c->key) + 32 /* bit of slack */,
+               "RSA signature")) == NULL)
+        return STF_INTERNAL_ERROR;
+    elen = RSA_private_encrypt(hash_len, hash_val, buf,
+                   ((EVP_PKEY *)(c->key))->pkey.rsa,
+                   RSA_PKCS1_PADDING);
+    if (!out_generic_raw(ISAKMP_NEXT_NONE, &isakmp_signature_desc, &md->rbody
+                 , buf, elen, "SIG_I"))
+      return STF_INTERNAL_ERROR;
+    pfree(buf);
+   
+	DBG(DBG_PARSING,
+	    DBG_log("Selected auth mechanism is %s",
+        	enum_show(&oakley_auth_names, st->st_oakley.auth));
+	)
+    break;
+
+  case OAKLEY_DSS_SIG:
+    /* We don't have to check whether the hash is a SHA1 */
+    /* one, since the ciphersuite offering DSA is only */
+    /* configured with SHA1. Don't change this configuration */
+    if (c->cert_options & CERT_OPTION_DSS_SHA)
+      main_mode_sha1(st, hash_val, &hash_len, TRUE, TRUE);
+
+    buf = alloc_bytes(EVP_PKEY_size(c->key) + 32 /* bit of slack */,
+              "DSA signature");
+    if (buf) {
+      ok = (c->cert_options & CERT_OPTION_DSS_ALT)
+        ? DSA_sign_raw(hash_val, hash_len,
+               buf, &elen, ((EVP_PKEY *)(c->key))->pkey.dsa)
+        : DSA_sign(EVP_PKEY_DSA, hash_val, hash_len,
+           buf, &elen, ((EVP_PKEY *)(c->key))->pkey.dsa);
+      if (!ok) {
+        /* DSA signing failed */
+        log_err();
+        return STF_INTERNAL_ERROR;
+      }
+      if (!out_generic_raw(ISAKMP_NEXT_NONE, &isakmp_signature_desc,
+               &md->rbody, buf, elen, "SIG_I"))
+        return STF_INTERNAL_ERROR;
+      pfree(buf);
+    } else
+      return STF_INTERNAL_ERROR;
+   
+	DBG(DBG_PARSING | DBG_CONTROL, 
+	DBG_log("Selected auth mechanism is %s",
+	  enum_show(&oakley_auth_names, st->st_oakley.auth));
+	);
+    break;
+    /* If we get to any of these, something has gone WAY wrong */
+  case OAKLEY_RSA_ENC:
+    return STF_INTERNAL_ERROR;
+  case OAKLEY_ELGAMAL_ENC:
+    return STF_INTERNAL_ERROR;
+  case OAKLEY_RSA_ENC_REV:
+    return STF_INTERNAL_ERROR;
+  case OAKLEY_ELGAMAL_ENC_REV:
+    return STF_INTERNAL_ERROR;
+  default:
+	} /* switch done */
+  } /* HASH_I out, openssl done. */
+}
+else
+{
+#endif /* OPENSSL */
+  /* HASH_I or SIG_I out, !OPENSSL */
+  {
+	u_char hash_val[MAX_DIGEST_LEN];
+	size_t hash_len = main_mode_hash(st, hash_val, TRUE, TRUE);
+
+	if (auth_payload == ISAKMP_NEXT_HASH)
+	{
+	    /* HASH_I out */
+	    if (!out_generic_raw(ISAKMP_NEXT_NONE, &isakmp_hash_desc, &md->rbody
+	    , hash_val, hash_len, "HASH_I"))
+		return STF_INTERNAL_ERROR;
+	}
+	else
+	{
+	    /* SIG_I out */
+	    u_char sig_val[RSA_MAX_OCTETS];
+	    size_t sig_len = RSA_sign_hash(st->st_connection, 
+			sig_val, hash_val, hash_len);
+
+	    if (sig_len == 0)
+	    {
+		loglog(RC_LOG_SERIOUS, "unable to locate my private key for RSA Signature");
+		return STF_FAIL + AUTHENTICATION_FAILED;
+	    }
+
+	    if (!out_generic_raw(ISAKMP_NEXT_NONE, &isakmp_signature_desc
+	    , &md->rbody, sig_val, sig_len, "SIG_I"))
+		return STF_INTERNAL_ERROR;
+	}
+  }
+#ifdef OPENSSL
+}
+#endif /* OPENSSL */
+
+    /* encrypt message, except for fixed part of header */
+
+    /* st_new_iv was computed by generate_skeyids_iv */
+    if (!encrypt_message(&md->rbody, st))
+	return STF_INTERNAL_ERROR;	/* ??? we may be partly committed */
+
+    /* Advance state */
+    st->st_state = STATE_MAIN_I3;
+
+    DBG(DBG_PARSING,
+    DBG_log("finished main_inR2_outI3");
+    );
+
+    return STF_REPLY;
+}
+
+#ifdef OPENSSL
+/*
+ * Handle HDR;KE;<IDir_b>PubKey_i;<Nr_b>PubKey_i from responder.
+ * Send a HDR*;HASH_I back.
+ */
+stf_status main_inR2_outI3_pk(struct msg_digest *md)
+{
+    struct state *const st = md->st;
+    pb_stream *const keyex_pbs = &md->chain[ISAKMP_NEXT_KE]->pbs;
+
+    DBG(DBG_PARSING,
+    DBG_log("in main_inR2_outI3_pk");
+    );
+
+    /* KE in */
+    RETURN_STF_FAILURE(accept_KE(&st->st_gr, "Gr", 
+	st->st_oakley.group, keyex_pbs));
+
+    /* IDir in */
+    if (!decode_peer_id(md, TRUE))
+    return STF_FAIL + INVALID_ID_INFORMATION;
+
+    /* Nr in */
+    RETURN_STF_FAILURE(accept_nonce(md, &st->st_nr, "<Nr_b>PubKey_i"));
+
+    /* done parsing; initialize crypto  */
+
+    compute_dh_shared(st, st->st_gr, st->st_oakley.group);
+#ifdef DODGE_DH_MISSING_ZERO_BUG
+    if (st->st_shared.ptr[0] == 0)
+       return STF_REPLACE_DOOMED_EXCHANGE;
+#endif
+    if (!generate_skeyids_iv(st))
+    return STF_FAIL + AUTHENTICATION_FAILED;
+
+    /**************** build output packet HDR*;HASH_I ****************/
+
+    /* HDR* out done */
+
+    /* HASH_I out */
+    {
+  u_char hash_val[MAX_DIGEST_LEN];
+  size_t hash_len = main_mode_hash(st, hash_val, TRUE, TRUE);
+
+  if (!out_generic_raw(ISAKMP_NEXT_NONE, &isakmp_hash_desc, &md->rbody
+  , hash_val, hash_len, "HASH_I"))
+      return STF_INTERNAL_ERROR;
+    }
+
+    /* encrypt message, except for fixed part of header */
+
+    /* st_new_iv was computed by generate_skeyids_iv */
+    if (!encrypt_message(&md->rbody, st))
+    return STF_INTERNAL_ERROR;  /* ??? we may be partly committed */
+
+    /* Advance state */
+    st->st_state = STATE_MAIN_I3;
+
+    DBG(DBG_PARSING,
+    DBG_log("finished main_inR2_outI3_pk");
+    );
+
+    return STF_REPLY;
+}
+#endif /* OPENSSL */
+
+#ifdef OPENSSL
+/* Handle HDR;KE;<Nr_b>PubKey_i;<KE_b>Ke_r;<IDr1_b>Ke_r from responder.
+ * Send a HDR*;HASH_I back.
+ */
+stf_status
+main_inR2_outI3_rpk(struct msg_digest *md)
+{
+    struct state *const st = md->st;
+    pb_stream *const keyex_pbs = &md->chain[ISAKMP_NEXT_KE]->pbs;
+
+    DBG(DBG_PARSING,
+    DBG_log("in main_inR2_outI3_rpk");
+    );
+
+    /* Nr in */
+    RETURN_STF_FAILURE(accept_nonce(md, &st->st_nr, "<Nr_b>PubKey_i"));
+
+    /* KE in */
+    RETURN_STF_FAILURE(accept_KE(&st->st_gr, "Gr", 
+      st->st_oakley.group, keyex_pbs));
+
+    /* IDir in */
+    if (!decode_peer_id(md, TRUE))
+      return STF_FAIL + INVALID_ID_INFORMATION;
+
+    /* done parsing; initialize crypto  */
+
+    compute_dh_shared(st, st->st_gr, st->st_oakley.group);
+#ifdef DODGE_DH_MISSING_ZERO_BUG
+    if (st->st_shared.ptr[0] == 0)
+	return STF_REPLACE_DOOMED_EXCHANGE;
+#endif
+    if (!generate_skeyids_iv(st))
+  return STF_FAIL + AUTHENTICATION_FAILED;
+
+    /**************** build output packet HDR*;HASH_I ****************/
+
+    /* HDR* out done */
+
+    /* HASH_I out */
+    {
+      u_char hash_val[MAX_DIGEST_LEN];
+
+      size_t hash_len = main_mode_hash(st, hash_val, TRUE, TRUE);
+
+      if (!out_generic_raw(ISAKMP_NEXT_NONE, &isakmp_hash_desc, &md->rbody, 
+        hash_val, hash_len, "HASH_I"))
+      return STF_INTERNAL_ERROR;
+    }
+
+    /* encrypt message, except for fixed part of header */
+
+    /* st_new_iv was computed by generate_skeyids_iv */
+    if (!encrypt_message(&md->rbody, st))
+    return STF_INTERNAL_ERROR;  /* ??? we may be partly committed */
+
+    /* Advance state */
+    st->st_state = STATE_MAIN_I3;
+
+    DBG(DBG_PARSING,
+    DBG_log("fnished main_inR2_outI3_rpk");
+    );
+
+    return STF_REPLY;
+}
+#endif /* OPENSSL */
+
+
+#ifdef OPENSSL
+/* STATE_MAIN_R2:
+ * Which type of DS are we currently handling?
+ * Classic? OPENSSL?
+ */
+stf_status
+main_inI3_outR3_whichds(struct msg_digest *md)
+{ 
+	if (! use_openssl(md->st->st_connection)) {
+		return main_inI3_outR3(md);
+	} else {
+		return main_inI3_outR3_ds(md);
+	}
+}
+#endif /* OPENSSL */
+
+/* STATE_MAIN_R2:
+ * PSK_AUTH: HDR*, IDi1, HASH_I --> HDR*, IDr1, HASH_R
+ * DS_AUTH: HDR*, IDi1, [ CERT, ] SIG_I --> HDR*, IDr1, [ CERT, ] SIG_R
+ * PKE_AUTH, RPKE_AUTH: HDR*, HASH_I --> HDR*, HASH_R
+ */
+stf_status
+main_inI3_outR3(struct msg_digest *md)
+{ 
+    struct state *const st = md->st;
+
+    int auth_payload = st->st_oakley.auth == OAKLEY_PRESHARED_KEY
+	? ISAKMP_NEXT_HASH : ISAKMP_NEXT_SIG;
+
+    DBG(DBG_PARSING,
+    DBG_log("in main_inI3_outR3");
+    );
+
+    /* input code similar to main_inR3 -- should be factored */
+
+    /* IDii in */
+    if (!decode_peer_id(md, FALSE))
+	return STF_FAIL + INVALID_ID_INFORMATION;
+
+    /* HASH_I or SIG_I in */
+    RETURN_STF_FAILURE(check_main_authenticator(md, TRUE));
+
+    /*************** build output packet HDR*;IDir;HASH/SIG_R ***************/
+    /* ??? NOTE: this is almost the same as main_inR2_outI3's code */
+
+    /* IDir out */
+    {
+	struct isakmp_ipsec_id id_hd;
+	chunk_t id_b;
+	pb_stream r_id_pbs;
+
+	build_id_payload(&id_hd, &id_b, &st->st_connection->this);
+	id_hd.isaiid_np = auth_payload;
+	if (!out_struct(&id_hd, &isakmp_ipsec_identification_desc, &md->rbody, &r_id_pbs)
+	|| !out_chunk(id_b, &r_id_pbs, "my identity"))
+	    return STF_INTERNAL_ERROR;
+	close_output_pbs(&r_id_pbs);
+    }
+
+    /* HASH_R or SIG_R out */
+    {
+	u_char hash_val[MAX_DIGEST_LEN];
+	size_t hash_len = main_mode_hash(st, hash_val, FALSE, TRUE);
+
+	if (auth_payload == ISAKMP_NEXT_HASH)
+	{
+	    /* HASH_R out */
+	    if (!out_generic_raw(ISAKMP_NEXT_NONE, &isakmp_hash_desc, &md->rbody
+	    , hash_val, hash_len, "HASH_R"))
+		return STF_INTERNAL_ERROR;
+	}
+	else
+	{
+	    /* SIG_R out */
+	    u_char sig_val[RSA_MAX_OCTETS];
+	    size_t sig_len = RSA_sign_hash(st->st_connection
+		, sig_val, hash_val, hash_len);
+
+	    if (sig_len == 0)
+	    {
+		loglog(RC_LOG_SERIOUS, "unable to locate my private key for RSA Signature");
+		return STF_FAIL + AUTHENTICATION_FAILED;
+	    }
+
+	    if (!out_generic_raw(ISAKMP_NEXT_NONE, &isakmp_signature_desc
+	    , &md->rbody, sig_val, sig_len, "SIG_R"))
+		return STF_INTERNAL_ERROR;
+	}
+    }
+
+    /* encrypt message, sans fixed part of header */
+
+    if (!encrypt_message(&md->rbody, st))
+	return STF_INTERNAL_ERROR;	/* ??? we may be partly committed */
+
+    /* Last block of Phase 1 (R3), kept for Phase 2 IV generation */
+    DBG_cond_dump(DBG_CRYPT, "last encrypted block of Phase 1:"
+	, st->st_new_iv, st->st_new_iv_len);
+
+    /* Advance state */
+    st->st_state = STATE_MAIN_R3;
+    ISAKMP_SA_established(st->st_connection, st->st_serialno);
+
+    /* ??? If st->st_connectionc->gw_info != NULL,
+     * we should keep the public key -- it tested out.
+     */
+
+    return STF_REPLY;
+}
+
+/* STATE_MAIN_I3:
+ * Handle HDR*;IDir;HASH/SIG_R from responder.
+ */
+stf_status
+main_inR3(struct msg_digest *md)
+{
+    struct state *const st = md->st;
+    struct connection *c = st->st_connection;
+
+    DBG(DBG_PARSING,
+    DBG_log("in main_inR3");
+    );
+
+    /* input code similar to main_inI3_outR3 -- should be factored */
+
+    /* IDir in */
+    if (!decode_peer_id(md, TRUE))
+	return STF_FAIL + INVALID_ID_INFORMATION;
+
+    /* HASH_R or SIG_R in */
+    RETURN_STF_FAILURE(check_main_authenticator(md, FALSE));
+
+    /**************** done input ****************/
+
+    /* Advance state */
+    st->st_state = STATE_MAIN_I4;
+    ISAKMP_SA_established(c, st->st_serialno);
+
+    /* ??? If c->gw_info != NULL,
+     * we should keep the public key -- it tested out.
+     */
+
+    update_iv(st);	/* finalize our Phase 1 IV */
+
+    DBG(DBG_PARSING,
+    DBG_log("finished main_inR3");
+    );
+
+    return STF_UNPEND_QUICK;
+}
+
+#ifdef OPENSSL
+/* Handle HDR*;IDir;[CERT];SIG_R from responder.
+ */
+stf_status
+main_inR3_ds(struct msg_digest *md)
+{
+    struct state *const st = md->st;
+    struct connection *c = st->st_connection;
+    u_char hash_val[MAX_DIGEST_LEN], *buf;
+    pb_stream *sig_pbs;
+    unsigned int dlen;
+    struct payload_digest *id_pld;
+    size_t hash_len = main_mode_hash(st, hash_val, FALSE, FALSE);
+    // size_t hash_len;
+    // main_mode_hash(st, hash_val, &hash_len, FALSE, FALSE);
+
+    /* input code similar to main_inI3_outR3 -- should be factored */
+
+    DBG(DBG_PARSING,
+    DBG_log("in main_inR3_ds");
+    );
+
+    /* IDir in */
+    if (!decode_peer_id(md, TRUE))
+      return STF_FAIL + INVALID_ID_INFORMATION;
+
+    switch (st->st_oakley.auth) {
+    case OAKLEY_RSA_SIG: /* check SIG_I */
+      {
+      RSA *rsa;
+      STACK_OF(X509) *peerlist;
+      X509 *recv_cert, *cert;
+      pb_stream *cert_pbs;
+      int i, success;
+
+      recv_cert = NULL;
+      /* First check to see if we have a certificate sent to us */
+      if ((md->chain[ISAKMP_NEXT_CERT] != NULL) &&
+          ((cert_pbs = &md->chain[ISAKMP_NEXT_CERT]->pbs) != NULL)) {
+        u_char *crt;
+        unsigned long len;
+
+        switch(cert_pbs->cur[0]) {
+        case CERT_TYPE_X509_SIG:
+          crt = &(cert_pbs->cur[1]);
+          len = pbs_left(cert_pbs)-1;
+          recv_cert = d2i_X509(NULL, &crt, len);
+          break;
+        default:
+              DBG(DBG_PARSING,
+                      DBG_log("Unhandled certificate encoding: %s",
+                      enum_show(&cert_names, cert_pbs->cur[0]));
+              );
+          break;
+        }
+      }
+
+      if (recv_cert) {
+        char buf[200];
+
+        X509_NAME_oneline(X509_get_subject_name(recv_cert)
+                          , buf, sizeof(buf));
+              DBG(DBG_PARSING,
+                      DBG_log("Sent certificate \"%s\"", buf);
+              );
+      }
+
+      id_pld = md->chain[ISAKMP_NEXT_ID];
+      if ((peerlist =
+           peer_cert_list((STACK_OF(XMAP) *)c->lu,
+                          EVP_PKEY_RSA, recv_cert, id_pld,
+                          (c->cert_options & CERT_OPTION_STRICT) ? TRUE : FALSE)) == NULL) {
+        log("Verification certificate(s) unavailable to check signature in Main R3");
+        return STF_FAIL + INVALID_SIGNATURE;
+      }
+
+      if (sk_X509_num(peerlist) == 0) {
+        log("Unable to get any certificate for peer in Main R3");
+        return STF_FAIL + INVALID_SIGNATURE;
+      }
+
+      if ((md->chain[ISAKMP_NEXT_SIG] == NULL) ||
+              ((sig_pbs = &md->chain[ISAKMP_NEXT_SIG]->pbs) == NULL)) {
+        log("Signature not present in Main R3");
+        return STF_FAIL + INVALID_SIGNATURE;
+      }
+      DBG(DBG_PARSING,
+              DBG_dump("Computed hash", hash_val, hash_len);
+      );
+      /* Iterate through all certificates in the peer list until */
+      /* we have one which verifies the signature, or we have no */
+      /* more certificates to verify with */
+      for(i=0, success=0, buf = NULL; ((success == 0) && (i < sk_X509_num(peerlist))); i++) {
+        rsa = X509_get_pubkey(sk_X509_value(peerlist, i))->pkey.rsa;
+        if ((buf = alloc_bytes(EVP_PKEY_size(X509_get_pubkey(sk_X509_value(peerlist, i))),
+                               "RSA decrypt sig")) != NULL) {
+          dlen = RSA_public_decrypt(pbs_left(sig_pbs), sig_pbs->cur, buf, rsa
+                                    , RSA_PKCS1_PADDING);
+              DBG(DBG_PARSING,
+                      DBG_dump("Decrypted hash", buf, (dlen > hash_len)
+                              ? hash_len : dlen);
+              );
+          if ((dlen == hash_len) && (memcmp(buf, hash_val, hash_len) == 0)) {
+                      DBG(DBG_PARSING,
+                              DBG_log("SIG_R matches computed hash");
+                      )
+            success = 1;
+            cert = X509_dup(sk_X509_value(peerlist, i));
+          } else {
+                      DBG(DBG_PARSING,
+                              DBG_log("SIG_R does not match computed hash");
+                      );
+          }
+          pfree(buf);
+          buf = NULL;
+        }
+      }
+      if (buf) pfree(buf);
+
+      if (!success) {
+        log_err();
+        DBG_cond_dump(DBG_CRYPT,
+                      "received SIG_R does not match computed value in Main R3:"
+                      , sig_pbs->cur, pbs_left(sig_pbs));
+        sk_X509_pop_free(peerlist, X509_free);
+        return STF_FAIL + INVALID_SIGNATURE;
+      } else {
+        /* We know that certificate 'cert' was used to */
+        /* sign the accurate hash which accompanied the method */
+        /* Now we have to verify that it is a valid certificate */
+        /* to be signing anything */
+              DBG(DBG_PARSING,
+                      DBG_log("Verifying certificate along path %s", c->path);
+              );
+              if (verify_certificate( cert, c->lu, c->path,
+                      (c->cert_options & CERT_OPTION_STRICT) ? TRUE : FALSE ))
+              {
+                      DBG(DBG_PARSING,
+                              DBG_log("Signing certificate is valid");
+                      );
+              } else {
+                      sk_X509_pop_free(peerlist, X509_free);
+                      return STF_FAIL + INVALID_CERTIFICATE;
+              }
+      }
+      sk_X509_pop_free(peerlist, X509_free);
+      }
+      break;
+    case OAKLEY_DSS_SIG:
+      {
+      DSA *dsa;
+      STACK_OF(X509) *peerlist;
+      X509 *recv_cert, *cert;
+      pb_stream *cert_pbs;
+      int i, success;
+
+      if (c->cert_options & CERT_OPTION_DSS_SHA)
+        main_mode_sha1(st, hash_val, &hash_len, FALSE, FALSE);
+      recv_cert = NULL;
+      /* First check to see if we have a certificate sent to us */
+      if ((md->chain[ISAKMP_NEXT_CERT] != NULL) &&
+          ((cert_pbs = &md->chain[ISAKMP_NEXT_CERT]->pbs) != NULL)) {
+        u_char *crt;
+        unsigned long len;
+
+        switch(cert_pbs->cur[0]) {
+        case CERT_TYPE_X509_SIG:
+          crt = &(cert_pbs->cur[1]);
+          len = pbs_left(cert_pbs)-1;
+          recv_cert = d2i_X509(NULL, &crt, len);
+          break;
+        default:
+              DBG(DBG_PARSING,
+                  DBG_log("Unhandled certificate encoding: %s",
+                          enum_show(&cert_names, cert_pbs->cur[0]));
+              );
+          break;
+        }
+      }
+
+      if (recv_cert) {
+        char buf[200];
+
+        X509_NAME_oneline(X509_get_subject_name(recv_cert)
+                          , buf, sizeof(buf));
+              DBG(DBG_PARSING,
+                      DBG_log("Sent certificate \"%s\"", buf);
+              );
+      }
+
+      /* We know this field is legitimate, because the */
+      /* decode_peer_id has been called before */
+      id_pld = md->chain[ISAKMP_NEXT_ID];
+
+      if ((peerlist =
+           peer_cert_list((STACK_OF(XMAP) *)c->lu,
+                          EVP_PKEY_DSA, recv_cert,
+                          id_pld,
+                          (c->cert_options & CERT_OPTION_STRICT) ? TRUE : FALSE )) == NULL) {
+        log("Verification certificate(s) unavailable to check signature in Main R3");
+        return STF_FAIL + INVALID_SIGNATURE;
+      }
+
+      if (sk_X509_num(peerlist) == 0) {
+        log("Unable to get any certificate for peer in Main R3");
+        return STF_FAIL + INVALID_SIGNATURE;
+      }
+
+      if ((md->chain[ISAKMP_NEXT_SIG] == NULL) ||
+          ((sig_pbs = &md->chain[ISAKMP_NEXT_SIG]->pbs) == NULL)) {
+        log("Signature not present in Main R3");
+        return STF_FAIL + INVALID_SIGNATURE;
+      }
+      DBG(DBG_PARSING,
+              DBG_dump("Computed hash", hash_val, hash_len);
+      );
+      /* Iterate through all certificates in the peer list until */
+      /* we have one which verifies the signature, or we have no */
+      /* more certificates to verify with */
+      for(i=0, success=0, buf=NULL; ((success == 0) && (i < sk_X509_num(peerlist))); i++) {
+        dsa = X509_get_pubkey(sk_X509_value(peerlist, i))->pkey.dsa;
+        if ((buf = alloc_bytes(SHA1_DIGEST_SIZE, "DSA decrypt sig")) != NULL) {
+          success = (c->cert_options & CERT_OPTION_DSS_ALT)
+            ? DSA_verify_raw(hash_val, hash_len,
+                             sig_pbs->cur, pbs_left(sig_pbs),
+                             dsa)
+            : DSA_verify(EVP_PKEY_DSA,
+                         hash_val, hash_len,
+                         sig_pbs->cur, pbs_left(sig_pbs),
+                         dsa);
+          if (success == 1) {
+                      DBG(DBG_PARSING,
+                              DBG_log("SIG_I matches computed hash");
+                      );
+            cert = X509_dup(sk_X509_value(peerlist, i));;
+          } else if (success == 0) {
+                      DBG(DBG_PARSING,
+                              DBG_log("SIG_I does not match computed hash");
+                      );
+          } else {
+                      DBG(DBG_PARSING,
+                    DBG_log("Verification error");
+                      );
+            log_err();
+          }
+          pfree(buf);
+          buf = NULL;
+        }
+      }
+      if (buf) pfree(buf);
+      if (!success) {
+        log_err();
+        DBG_cond_dump(DBG_CRYPT, "received SIG_I does not match computed value in Main I3:"
+                      , sig_pbs->cur, pbs_left(sig_pbs));
+        sk_X509_pop_free(peerlist, X509_free);
+        return STF_FAIL + INVALID_SIGNATURE;
+      } else {
+        /* We know that certificate 'cert' was used to */
+        /* sign the accurate hash which accompanied the method */
+        /* Now we have to verify that it is a valid certificate */
+        /* to be signing anything */
+              DBG(DBG_PARSING,
+                      DBG_log("Verifying certificate along path %s", c->path);
+              );
+        if (verify_certificate( cert, c->lu, c->path, (c->cert_options & CERT_OPTION_STRICT) ? TRUE : FALSE ))
+              {
+                      DBG(DBG_PARSING,
+                              DBG_log("Signing certificate is valid");
+                      );
+              }
+        else {
+          sk_X509_pop_free(peerlist, X509_free);
+          return STF_FAIL + INVALID_CERTIFICATE;
+        }
+      }
+      sk_X509_pop_free(peerlist, X509_free);
+      }
+      break;
+    default:
+      return STF_INTERNAL_ERROR;
+      break;
 	}
-    }
-
-    /* encrypt message, sans fixed part of header */
-
-    if (!encrypt_message(&md->rbody, st))
-	return STF_INTERNAL_ERROR;	/* ??? we may be partly committed */
 
-    /* Last block of Phase 1 (R3), kept for Phase 2 IV generation */
-    DBG_cond_dump(DBG_CRYPT, "last encrypted block of Phase 1:"
-	, st->st_new_iv, st->st_new_iv_len);
+    /**************** done input ****************/
 
     /* Advance state */
-    st->st_state = STATE_MAIN_R3;
-    ISAKMP_SA_established(st->st_connection, st->st_serialno);
+    st->st_state = STATE_MAIN_I4;
+    ISAKMP_SA_established(c, st->st_serialno);
 
-    /* ??? If st->st_connectionc->gw_info != NULL,
-     * we should keep the public key -- it tested out.
-     */
+    update_iv(st);    /* finalize our Phase 1 IV */
 
-    return STF_REPLY;
+    DBG(DBG_PARSING,
+    DBG_log("finished main_inR3_ds");
+    );
+
+    return STF_UNPEND_QUICK;
 }
+#endif
 
-/* STATE_MAIN_I3:
- * Handle HDR*;IDir;HASH/SIG_R from responder.
+#ifdef OPENSSL
+/* Handle HDR*;HASH_R from responder.
  */
 stf_status
-main_inR3(struct msg_digest *md)
+main_inR3_pk(struct msg_digest *md)
 {
     struct state *const st = md->st;
     struct connection *c = st->st_connection;
 
     /* input code similar to main_inI3_outR3 -- should be factored */
 
-    /* IDir in */
-    if (!decode_peer_id(md, TRUE))
-	return STF_FAIL + INVALID_ID_INFORMATION;
+    DBG(DBG_PARSING,
+    DBG_log("in main_inR3_pk");
+    );
 
-    /* HASH_R or SIG_R in */
+    /* HASH_R in */
+    // CHECK_HASH(main_mode_hash(st, hash_val, &hash_len, FALSE, FALSE)
+      // , "HASH_R", "Main R3");
     RETURN_STF_FAILURE(check_main_authenticator(md, FALSE));
 
     /**************** done input ****************/
@@ -2207,14 +3845,16 @@
     st->st_state = STATE_MAIN_I4;
     ISAKMP_SA_established(c, st->st_serialno);
 
-    /* ??? If c->gw_info != NULL,
-     * we should keep the public key -- it tested out.
-     */
-
     update_iv(st);	/* finalize our Phase 1 IV */
 
+    DBG(DBG_PARSING,
+    DBG_log("finished main_inR3_pk");
+    );
+
     return STF_UNPEND_QUICK;
 }
+#endif
+
 
 /* Handle first message of Phase 2 -- Quick Mode.
  * HDR*, HASH(1), SA, Ni [, KE ] [, IDci, IDcr ] -->
@@ -2300,15 +3940,14 @@
     else
     {
 	/* implicit IDci and IDcr: peer and self */
-	const struct af_info *afi = aftoinfo(addrtypeof(&c->this.host_addr));
 	err_t ugh;
 
 	if (!sameaddrtype(&c->this.host_addr, &c->that.host_addr))
 	    return STF_FAIL;
 
-	ugh = initsubnet(&c->this.host_addr, afi->mask_cnt, '0', &our_net);
+        ugh = rangetosubnet(&c->this.host_addr, &c->this.host_addr, &our_net);
 	passert(ugh == NULL);
-	ugh = initsubnet(&c->that.host_addr, afi->mask_cnt, '0', &peer_net);
+        ugh = rangetosubnet(&c->that.host_addr, &c->that.host_addr, &peer_net);
 	passert(ugh == NULL);
     }
 
@@ -2350,15 +3989,22 @@
 	{
 	    /* use p, not c */
 
-	    if (HasWildcardIP(*p))
+            /* We've got a better connection: it can support the
+             * specified clients.  But it may need instantiation.
+             */
+            if (p->kind == CK_TEMPLATE)
 	    {
-		if (HasWildcardClient(c))
+                /* Yup, it needs instantiation.  How much?
+                 * Is it a Road Warrior connection (simple)
+                 * or is it an Opportunistic connection (needing gw validation)?                 */
+		if (HasWildcardClient(p))
 		{
-		    /* We've now found out the peer's client
-		     * in an inbound Opportunistic negotiation.
+                    /* Opportunistic.
 		     * We need to determine if this peer is authorized
 		     * to negotiate for this client!  If the peer's
-		     * client is the peer, we don't need to do this.
+                     * client is the peer, we assume that it is authorized.
+                     * Since p isn't yet instantiated, we need to look
+                     * in c for description of peer.
 		     */
 		    struct gw_info *gw = c->gw_info;
 		    ip_address our_client
@@ -2371,26 +4017,20 @@
 
 		    if (!sameaddr(&c->that.host_addr, &peer_client))
 		    {
-			err_t ugh = discover_gateway(&peer_client);
+                        err_t ugh = discover_gateway(&peer_client
+                            , &c->that.id, &gw);
 
 			if (ugh != NULL)
 			{
-			    loglog(RC_OPPOFAILURE, "failure discovering gateway: %s", ugh);
-			    return STF_FAIL + INVALID_ID_INFORMATION;
-			}
-			gw = gateways;
-			if (!sameaddr(&c->that.host_addr, &gw->gw))
-			{
 			    char fgwb[ADDRTOT_BUF]
-				, cb[ADDRTOT_BUF]
-				, rgwb[ADDRTOT_BUF];
+                                , cb[ADDRTOT_BUF];
 
 			    addrtot(&c->that.host_addr, 0, fgwb, sizeof(fgwb));
 			    addrtot(&peer_client, 0, cb, sizeof(cb));
-			    addrtot(&gw->gw, 0, rgwb, sizeof(rgwb));
 			    loglog(RC_OPPOFAILURE
-				, "gateway %s claims client %s, but client says gateway is %s"
-				, fgwb, cb, rgwb);
+                                , "gateway %s claims client %s, but DNS for client fails to confirm: %s"
+                                , fgwb, cb, ugh);
+
 			    return STF_FAIL + INVALID_ID_INFORMATION;
 			}
 
@@ -2399,7 +4039,6 @@
 			    loglog(RC_OPPOFAILURE, "peer and client disagree about public key");
 			    return STF_FAIL + INVALID_ID_INFORMATION;
 			}
-			gw->last_worked_time = now();
 		    }
 
 		    /* Instantiate inbound Opportunism, carrying over his ID
@@ -2492,10 +4131,8 @@
 
 	/* MPZ-Operations might be done after sending the packet... */
 
+#ifndef DODGE_DH_MISSING_ZERO_BUG
 	compute_dh_shared(st, st->st_gi, st->st_pfs_group);
-#ifdef DODGE_DH_MISSING_ZERO_BUG
-	if (st->st_shared.ptr[0] == 0)
-	    return STF_DROP_DOOMED_EXCHANGE;
 #endif
     }
 
@@ -2660,8 +4297,510 @@
     if (c->gw_info != NULL)
 	c->gw_info->last_worked_time = now();
 
+    DBG(DBG_PARSING,
+    DBG_log("finished main_inI3_outR3");
+    );
+
+    return STF_REPLY;
+}
+
+#ifdef OPENSSL
+/*
+ * Handle HDR*;IDii;HASH_I from initiator. Send a HDR*;IDir;HASH_R back.
+ */
+stf_status
+main_inI3_outR3_ds(struct msg_digest *md)
+{
+    struct state *const st = md->st;
+
+    struct connection *c = st->st_connection;
+    u_char hash_val[MAX_DIGEST_LEN], *buf;
+    pb_stream *sig_pbs;
+    unsigned int dlen;
+    struct payload_digest *id_pld;
+    size_t hash_len = main_mode_hash(st, hash_val, TRUE, FALSE);
+
+    DBG(DBG_PARSING,
+    DBG_log("in main_inI3_outR3_ds");
+    );
+
+    /* input code similar to main_inR3 -- should be factored */
+
+    /* IDii in */
+    if (!decode_peer_id(md, FALSE))
+    return STF_FAIL + INVALID_ID_INFORMATION;
+
+    switch (st->st_oakley.auth) {
+    case OAKLEY_RSA_SIG: /* check SIG_I */
+      {
+  RSA *rsa;
+  STACK_OF(X509) *peerlist;
+  X509 *recv_cert, *cert;
+  pb_stream *cert_pbs;
+  int i, success;
+
+  recv_cert = NULL;
+  /* First check to see if we have a certificate sent to us */
+  if ((md->chain[ISAKMP_NEXT_CERT] != NULL) &&
+      ((cert_pbs = &md->chain[ISAKMP_NEXT_CERT]->pbs) != NULL)) {
+    u_char *crt;
+    unsigned long len;
+
+    switch(cert_pbs->cur[0]) {
+    case CERT_TYPE_X509_SIG:
+      crt = &(cert_pbs->cur[1]);
+      len = pbs_left(cert_pbs)-1;
+      recv_cert = d2i_X509(NULL, &crt, len);
+      break;
+    default:
+      DBG(DBG_PARSING,
+      DBG_log("Unhandled certificate encoding: %s",
+        enum_show(&cert_names, cert_pbs->cur[0]));
+      );
+      break;
+    }
+  }
+
+  if (recv_cert) {
+    char buf[200];
+
+    X509_NAME_oneline(X509_get_subject_name(recv_cert)
+              , buf, sizeof(buf));
+    DBG(DBG_PARSING,
+    DBG_log("Received certificate \"%s\"", buf);
+    );
+  }
+
+  /* We know this field is legitimate, because the */
+  /* decode_peer_id has been called before */
+  id_pld = md->chain[ISAKMP_NEXT_ID];
+
+  if ((peerlist = peer_cert_list((STACK_OF(XMAP) *)(c->lu),
+                     EVP_PKEY_RSA,
+                     recv_cert,
+                     id_pld,
+                     (c->cert_options & CERT_OPTION_STRICT)
+                     ? TRUE : FALSE)) == NULL) {
+    log("Verification certificate(s) unavailable to check signature in Main R3");
+    return STF_FAIL + INVALID_SIGNATURE;
+  }
+
+  if (sk_X509_num(peerlist) == 0) {
+    log("Unable to get any certificate for peer in Main R3");
+    return STF_FAIL + INVALID_SIGNATURE;
+  }
+
+  if ((md->chain[ISAKMP_NEXT_SIG] == NULL) ||
+      ((sig_pbs = &md->chain[ISAKMP_NEXT_SIG]->pbs) == NULL)) {
+    log("Signature not present in Main R3");
+    return STF_FAIL + INVALID_SIGNATURE;
+  }
+  DBG(DBG_PARSING,
+  DBG_dump("Computed hash", hash_val, hash_len);
+  );
+  /* Iterate through all certificates in the peer list until */
+  /* we have one which verifies the signature, or we have no */
+  /* more certificates to verify with */
+  for (i=0, success = 0; (success == 0) && (i<sk_X509_num(peerlist)); i++) {
+    X509 *xx = sk_X509_value(peerlist, i);
+
+    rsa = X509_get_pubkey(xx)->pkey.rsa;
+    if ((buf = alloc_bytes(EVP_PKEY_size(X509_get_pubkey(xx)),
+     "RSA decrypt sig")) != NULL) {
+      dlen = RSA_public_decrypt(pbs_left(sig_pbs), sig_pbs->cur, buf,
+        rsa, RSA_PKCS1_PADDING);
+      DBG(DBG_PARSING,
+      DBG_dump("Decrypted hash", buf, (dlen > hash_len) 
+        ? hash_len : dlen);
+      );
+      if ((dlen == hash_len) && (memcmp(buf, hash_val, hash_len) == 0)) {
+        DBG(DBG_PARSING,
+        DBG_log("SIG_I matches computed hash");
+        );
+        success = 1;
+        cert = X509_dup(xx);
+      } else {
+        DBG(DBG_PARSING,
+        DBG_log("SIG_I does not computed hash");
+        );
+      }
+      pfree(buf);
+    }
+  }
+  if (!success) {
+    log_err();
+    DBG_cond_dump(DBG_CRYPT, 
+      "received SIG_I does not match computed value in Main I3:"
+      , sig_pbs->cur, pbs_left(sig_pbs));
+    sk_X509_pop_free(peerlist, X509_free);
+    return STF_FAIL + INVALID_SIGNATURE;
+  } else {
+    /* We know that certificate 'cert' was used to */
+    /* sign the accurate hash which accompanied the method */
+    /* Now we have to verify that it is a valid certificate */
+    /* to be signing anything */
+    DBG(DBG_PARSING,
+    DBG_log("Verifying certificate along path %s", c->path);
+    );
+    if (verify_certificate( cert, c->lu, c->path, 
+      (c->cert_options & CERT_OPTION_STRICT) ? TRUE : FALSE ))
+      {
+        DBG(DBG_PARSING,
+        DBG_log("Signing certificate is valid.");
+        );
+      } else {
+        DBG(DBG_PARSING,
+        DBG_log("Signing certificate NOT valid.");
+        );
+        sk_X509_pop_free(peerlist, X509_free);
+        return STF_FAIL + INVALID_CERTIFICATE;
+      }
+  }
+  sk_X509_pop_free(peerlist, X509_free);
+      }
+      break;
+    case OAKLEY_DSS_SIG:
+      {
+  DSA *dsa;
+  STACK_OF(X509) *peerlist;
+  X509 *recv_cert, *cert;
+  pb_stream *cert_pbs;
+  int i, success;
+
+  if (c->cert_options & CERT_OPTION_DSS_SHA)
+    main_mode_sha1(st, hash_val, &hash_len, TRUE, FALSE);
+  recv_cert = NULL;
+  /* First check to see if we have a certificate sent to us */
+  if ((md->chain[ISAKMP_NEXT_CERT] != NULL) &&
+      ((cert_pbs = &md->chain[ISAKMP_NEXT_CERT]->pbs) != NULL)) {
+    u_char *crt;
+    unsigned long len;
+
+    switch(cert_pbs->cur[0]) {
+    case CERT_TYPE_X509_SIG:
+      crt = &(cert_pbs->cur[1]);
+      len = pbs_left(cert_pbs)-1;
+      recv_cert = d2i_X509(NULL, &crt, len);
+      break;
+    default:
+		DBG(DBG_PARSING,
+			DBG_log("Unhandled certificate encoding: %s",
+				enum_show(&cert_names, cert_pbs->cur[0]));
+		);
+      break;
+    }
+  }
+
+  if (recv_cert) {
+    char buf[200];
+
+    X509_NAME_oneline(X509_get_subject_name(recv_cert)
+              , buf, sizeof(buf));
+    DBG(DBG_PARSING,
+    DBG_log("Received certificate \"%s\"", buf);
+    );
+  }
+
+  /* We know this field is legitimate, because the */
+  /* decode_peer_id has been called before */
+  id_pld = md->chain[ISAKMP_NEXT_ID];
+
+  if ((peerlist =
+       peer_cert_list((STACK_OF(XMAP) *)(c->lu), EVP_PKEY_DSA,
+              recv_cert, id_pld,
+              (c->cert_options & CERT_OPTION_STRICT) ? TRUE : FALSE)) == NULL) {
+    log("Verification certificate(s) unavailable to check signature in Main R3");
+    return STF_FAIL + INVALID_SIGNATURE;
+  }
+
+  if (sk_X509_num(peerlist) == 0) {
+    log("Unable to get any certificate for peer in Main R3");
+    return STF_FAIL + INVALID_SIGNATURE;
+  }
+
+  if ((md->chain[ISAKMP_NEXT_SIG] == NULL) ||
+      ((sig_pbs = &md->chain[ISAKMP_NEXT_SIG]->pbs) == NULL)) {
+    log("Signature not present in Main R3");
+    return STF_FAIL + INVALID_SIGNATURE;
+  }
+
+  DBG(DBG_PARSING,
+  DBG_dump("Computed hash", hash_val, hash_len);
+  );
+  /* Iterate through all certificates in the peer list until */
+  /* we have one which verifies the signature, or we have no */
+  /* more certificates to verify with */
+  for(i=0, success=0, buf = NULL;
+      ((success == 0) && (i < sk_X509_num(peerlist))); i++) {
+    dsa = X509_get_pubkey(sk_X509_value(peerlist, i))->pkey.dsa;
+    if ((buf = alloc_bytes(SHA1_DIGEST_SIZE, "DSA sig space")) != NULL) {
+      success = (c->cert_options & CERT_OPTION_DSS_ALT)
+        ? DSA_verify_raw(hash_val, hash_len,
+                 sig_pbs->cur, pbs_left(sig_pbs),
+                 dsa)
+        : DSA_verify(EVP_PKEY_DSA,
+             hash_val, hash_len,
+             sig_pbs->cur, pbs_left(sig_pbs),
+             dsa)
+        ;
+      if (success == 1) {
+        DBG(DBG_PARSING,
+        DBG_log("SIG_I matches computed hash");
+        );
+        cert = X509_dup(sk_X509_value(peerlist, i));
+      } else if (success == 0) {
+        DBG(DBG_PARSING,
+        DBG_log("SIG_I does not computed hash");
+        );
+      } else {
+        DBG(DBG_PARSING,
+       	DBG_log("Verification error");
+        );
+        log_err();
+      }
+      pfree(buf);
+      buf = NULL;
+    }
+  }
+  if (buf) pfree(buf);
+  if (!success) {
+    log_err();
+    DBG_cond_dump(DBG_CRYPT, "received SIG_I does not match computed value in Main I3:"
+          , sig_pbs->cur, pbs_left(sig_pbs));
+    sk_X509_pop_free(peerlist, X509_free);
+    return STF_FAIL + INVALID_SIGNATURE;
+  } else {
+    /* We know that certificate 'cert' was used to */
+    /* sign the accurate hash which accompanied the method */
+    /* Now we have to verify that it is a valid certificate */
+    /* to be signing anything */
+    DBG(DBG_PARSING,
+    DBG_log("Verifying certificate along path %s", c->path);
+    );
+    if (verify_certificate( cert, c->lu, c->path, 
+      (c->cert_options & CERT_OPTION_STRICT) ? TRUE : FALSE ))
+    {
+      DBG(DBG_PARSING,
+      DBG_log("Signing certificate is valid");
+      );
+    } else {
+      sk_X509_pop_free(peerlist, X509_free);
+      return STF_FAIL + INVALID_CERTIFICATE;
+    }
+  }
+  sk_X509_pop_free(peerlist, X509_free);
+      }
+      break;
+      /* Should never get here */
+    default:
+      return STF_INTERNAL_ERROR;
+    }
+
+    /************* build output packet HDR*;IDir;[CERT];SIG_R ******/
+    /* ??? NOTE: this is almost the same as main_inR2_outI3's code */
+
+    /* IDir out */
+    {
+  struct isakmp_ipsec_id r_id;
+  pb_stream r_id_pbs;
+  chunk_t r_id_chunk;
+
+  // r_id.isaiid_idtype = st->st_myidentity_type;
+  r_id.isaiid_idtype = st->st_connection->this.id.kind;
+  r_id.isaiid_protoid = 0;    /* ??? is this right? */
+  r_id.isaiid_port = 0;   /* ??? is this right? */
+
+  build_id_payload(&r_id, &r_id_chunk, &st->st_connection->this);
+
+  if ((c->cert_options & CERT_OPTION_SEND) == 0)
+    r_id.isaiid_np = ISAKMP_NEXT_SIG;
+  else
+    r_id.isaiid_np = ISAKMP_NEXT_CERT;
+
+  if (!out_struct(&r_id, &isakmp_ipsec_identification_desc, &md->rbody, 
+    &r_id_pbs) || !out_chunk(r_id_chunk, &r_id_pbs, "my identity"))
+      return STF_INTERNAL_ERROR;
+  close_output_pbs(&r_id_pbs);
+
+#if 0
+  /* if a permanent cast is needed, we'll need to rethink this. */
+  r_id_chunk.len = sizeof(st->st_connection->this.id.ip_addr);
+  memcpy(&(r_id_chunk.ptr), &(st->st_connection->this.id.ip_addr), r_id_chunk.len);
+ 
+  if (!out_struct(&r_id, &isakmp_ipsec_identification_desc,
+          &md->rbody, &r_id_pbs)
+      || !out_chunk(r_id_chunk, &r_id_pbs, "my identity"))
+    return STF_INTERNAL_ERROR;
+  close_output_pbs(&r_id_pbs);
+#endif
+    }
+
+    if ((c->cert_options & CERT_OPTION_SEND) != 0) {
+      /* Send the signing certificate */
+      u_char *crt, *cx;
+      unsigned long ulen;
+      /* Send the signing certificate */
+    
+      ulen = i2d_X509(c->cert, NULL);
+      ulen++;
+      if ((cx = alloc_bytes(ulen, "ASN.1 cert")) == NULL)
+  { return STF_INTERNAL_ERROR; }
+      cx[0] = (u_char)(CERT_TYPE_X509_SIG);
+      crt = &(cx[1]);
+      i2d_X509(c->cert, &crt);
+      if (!out_generic_raw(ISAKMP_NEXT_SIG, &isakmp_ipsec_certificate_desc
+             , &md->rbody, cx, ulen, "CERT_R"))
+  return STF_INTERNAL_ERROR;
+      pfree(cx);
+    }
+
+    /* SIG_R out */
+    {
+  u_char hash_val[MAX_DIGEST_LEN];
+  u_int elen;
+  bool ok;
+
+  // size_t hash_len;
+  // main_mode_hash(st, hash_val, &hash_len, FALSE, TRUE);
+  size_t hash_len = main_mode_hash(st, hash_val, FALSE, TRUE);
+
+  /* Output the signature/hash as defined by the selected Oakley transform */
+  switch (st->st_oakley.auth) {
+  case OAKLEY_RSA_SIG: /* output signed HASH_R */
+    if ((buf = alloc_bytes(EVP_PKEY_size(c->key) + 32 /* bit of slack */,
+               "RSA sig")) == NULL)
+      return STF_INTERNAL_ERROR;
+    elen = RSA_private_encrypt(hash_len, hash_val, buf,
+                   ((EVP_PKEY *)(c->key))->pkey.rsa,
+                   RSA_PKCS1_PADDING);
+    if (!out_generic_raw(ISAKMP_NEXT_NONE, &isakmp_signature_desc,
+                 &md->rbody, buf, elen, "SIG_R"))
+      return STF_INTERNAL_ERROR;
+    break;
+  case OAKLEY_DSS_SIG:
+    if (c->cert_options & CERT_OPTION_DSS_SHA)
+      main_mode_sha1(st, hash_val, &hash_len, FALSE, TRUE);
+
+    if ((buf = alloc_bytes(EVP_PKEY_size(c->key) + 32 /* bit of slack */,
+              "DSA sig")) == NULL)
+      return STF_INTERNAL_ERROR;
+    ok = (c->cert_options & CERT_OPTION_DSS_ALT)
+      ? DSA_sign_raw(hash_val, hash_len,
+             buf, &elen,
+             ((EVP_PKEY *)(c->key))->pkey.dsa)
+      : DSA_sign(EVP_PKEY_DSA, hash_val, hash_len,
+             buf, &elen,
+             ((EVP_PKEY *)(c->key))->pkey.dsa);
+    if (!ok) {
+      log_err();
+      return STF_INTERNAL_ERROR;
+    }
+    if (!out_generic_raw(ISAKMP_NEXT_NONE, &isakmp_signature_desc,
+                 &md->rbody, buf, elen, "SIG_I"))
+      return STF_INTERNAL_ERROR;
+   
+	DBG(DBG_PARSING,
+	    DBG_log("Selected auth mechanism is %s",
+			enum_show(&oakley_auth_names, st->st_oakley.auth));
+	);
+    break;
+  default:
+    return STF_INTERNAL_ERROR;
+  }
+  pfree(buf);
+    }
+
+    /* encrypt message, sans fixed part of header */
+
+    if (!encrypt_message(&md->rbody, st))
+  return STF_INTERNAL_ERROR;  /* ??? we may be partly committed */
+
+    /* Last block of Phase 1 (R3), kept for Phase 2 IV generation */
+    DBG_cond_dump(DBG_CRYPT, "last encrypted block of Phase 1:"
+  , st->st_new_iv, st->st_new_iv_len);
+
+    /* Advance state */
+    st->st_state = STATE_MAIN_R3;
+    ISAKMP_SA_established(st->st_connection, st->st_serialno);
+
+    DBG(DBG_PARSING,
+    DBG_log("finished main_inI3_outR3_ds");
+    );
+
+    return STF_REPLY;
+}
+#endif /* OPENSSL */
+
+#ifdef OPENSSL
+/*
+ * Handle HDR*;HASH_I from initiator. Send a HDR*;HASH_R back.
+ */
+stf_status
+main_inI3_outR3_pk(struct msg_digest *md)
+{
+    struct state *const st = md->st;
+
+    /* input code similar to main_inR3 -- should be factored */
+
+    DBG(DBG_PARSING,
+    DBG_log("in main_inI3_outR3_pk");
+    );
+
+    /* HASH_I in */
+    // CHECK_HASH(main_mode_hash(st, hash_val, &hash_len, TRUE, FALSE)
+  	// , "HASH_I", "Main I3");
+	RETURN_STF_FAILURE(check_main_authenticator(md, TRUE));
+
+    /**************** build output packet HDR*;HASH_R ****************/
+
+    /* HASH_R out */
+    {
+  u_char hash_val[MAX_DIGEST_LEN];
+  
+  // size_t hash_len;
+  // main_mode_hash(st, hash_val, &hash_len, FALSE, TRUE);
+  size_t hash_len = main_mode_hash(st, hash_val, FALSE, TRUE);
+
+  if (!out_generic_raw(ISAKMP_NEXT_NONE, &isakmp_hash_desc, &md->rbody
+  , hash_val, hash_len, "HASH_R"))
+      return STF_INTERNAL_ERROR;
+    }
+   
+    /* encrypt message, sans fixed part of header */
+    if (!encrypt_message(&md->rbody, st))
+  return STF_INTERNAL_ERROR;  /* ??? we may be partly committed */
+
+    /* Last block of Phase 1 (R3), kept for Phase 2 IV generation */
+    DBG_cond_dump(DBG_CRYPT, "last encrypted block of Phase 1:"
+  , st->st_new_iv, st->st_new_iv_len);
+
+    /* Advance state */
+    st->st_state = STATE_MAIN_R3;
+    ISAKMP_SA_established(st->st_connection, st->st_serialno);
+
+    DBG(DBG_PARSING,
+    DBG_log("finished main_inI3_outR3_pk");
+    );
+
     return STF_REPLY;
 }
+#endif
+
+#ifdef OPENSSL
+/* STATE_MAIN_I3:
+ * Handle HDR*;IDir;HASH/SIG_R from responder.
+ */
+stf_status
+main_inR3_whichds(struct msg_digest *md)
+{
+	if (!use_openssl(md->st->st_connection)) {
+		return main_inR3(md);
+	} else {
+		return main_inR3_ds(md);
+	}
+}
+#endif /* OPENSSL */
+
 
 /* Handle last message of Quick Mode.
  * HDR*, HASH(3) -> done
diff -bruN freeswan-1.9.orig/pluto/ipsec_doi.h freeswan-1.9/pluto/ipsec_doi.h
--- freeswan-1.9.orig/pluto/ipsec_doi.h	Tue Jun 20 22:27:28 2000
+++ freeswan-1.9/pluto/ipsec_doi.h	Tue Jun  5 15:57:36 2001
@@ -11,11 +11,11 @@
  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  * for more details.
  *
- * RCSID $Id: ipsec_doi.h,v 1.22 2000/06/21 02:27:28 dhr Exp $
+ * RCSID $Id: ipsec_doi.h,v 1.23 2001/05/08 05:37:22 dhr Exp $
  */
 
 extern void ipsecdoi_initiate(int whack_sock, struct connection *c
-    , bool pending_quick, lset_t policy, unsigned long try);
+    , lset_t policy, unsigned long try);
 
 extern void ipsecdoi_replace(struct state *st, unsigned long try);
 
@@ -28,9 +28,27 @@
     main_inI1_outR1,
     main_inR1_outI2,
     main_inI2_outR2,
+#ifdef OPENSSL
+    main_inI2_outR2_pk,
+    main_inI2_outR2_rpk,
+#endif
     main_inR2_outI3,
+#ifdef OPENSSL
+    main_inR2_outI3_pk,
+    main_inR2_outI3_rpk,
+#endif
     main_inI3_outR3,
+#ifdef OPENSSL
+    main_inI3_outR3_whichds,
+    main_inI3_outR3_ds,
+    main_inI3_outR3_pk,
+#endif
     main_inR3,
+#ifdef OPENSSL
+    main_inR3_whichds,
+    main_inR3_ds,
+    main_inR3_pk,
+#endif
     quick_inI1_outR1,
     quick_inR1_outI2,
     quick_inI2;
diff -bruN freeswan-1.9.orig/pluto/kernel.c freeswan-1.9/pluto/kernel.c
--- freeswan-1.9.orig/pluto/kernel.c	Mon Jan 29 01:20:43 2001
+++ freeswan-1.9/pluto/kernel.c	Thu Jun  7 12:02:17 2001
@@ -12,7 +12,7 @@
  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  * for more details.
  *
- * RCSID $Id: kernel.c,v 1.105 2001/01/29 06:20:43 dhr Exp $
+ * RCSID $Id: kernel.c,v 1.121 2001/06/02 19:34:22 dhr Exp $
  */
 
 #include <stddef.h>
@@ -44,11 +44,13 @@
 #include "id.h"
 #include "connections.h"	/* needs id.h */
 #include "state.h"
+#include "timer.h"
 #include "kernel.h"
 #include "log.h"
 #include "server.h"
 #include "whack.h"	/* for RC_LOG_SERIOUS */
 
+extern int send_delete(struct state *st, ipsec_spi_t *spi, bool ESP);
 
 bool can_do_IPcomp = TRUE;  /* can system actually perform IPCOMP? */
 
@@ -57,7 +59,80 @@
  */
 #define REPLAY_WINDOW	64
 
-#ifdef KLIPS
+static bool route_and_eroute(struct connection *c
+    , struct state *st);       /* forward declaration */
+
+/* test if the routes required for two different connections agree
+ * It is assumed that the destination subnets agree; we are only
+ * testing that the interfaces and nexthops match.
+ */
+#define routes_agree(c, d) ((c)->interface == (d)->interface \
+         && sameaddr(&(c)->this.host_nexthop, &(d)->this.host_nexthop))
+
+#ifndef KLIPS
+
+bool no_klips = TRUE;  /* don't actually use KLIPS */
+
+#else /* !KLIPS */
+
+/* declare eroute things early enough for uses */
+
+#define ERO_REPLACE_FLAG   0x100       /* out of band */
+#define ERO_DELETE     SADB_X_DELFLOW
+#define ERO_ADD        SADB_X_ADDFLOW
+#define ERO_REPLACE    (SADB_X_ADDFLOW | ERO_REPLACE_FLAG)
+
+/* bare (connectionless) shunt (eroute) table
+ *
+ * Bare shunts are those that don't "belong" to a connection.
+ * This happens because some TRAPped traffic hasn't yet or cannot be
+ * assigned to a connection.  The usual reason is that we cannot discover
+ * the peer SG.  Another is that even when the peer has been discovered,
+ * it may be that no connection matches all the particulars.
+ * Bare shunts are either HOLD or PASS.
+ * We record them so that, with scanning, we can discover
+ * which HOLDs are news and which PASSes should expire.
+ */
+
+#define SHUNT_SCAN_INTERVAL    (60 * 2)   /* time between scans of eroutes */
+
+/* SHUNT_PATIENCE only has resolution down to a multiple of the sample rate,
+ * SHUNT_SCAN_INTERVAL.
+ * By making SHUNT_PATIENCE an odd multiple of half of SHUNT_SCAN_INTERVAL,
+ * we minimize the effects of jitter.
+ */
+#define SHUNT_PATIENCE (SHUNT_SCAN_INTERVAL * 15 / 2)  /* inactivity timeout */
+struct bare_shunt {
+    ip_subnet ours;
+    ip_subnet his;
+    ip_said said;
+    unsigned long count;
+    time_t last_activity;
+    struct bare_shunt *next;
+};
+
+static struct bare_shunt *bare_shunts = NULL;
+
+/* information from /proc/net/ipsec_eroute */
+
+struct eroute_info {
+    unsigned long count;
+    ip_subnet ours;
+    ip_subnet his;
+    ip_address dst;
+    ip_said    said;
+    struct eroute_info *next;
+};
+
+/* The orphaned_holds table records HOLDs for which we
+ * scan_proc_shunts found no representation of in any connection.
+ * The corresponding ACQUIRE message might have been lost.
+ */
+struct eroute_info *orphaned_holds = NULL;
+
+
+static bool shunt_eroute(struct connection *c
+    , unsigned int op, const char *opname);    /* forward declaration */
 
 bool no_klips = FALSE;	/* don't actually use KLIPS */
 
@@ -184,22 +259,12 @@
 static pfkey_item *pfkey_iq_head = NULL;	/* oldest */
 static pfkey_item *pfkey_iq_tail;	/* youngest */
 
-/* get a PF_KEY message from kernel.
- * Returns TRUE is message found, FALSE if no message pending,
- * and aborts or keeps trying when an error is encountered.
- * The only validation of the message is that the message length
- * received matches that in the message header, and that the message
- * is for this process.
- */
 static bool
-pfkey_get(pfkey_buf *buf)
+pfkey_input_ready(void)
 {
-    for (;;)
-    {
 	fd_set readfds;
 	int ndes;
 	struct timeval tm;
-	ssize_t len;
 
 	tm.tv_sec = 0;	/* don't wait at all */
 	tm.tv_usec = 0;
@@ -216,6 +281,25 @@
 	    return FALSE;	/* nothing to read */
 
 	passert(ndes == 1 && FD_ISSET(pfkeyfd, &readfds));
+    return TRUE;
+}
+
+/* get a PF_KEY message from kernel.
+ * Returns TRUE is message found, FALSE if no message pending,
+ * and aborts or keeps trying when an error is encountered.
+ * The only validation of the message is that the message length
+ * received matches that in the message header, and that the message
+ * is for this process.
+ */
+static bool
+pfkey_get(pfkey_buf *buf)
+{
+    for (;;)
+    {
+	ssize_t len;
+
+        if (!pfkey_input_ready())
+           return FALSE;
 
 	len = read(pfkeyfd, buf->bytes, sizeof(buf->bytes));
 
@@ -345,6 +429,59 @@
     }
 }
 
+static void
+record_and_initiate_opportunistic(ip_subnet *ours, ip_subnet *his)
+{
+    passert(samesubnettype(ours, his));
+
+    /* Add to bare shunt list.
+     * We need to do this because the shunt was installed by KLIPS
+     * which can't do this itself.
+     */
+    {
+       struct bare_shunt *bs = alloc_thing(struct bare_shunt, "bare shunt");
+
+       bs->ours = *ours;
+       bs->his = *his;
+
+       bs->said.proto = SA_INT;
+       bs->said.spi = htonl(SPI_HOLD);
+       bs->said.dst = *aftoinfo(subnettypeof(ours))->any;
+
+       bs->count = 0;
+       bs->last_activity = now();
+
+       bs->next = bare_shunts;
+       bare_shunts = bs;
+    }
+
+    /* actually initiate opportunism */
+    {
+       ip_address src, dst;
+
+       networkof(ours, &src);
+       networkof(his, &dst);
+       initiate_opportunistic(&src, &dst, TRUE, NULL_FD);
+    }
+
+    /* if present, remove from orphaned_holds list.
+     * NOTE: we do this last in case ours or his is a pointer into a member.
+     */
+    {
+       struct eroute_info **pp, *p;
+
+       for (pp = &orphaned_holds; (p = *pp) != NULL; pp = &p->next)
+       {
+           if (samesubnet(ours, &p->ours) && samesubnet(his, &p->his))
+           {
+               *pp = p->next;
+               pfree(p);
+               break;
+           }
+       }
+    }
+}
+
 /* Processs a SADB_ACQUIRE message from KLIPS.
  * Try to build an opportunistic connection!
  * See RFC 2367 "PF_KEY Key Management API, Version 2" 3.1.6
@@ -365,9 +502,10 @@
 static void
 process_pfkey_acquire(pfkey_buf *buf, struct sadb_ext *extensions[SADB_EXT_MAX + 1])
 {
-    ip_address src, dst;
     struct sadb_address *srcx = (void *) extensions[SADB_EXT_ADDRESS_SRC];
     struct sadb_address *dstx = (void *) extensions[SADB_EXT_ADDRESS_DST];
+    ip_address src, dst;
+    ip_subnet ours, his;
     err_t ugh;
 
     if (buf->msg.sadb_msg_pid != 0)
@@ -383,7 +521,15 @@
     ugh = sockaddr_to_ip_address((struct sockaddr *)(void *)&dstx[1], &dst);
     passert(ugh == NULL);
 
-    initiate_opportunistic(&src, &dst, NULL_FD);
+    passert(addrtypeof(&src) == addrtypeof(&dst));
+
+    ugh = rangetosubnet(&src, &src, &ours);
+    passert(ugh == NULL);
+
+    ugh = rangetosubnet(&dst, &dst, &his);
+    passert(ugh == NULL);
+
+    record_and_initiate_opportunistic(&ours, &his);
 }
 
 /* Handle PF_KEY messages from the kernel that are not dealt with
@@ -444,6 +590,17 @@
 	pfkey_iq_head = it->next;
 	pfree(it);
     }
+
+    /* Handle any orphaned holds, but only if no pfkey input is pending.
+     * For each, we initiate Opportunistic.
+     * note: we don't need to advance the pointer because
+     * record_and_initiate_opportunistic will remove the current
+     * record each time we call it.
+     */
+    while (orphaned_holds != NULL && !pfkey_input_ready())
+       record_and_initiate_opportunistic(&orphaned_holds->ours
+           , &orphaned_holds->his);
+
 }
 
 /* asynchronous messages directly from PF_KEY socket */
@@ -597,6 +754,7 @@
 
     /* form the command string */
     {
+	const ip_subnet *epc = EffectivePeerClient(c);
 	char
 	    nexthop_str[ADDRTOT_BUF],
 	    me_str[ADDRTOT_BUF],
@@ -619,10 +777,10 @@
 	addrtot(&ta, 0, myclientmask_str, sizeof(myclientmask_str));
 
 	addrtot(&c->that.host_addr, 0, peer_str, sizeof(peer_str));
-	subnettot(&c->that.client, 0, peerclient_str, sizeof(peerclientnet_str));
-	networkof(&c->that.client, &ta);
+        subnettot(epc, 0, peerclient_str, sizeof(peerclientnet_str));
+        networkof(epc, &ta);
 	addrtot(&ta, 0, peerclientnet_str, sizeof(peerclientnet_str));
-	maskof(&c->that.client, &ta);
+	maskof(epc, &ta);
 	addrtot(&ta, 0, peerclientmask_str, sizeof(peerclientmask_str));
 
 	if (-1 == snprintf(cmd, sizeof(cmd),
@@ -742,114 +900,85 @@
     return TRUE;
 }
 
-bool
-route_connection(struct connection *c, bool doit)
+/* Check that we can route (and eroute).  Diagnose if we cannot. */
+
+static bool
+could_route(struct connection *c)
 {
-    if (c->routed)
-    {
-	/* already done */
-    }
-    else if (HasWildcardIP(*c) && HasWildcardClient(c))
-    {
-	loglog(RC_ROUTE, "cannot route uninstantiated opportunistic connection");
-    }
-    else if (isanyaddr(&c->this.host_nexthop))
+     struct connection *ero     /* who, if anyone, owns our eroute? */
+        , *ro = route_owner(c, &ero);   /* who owns our route? */
+ 
+     /* if we don't know nexthop, we cannot route */
+     if (isanyaddr(&c->this.host_nexthop))
     {
 	loglog(RC_ROUTE, "cannot route connection without knowing nexthop");
+        return FALSE;
     }
-    else if (!no_klips
+
+    /* if routing would affect IKE messages, reject */
+    if (!no_klips
     && c->this.host_port != IKE_UDP_PORT
-    && addrinsubnet(&c->that.host_addr, &c->that.client))
+    && addrinsubnet(&c->that.host_addr, EffectivePeerClient(c)))
     {
 	loglog(RC_LOG_SERIOUS, "cannot install route: peer is within its client");
+	return FALSE;
     }
-    else if (!doit)
-    {
-	/* just testing -- we expect to be able to do it */
-	return TRUE;
-    }
-    else
-    {
-	struct connection *d = route_owner(c, FALSE);
 
-	passert(c->eroute_owner == SOS_NOBODY);
-	if (d == NULL)
-	{
-	    /* nobody's got it: we can try to install our route */
-	    (void) do_command(c, "prepare");	/* just in case; ignore failure */
-	    if (do_command(c, "route"))
-		c->routed = TRUE;
-	}
-	else if (sameaddr(&d->this.host_nexthop, &c->this.host_nexthop)
-	&& d->interface == c->interface)
-	{
-	    /* The other connection has the same nexthop and interface,
-	     * so we're done.
+    /* If there is already a route for peer's client subnet
+     * and it disagrees about interface or nexthop, we cannot steal it.
+     * Note: if this connection is already routed (perhaps for another
+     * state object), the route will agree.
+     * This is as it should be -- it will arise during rekeying.
 	     */
-	    c->routed = TRUE;
-	}
-	else if (d->eroute_owner == SOS_NOBODY)
+    if (ro != NULL && !routes_agree(ro, c))
 	{
-	    /* The other connection has the route, and it conflicts
-	     * (the nexthop or interface differs), but that connection
-	     * isn't using the route.  We'll steal it!  There might be
-	     * other connections using the same route, but none of
-	     * them is using it either (otherwise route_owner()
-	     * would have returned one that did).
-	     *
-	     * A feature of LINUX allows us to install the new route
-	     * before deleting the old if the nexthops differ.
-	     * This reduces the "window of vulnerability" when packets
-	     * might flow in the clear.
-	     *
-	     * c->routed must be set last so that route_owner()
-	     * doesn't find it.
-	     */
-
-	    bool preadd = !sameaddr(&d->this.host_nexthop, &c->this.host_nexthop);
-
-	    if (!preadd || do_command(c, "route"))
-	    {
-		/* one unroute for all */
-		if (do_command(d, "unroute"))
-		{
-		    do {
-			passert(d->eroute_owner == SOS_NOBODY);
-			d->routed = FALSE;
-			d = route_owner(c, FALSE);
-		    } while (d != NULL);
-
-		    if (preadd || do_command(c, "route"))
-			c->routed = TRUE;
-		}
-	    }
+       loglog(RC_LOG_SERIOUS, "cannot route -- route already in use for \"%s\""
+           , ro->name);
+       return FALSE;   /* another connection already using the eroute */
 	}
-	else
+#ifdef KLIPS
+    /* if there is an eroute for another connection, there is a problem */
+    if (ero != NULL && ero != c)
 	{
-	    loglog(RC_LOG_SERIOUS, "cannot install route: connection \"%s\" already has it"
-		, d->name);
-	}
+       loglog(RC_LOG_SERIOUS, "cannot install eroute -- it is in use for \"%s\""
+           , ero->name);
+       return FALSE;   /* another connection already using the eroute */
     }
-    return c->routed;
+#endif /* KLIPS */
+    return TRUE;
 }
 
+bool
+trap_connection(struct connection *c)
+{
+    return could_route(c) && route_and_eroute(c, NULL);
+}
+
+/* delete any eroute for a connection and unroute it if route isn't shared */
 void
 unroute_connection(struct connection *c)
 {
-    /* only unroute if no other connection shares it */
-    if (c->routed)
+    enum routing_t cr = c->routing;
+
+    if (erouted(cr))
     {
-	c->routed = FALSE;
-	if (route_owner(c, FALSE) == NULL && !do_command(c, "unroute"))
-	    c->routed = TRUE;	/* undo on failure */
+       passert(cr != RT_ROUTED_TUNNEL);        /* cannot handle a live one */
+       shunt_eroute(c, ERO_DELETE, "delete");
     }
+
+    c->routing = RT_UNROUTED;  /* do now so route_owner won't find us */
+
+    /* only unroute if no other connection shares it */
+    if (routed(cr)
+    && route_owner(c, NULL) == NULL)
+       (void) do_command(c, "unroute");
 }
 
 
 #ifdef KLIPS
 
 static void
-set_text_said(char *text_said, ip_address *dst, ipsec_spi_t spi, int proto)
+set_text_said(char *text_said, const ip_address *dst, ipsec_spi_t spi, int proto)
 {
     ip_said said;
 
@@ -893,13 +1022,19 @@
 /* pfkey_build + pfkey_address_build */
 static bool
 pfkeyext_address(u_int16_t exttype
-, ip_address *address
+, const ip_address *address
 , const char *description
 , const char *text_said
 , struct sadb_ext *extensions[SADB_EXT_MAX + 1])
 {
+    /* the following variable is only needed to silence
+     * a warning caused by the fact that the argument
+     * to sockaddrof is NOT pointer to const!
+     */
+    ip_address t = *address;
+
     return pfkey_build(pfkey_address_build(extensions + exttype
-	    , exttype, 0, 0, sockaddrof(address))
+           , exttype, 0, 0, sockaddrof(&t))
 	, description, text_said, extensions);
 }
 
@@ -941,8 +1076,17 @@
 
 	    if (r != (ssize_t)len)
 	    {
+               if (r < 0)
+               {
 		log_errno((e, "pfkey write() of %s %s failed"
 		    , description, text_said));
+               }
+               else
+               {
+                   loglog(RC_LOG_SERIOUS, "ERROR: pfkey write() of %s %s truncated: %ld instead of %ld"
+                       , description, text_said
+                       , (long)r, (long)len);
+               }
 		success = FALSE;
 	    }
 	    else
@@ -956,24 +1100,11 @@
 
 		if (!pfkey_get_response(bp, ((struct sadb_msg *) extensions[0])->sadb_msg_seq))
 		{
-/*FUDGE*/	/* temporary fudge: KLIPS doesn't yet generate replies for all messages */
-/*FUDGE*/	switch (pfkey_msg->sadb_msg_type)
-/*FUDGE*/	{
-/*FUDGE*/	case SADB_X_GRPSA:
-/*FUDGE*/	case SADB_X_ADDFLOW:
-/*FUDGE*/	case SADB_X_DELFLOW:
-/*FUDGE*/	    loglog(RC_LOG_SERIOUS
-/*FUDGE*/		, "ignoring: no response to our PF_KEY %s message for %s %s"
-/*FUDGE*/		, sparse_val_show(pfkey_type_names, pfkey_msg->sadb_msg_type)
-/*FUDGE*/		, description, text_said);
-/*FUDGE*/	    break;
-/*FUDGE*/	default:
 		    loglog(RC_LOG_SERIOUS
 			, "ERROR: no response to our PF_KEY %s message for %s %s"
 			, sparse_val_show(pfkey_type_names, pfkey_msg->sadb_msg_type)
 			, description, text_said);
 		    success = FALSE;
-/*FUDGE*/	}
 		}
 		else if (pfkey_msg->sadb_msg_type != bp->msg.sadb_msg_type)
 		{
@@ -1038,20 +1169,32 @@
     pfkey_register_proto(SADB_X_SATYPE_IPIP, "IPIP");
 }
 
+/* find an entry in the bare_shunt table.
+ * Trick: return a pointer to the entry; this allows the entry to be deleted.
+ */
+static struct bare_shunt **
+bare_shunt_ptr(ip_subnet *ours, ip_subnet *his)
+{
+    struct bare_shunt *p, **pp;
+
+    for (pp = &bare_shunts; (p = *pp) != NULL; pp = &p->next)
+       if (samesubnet(ours, &p->ours)
+       && samesubnet(his, &p->his))
+           return pp;
+    return NULL;
+}
+
 /* Setup an IPsec route entry. Code taken from addrt.c.
  * We are only dealing with outbound SAs.
- * op is one of the following KLIPS operators:
+ * op is one of the ERO_* operators.
  */
 
-#define ERO_REPLACE_FLAG   0x100	/* out of band */
-#define ERO_DELETE	SADB_X_DELFLOW
-#define ERO_ADD	SADB_X_ADDFLOW
-#define ERO_REPLACE	(SADB_X_ADDFLOW | ERO_REPLACE_FLAG)
-
 static bool
-do_eroute(struct state *st, unsigned op, const char *opname UNUSED)
+raw_eroute(const ip_address *this_host, const ip_subnet *this_client
+, const ip_address *that_host, const ip_subnet *that_client
+, ipsec_spi_t spi, unsigned int proto, unsigned int satype
+, unsigned int op, const char *opname UNUSED)
 {
-    struct connection *c = st->st_connection;
     struct sadb_ext *extensions[SADB_EXT_MAX + 1];
     ip_address
     	sflow_ska,
@@ -1059,6 +1202,151 @@
     	smask_ska,
     	dmask_ska;
     char text_said[SATOT_BUF];
+
+    set_text_said(text_said, that_host, spi, proto);
+
+    networkof(this_client, &sflow_ska);
+    maskof(this_client, &smask_ska);
+
+    networkof(that_client, &dflow_ska);
+    maskof(that_client, &dmask_ska);
+
+    DBG(DBG_CONTROL,
+       {
+           char mybuf[SUBNETTOT_BUF];
+           char peerbuf[SUBNETTOT_BUF];
+
+           subnettot(this_client, 0, mybuf, sizeof(mybuf));
+           subnettot(that_client, 0, peerbuf, sizeof(peerbuf));
+           DBG_log("%s eroute %s to %s via %s"
+               , opname, mybuf, peerbuf, text_said);
+       });
+
+    return pfkey_msg_start(op & ~ERO_REPLACE_FLAG, satype
+       , "pfkey_msg_hdr flow", text_said, extensions)
+
+    && (op == ERO_DELETE
+       || (pfkey_build(pfkey_sa_build(&extensions[SADB_EXT_SA]
+               , SADB_EXT_SA
+               , spi   /* in network order */
+               , 0, 0, 0, 0, op == ERO_REPLACE? SADB_X_SAFLAGS_REPLACEFLOW : 0)
+           , "pfkey_sa add flow", text_said, extensions)
+
+           && pfkeyext_address(SADB_EXT_ADDRESS_SRC, this_host
+               , "pfkey_addr_s add flow", text_said, extensions)
+
+           && pfkeyext_address(SADB_EXT_ADDRESS_DST, that_host
+               , "pfkey_addr_d add flow", text_said, extensions)))
+
+    && pfkeyext_address(SADB_X_EXT_ADDRESS_SRC_FLOW, &sflow_ska
+       , "pfkey_addr_sflow", text_said, extensions)
+
+    && pfkeyext_address(SADB_X_EXT_ADDRESS_DST_FLOW, &dflow_ska
+       , "pfkey_addr_dflow", text_said, extensions)
+
+    && pfkeyext_address(SADB_X_EXT_ADDRESS_SRC_MASK, &smask_ska
+       , "pfkey_addr_smask", text_said, extensions)
+
+    && pfkeyext_address(SADB_X_EXT_ADDRESS_DST_MASK, &dmask_ska
+       , "pfkey_addr_dmask", text_said, extensions)
+
+    && finish_pfkey_msg(extensions, "flow", text_said, NULL);
+}
+
+/* Replace (or delete) a shunt that is in the bare_shunts table.
+ * Issues the PF_KEY commands and updates the bare_shunts table.
+ */
+bool
+replace_bare_shunt(const ip_address *src, const ip_address *dst
+, ipsec_spi_t shunt_spi        /* in host order! */
+, bool repl, const char *opname)
+{
+    err_t ugh;
+    ip_subnet this_client, that_client;
+    const ip_address *null_host = aftoinfo(addrtypeof(src))->any;
+    unsigned int op = repl? ERO_REPLACE : ERO_DELETE;
+
+    passert(addrtypeof(src) == addrtypeof(dst));
+    ugh = rangetosubnet(src, src, &this_client);
+    passert(ugh == NULL);
+    ugh = rangetosubnet(dst, dst, &that_client);
+    passert(ugh == NULL);
+
+    if (raw_eroute(null_host, &this_client, null_host, &that_client
+    , htonl(shunt_spi), SA_INT, SADB_X_SATYPE_INT, op, opname))
+    {
+       struct bare_shunt **bs_pp = bare_shunt_ptr(&this_client, &that_client);
+       struct bare_shunt *bs = *bs_pp;
+
+       if (repl)
+       {
+           /* change over to new bare eroute */
+           bs->said.spi = htonl(shunt_spi);
+           bs->said.proto = SA_INT;
+           bs->said.dst = *null_host;
+           bs->count = 0;
+           bs->last_activity = now();
+       }
+       else
+       {
+           /* a delete bare eroute */
+           *bs_pp = bs->next;
+           pfree(bs);
+       }
+       return TRUE;
+    }
+    else
+    {
+       return FALSE;
+    }
+}
+
+static bool
+eroute_connection(struct connection *c
+, ipsec_spi_t spi, unsigned int proto, unsigned int satype
+, unsigned int op, const char *opname)
+{
+    return raw_eroute(&c->this.host_addr, &c->this.client
+       , &c->that.host_addr, EffectivePeerClient(c)
+       , spi, proto, satype, op, opname);
+}
+
+/* assign a bare hold to a connection */
+
+bool
+assign_hold(struct connection *c
+, const ip_address *src, const ip_address *dst)
+{
+    /* either the automatically installed HOLD eroute is broad enough
+     * or we try to add a broader one and delete the automatic one.
+     */
+    if (subnetishost(&c->this.client) && subnetishost(&c->that.client))
+    {
+       /* although HOLD is appropriately broad, it will no longer be bare
+        * so we must ditch it from the bare table.
+        */
+       struct bare_shunt **bs_pp = bare_shunt_ptr(&c->this.client
+           , &c->that.client);
+       struct bare_shunt *bs = *bs_pp;
+
+       *bs_pp = bs->next;
+       pfree(bs);
+       return TRUE;
+    }
+    else
+    {
+       /* we broaden by adding an HOLD eroute and deleting the old bare HOLD */       return eroute_connection(c, htonl(SPI_HOLD), SA_INT, SADB_X_SATYPE_INT
+               , ERO_ADD, "add broader HOLD")
+           && replace_bare_shunt(src, dst, SPI_HOLD, FALSE
+               , "delete for broader HOLD");
+    }
+}
+
+/* install or remove eroute for SA Group */
+static bool
+sag_eroute(struct state *st, unsigned op, const char *opname)
+{
+    struct connection *c = st->st_connection;
     unsigned int
     	inner_proto,
 	inner_satype;
@@ -1099,58 +1387,275 @@
 	passert(FALSE);	/* no transform at all! */
     }
 
-    set_text_said(text_said, &c->that.host_addr, inner_spi, inner_proto);
+    return eroute_connection(c
+       , inner_spi, inner_proto, inner_satype
+       , op, opname);
+}
+
+/* Add/replace/delete a shunt eroute.
+ * Such an eroute determines the fate of packets without the use
+ * of any SAs.  These are defaults, in effect.
+ * If a negotiation has not been attempted, use TRAP.
+ * If negotiation has failed, the choice between TRAP/PASS/DROP/REJECT
+ * is specified in the policy of connection c.
+ */
+static bool
+shunt_eroute(struct connection *c, unsigned int op, const char *opname)
+{
+    /* We are constructing a special SAID for the eroute.
+     * The destination doesn't seem to matter, but the family does.
+     * The protocol is SA_INT -- mark this as shunt.
+     * The satype has no meaning, but is required for PF_KEY header!
+     * The SPI signifies the kind of shunt.
+     */
+
+    /* note: these are in host order :-( */
+    static ipsec_spi_t shunt_spi[] = { SPI_TRAP /* */
+       , SPI_PASS      /* --pass */
+       , SPI_DROP      /* --drop */
+       , SPI_REJECT }; /* --pass --drop */
 
-    networkof(&c->this.client, &sflow_ska);
-    maskof(&c->this.client, &smask_ska);
+    ipsec_spi_t spi = c->routing == RT_ROUTED_PROSPECTIVE? SPI_TRAP
+       : shunt_spi[(c->policy & POLICY_OPPO_MASK) >> POLICY_OPPO_SHIFT];
 
-    networkof(&c->that.client, &dflow_ska);
-    maskof(&c->that.client, &dmask_ska);
+    return eroute_connection(c, htonl(spi), SA_INT, SADB_X_SATYPE_INT, op, opname);
+}
 
-    DBG(DBG_CONTROL,
+/* scan /proc/net/ipsec_eroute every once in a while, looking for:
+ *
+ * - HOLD shunts of which Pluto isn't aware.  This situation could
+ *   be caused by lost ACQUIRE messages.  When found, they will
+ *   added to orphan_holds.  This in turn will lead to Opportunistic
+ *   initiation.
+ *
+ * - PASS shunts that haven't been used recently.  These will be
+ *   deleted.
+ *
+ * - (eventually) other shunt eroutes that haven't been used in a while.
+ *
+ * Here are some sample lines:
+ *  10.3.2.1.0/24    -> 0.0.0.0/0          => int0x104@0.0.0.0
+ *  10.3.2.1.115/32  -> 10.19.75.161/32  => tun0x1002@10.19.75.145
+ *  10.44.73.97/32   -> 0.0.0.0/0          => int0x104@0.0.0.0
+ *  10.44.73.97/32   -> 10.114.121.41.23/32   => int0x100@10.114.121.41.23
+ * Newer versions of KLIPS start each line with a 32-bit packet count.
+ * If available, these counts are used to detect
+ */
+void
+scan_proc_shunts(void)
+{
+    static const char procname[] = "/proc/net/ipsec_eroute";
+    FILE *f;
+    time_t nw = now();
+    int lino;
+    struct eroute_info *expired = NULL;
+
+    event_schedule(EVENT_SHUNT_SCAN, SHUNT_SCAN_INTERVAL, NULL);
+
+    /* free any leftover entries: they will be refreshed if still current */
+    while (orphaned_holds != NULL)
 	{
-	    char mybuf[SUBNETTOT_BUF];
-	    char peerbuf[SUBNETTOT_BUF];
+       struct eroute_info *p = orphaned_holds;
 
-	    subnettot(&c->this.client, 0, mybuf, sizeof(mybuf));
-	    subnettot(&c->that.client, 0, peerbuf, sizeof(peerbuf));
-	    DBG_log("%s eroute %s to %s via %s"
-		, opname, mybuf, peerbuf, text_said);
-	});
+       orphaned_holds = p->next;
+       pfree(orphaned_holds);
+    }
 
-    return pfkey_msg_start(op & ~ERO_REPLACE_FLAG, inner_satype
-	, "pfkey_msg_hdr flow", text_said, extensions)
+    /* decode the /proc file.  Don't do anything strenuous to it
+     * (certainly no PF_KEY stuff) to minimize the chance that it
+     * might change underfoot.
+     */
 
-    && (op == ERO_DELETE
-	|| (pfkey_build(pfkey_sa_build(&extensions[SADB_EXT_SA]
-	    	, SADB_EXT_SA
-		, inner_spi	/* in network order */
-	    	, 0, 0, 0, 0, op == ERO_REPLACE? SADB_X_SAFLAGS_REPLACEFLOW : 0)
-	    , "pfkey_sa add flow", text_said, extensions)
+    f = fopen(procname, "r");
+    if (f == NULL)
+       return;
 
-	    && pfkeyext_address(SADB_EXT_ADDRESS_SRC, &c->this.host_addr
-		, "pfkey_addr_s add flow", text_said, extensions)
+    /* for each line... */
+    for (lino = 1; ; lino++)
+    {
+       unsigned char buf[1024];        /* should be big enough */
+       chunk_t field[10];      /* 10 is loose upper bound */
+       chunk_t *ff;    /* fixed fields (excluding optional count) */
+       int fi;
+       struct eroute_info eri;
+       char *cp;
+       err_t context = ""
+           , ugh = NULL;
 
-	    && pfkeyext_address(SADB_EXT_ADDRESS_DST, &c->that.host_addr
-		, "pfkey_addr_d add flow", text_said, extensions)))
+       cp = fgets(buf, sizeof(buf), f);
+       if (cp == NULL)
+           break;
 
-    && pfkeyext_address(SADB_X_EXT_ADDRESS_SRC_FLOW, &sflow_ska
-	, "pfkey_addr_sflow", text_said, extensions)
+       /* break out each field
+        * Note: if there are too many fields, just stop;
+        * it will be diagnosed a little later.
+        */
+       for (fi = 0; fi < (int)elemsof(field); fi++)
+	{
+           static const char sep[] = " \t\n";  /* field-separating whitespace */
+           size_t w;
+
+           cp += strspn(cp, sep);      /* find start of field */
+           w = strcspn(cp, sep);       /* find width of field */
+           setchunk(field[fi], cp, w);
+           cp += w;
+           if (w == 0)
+               break;
+       }
 
-    && pfkeyext_address(SADB_X_EXT_ADDRESS_DST_FLOW, &dflow_ska
-	, "pfkey_addr_dflow", text_said, extensions)
+       /* This odd do-hickey is to share error reporting code.
+        * A break will get to that common code.  The setting
+        * of "ugh" and "context" parameterize it.
+        */
+       do {
+           /* Old entries have no packet count; new ones do.
+            * check if things are as they should be.
+            */
+           if (fi == 5)
+               ff = &field[0]; /* old form, with no count */
+           else if (fi == 6)
+               ff = &field[1]; /* new form, with count */
+           else
+           {
+               ugh = "has wrong number of fields";
+               break;
+           }
 
-    && pfkeyext_address(SADB_X_EXT_ADDRESS_SRC_MASK, &smask_ska
-	, "pfkey_addr_smask", text_said, extensions)
+           if (ff[1].len != 2
+           || strncmp(ff[1].ptr, "->", 2) != 0
+           || ff[3].len != 2
+           || strncmp(ff[3].ptr, "=>", 2) != 0)
+           {
+               ugh = "is missing -> or =>";
+               break;
+           }
 
-    && pfkeyext_address(SADB_X_EXT_ADDRESS_DST_MASK, &dmask_ska
-	, "pfkey_addr_dmask", text_said, extensions)
+           /* actually digest fields of interest */
 
-    && finish_pfkey_msg(extensions, "flow", text_said, NULL);
+           /* packet count */
+
+           eri.count = 0;
+           if (ff != field)
+           {
+               context = "count field is malformed: ";
+               ugh = ttoul(field[0].ptr, field[0].len, 10, &eri.count);
+               if (ugh != NULL)
+                   break;
+           }
+
+           /* our client */
+
+           context = "source subnet field malformed: ";
+           ugh = ttosubnet(ff[0].ptr, ff[0].len, AF_INET, &eri.ours);
+           if (ugh != NULL)
+               break;
+
+           /* his client */
+
+           context = "source subnet field malformed: ";
+           ugh = ttosubnet(ff[2].ptr, ff[2].len, AF_INET, &eri.his);
+           if (ugh != NULL)
+               break;
+
+           /* SAID */
+
+           context = "SA ID field malformed: ";
+           ugh = ttosa(ff[4].ptr, ff[4].len, &eri.said);
+       } while (FALSE);
+
+       if (ugh != NULL)
+       {
+           log("INTERNAL ERROR: %s line %d %s%s"
+               , procname, lino, context, ugh);
+           continue;   /* ignore rest of line */
+       }
+
+       /* Now we have decoded eroute, let's consider it.
+        * We only care about shunt eroutes.
+        *
+        * HOLD: if not known, add to orphaned_holds list for initiation
+        *    because ACQUIRE might have been lost.
+        *
+        * PASS: determine if idle; if so, blast it away.
+        *    Can occur bare (if DNS provided insufficient information)
+        *    or with a connection (failure context).
+        *    Could even be installed by ipsec manual.
+        *
+        * TRAP: always welcome.
+        *
+        * others: handling as yet undesigned.  Generally associated
+        *    with a failure context.
+        */
+       if (eri.said.proto == SA_INT)
+       {
+           switch (ntohl(eri.said.spi))
+           {
+           case SPI_HOLD:
+               if (bare_shunt_ptr(&eri.ours, &eri.his) == NULL
+               && shunt_owner(&eri.ours, &eri.his) == NULL)
+               {
+                   eri.next = orphaned_holds;
+                   orphaned_holds = clone_thing(eri, "orphaned HOLD");
+               }
+               break;
+
+           case SPI_PASS:
+               /* nothing sensible to do if we don't have counts */
+               if (ff != field)
+               {
+                   struct bare_shunt **bs_pp
+                       = bare_shunt_ptr(&eri.ours, &eri.his);
+
+                   if (bs_pp != NULL)
+                   {
+                       struct bare_shunt *bs = *bs_pp;
+
+                       if (eri.count != bs->count)
+                       {
+                           bs->count = eri.count;
+                           bs->last_activity = nw;
+                       }
+                       else if (nw - bs->last_activity > SHUNT_PATIENCE)
+                       {
+                           eri.next = expired;
+                           expired = clone_thing(eri, "expired PASS");
+                       }
+                   }
+               }
+               break;
+
+           case SPI_DROP:
+           case SPI_REJECT:
+           case SPI_TRAP:
+               break;
+
+           default:
+               passert(FALSE);
+           }
+       }
+    }  /* for each line */
+    fclose(f);
+
+    /* Now that we've finished processing the /proc file,
+     * it is safe to delete the expired PASS shunts.
+     */
+    while (expired != NULL)
+    {
+       struct eroute_info *p = expired;
+       ip_address src, dst;
+
+       networkof(&p->ours, &src);
+       networkof(&p->his, &dst);
+       (void) replace_bare_shunt(&src, &dst
+           , SPI_PASS, FALSE, "delete expired PASS");
+       expired = p->next;
+       pfree(p);
+    }
 }
 
 static bool
-del_spi(ipsec_spi_t spi, int proto, ip_address *src, ip_address *dest)
+del_spi(ipsec_spi_t spi, int proto
+, const ip_address *src, const ip_address *dest)
 {
     struct sadb_ext *extensions[SADB_EXT_MAX + 1];
     char text_said[SATOT_BUF];
@@ -1570,30 +2075,24 @@
 	passert(FALSE);	/* neither AH nor ESP in outbound SA bundle! */
     }
 
+    send_delete(st, &f->our_spi, proto==SA_ESP?TRUE:FALSE);
+
     return inbound
 	? del_spi(f->our_spi, proto, &c->that.host_addr, &c->this.host_addr)
 	: del_spi(f->attrs.spi, proto, &c->this.host_addr, &c->that.host_addr);
 }
-
-/* demand that we can eroute */
-static bool
-could_eroute(struct connection *c, struct connection *ero)
-{
-    if (ero != NULL && ero != c && ero->eroute_owner != SOS_NOBODY)
-    {
-	loglog(RC_LOG_SERIOUS, "cannot install eroute -- it is in use for \"%s\"", ero->name);
-	return FALSE;	/* another connection already using the eroute */
-    }
-    return TRUE;
-}
 #endif /* KLIPS */
 
 
-void init_kernel(void)
+void
+init_kernel(void)
 {
 #ifdef KLIPS
     if (!no_klips)
+    {
 	init_pfkey();
+	event_schedule(EVENT_SHUNT_SCAN, SHUNT_SCAN_INTERVAL, NULL);
+    }
 #endif
 }
 
@@ -1612,112 +2111,199 @@
      * obsolete and should be eliminated.  Interestingly, this is
      * the only case in which we can tell that a connection is obsolete.
      */
-    if (!subnetishost(&c->that.client))
+    passert(c->kind != CK_TEMPLATE);
+    if (c->that.has_client)
     {
 	for (;;)
 	{
-	    struct connection *o = route_owner(c, FALSE);
+	    struct connection *o = route_owner(c, NULL);
 
 	    if (o == NULL)
 		break;	/* nobody has a route */
 
-	    if (sameaddr(&o->this.host_addr, &c->this.host_addr)
-	    && sameaddr(&o->that.host_addr, &c->that.host_addr))
+           /* note: we ignore the client addresses at this end */
+           if (sameaddr(&o->that.host_addr, &c->that.host_addr)
+           && o->interface == c->interface)
 		break;	/* existing route is compatible */
 
-	    loglog(RC_LOG_SERIOUS, "route to peer's client conflicts with \"%s\" %s; unorienting old connection to free the route"
+	    loglog(RC_LOG_SERIOUS, "route to peer's client conflicts with \"%s\" %s; releasing old connection to free the route"
 		, o->name, ip_str(&o->that.host_addr));
-	    unorient_connection(o);
+	    release_connection(o);
 	}
     }
-#ifdef KLIPS
-    /* check that we will be able to eroute */
-    if (!could_eroute(c, route_owner(c, TRUE)))
-	return FALSE;
-
-    /* Check that we will be able to route outgoing packets
-     * through ipsecN interface.  Actually, this only checks that
-     * our peer isn't inside his own subnet or if she is,
-     * that we're using UDP 500 so that IKE messages will not
-     * be processed.
-     */
-    if (!route_connection(c, FALSE))
+    /* check that we will be able to route and eroute */
+    if (!could_route(c))
 	return FALSE;
 
+#ifdef KLIPS
     /* (attempt to) actually set up the SAs */
     return setup_half_ipsec_sa(st, TRUE);
-
 #else /* !KLIPS */
     DBG(DBG_CONTROL, DBG_log("install_inbound_ipsec_sa()"));
     return TRUE;
 #endif /* !KLIPS */
 }
 
-bool
-install_ipsec_sa(struct state *st, bool inbound_also)
+/* Install a route and then a prospective shunt eroute or an SA group eroute.
+ * Assumption: could_route gave a go-ahead.
+ * Any SA Group must have already been created.
+ * On failure, steps will be unwound (where feasible: old shunt
+ * will be lost -- this may matter).
+ */
+static bool
+route_and_eroute(struct connection *c, struct state *st)
 {
 #ifdef KLIPS
-    bool res;
-    struct connection
-	*c = st->st_connection,
-	*ero = route_owner(c, TRUE);	/* who, if anyone, owns our eroute? */
+    struct connection *ero     /* who, if anyone, owns our eroute? */
+       , *ro = route_owner(c, &ero);
+    bool eroute_installed = FALSE
+       , firewall_notified = FALSE
+       , route_installed = FALSE;
+
+    /* install the eroute */
+
+    passert(ero == NULL || ero == c);
+    if (ero != NULL)
+    {
+       /* We're replacing an eroute */
+       eroute_installed = st == NULL
+           ? shunt_eroute(c, ERO_REPLACE, "replace")
+           : sag_eroute(st, ERO_REPLACE, "replace");
+    }
+    else
+    {
+       /* we're adding an eroute */
+       eroute_installed = st == NULL
+           ? shunt_eroute(c, ERO_ADD, "add")
+           : sag_eroute(st, ERO_ADD, "add");
+    }
 
-    if (!could_eroute(c, ero))
-	return FALSE;
+    /* notify the firewall of a new tunnel */
 
-    /* route outgoing packets through ipsecN interface.
-     * Note that we don't bother to undo this on failure.
+    if (eroute_installed)
+    {
+       /* do we have to notify the firewall?  Yes, if it wasn't notified
+        * for a previous tunnel with the same clients.  Any Previous
+        * tunnel would have to be for our connection, so the actual
+        * test is simple.
      */
-    if (!route_connection(c, TRUE))
-	return FALSE;
+       firewall_notified = c->eroute_owner != SOS_NOBODY
+           || do_command(c, "up");
+    }
 
-    /* (attempt to) actually set up the SAs */
-    res = (!inbound_also || setup_half_ipsec_sa(st, TRUE))
-	&& setup_half_ipsec_sa(st, FALSE);
+    /* install the route */
 
-    /* no other connection has this eroute, but
-     * this connection might have it for another SA.
-     * This is expected when rekeying.
-     * If another SA has it, we replace the eroute.
-     */
-    if (res)
+    if (!firewall_notified)
     {
-	/* succeed OR tear SA down again */
-	if (c->eroute_owner == SOS_NOBODY)
+       /* we're in trouble -- don't do routing */
+    }
+    else if (ro == NULL)
 	{
-	    /* new eroute: we also need to run "up" command */
-	    res = do_eroute(st, ERO_ADD, "add");
-	    if (res)
+       /* a new route: no deletion required, but preparation is */
+       (void) do_command(c, "prepare");        /* just in case; ignore failure */
+       route_installed = do_command(c, "route");
+    }
+    else if (routed(c->routing)
+    || routes_agree(ro, c))
 	    {
-		/* succeed OR tear eroute down again */
-		res = do_command(st->st_connection, "up");
-		if (!res)
-		    (void) do_eroute(st, ERO_DELETE, "delete");
+       route_installed = TRUE; /* nothing to be done */
 	    }
+    else
+    {
+       /* Some other connection must own the route
+        * and the route must disagree.  But since could_route
+        * must have allowed our stealing it, we'll do so.
+        *
+        * A feature of LINUX allows us to install the new route
+        * before deleting the old if the nexthops differ.
+        * This reduces the "window of vulnerability" when packets
+        * might flow in the clear.
+        */
+       if (sameaddr(&c->this.host_nexthop, &ro->this.host_nexthop))
+	{
+           (void) do_command(ro, "unroute");
+           route_installed = do_command(c, "route");
 	}
 	else
 	{
-	    /* old eroute being replaced -- no command required */
-	    res = do_eroute(st, ERO_REPLACE, "replace");
+           route_installed = do_command(c, "route");
+           (void) do_command(ro, "unroute");
 	}
-	if (res)
+
+       /* record unrouting */
+       if (route_installed)
+	{
+           do {
+               passert(!erouted(ro->routing));
+               ro->routing = RT_UNROUTED;
+               ro = route_owner(c, NULL);      /* no need to keep old value */
+           } while (ro != NULL);
+       }
+    }
+
+    /* all done -- clean up */
+    if (route_installed)
+    {
+       /* Success! */
+       if (st == NULL)
+       {
+           c->routing = RT_ROUTED_PROSPECTIVE;
+	}
+	else
 	{
+           c->routing = RT_ROUTED_TUNNEL;
 	    c->eroute_owner = st->st_serialno;
 	}
+
+       return TRUE;
+    }
 	else
 	{
-	    (void) teardown_half_ipsec_sa(st, FALSE);
-	    if (inbound_also)
-		(void) teardown_half_ipsec_sa(st, TRUE);
+       /* Failure!  Unwind our work. */
+       if (firewall_notified && c->eroute_owner == SOS_NOBODY)
+           (void) do_command(c, "down");
+
+       if (eroute_installed)
+       {
+           if (st == NULL)
+               (void) shunt_eroute(c, ERO_DELETE, "delete");
+           else
+               (void) sag_eroute(st, ERO_DELETE, "delete");
 	}
+
+       return FALSE;
     }
+#else /* !KLIPS */
+    return TRUE;
+#endif /* !KLIPS */
+}
 
-    return res;
+bool
+install_ipsec_sa(struct state *st, bool inbound_also)
+{
+    if (!could_route(st->st_connection))
+       return FALSE;
+
+#ifdef KLIPS
+    /* (attempt to) actually set up the SA group */
+    if ((inbound_also && !setup_half_ipsec_sa(st, TRUE))
+    || !setup_half_ipsec_sa(st, FALSE))
+       return FALSE;
+
+    if (!route_and_eroute(st->st_connection, st))
+    {
+       (void) delete_ipsec_sa(st, FALSE);
+       return FALSE;
+    }
 #else /* !KLIPS */
+    if (!could_route(st->st_connection))
+       return FALSE;
+
     DBG(DBG_CONTROL, DBG_log("install_ipsec_sa() %s"
 	, inbound_also? "inbound and oubound" : "outbound only"));
-    return route_connection(st->st_connection, TRUE);
 #endif /* !KLIPS */
+
+    return TRUE;
 }
 
 bool
@@ -1736,10 +2322,16 @@
     {
 	if (own_eroute)
 	{
-	    res = do_command(st->st_connection, "down")
-		&& do_eroute(st, ERO_DELETE, "delete");
-	    if (res)
 		c->eroute_owner = SOS_NOBODY;
+           c->routing = RT_ROUTED_PROSPECTIVE;
+           res = do_command(c, "down")
+               && shunt_eroute(c, ERO_REPLACE, "replace with shunt");
+           if (!res)
+           {
+               /* since we failed, restore our record of routing */
+               c->eroute_owner = st->st_serialno;
+               c->routing = RT_ROUTED_TUNNEL;
+           }
 	}
 	if (res)
 	    res = teardown_half_ipsec_sa(st, FALSE)
@@ -1748,7 +2340,7 @@
 
     return res;
 #else /* !KLIPS */
-    DBG(DBG_CONTROL, DBG_log("if I knew how, I'd do_eroute() and teardown_ipsec_sa()"));
+    DBG(DBG_CONTROL, DBG_log("if I knew how, I'd eroute() and teardown_ipsec_sa()"));
     return TRUE;
 #endif /* !KLIPS */
 }
diff -bruN freeswan-1.9.orig/pluto/kernel.h freeswan-1.9/pluto/kernel.h
--- freeswan-1.9.orig/pluto/kernel.h	Tue Jan 23 18:09:30 2001
+++ freeswan-1.9/pluto/kernel.h	Wed Jun  6 12:57:42 2001
@@ -11,7 +11,7 @@
  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  * for more details.
  *
- * RCSID $Id: kernel.h,v 1.18 2001/01/23 23:09:30 dhr Exp $
+ * RCSID $Id: kernel.h,v 1.23 2001/05/28 19:18:19 dhr Exp $
  */
 
 extern bool no_klips;	/* don't actually use KLIPS */
@@ -25,11 +25,20 @@
 
 extern void init_kernel(void);
 
+extern void scan_proc_shunts(void);
+
 extern void pfkey_event(void);
 
 struct connection;	/* forward declaration of tag */
-extern bool route_connection(struct connection *c, bool doit);
+extern bool trap_connection(struct connection *c);
 extern void unroute_connection(struct connection *c);
+
+extern bool replace_bare_shunt(const ip_address *src, const ip_address *dst
+    , ipsec_spi_t shunt_spi    /* in host order! */
+    , bool repl, const char *opname);
+
+extern bool assign_hold(struct connection *c
+    , const ip_address *src, const ip_address *dst);
 
 struct state;	/* forward declaration of tag */
 extern ipsec_spi_t get_ipsec_spi(ipsec_spi_t avoid);
diff -bruN freeswan-1.9.orig/pluto/kernel_comm.c freeswan-1.9/pluto/kernel_comm.c
--- freeswan-1.9.orig/pluto/kernel_comm.c	Tue Jan 23 18:09:30 2001
+++ freeswan-1.9/pluto/kernel_comm.c	Wed Jun  6 13:36:22 2001
@@ -12,7 +12,7 @@
  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  * for more details.
  *
- * RCSID $Id: kernel_comm.c,v 1.53 2001/01/23 23:09:30 dhr Exp $
+ * RCSID $Id: kernel_comm.c,v 1.61 2001/05/29 18:39:57 dhr Exp $
  */
 
 #include <stdio.h>
@@ -46,9 +46,8 @@
 
 /* helper variables and function to decode strings from whack message */
 
-static char
-    *next_str,
-    *str_roof;
+static char *next_str
+    , *str_roof;
 
 static bool
 unpack_str(char **p)
@@ -96,22 +95,19 @@
 
     /* sanity check message */
     {
-	int ughno = RC_BADWHACKMESSAGE;
-	char ugh[200];	/* sufficient for our messages (we hope) */
+	err_t ugh = NULL;
 
 	next_str = msg.string;
 	str_roof = (char *)&msg + n;
 
 	if (next_str > str_roof)
 	{
-	    snprintf(ugh, sizeof(ugh)
-		, "truncated message from whack: got %d bytes; expected %d.  Message ignored."
+		ugh = builddiag("truncated message from whack: got %d bytes; expected %d.  Message ignored."
 		, n, (int) sizeof(msg));
 	}
 	else if (msg.magic != WHACK_MAGIC)
 	{
-	    snprintf(ugh, sizeof(ugh)
-		, "message from whack has bad magic %d; should be %d; probably wrong version.  Message ignored"
+		ugh = builddiag("message from whack has bad magic %d; should be %d; probably wrong version.  Message ignored"
 		, msg.magic, WHACK_MAGIC);
 	}
 	else if (!unpack_str(&msg.name)	/* string 1 */
@@ -122,18 +118,16 @@
 	|| !unpack_str(&msg.keyid)	/* string 6 */
 	|| str_roof - next_str != (ptrdiff_t)msg.keyval.len)	/* check chunk */
 	{
-	    snprintf(ugh, sizeof(ugh)
-		, "message from whack contains bad string");
+	    ugh = "message from whack contains bad string";
 	}
 	else
 	{
 	    msg.keyval.ptr = next_str;	/* grab chunk */
-	    ughno = 0;	/* ran through the gauntlet -- success */
 	}
 
-	if (ughno != 0)
+	if (ugh != NULL)
 	{
-	    loglog(ughno, "%s", ugh);
+	    loglog(RC_BADWHACKMESSAGE, "%s", ugh);
 	    whack_log_fd = NULL_FD;
 	    close(whackfd);
 	    return;
@@ -149,8 +143,8 @@
 	     * cause the message to print, it will be printed.
 	     */
 	    cur_debugging |= msg.debugging;
-	    DBG(DBG_CONTROL,
-		DBG_log("base debugging = %s"
+	    DBG(DBG_CONTROL
+		, DBG_log("base debugging = %s"
 		    , bitnamesof(debug_bit_names, msg.debugging)));
 	    cur_debugging = base_debugging = msg.debugging;
 	}
@@ -161,8 +155,8 @@
 	    if (c != NULL)
 	    {
 		c->extra_debugging = msg.debugging;
-		DBG(DBG_CONTROL,
-		    DBG_log("\"%s\" extra_debugging = %s"
+		DBG(DBG_CONTROL
+		    , DBG_log("\"%s\" extra_debugging = %s"
 			, c->name
 			, bitnamesof(debug_bit_names, c->extra_debugging)));
 	    }
@@ -244,9 +238,10 @@
 	    if (c != NULL)
 	    {
 		SET_CUR_CONNECTION(c);
-		if (!orient(c, TRUE))
-		    whack_log(RC_ORIENT, "could not orient connection");
-		else if (!route_connection(c, TRUE))
+               if (!oriented(*c))
+                   whack_log(RC_ORIENT
+                       , "we have no ipsecN interface for either end of this connection");
+               else if (!trap_connection(c))
 		    whack_log(RC_ROUTE, "could not route");
 		UNSET_CUR_CONNECTION();
 	    }
@@ -260,7 +255,7 @@
 	if (c != NULL)
 	{
 	    SET_CUR_CONNECTION(c);
-	    if (c->eroute_owner != SOS_NOBODY)
+	    if (c->routing >= RT_ROUTED_TUNNEL)
 		whack_log(RC_RTBUSY, "cannot unroute: route busy");
 	    else
 		unroute_connection(c);
@@ -283,6 +278,7 @@
 	    whack_log(RC_DEAF, "need --listen before opportunistic initiation");
 	else
 	    initiate_opportunistic(&msg.oppo_my_client, &msg.oppo_peer_client
+		, FALSE
 		, msg.whack_async? NULL_FD : dup_any(whackfd));
     }
 
@@ -291,6 +287,8 @@
 
     if (msg.whack_status)
     {
+	show_ifaces_status();
+	whack_log(RC_COMMENT, BLANK_FORMAT);    /* spacer */
 	show_connections_status();
 	whack_log(RC_COMMENT, BLANK_FORMAT);	/* spacer */
 	show_states_status();
diff -bruN freeswan-1.9.orig/pluto/log.c freeswan-1.9/pluto/log.c
--- freeswan-1.9.orig/pluto/log.c	Tue Sep 12 02:59:29 2000
+++ freeswan-1.9/pluto/log.c	Wed Jun  6 16:40:09 2001
@@ -12,7 +12,7 @@
  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  * for more details.
  *
- * RCSID $Id: log.c,v 1.34 2000/09/12 06:59:29 dhr Exp $
+ * RCSID $Id: log.c,v 1.38 2001/05/05 17:20:01 dhr Exp $
  */
 
 #include <stdio.h>
@@ -279,13 +279,49 @@
 	len = strlen(m);
 	m[len] = '\n';	/* don't need NUL, do need NL */
 
+	/* write to whack socket, but ignore any SIGPIPE that results */
 	{
-	    void (*old_sigpipe)(int) = signal(SIGPIPE, SIG_IGN);
+           int r;
+           struct sigaction act
+               , oldact;
+
+           act.sa_handler = SIG_IGN;
+           sigemptyset(&act.sa_mask);
+           act.sa_flags = 0;   /* no nothing */
+           r = sigaction(SIGPIPE, &act, &oldact);
+           passert(r == 0);
 
-	    write(wfd, m, len + 1);
-	    signal(SIGPIPE, old_sigpipe);
+           (void) write(wfd, m, len + 1);
+
+           r = sigaction(SIGPIPE, &oldact, NULL);
+           passert(r == 0);
 	}
     }
+}
+
+/* Build up a diagnostic in a static buffer.
+ * Although this would be a generally useful function, it is very
+ * hard to come up with a discipline that prevents different uses
+ * from interfering.  It is intended that by limiting it to building
+ * diagnostics, we will avoid this problem.
+ * Juggling is performed to allow an argument to be a previous
+ * result: the new string may safely depend on the old one.  This
+ * restriction is not checked in any way: violators will produce
+ * confusing results (without crashing!).
+ */
+err_t
+builddiag(const char *fmt, ...)
+{
+    static char msg[1024];     /* longer messages will be truncated */
+    char t[sizeof(msg)];       /* build result here first */
+    va_list args;
+
+    va_start(args, fmt);
+    t[0] = '\0';       /* in case nothing terminates string */
+    vsnprintf(t, sizeof(t), fmt, args);
+    va_end(args);
+    strcpy(msg, t);
+    return msg;
 }
 
 /* Debugging message support */
diff -bruN freeswan-1.9.orig/pluto/log.h freeswan-1.9/pluto/log.h
--- freeswan-1.9.orig/pluto/log.h	Tue Sep 12 02:59:29 2000
+++ freeswan-1.9/pluto/log.h	Wed Jun  6 13:41:37 2001
@@ -11,7 +11,7 @@
  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  * for more details.
  *
- * RCSID $Id: log.h,v 1.23 2000/09/12 06:59:29 dhr Exp $
+ * RCSID $Id: log.h,v 1.26 2001/05/05 17:20:01 dhr Exp $
  */
 
 #include <freeswan.h>
@@ -96,6 +96,18 @@
  * Much like log, actually, except for specifying mess_no.
  */
 extern void loglog(int mess_no, const char *message, ...) PRINTF_LIKE(2);
+
+/* Build up a diagnostic in a static buffer.
+ * Although this would be a generally useful function, it is very
+ * hard to come up with a discipline that prevents different uses
+ * from interfering.  It is intended that by limiting it to building
+ * diagnostics, we will avoid this problem.
+ * Juggling is performed to allow an argument to be a previous
+ * result: the new string may safely depend on the old one.  This
+ * restriction is not checked in any way: violators will produce
+ * confusing results (without crashing!).
+ */
+extern err_t builddiag(const char *fmt, ...) PRINTF_LIKE(1);
 
 #ifdef DEBUG
 
diff -bruN freeswan-1.9.orig/pluto/main.c freeswan-1.9/pluto/main.c
--- freeswan-1.9.orig/pluto/main.c	Tue Jan 23 18:09:31 2001
+++ freeswan-1.9/pluto/main.c	Wed Jun  6 13:42:06 2001
@@ -12,7 +12,7 @@
  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  * for more details.
  *
- * RCSID $Id: main.c,v 1.40 2001/01/23 23:09:31 dhr Exp $
+ * RCSID $Id: main.c,v 1.41 2001/03/13 09:22:05 dhr Exp $
  */
 
 #include <stdio.h>
@@ -29,6 +29,11 @@
 
 #include <freeswan.h>
 
+#ifdef OPENSSL
+#include <openssl/evp.h>
+#include <openssl/err.h>
+#endif
+
 #include "constants.h"
 #include "defs.h"
 #include "id.h"
@@ -42,6 +47,20 @@
 #include "rnd.h"
 #include "state.h"
 
+#ifdef OPENSSL
+#include "openssl.h"
+#include "xmap_dir.h"
+#include "xmap_file.h"
+#ifdef HAVE_DB
+#include "xmap_db.h"
+#endif
+#ifdef HAVE_LDAP
+#include "xmap_ldap.h"
+#endif
+#include "xmap.h"
+
+#endif /* OPENSSL */
+
 #include "sha1.h"
 #include "md5.h"
 #include "crypto.h"	/* requires sha1.h and md5.h */
@@ -158,6 +177,21 @@
     bool log_to_stderr_desired = FALSE;
     int lockfd;
 
+#ifdef OPENSSL
+    SSLeay_add_all_algorithms();
+    X509V3_add_standard_extensions();
+    ERR_load_crypto_strings();
+    ERR_load_ElGamal_strings();
+    XMAP_register(XMAP_METHOD_file());
+    XMAP_register(XMAP_METHOD_dir());
+#ifdef HAVE_DB
+    XMAP_register(XMAP_METHOD_db());
+#endif /* HAVE_DB */
+#ifdef HAVE_LDAP
+    XMAP_register(XMAP_METHOD_ldap());
+#endif /* HAVE_LDAP */
+#endif
+
     /* handle arguments */
     for (;;)
     {
@@ -384,6 +418,7 @@
 
     close(lockfd);
 
+    init_constants();
     init_log();
     /* Note: some scripts may look for this exact message -- don't change */
     log("Starting Pluto (FreeS/WAN Version %s)", freeswan_version);
@@ -417,6 +452,10 @@
 #ifdef LEAK_DETECTIVE
     report_leaks();
 #endif /* LEAK_DETECTIVE */
+#ifdef OPENSSL
+    X509V3_EXT_cleanup();
+    ERR_free_strings();
+#endif
     close_log();
     exit(status);
 }
diff -bruN freeswan-1.9.orig/pluto/md5.c freeswan-1.9/pluto/md5.c
--- freeswan-1.9.orig/pluto/md5.c	Sat Dec 11 20:31:36 1999
+++ freeswan-1.9/pluto/md5.c	Wed May 16 10:57:20 2001
@@ -139,7 +139,11 @@
 /* MD5 initialization. Begins an MD5 operation, writing a new context.
  */
 void MD5Init (context)
+#ifndef OPENSSL
 MD5_CTX *context;                                        /* context */
+#else
+PLUTO_MD5_CTX *context;                                  /* context */
+#endif
 {
   context->count[0] = context->count[1] = 0;
   /* Load magic initialization constants.
@@ -155,7 +159,11 @@
   context.
  */
 void MD5Update (context, input, inputLen)
+#ifndef OPENSSL
 MD5_CTX *context;                                        /* context */
+#else
+PLUTO_MD5_CTX *context;                                  /* context */
+#endif
 unsigned char *input;                                /* input block */
 UINT4 inputLen;                            /* length of input block */
 {
@@ -194,7 +202,11 @@
  */
 void MD5Final (digest, context)
 unsigned char digest[16];                         /* message digest */
+#ifndef OPENSSL
 MD5_CTX *context;                                       /* context */
+#else
+PLUTO_MD5_CTX *context;
+#endif /* OPENSSL */
 {
   unsigned char bits[8];
   unsigned int index, padLen;
diff -bruN freeswan-1.9.orig/pluto/md5.h freeswan-1.9/pluto/md5.h
--- freeswan-1.9.orig/pluto/md5.h	Sat Dec 11 20:31:36 1999
+++ freeswan-1.9/pluto/md5.h	Wed May 16 10:57:20 2001
@@ -61,11 +61,22 @@
   UINT4 state[4];                                   /* state (ABCD) */
   UINT4 count[2];        /* number of bits, modulo 2^64 (lsb first) */
   unsigned char buffer[64];                         /* input buffer */
+#ifndef OPENSSL
 } MD5_CTX;
+#else
+} PLUTO_MD5_CTX;
+#endif /* OPENSSL */
 
+#ifndef OPENSSL
 void MD5Init PROTO_LIST ((MD5_CTX *));
 void MD5Update PROTO_LIST
   ((MD5_CTX *, unsigned char *, UINT4));
 void MD5Final PROTO_LIST ((unsigned char [16], MD5_CTX *));
+#else
+void MD5Init PROTO_LIST ((PLUTO_MD5_CTX *));
+void MD5Update PROTO_LIST
+  ((PLUTO_MD5_CTX *, unsigned char *, unsigned int));
+void MD5Final PROTO_LIST ((unsigned char [16], PLUTO_MD5_CTX *));
+#endif /* OPENSSL */
 
 #define _MD5_H_
diff -bruN freeswan-1.9.orig/pluto/openssl.c freeswan-1.9/pluto/openssl.c
--- freeswan-1.9.orig/pluto/openssl.c	Wed Dec 31 19:00:00 1969
+++ freeswan-1.9/pluto/openssl.c	Wed May 16 11:02:00 2001
@@ -0,0 +1,2134 @@
+#ifdef OPENSSL
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include <sys/types.h>
+#include <dirent.h>
+
+#include <freeswan.h>
+
+#include <openssl/pem.h>
+
+#include "constants.h"
+#include "defs.h"
+#include "id.h"
+#include "connections.h" /* needs id.h */
+#include "state.h"
+#include "kernel.h"
+#include "log.h"
+#include "packet.h"
+#include "preshared.h" /* for RSA_public_key used in FreeS/WAN */
+#include "spdb.h"
+#include "demux.h"
+#include "openssl.h"
+#include "xmap.h"
+
+#include "whack.h" /* for RC_LOG_SERIOUS value, for loglog()s. */
+
+struct _tok_node {
+  char *s;
+  struct _tok_node *next;
+};
+
+typedef struct _tok_node *tok_list;
+
+enum tok_state { TOK_NORMAL, TOK_QUOTE, TOK_BACKSLASH, TOK_BACKSLASH_Q };
+
+void tok_append(tok_list *t, const char *s);
+tok_list tokenize( const char *s, const char sep );
+void tok_free( tok_list t );
+X509_CRL *lookup_crl(STACK_OF(XMAP) *lu, X509_NAME *name);
+static STACK_OF(X509) *lookup_certs_by_subject(STACK_OF(XMAP) *lu, 
+					X509_NAME *name);
+
+#if 0 /* not used */
+static STACK_OF(X509) *lookup_certs_by_issuer(STACK_OF(XMAP) *lu, 
+					X509_NAME *name);
+#endif
+
+void build_cert_chain( STACK_OF(X509) **ch, STACK_OF(XMAP) *lu, X509 *x );
+static int cert_compare(X509 *a, X509 *b);
+static STACK_OF(X509) *lookup_certs_by_ip(STACK_OF(XMAP) *lu,
+					  const char *id,
+					  const size_t len);
+static int ASN1_UTCTIME_cmp(ASN1_UTCTIME *a, ASN1_UTCTIME *b);
+static int cb( int ok, X509_STORE_CTX *ctx );
+
+void
+tok_append(tok_list *t, const char *s) {
+  tok_list p, pp;
+
+  if (!t) return;
+  if ((p = malloc(sizeof(struct _tok_node))) == NULL) return;
+  if ((p->s = strdup(s)) == NULL) { free(p); return; }
+  p->next = NULL;
+
+  if (*t == NULL) { *t = p; return; }; /* Empty list */
+  pp = *t;
+  while (pp->next != NULL) pp = pp->next;
+  pp->next = p;
+}
+
+tok_list
+tokenize( const char *s, const char sep )
+{
+  tok_list t = NULL;
+  int len, i, cnt, size;
+  char *buf;
+  enum tok_state st = TOK_NORMAL;
+
+  cnt = 0;
+  len = strlen(s);
+  size = 256; /* Initial size */
+  if ((buf = malloc(size)) == NULL) return t;
+  memset(buf, 0, size);
+  for(i=0; i<len; i++) {
+    /* resize buf if necessary */
+    if (cnt == size-1) {
+      size += 256;
+      if ((buf = realloc(buf, size)) == NULL) return t;
+    }
+    switch(st) {
+    case TOK_NORMAL:
+      if (s[i] == '\\')
+	st = TOK_BACKSLASH;
+      else if (s[i] == '\'')
+	st = TOK_QUOTE;
+      else if (s[i] == sep) {
+	/* Reached the end of a token */
+	tok_append(&t, buf);
+	memset(buf, 0, size);
+	cnt = 0;
+      } else {
+	buf[cnt] = s[i];
+	cnt++;
+	buf[cnt] = '\0';
+      }
+      break;
+    case TOK_QUOTE:
+      if (s[i] == '\\')
+	st = TOK_BACKSLASH_Q;
+      else if (s[i] == '\'') {
+	st = TOK_NORMAL;
+      } else {
+	buf[cnt] = s[i];
+	cnt++;
+	buf[cnt] = '\0';
+      }
+      break;
+    case TOK_BACKSLASH:
+      buf[cnt] = s[i];
+      cnt++;
+      buf[cnt] = '\0';
+      st = TOK_NORMAL;
+      break;
+    case TOK_BACKSLASH_Q:
+      buf[cnt] = s[i];
+      cnt++;
+      buf[cnt] = '\0';
+      st = TOK_QUOTE;
+      break;
+    }
+  }
+  tok_append(&t, buf);
+  memset(buf, 0, size);
+  cnt = 0;
+  free(buf);
+  return t;
+}
+
+void
+tok_free( tok_list t )
+{
+  tok_list p = t;
+
+  while (p) {
+    tok_list pp = p->next;
+
+    free(p->s);
+    free(p);
+    p = pp;
+  }
+}
+
+void
+log_err( void )
+{
+  unsigned long l;
+  char buf[200];
+  const char *file, *data;
+  int line, flags;
+  unsigned long es;
+  
+  es=CRYPTO_thread_id();
+  while ((l=ERR_get_error_line_data(&file,&line,&data,&flags)) != 0)
+    {
+      log("%lu:%s:%s:%d:%s\n",es,ERR_error_string(l,buf),
+	  file,line,(flags&ERR_TXT_STRING)?data:"");
+    }
+}
+
+bool
+make_lookups( STACK_OF(XMAP) **lu, const char *spec )
+{
+#define MAXSPEC 10
+  const char *delim = ", ";
+  char *s, *p, *specs[MAXSPEC];
+  int i;
+  XMAP *xm;
+  bool retval = TRUE;
+
+  for(i=0; i<MAXSPEC; i++) specs[i] = NULL;
+  s = clone_bytes(spec, strlen(spec)+1, "lookup specification");
+  p = strtok(s, delim);
+  i = 0;
+  while ((i < MAXSPEC) && (p)) {
+    char *sp = clone_bytes(p, strlen(p)+1, "lookup spec");
+    specs[i++] = sp;
+    p = strtok( NULL, delim );
+  }
+
+  if ((*lu = sk_XMAP_new_null()) != NULL) {
+    for(i=0; specs[i]; i++) {
+      DBG(DBG_PARSING,
+      DBG_log("Adding LU spec: %s", specs[i]);
+      );
+      if ((xm = XMAP_new(specs[i])) != NULL) {
+        sk_XMAP_push(*lu, xm);
+      } else {
+        DBG(DBG_PARSING,
+        DBG_log("Could not add LU spec: %s", specs[i]);
+        );
+	retval = FALSE;
+      }
+    }
+  }
+  
+  for(i=0; specs[i]; i++) pfree(specs[i]);
+  pfree(s);
+
+  return retval;
+}
+
+/* Really need to make this routine far more tolerant */
+/* of other formats for certs & keys. For example, it */
+/* would be nice to be able to use PKCS8 private key forms */
+/* or a PKCS12 bag to hold both certificate and key */
+/* For the moment, though, we can handle certs in DER or */
+/* PEM format, and keys in PEM format only -- nd */
+void
+load_cert_and_key( const char *cert, const char *key,
+		   X509 **x, EVP_PKEY **k )
+{
+  BIO *b = NULL;
+  char keystr[32] = "PEM private key";
+
+  log("Loading certificates and key");
+  if ((! x) || (! k)) return;
+  *x = NULL;
+  *k = NULL;
+  if (cert[0] == '\0') return;
+  if (key[0] == '\0') return;
+
+  if ((b = BIO_new_file(cert, "r")) == NULL) {
+    log_err();
+    return;
+  }
+#if OPENSSL_VERSION_NUMBER > 0x00903000L
+  *x = PEM_read_bio_X509(b, NULL, NULL, NULL);
+#else
+  *x = PEM_read_bio_X509(b, NULL, NULL);
+#endif
+  if (*x == NULL) {
+    /* Try DER read */
+    BIO_ctrl(b, BIO_CTRL_RESET, 0, NULL);
+    if ((*x = d2i_X509_bio(b, NULL)) == NULL) {
+      log_err();
+      BIO_free(b);
+      return;
+    }
+  }
+  DBG(DBG_PARSING,
+  DBG_log("Read certificate from %s", cert);
+  );
+  BIO_free(b);
+  
+  if ((b = BIO_new_file(key, "r")) == NULL) {
+    log_err();
+    X509_free(*x);
+    *x = NULL;
+    return;
+  }
+  
+#if OPENSSL_VERSION_NUMBER > 0x00903000L
+  *k = PEM_read_bio_PrivateKey(b, NULL, NULL, NULL);
+#else
+  *k = PEM_read_bio_PrivateKey(b, NULL, NULL);
+#endif
+  if (!*k) {
+    RSA *r;
+    
+    /* Try DER reading of RSA Key */
+    BIO_ctrl(b, BIO_CTRL_RESET, 0, NULL);
+    r = d2i_RSAPrivateKey_bio(b, NULL);
+    if (r) {
+      if ((*k = EVP_PKEY_new()) != NULL) {
+	(*k)->type = EVP_PKEY_RSA;
+	(*k)->pkey.rsa = r;
+	strncpy(keystr, "DER RSA private key", sizeof(keystr)-1);
+      } else
+	RSA_free(r);
+    }
+  }
+  
+  if (!*k) {
+    DSA *d;
+    
+    /* Try DER reading of DSA/El Gamal Key */
+    BIO_ctrl(b, BIO_CTRL_RESET, 0, NULL);
+    d = d2i_DSAPrivateKey_bio(b, NULL);
+    if (d) {
+      if ((*k = EVP_PKEY_new()) != NULL) {
+	(*k)->type = EVP_PKEY_DSA;
+	(*k)->pkey.dsa = d;
+	strncpy(keystr, "DER DSA private key", sizeof(keystr)-1);
+      } else
+	DSA_free(d);
+    }
+  }
+  
+  if (!*k) {
+    PKCS8_PRIV_KEY_INFO *p8inf = NULL;
+    
+    BIO_ctrl(b, BIO_CTRL_RESET, 0, NULL);
+    /* try PKCS8 (unencrypted) keyform */
+    
+    BIO_ctrl(b, BIO_CTRL_RESET, 0, NULL);
+    p8inf = PEM_read_bio_PKCS8_PRIV_KEY_INFO(b, NULL, NULL, NULL);
+    if (!p8inf) {
+      /* Try reading PKCS8 in DER format */
+      BIO_ctrl(b, BIO_CTRL_RESET, 0, NULL);
+      p8inf = d2i_PKCS8_PRIV_KEY_INFO_bio(b, NULL);
+    } else 
+      strncpy(keystr, "PEM PKCS-8 private key", sizeof(keystr)-1);
+    if (!p8inf) {
+      log("Error in loading PKCS-8 private key");
+      log_err();
+      X509_free(*x);
+      *x = NULL;
+      BIO_free(b);
+      return;
+    } else
+      strncpy(keystr, "DER PKCS-8 private key", sizeof(keystr)-1);
+    if ((*k = EVP_PKCS82PKEY(p8inf)) == NULL) {
+      log("Error in converting PKCS-8 private key");
+      log_err();
+      X509_free(*x);
+      *x = NULL;
+      BIO_free(b);
+      return;
+    }
+  }
+  DBG(DBG_PARSING,
+  DBG_log("Read %s from %s", keystr, key);
+  );
+  BIO_free(b);
+}
+
+static int
+cert_compare(X509 *a, X509 *b)
+{
+  /* Check for equality of 2 X509 certificates */
+  /* certs are equal if their issuers, serial numbers */
+  /* subject names and public keys are the same */
+  /* We could probably do all of this by converting the */
+  /* certs to DER format and comparing the byte streams */
+  /* but that's likely to be inefficient -- nd */
+  int c;
+  EVP_PKEY *ka, *kb;
+
+  if ((c = X509_issuer_and_serial_cmp(a, b)) != 0)
+    return c;
+  if ((c = X509_NAME_cmp(X509_get_issuer_name(a),
+			 X509_get_issuer_name(b))) != 0)
+    return c;
+  ka = X509_get_pubkey(a);
+  kb = X509_get_pubkey(b);
+  if (ka->type != kb->type) return 1;
+  switch (ka->type) {
+  case EVP_PKEY_RSA:
+    {
+      /* RSA compare - if public exponent and modulus are equal, return 0 */
+      RSA *ra, *rb;
+
+      ra = ka->pkey.rsa;
+      rb = ka->pkey.rsa;
+
+      if (BN_cmp(ra->e, rb->e) != 0) return 1;
+      if (BN_cmp(ra->n, rb->n) != 0) return 1;
+    }
+    break;
+  case EVP_PKEY_DSA:
+    {
+      /* DSA compare, g, modulus and pubkey must be equal */
+      DSA *da, *db;
+
+      da = ka->pkey.dsa;
+      db = ka->pkey.dsa;
+
+      if (BN_cmp(da->g, db->g) != 0) return 1;
+      if (BN_cmp(da->p, db->p) != 0) return 1;
+      if (BN_cmp(da->pub_key, db->pub_key) != 0) return 1;
+    }
+    break;
+  default:
+    DBG(DBG_PARSING,
+    DBG_log("Unknown key type presented: %d", ka->type);
+    );
+    return 1;
+    break;
+  }
+  return 0;
+}
+
+static STACK_OF(X509) *
+lookup_certs_by_ip(STACK_OF(XMAP) *lu,
+		   const char *id,
+		   const size_t len)
+{
+  STACK_OF(X509) *osk = sk_X509_new_null();
+  int i;
+
+  for(i=0; i<sk_XMAP_num(lu); i++) {
+    XMAP *xm = sk_XMAP_value(lu, i);
+    u_char *cl = clone_bytes(id, len, "IPv4 address");
+    STACK_OF(X509_OBJECT) *op = NULL;
+
+    DBG(DBG_PARSING | DBG_CONTROL,
+    DBG_log("Searching map %d", i+1);
+    DBG_dump("IPv4:", cl, len);
+    );
+    if ((op = XMAP_lookup(xm, X509_LU_X509, "ip", cl)) != NULL) {
+      int j;
+
+      DBG(DBG_PARSING,
+      DBG_log("Search returns %d certificates", sk_X509_OBJECT_num(op));
+      );
+      for(j=0; j < sk_X509_OBJECT_num(op); j++) {
+	X509_OBJECT *o = sk_X509_OBJECT_value(op, j);
+	X509 *c = X509_dup(o->data.x509);
+	int k, found;
+
+	for(k=0, found=0; (!found) && (k < sk_X509_num(osk)); k++) {
+	  if (cert_compare(sk_X509_value(osk, k), c) == 0)
+	    found = 1;
+	}
+
+	if (!found) {
+	  if (sk_X509_num(osk) == 0) {
+	    sk_X509_push(osk, c);
+	  } else {
+	    ASN1_UTCTIME *new_notBefore = X509_get_notBefore(c);
+	    ASN1_UTCTIME *new_notAfter = X509_get_notAfter(c);
+	    
+	    for(k=0; k<sk_X509_num(osk); k++) {
+	      /* certificate already in stack */
+	      X509 *tx = sk_X509_value(osk, k); 
+	      ASN1_UTCTIME *notBefore = X509_get_notBefore(tx);
+	      ASN1_UTCTIME *notAfter = X509_get_notAfter(tx);
+	      int c1 = ASN1_UTCTIME_cmp(new_notBefore, notBefore);
+	      int c2 = ASN1_UTCTIME_cmp(new_notAfter, notAfter);
+	      
+	      if (c1 == 0) {
+		/* certs start at same time */
+		/* insert here if c expiry is later than tx */
+		if (c2 > 0) break; 
+	      } else
+	      /* insert here is c start date is later than tx */
+	      if (c1 > 0) break; 
+	      /* else move on to the next certificate in the 
+	      current output stack */
+	    }
+	    sk_X509_insert(osk, c, k); /* Insert into the output stack */
+	  }
+	}
+      }
+      sk_X509_OBJECT_pop_free(op, X509_OBJECT_free);
+      pfree(cl);
+    }
+  }
+  if (osk) DBG(DBG_PARSING,
+           DBG_log("Returning %d certs in list", sk_X509_num(osk))
+           );
+  return osk;
+} 
+
+/* peer_cert_list takes a supplied list of XMAPs */
+/* and adds all of the X509 certificates whose */
+/* public key matches 'type' into a safe stack certificates */
+/* If the parameter 'cert' is non-NULL, only the certificate */
+/* which matches it will be added to the list */
+STACK_OF(X509) *
+peer_cert_list( STACK_OF(XMAP) *lu, int type, X509 *cert,
+		struct payload_digest *const id_pld,
+		bool strict )
+{
+  STACK_OF(X509) *sk = NULL, *osk = NULL;
+  pb_stream *const id_pbs = &id_pld->pbs;
+  struct isakmp_id *const id = &id_pld->payload.id;
+  int i, found;
+
+  switch(id->isaid_idtype) {
+  case ID_IPV4_ADDR:
+    if (pbs_left(id_pbs) != sizeof(struct in_addr)) {
+      DBG(DBG_PARSING,
+      DBG_log("ID size is not equal to that of an IPv4 address");
+      );
+      return NULL;
+    }
+    /* 
+     * lookup_certs_by_ip(STACK_OF(XMAP) *lu, 
+     *   const char *id, const size_t len)
+     */
+    if ((sk = lookup_certs_by_ip(lu,
+				id_pbs->cur,
+				sizeof(struct in_addr))) == NULL) {
+      DBG(DBG_PARSING,
+      DBG_log("No certs for this IP address");
+      );
+      return NULL;
+    }
+    break;
+  case ID_DER_ASN1_DN:
+    {
+      X509_NAME *xn = NULL;
+      long derlen;
+      unsigned char *der;
+
+      derlen = (long)pbs_left(id_pbs);
+      der = (unsigned char *)(id_pbs->cur);
+
+     xn = d2i_X509_NAME(&xn, &der, derlen);
+
+      if (xn != NULL) {
+        if ((sk = lookup_certs_by_subject(lu, xn)) == NULL) {
+          DBG(DBG_PARSING,
+          DBG_log("No certs for this ID_DER_ASN1_DN");
+          );
+          return NULL;
+        } 
+      } else {
+        DBG(DBG_PARSING,
+        DBG_log("Error in DER string. (Not a DER string?)");
+        );
+        return NULL;
+      }
+      X509_NAME_free(xn);
+      break;
+    }
+  default:
+    DBG(DBG_PARSING,
+    DBG_log("No means to check certificates for ID type = %s",
+	    enum_show(&ident_names, id->isaid_idtype));
+    );
+    return NULL;
+  }
+
+  /* Now filter out any certificates not of type 'type' */
+  if ((osk = sk_X509_new_null()) != NULL) {
+    for(i=0; i<sk_X509_num(sk); i++) {
+      X509 *x = sk_X509_value(sk, i);
+      EVP_PKEY *pk = X509_get_pubkey(x);
+
+      if (pk->type == type) {
+	sk_X509_push(osk, X509_dup(x));
+      } else {
+        DBG(DBG_PARSING,
+        DBG_log("Rejecting certificate: wrong type: %d", pk->type);
+        );
+      }
+    }
+    sk_X509_pop_free(sk, X509_free);
+    sk = osk; /* Make sk the new filtered list */
+  } else {
+    DBG(DBG_PARSING,
+    DBG_log("Error in allocating new sk_X509");
+    );
+    sk_X509_pop_free(sk, X509_free);
+    sk = NULL;
+  }
+
+  if ((sk) && (cert)) {
+    /* If a certificate was presupplied, we want to check */
+    /* whether it is in the list of acceptable certificates */
+    /* for this connection. If no certificate is presupplied */
+    /* then it is assumed that one of the certificates in */
+    /* the list will correctly decrypt the signature/nonces */
+
+    for(i=0, found=0; ((!found) && (i < sk_X509_num(sk))); i++)
+      if (cert_compare(sk_X509_value(sk, i), cert) == 0) found = 1;
+
+    if (found) {
+      DBG(DBG_PARSING,
+      DBG_log("Certificate supplied is in list");
+      );
+    } else {
+      DBG(DBG_PARSING,
+      DBG_log("Certificate supplied is NOT in list");
+      );
+
+      /* If strict is not set, this certificate will be allowed */
+      /* to pass, even though the host cannot recognise it as */
+      /* in the list of known certificates for this ID. Otherwise */
+      /* we erase the list and return NULL -- an error condition */
+      if (strict) {
+	sk_X509_pop_free(sk, X509_free);
+	sk = NULL;
+      }
+    }
+  }
+
+  return sk;
+}
+
+bool
+have_rsa_key( struct state *st )
+{
+  struct connection *c = st->st_connection;
+
+  if (c->key == NULL) { 
+	DBG(DBG_PARSING,
+	DBG_log("No key present");
+	);
+	return FALSE; 
+  }
+  if ( ((EVP_PKEY *)(c->key))->type != EVP_PKEY_RSA ) { return FALSE; }
+  return TRUE;
+}
+
+bool
+have_dss_key( struct state *st )
+{
+  struct connection *c = st->st_connection;
+
+  if (c->key == NULL) { 
+	DBG(DBG_PARSING,
+	DBG_log("No key present"); 
+	);
+	return FALSE; 
+  }
+  if ( ((EVP_PKEY *)(c->key))->type != EVP_PKEY_DSA ) { return FALSE; }
+  return TRUE;
+}
+
+bool
+have_othercert( struct connection *c, int type )
+{
+  struct end *that = &c->that;
+  STACK_OF(X509) *op = NULL;
+  X509 *x;
+  int i;
+  bool found;
+
+  /* First check to see if we've already done */
+  /* this lookup and stored the certificate in */
+  /* c->other[] */
+
+  for(i=0; i<MAX_OTHER; i++)
+    if ((c->other[i].type == type) &&
+	(c->other[i].cert != NULL)) {
+      DBG(DBG_PARSING,
+      DBG_log("Already stored a type %d cert", type);
+      );
+      return TRUE;
+    }
+
+  switch (c->that.id.kind)
+  {
+    case ID_IPV4_ADDR:
+    op = lookup_certs_by_ip((STACK_OF(XMAP) *)c->lu,
+      (const char *)&that->host_addr,
+      sizeof(that->host_addr));
+    break;
+
+    case ID_DER_ASN1_DN:
+    {
+
+/*
+ * The 'd2i' function copies a binary representation into a C structure.  It
+ * operates as follows.  'a' is a pointer to a pointer to
+ * the structure to populate, 'pp' is a pointer to a pointer to where the DER
+ * byte string is located and 'length' is the length of the '*pp' data.
+ * If there are no errors, a pointer to the populated structure is returned.
+ *
+ * X509_NAME *     X509_NAME_new(void);
+ * void            X509_NAME_free(X509_NAME *a);
+ * int             i2d_X509_NAME(X509_NAME *a,unsigned char **pp);
+ * X509_NAME *     d2i_X509_NAME(X509_NAME **a,unsigned char **pp,long length);
+ * int             X509_NAME_set(X509_NAME **xn, X509_NAME *name);
+ */
+      X509_NAME *xn = X509_NAME_new();
+      chunk_t temp_ptr = c->that.id.der_asn1_dn;
+
+      xn = d2i_X509_NAME(&xn, &(c->that.id.der_asn1_dn.ptr), 
+        (long)c->that.id.der_asn1_dn.len);
+	c->that.id.der_asn1_dn = temp_ptr;
+
+      if (xn != NULL) {
+        op = lookup_certs_by_subject((STACK_OF(XMAP) *)c->lu, xn);
+      } else {
+        DBG(DBG_PARSING,
+        DBG_log("Error in DER string. (Not a DER string?)");
+        );
+      }
+
+      X509_NAME_free(xn);
+    }
+    break;
+  }
+
+  if (!op) {
+    DBG(DBG_PARSING,
+    DBG_log("Lookup returns NULL");
+    );
+  } else {
+    int i;
+
+    for(i=0, found = FALSE; ((!found) && (i < sk_X509_num(op))); i++) {
+      x = sk_X509_value(op, i);
+      if (X509_get_pubkey(x)->type == type) {
+	found = TRUE;
+	for(i=0; i<MAX_OTHER; i++) {
+ 	  if (c->other[i].cert == NULL) {
+            DBG(DBG_PARSING,
+            DBG_log("Storing type %d cert at position %d", type, i);
+            );
+	    c->other[i].type = type;
+	    c->other[i].cert = (void *)X509_dup(x);
+	    break;
+	  }
+	}
+      }
+    }
+
+    if (found) {
+      DBG(DBG_PARSING,
+      DBG_log("Found type %d cert at position %d:",
+	      type, i+1);
+      );
+    }
+    sk_X509_pop_free(op, X509_free);
+  }
+  return (found);
+}
+
+bool
+have_rsa_keypair( struct state *st )
+{
+  bool r = have_othercert(st->st_connection, EVP_PKEY_RSA);
+  if (r) r = have_rsa_key(st);
+
+  DBG(DBG_PARSING,
+  DBG_log("Have RSA other cert = %s", r  ? "TRUE" : "FALSE");
+  );
+  return r;
+}
+
+bool
+have_elgamal_keypair( struct state *st )
+{
+  bool r = have_othercert(st->st_connection, EVP_PKEY_DSA); 
+  if (r) r = have_dss_key(st);
+
+  DBG(DBG_PARSING,
+  DBG_log("Have El Gamal other cert = %s", r  ? "TRUE" : "FALSE");
+  );
+  return r;
+}
+
+static int
+cb( int ok, X509_STORE_CTX *ctx )
+{
+  char buf[200];
+  
+  if (!ok) {
+    if (ctx->error == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT) {
+      /* Check to see if it is a CA certificate, ie with */
+      /* basicConstraints, and perhaps other checks */
+      /* For the moment, we just let it slide */
+      ok = 1;
+    } else {
+      X509_NAME_oneline(X509_get_subject_name(ctx->current_cert), buf, sizeof(buf));
+      
+      DBG(DBG_PARSING,
+      DBG_log("Error for certificate: %s", buf);
+      DBG_log("Error %d: Depth %d: %s",
+              ctx->error,
+              ctx->error_depth,
+              X509_verify_cert_error_string(ctx->error));
+      );
+    }
+  }
+  return (ok);
+}
+
+static int
+ASN1_UTCTIME_cmp(ASN1_UTCTIME *a, ASN1_UTCTIME *b)
+{
+  char buff1[14],buff2[14],*p;
+  int i,j;
+ 
+  /* Degenerate cases */
+  if (!a && !b) return 0;
+  if (a && !b) return 1;
+  if (!a && b) return -1;
+ 
+  memset(buff1, 0, sizeof(buff1));
+  memset(buff2, 0, sizeof(buff2));
+ 
+  p=buff1;
+  i=a->length;
+  if ((i < 11) || (i > 17)) return(0);
+  memcpy(p,a->data,12);
+ 
+  p=buff2;
+  j=b->length;
+  if ((j < 11) || (j > 17)) return(0);
+  memcpy(p,b->data,12);
+ 
+  /* Correct for Y2K */
+  i=(buff1[0]-'0')*10+(buff1[1]-'0');
+  if (i < 50) i+=100; /* cf. RFC 2459 */
+  j=(buff2[0]-'0')*10+(buff2[1]-'0');
+  if (j < 50) j+=100;
+ 
+  if (i < j) return (-1);
+  if (i > j) return (1);
+ 
+  i=strcmp(buff1,buff2);
+ 
+  if (i == 0)
+    return 0;
+  else if (i < 0)
+    return(-1);
+  else
+    return(1);
+}
+
+X509_CRL *
+lookup_crl(STACK_OF(XMAP) *lu, X509_NAME *name)
+{
+  X509_CRL *x = NULL;
+  STACK_OF(X509_CRL) *osk = sk_X509_CRL_new_null();
+  int i, j, k, found;
+
+  for(i=0; i<sk_XMAP_num(lu); i++) {
+    XMAP *xm = sk_XMAP_value(lu, i);
+    STACK_OF(X509_OBJECT) *xo = NULL;
+
+    if (xm) {
+      XMAP_dump(xm);
+      if ((xo = XMAP_lookup(xm, X509_LU_CRL, "issuer", name)) != NULL) {
+	for(j=0; j<sk_X509_OBJECT_num(xo); j++) {
+	  X509_OBJECT *o = sk_X509_OBJECT_value(xo, j);
+	  X509_CRL *xx = X509_CRL_dup(o->data.crl);
+	  
+	  for(k=0, found = 0; (!found) && (k<sk_X509_CRL_num(osk)); k++) {
+	    X509_CRL *tx = sk_X509_CRL_value(osk, k);
+	    
+	    if ((X509_NAME_cmp(X509_CRL_get_issuer(xx),
+			       X509_CRL_get_issuer(tx))==0) &&
+		(ASN1_UTCTIME_cmp(X509_CRL_get_lastUpdate(xx),
+				  X509_CRL_get_lastUpdate(tx)) == 0) &&
+		(ASN1_UTCTIME_cmp(X509_CRL_get_nextUpdate(xx),
+				  X509_CRL_get_nextUpdate(tx)) == 0))
+	      found = 1;
+	  }
+	  
+	  if (!found) {
+	    if (sk_X509_CRL_num(osk) == 0)
+	      sk_X509_CRL_push(osk, xx);
+	    else {
+	      /* insert the certificate into the stack in date order */
+	      for(k=0; k<sk_X509_CRL_num(osk); k++) {
+		/* certificate already in stack */
+		X509_CRL *tx = sk_X509_CRL_value(osk, k); 
+		
+		if (ASN1_UTCTIME_cmp(X509_CRL_get_lastUpdate(xx),
+				     X509_CRL_get_lastUpdate(tx)) > 0)
+		  /* insert here if last Update is newer than current crl */
+		  break; 
+	      }
+	      /* Insert into the output stack */
+	      sk_X509_CRL_insert(osk, xx, k); 
+	    }
+	  } else
+	    X509_CRL_free(xx);
+	}
+	/* drop search return values */
+	sk_X509_OBJECT_pop_free(xo, X509_OBJECT_free); 
+      }
+    }
+  }
+
+  if (sk_X509_CRL_num(osk) > 0)
+    /* use first certificate in stack */
+    x = X509_CRL_dup(sk_X509_CRL_value(osk, 0)); 
+  /* get rid of output stack */
+  sk_X509_CRL_pop_free(osk, X509_CRL_free); 
+  return x; 
+}
+
+static STACK_OF(XMAP) *lookups = NULL;
+static bool verify_strict;
+/* only way I can think to get the verify function (which is) */
+/* used as a callback to access the 'strict verification' flag */
+/* The problem is that there isn't any space in the parameters */
+/* to the verify_func in which to add this flag. Pity, because */
+/* a static global controlling verification policy is a fairly */
+/* stinky idea -- nd */
+
+
+/* The following code is simply the code from x509_vfy.c */
+/* with CRL checking added, and basicConstraints checking */
+static int
+verify_func(X509_STORE_CTX *ctx)
+{
+  int i,ok=0,n;
+  X509 *xs,*xi;
+  EVP_PKEY *pkey=NULL;
+  int (*cb)();
+  X509_CRL *crl;
+  
+  cb=ctx->ctx->verify_cb;
+  
+  n=sk_X509_num(ctx->chain);
+  DBG(DBG_PARSING,
+  DBG_log("%d certs in chain", n);
+  );
+  ctx->error_depth=n-1;
+  n--;
+  xi=sk_X509_value(ctx->chain,n);
+
+  if (X509_NAME_cmp(X509_get_subject_name(xi),
+		    X509_get_issuer_name(xi)) == 0)
+    xs=xi;
+  else {
+    if (n <= 0) {
+      ctx->error=X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE;
+      ctx->current_cert=xi;
+      ok=cb(0,ctx);
+      goto end;
+    } else {
+      n--;
+      ctx->error_depth=n;
+      xs=sk_X509_value(ctx->chain,n);
+    }
+  }
+  
+  while (n >= 0) {
+    ctx->error_depth=n;
+    if (!xs->valid) {
+      if ((pkey=X509_get_pubkey(xi)) == NULL)
+	{
+	  ctx->error=X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY;
+	  ctx->current_cert=xi;
+	  ok=(*cb)(0,ctx);
+	  if (!ok) goto end;
+	}
+      if (X509_verify(xs,pkey) <= 0) {
+	EVP_PKEY_free(pkey);
+	ctx->error=X509_V_ERR_CERT_SIGNATURE_FAILURE;
+	ctx->current_cert=xs;
+	ok=(*cb)(0,ctx);
+	if (!ok) goto end;
+      }
+      EVP_PKEY_free(pkey);
+      pkey=NULL;
+
+      i=X509_cmp_current_time(X509_get_notBefore(xs));
+      if (i == 0) {
+	ctx->error=X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD;
+	ctx->current_cert=xs;
+	ok=(*cb)(0,ctx);
+	if (!ok) goto end;
+      }
+      if (i > 0) {
+	ctx->error=X509_V_ERR_CERT_NOT_YET_VALID;
+	ctx->current_cert=xs;
+	ok=(*cb)(0,ctx);
+	if (!ok) goto end;
+      }
+      xs->valid=1;
+    }
+
+    i=X509_cmp_current_time(X509_get_notAfter(xs));
+    if (i == 0) {
+      ctx->error=X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD;
+      ctx->current_cert=xs;
+      ok=(*cb)(0,ctx);
+      if (!ok) goto end;
+    }
+    
+    if (i < 0) {
+      ctx->error=X509_V_ERR_CERT_HAS_EXPIRED;
+      ctx->current_cert=xs;
+      ok=(*cb)(0,ctx);
+      if (!ok) goto end;
+    }
+
+    if (n == sk_X509_num(ctx->chain)-1) {
+      /* This is the root certificate */
+      int loc = X509_get_ext_by_NID(xs, NID_basic_constraints, -1);
+      if (loc >= 0) {
+	X509_EXTENSION *ext;
+	BASIC_CONSTRAINTS *p = NULL;
+	
+	ext = X509_get_ext(xs, loc);
+	if (ext) {
+	  p = X509V3_EXT_d2i(ext);
+	  if (! p->ca) {
+	    BASIC_CONSTRAINTS_free(p);
+	    ctx->error=X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN;
+	    ctx->current_cert=xs;
+	    ok=(*cb)(0,ctx);
+	    if (!ok) goto end;
+	  } else {
+        DBG(DBG_PARSING,
+	    DBG_log("Root certificate has CA = True");
+        );
+	    BASIC_CONSTRAINTS_free(p);
+	  }
+	} else {
+	  /* The cert has a basicConstraints extension, but */
+	  /* we couldn't get it */
+	  ctx->error=X509_V_ERR_APPLICATION_VERIFICATION;
+	  ctx->current_cert=xs;
+	  ok=(*cb)(0,ctx);
+	  if (!ok) goto end;
+	}
+      } else {
+#ifndef DONT_BE_FASCIST
+	ctx->error=X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN;
+	ctx->current_cert=xs;
+	ok=(*cb)(0,ctx);
+	if (!ok) goto end;
+#endif
+      }
+    }
+
+    /* CRL CHECK */
+    if ((crl = lookup_crl(lookups, X509_get_issuer_name(xs))) != NULL) {
+      EVP_PKEY *pkey = X509_get_pubkey(xi);
+      STACK_OF(X509_REVOKED) *rev;
+      int nrev;
+      
+      DBG(DBG_PARSING,
+      DBG_log("Checking CRL for issuer");
+      );
+      
+      if (pkey == NULL) {
+	ctx->error=X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY;
+	X509_CRL_free(crl);
+	ctx->current_cert=xs;
+	ok=(*cb)(0,ctx);
+	if (!ok) goto end;
+      }
+      
+      if (X509_CRL_verify(crl, pkey) <= 0) {
+	ctx->error=X509_V_ERR_CRL_SIGNATURE_FAILURE;
+	X509_CRL_free(crl);
+	ctx->current_cert=xs;
+	ok=(*cb)(0,ctx);
+	if (!ok) goto end;
+      }
+      
+      i = X509_cmp_current_time(X509_CRL_get_lastUpdate(crl));
+      if (i == 0) {
+	ctx->error=X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD;
+	X509_CRL_free(crl);
+	ctx->current_cert=xs;
+	ok=(*cb)(0,ctx);
+	if (!ok) goto end;
+      }
+      if (i > 0) {
+	ctx->error=X509_V_ERR_CRL_NOT_YET_VALID;
+	X509_CRL_free(crl);
+	ctx->current_cert=xs;
+	ok=(*cb)(0,ctx);
+	if (!ok) goto end;
+      }
+      
+      i = X509_cmp_current_time(X509_CRL_get_nextUpdate(crl));
+      if (i == 0) {
+	ctx->error=X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD;
+	X509_CRL_free(crl);
+	ctx->current_cert=xs;
+	ok=(*cb)(0,ctx);
+	if (!ok) goto end;
+      }
+      if (i < 0) {
+	ctx->error=X509_V_ERR_CRL_HAS_EXPIRED;
+	X509_CRL_free(crl);
+	ctx->current_cert=xs;
+	ok=(*cb)(0,ctx);
+	if (!ok) goto end;
+      }
+      
+      rev = X509_CRL_get_REVOKED(crl);
+      nrev = sk_X509_REVOKED_num(rev);
+      DBG(DBG_PARSING,
+      DBG_log("%d certificates revoked in CRL", nrev);
+      );
+      for(i=0; i<nrev; i++) {
+	X509_REVOKED *rv = sk_X509_REVOKED_value(rev, i);
+	
+	if (ASN1_INTEGER_cmp(X509_get_serialNumber(xs), 
+	  rv->serialNumber) == 0) {
+	  /* It's this certificate that's been revoked */
+	  int c = X509_cmp_current_time(rv->revocationDate);
+	  if (c < 0) {
+	    ctx->error=X509_V_ERR_CERT_REVOKED;
+	    X509_CRL_free(crl);
+	    ctx->current_cert=xs;
+	    ok=(*cb)(0,ctx);
+	    if (!ok) goto end;
+	  }
+      DBG(DBG_PARSING,
+	  DBG_log("Serial Number matches");
+      );
+	}
+      }
+
+      X509_CRL_free(crl);
+    } else {
+      char buf[200];
+      
+      X509_NAME_oneline(X509_get_issuer_name(xs), buf, sizeof(buf));
+      DBG(DBG_PARSING,
+      DBG_log("Cant locate a CRL for issuer %s", buf);
+      );
+      /* If we're being paranoid here, we really should fail */
+      /* the verification. An attacker capable of mounting */
+      /* a denial of service attack could cause us fail to */
+      /* load the CRL, and use a revoked, but otherwise valid */
+      /* certificate in the  exchange to set up a valid SA */
+      /* In this case, we let it go, but an idea might be */
+      /* to have an ipsec.conf specified policy on how mandatory */
+      /* CRLs are in the verification sequence -- nd */
+      if (verify_strict) {
+	ctx->error=X509_V_ERR_UNABLE_TO_GET_CRL;
+	ctx->current_cert=xs;
+	ok=(*cb)(0,ctx);
+	if (!ok) goto end;
+      }
+    }
+
+    /* The last error (if any) is still in the error value */
+    ctx->current_cert=xs;
+    ok=(*cb)(1,ctx);
+    if (!ok) goto end;
+
+    n--;
+    if (n >= 0) {
+      xi=xs;
+      xs=sk_X509_value(ctx->chain,n);
+    }
+  }
+  ok=1;
+ end:
+  return(ok);
+}
+
+static STACK_OF(X509) *
+lookup_certs_by_subject(STACK_OF(XMAP) *lu, X509_NAME *xn)
+{
+  /* output stack - concatenation of certificates */
+  /* return value */
+  STACK_OF(X509) *osk = sk_X509_new_null(); 
+  int i, j, k, found;
+  
+  DBG(DBG_PARSING,
+  DBG_log("Looking up certificate by subject");
+  );
+  for(i=0; i<sk_XMAP_num(lu); i++) {
+    /* individual searchable directory */
+    XMAP *xm = sk_XMAP_value(lu, i); 
+    /* list of objects from individual searches */
+    STACK_OF(X509_OBJECT) *xo = NULL; 
+
+    if (xm) {
+     if (xm->pmap) {
+      DBG(DBG_PARSING,
+      DBG_log("by_subject: Searching map %d", i+1);
+      );
+      if ((xo = XMAP_lookup( xm, X509_LU_X509, "subject", xn)) != NULL) {
+        DBG(DBG_PARSING,
+        DBG_log("by_subject: Got %d certificates", sk_X509_OBJECT_num(xo));
+        );
+        for(j=0; j<sk_X509_OBJECT_num(xo); j++) {
+          X509_OBJECT *o = sk_X509_OBJECT_value(xo, j);
+          X509 *xx = X509_dup(o->data.x509);
+ 
+          for(k=0, found = 0; (!found) && (k<sk_X509_num(osk)); k++) {
+            X509 *tx = sk_X509_value(osk, k);
+
+            if (X509_issuer_and_serial_cmp(xx, tx) == 0) found = 1;
+          }
+ 
+          if (!found) {
+            if (sk_X509_num(osk) == 0) {
+              sk_X509_push(osk, xx);
+
+              DBG(DBG_PARSING,
+              DBG_log("by_subject: Initialized cert stack");
+              );
+
+            } else {
+              /* insert the certificate into the stack in date order */
+              ASN1_UTCTIME *new_notBefore = X509_get_notBefore(xx);
+              ASN1_UTCTIME *new_notAfter = X509_get_notAfter(xx);
+ 
+              for(k=0; k<sk_X509_num(osk); k++) {
+                /* certificate already in stack */
+                X509 *tx = sk_X509_value(osk, k); 
+                ASN1_UTCTIME *notBefore = X509_get_notBefore(tx);
+                ASN1_UTCTIME *notAfter = X509_get_notAfter(tx);
+                int c1 = ASN1_UTCTIME_cmp(new_notBefore, notBefore);
+                int c2 = ASN1_UTCTIME_cmp(new_notAfter, notAfter);
+ 
+                if (c1 == 0) {
+                  /* certs start at same time */
+                  /* insert here if xx expiry is later than tx */
+                  if (c2 > 0) break; 
+                } else
+                  /* insert here is xx start date is later than tx */
+                  if (c1 > 0) break; 
+                /* else move on to the next certificate 
+                 * in the current output stack */
+              }
+              /* Insert into the output stack */
+              sk_X509_insert(osk, xx, k); 
+            }
+          } else
+            X509_free(xx);
+        }
+        sk_X509_OBJECT_pop_free(xo, X509_OBJECT_free);
+      } /* if (xo != NULL) */
+      else
+      {
+        DBG(DBG_PARSING,
+        DBG_log("xo = XMAP_lookup( xm, X509_LU_X509, 
+          \"subject\", xn) == NULL.");
+        );
+      }
+     } /* if (xm->pmap) */
+    } /* if (xm) */
+  } /* for */
+  DBG(DBG_PARSING,
+  DBG_log("by_subject: Finished lookups");
+  );
+
+  if (osk) DBG(DBG_PARSING,
+	DBG_log("by_subject: Returning %d certs in list", sk_X509_num(osk)));
+  return osk;
+}
+
+#if 0 /* not currently used */
+static STACK_OF(X509) *
+lookup_certs_by_issuer(STACK_OF(XMAP) *lu, X509_NAME *xn)
+{
+  STACK_OF(X509) *osk = sk_X509_new_null(); 
+  int i, j, k, found;
+  
+  DBG(DBG_PARSING,
+  DBG_log("Looking up certificate by issuer");
+  );
+  for(i=0; i<sk_XMAP_num(lu); i++) {
+    /* individual searchable directory */
+    XMAP *xm = sk_XMAP_value(lu, i); 
+    /* list of objects from individual searches */
+    STACK_OF(X509_OBJECT) *xo = NULL; 
+
+    if (xm) {
+      DBG(DBG_PARSING,
+      DBG_log("by_issuer: Searching map %d", i+1);
+      );
+      if ((xo = XMAP_lookup( xm, X509_LU_X509, "issuer", xn)) != NULL) {
+        DBG(DBG_PARSING,
+        DBG_log("by_issuer: Got %d certificates", sk_X509_OBJECT_num(xo));
+        );
+        for(j=0; j<sk_X509_OBJECT_num(xo); j++) {
+          X509_OBJECT *o = sk_X509_OBJECT_value(xo, j);
+          X509 *xx = X509_dup(o->data.x509);
+ 
+          for(k=0, found = 0; (!found) && (k<sk_X509_num(osk)); k++) {
+            X509 *tx = sk_X509_value(osk, k);
+
+            if (X509_issuer_and_serial_cmp(xx, tx) == 0) found = 1;
+          }
+ 
+          if (!found) {
+            if (sk_X509_num(osk) == 0) {
+              sk_X509_push(osk, xx);
+
+              DBG(DBG_PARSING,
+              DBG_log("by_issuer: Initialized cert stack");
+              );
+
+            } else {
+              /* insert the certificate into the stack in date order */
+              ASN1_UTCTIME *new_notBefore = X509_get_notBefore(xx);
+              ASN1_UTCTIME *new_notAfter = X509_get_notAfter(xx);
+ 
+              for(k=0; k<sk_X509_num(osk); k++) {
+                /* certificate already in stack */
+                X509 *tx = sk_X509_value(osk, k); 
+                ASN1_UTCTIME *notBefore = X509_get_notBefore(tx);
+                ASN1_UTCTIME *notAfter = X509_get_notAfter(tx);
+                int c1 = ASN1_UTCTIME_cmp(new_notBefore, notBefore);
+                int c2 = ASN1_UTCTIME_cmp(new_notAfter, notAfter);
+ 
+                if (c1 == 0) {
+                  /* certs start at same time */
+                  /* insert here if xx expiry is later than tx */
+                  if (c2 > 0) break; 
+                } else
+                  /* insert here is xx start date is later than tx */
+                  if (c1 > 0) break; 
+                /* else move on to the next certificate 
+                 * in the current output stack */
+              }
+              /* Insert into the output stack */
+              sk_X509_insert(osk, xx, k); 
+            }
+          } else
+            X509_free(xx);
+        }
+        sk_X509_OBJECT_pop_free(xo, X509_OBJECT_free);
+      } /* if (xo != NULL) */
+      else
+      {
+        DBG(DBG_PARSING,
+        DBG_log("xo = XMAP_lookup( xm, X509_LU_X509, 
+          \"issuer\", xn) == NULL.");
+        );
+      }
+    } /* if (xm) */
+  } /* for */
+  DBG(DBG_PARSING,
+  DBG_log("by_issuer: Finished lookups");
+  );
+
+  if (osk) DBG(DBG_PARSING,
+    DBG_log("by_issuer: Returning %d certs in list", sk_X509_num(osk)));
+  return osk;
+}
+#endif /* not used */
+
+void
+build_cert_chain( STACK_OF(X509) **ch, STACK_OF(XMAP) *lu, X509 *x )
+{
+  int done = 0;
+  X509 *xx;
+
+  if (!ch) return;
+  if ((*ch = sk_X509_new_null()) == NULL) return;
+  xx = x;
+
+  sk_X509_push(*ch, X509_dup(xx));
+  while (!done) {
+    X509 *xi;
+
+    /* look for self-signed cert. It would have issuer data 
+     * same as subject field */
+    if ((xi = sk_X509_value(lookup_certs_by_subject(lu, 
+	X509_get_issuer_name(xx)), 0)) != NULL) 
+    {
+      sk_X509_push(*ch, xi);
+      if (X509_NAME_cmp(X509_get_subject_name(xi),
+			X509_get_issuer_name(xi)) == 0) {
+        DBG(DBG_PARSING,
+        DBG_log("Found the issuer's self-signed cert.");
+        );
+	done = 1;
+      } else {
+        /* the 2 fields are not exactly the same. Narrowing search. */
+	xx = xi;
+      }
+    } else 
+      /* Did not find self-signed certificate */
+      DBG(DBG_PARSING,
+      DBG_log("Did not find the issuer's self-signed cert.");
+      );
+      done = 1; 
+  }
+}
+
+bool
+verify_certificate( X509 *x, STACK_OF(XMAP) *lu,
+		    const char *path, bool strict )
+{
+  X509_STORE *ctx = NULL;
+  X509_STORE_CTX csc;
+  int ver;
+
+
+  if ((ctx = X509_STORE_new()) == NULL) {
+    DBG(DBG_PARSING,
+    DBG_log("Cant allocate file lookup");
+    );
+    log_err();
+    return 0;
+  }
+
+  X509_STORE_set_verify_cb_func(ctx, cb);
+
+  ERR_clear_error();
+  verify_strict = strict;
+  lookups = lu;
+  X509_STORE_CTX_init(&csc, ctx, x, NULL);
+
+  build_cert_chain(&(csc.chain), lu, x);
+  ver = verify_func(&csc);
+  X509_STORE_CTX_cleanup(&csc);
+
+  if (ctx) X509_STORE_free(ctx);
+
+  if (ver) {
+    DBG(DBG_PARSING,
+    DBG_log("Certificate verification succeeded");
+    );
+  } else {
+    DBG(DBG_PARSING,
+    DBG_log("Verification failed");
+    );
+    log_err();
+  }
+
+  return ver;
+}
+
+struct cert_options {
+  const char *opt;
+  u_int32_t optflag;
+};
+
+static struct cert_options certopts[] = {
+  { "send", CERT_OPTION_SEND },
+  { "pkcs7", CERT_OPTION_PKCS7 },
+  { "pk", CERT_OPTION_PK },
+  { "rev", CERT_OPTION_REV },
+  { "strict", CERT_OPTION_STRICT },
+  { "dss-sha", CERT_OPTION_DSS_SHA },
+  { "dss-alt", CERT_OPTION_DSS_ALT },
+  { NULL, 0 }
+};
+
+u_int32_t
+parse_options( const char *s )
+{
+  tok_list tl, p;
+  u_int32_t i, ret = 0, b4;
+
+  tl = tokenize(s, ',');
+  for(p=tl; p; p=p->next) {
+    int found = 0;
+    char *st = p->s;
+
+    while (isspace(*st)) st++; /* skip whitespace */
+    for(i=0; (!found) && (certopts[i].opt != NULL); i++) {
+      if ((st[0] == '!') &&
+	  (strncasecmp(&(st[1]), certopts[i].opt,
+		       strlen(certopts[i].opt)) == 0)) {
+	found = 1;
+	b4 = ret;
+	ret &= ~certopts[i].optflag;
+
+	DBG(DBG_PARSING,
+	DBG_log("Cert option: Clearing option %s: %08x -> %08x", 
+	  certopts[i].opt, b4, ret);
+	);
+      } else if (strncasecmp(st, certopts[i].opt,
+			     strlen(certopts[i].opt)) == 0) {
+	found = 1;
+	b4 = ret;
+	ret |= certopts[i].optflag;
+
+	DBG(DBG_PARSING,
+	DBG_log("Cert option: Setting option %s: %08x -> %08x", 
+	  certopts[i].opt, b4, ret);
+	);
+      }
+    }
+  }
+  tok_free(tl);
+  return ret;
+}
+int
+DSA_sign_raw(unsigned char *dgst,int dlen,
+	     unsigned char *sig, unsigned int *siglen, DSA *dsa)
+{
+  DSA_SIG *s;
+  int offset;
+
+  DBG(DBG_PARSING,
+  DBG_log("DSA_sign_raw called");
+  );
+  s= DSA_do_sign(dgst, dlen, dsa);
+  if (s == NULL) {
+    *siglen=0;
+    return 0;
+  }
+  memset(sig, 0, SHA1_DIGEST_SIZE * 2);
+  offset = SHA1_DIGEST_SIZE - BN_num_bytes(s->r);
+  BN_bn2bin(s->r, &(sig[offset]));
+  offset = SHA1_DIGEST_SIZE - BN_num_bytes(s->s);
+  BN_bn2bin(s->s, &(sig[SHA1_DIGEST_SIZE + offset]));
+  *siglen = SHA1_DIGEST_SIZE * 2;
+  DSA_SIG_free(s);
+  return 1;
+}
+
+int DSA_verify_raw(const unsigned char *dgst,int dgst_len,
+		   unsigned char *sigbuf, int siglen, DSA *dsa)
+{
+  DSA_SIG *s;
+  int ret = -1;
+
+  DBG(DBG_PARSING,
+  DBG_log("DSA_verify_raw called");
+  );
+  if (siglen != (2 * SHA1_DIGEST_SIZE)) return ret;
+  s = DSA_SIG_new();
+  if (s == NULL) return ret;
+  s->r = BN_bin2bn(sigbuf, SHA1_DIGEST_SIZE,
+		   s->r);
+  s->s = BN_bin2bn(&(sigbuf[SHA1_DIGEST_SIZE]),
+		   SHA1_DIGEST_SIZE,
+		   s->s);
+  ret=DSA_do_verify(dgst, dgst_len,s,dsa);
+  DSA_SIG_free(s);
+  return ret;
+}
+
+/*
+ * The following code implements ElGamal encryption using DSA keys
+ * in a (hopefully) OpenSSL compatible fashion. It really belongs in 
+ * OpenSSL itself, when the code approaches being both tested and
+ * more efficient. In order to make things a bit faster, the modular
+ * operations use montogomery representation.
+ *
+ * NB - this implementation is pretty naive, and contains just the
+ * simplest implementation of ElGamal as per HAC, Ch8, Section 8.4,
+ * pp 294-295.
+ */
+
+static ERR_STRING_DATA ElGamal_str_functs[] =
+{
+  {ERR_PACK(0,ELGAMAL_F_ELGAMAL_PUBLIC_ENCRYPT,0),  "ElGamal_public_encrypt"},
+  {ERR_PACK(0,ELGAMAL_F_ELGAMAL_PRIVATE_DECRYPT,0), "ElGamal_private_decrypt"},
+  { 0, NULL }
+};
+
+static ERR_STRING_DATA ElGamal_str_reasons[] = 
+{
+  { ELGAMAL_R_UNKNOWN_PADDING_TYPE, "unknown padding type" },
+  { ELGAMAL_R_DATA_GREATER_THAN_MOD_LEN, "data longer than modulus length" },
+  { ELGAMAL_R_PADDING_CHECK_FAILED, "padding check failed" },
+  { 0, NULL }
+};
+
+void
+ERR_load_ElGamal_strings( void )
+{
+  static int init = 1;
+
+  if (init)
+    {
+      init = 0;
+
+      ERR_load_strings(ERR_LIB_ELGAMAL, ElGamal_str_functs);
+      ERR_load_strings(ERR_LIB_ELGAMAL, ElGamal_str_reasons);
+    }
+}
+
+int
+ElGamal_public_check( DSA *dsa )
+{
+  BIGNUM res;
+  BN_MONT_CTX *mont;
+  BN_CTX *ctx;
+  int r = 0;
+
+  /* Check that g^q = 1 (mod p), and that y^q = 1 (mod p) */
+  /* to avoid attacks involving generators which produce small */
+  /* subgroups */
+
+  BN_init(&res);
+  if ((ctx = BN_CTX_new()) == NULL) goto err;
+  if ((mont = BN_MONT_CTX_new()) == NULL) goto err;
+  if (! BN_MONT_CTX_set(mont, dsa->p, ctx)) goto err;
+
+  if (! BN_mod_exp_mont(&res, dsa->g, dsa->q, dsa->p, ctx, mont)) goto err;
+  if (! BN_is_one(&res)) goto err;
+  if (! BN_mod_exp_mont(&res, dsa->pub_key, dsa->q, dsa->p, ctx, mont)) goto err;
+  if (! BN_is_one(&res)) goto err;
+  r = 1; /* Key is OK */
+
+ err:
+  BN_clear_free(&res);
+  if (ctx) BN_CTX_free(ctx);
+  if (mont) BN_MONT_CTX_free(mont);
+
+  return r;
+}
+
+int
+ElGamal_public_encrypt( int flen, unsigned char *from,
+			unsigned char *to,
+			DSA *dsa, int padding )
+			    
+{
+  unsigned char *buf, *p;
+  int num = 0, i, j, k, r = -1;
+  BIGNUM kappa, alpha, beta, f;
+  BIGNUM BETA, F;
+  BN_MONT_CTX *pmont;
+  BN_CTX *ctx = NULL;
+
+  num = BN_num_bytes(dsa->p) ;
+  BN_init(&alpha);
+  BN_init(&beta);
+  BN_init(&kappa);
+  BN_init(&f);
+  BN_init(&BETA);
+  BN_init(&F);
+
+  if ((ctx = BN_CTX_new()) == NULL) goto err;
+  if ((pmont = BN_MONT_CTX_new()) == NULL) goto err;
+  if (! BN_MONT_CTX_set(pmont, dsa->p, ctx)) goto err;
+  if ((buf = (unsigned char *)Malloc(num)) == NULL) {
+    ElGamalerr(ELGAMAL_F_ELGAMAL_PUBLIC_ENCRYPT, ERR_R_MALLOC_FAILURE);
+    goto err;
+  }
+
+  /* generate k s.t. 1 <= k <= q-1 */
+  do {
+    if (! BN_rand(&kappa, BN_num_bits(dsa->q), 1, 1)) goto err;
+  } while (BN_cmp(&kappa, dsa->q) < 0);
+
+  switch (padding) {
+  case ELGAMAL_PKCS1_PADDING:
+    i = RSA_padding_add_PKCS1_type_2(buf, num, from, flen);
+    break;
+  case ELGAMAL_PKCS1_OAEP_PADDING:
+    i = RSA_padding_add_PKCS1_OAEP(buf, num, from, flen, NULL, 0);
+    break;
+  case ELGAMAL_NO_PADDING:
+    i = RSA_padding_add_none(buf, num, from, flen);
+    break;
+  default:
+    ElGamalerr( ELGAMAL_F_ELGAMAL_PUBLIC_ENCRYPT, 
+      ELGAMAL_R_UNKNOWN_PADDING_TYPE );
+    goto err;
+  }
+
+  if (i <= 0) goto err;
+
+  if (BN_bin2bn(buf, num, &f) == NULL) goto err;
+
+  /* Set alpha = g^k (mod p) */
+  if (!BN_mod_exp_mont(&alpha, dsa->g, &kappa, dsa->p, ctx, pmont)) goto err;
+
+  /* Set beta = M * y^k (mod p) */
+  if (!BN_mod_exp_mont(&beta, dsa->pub_key, &kappa, dsa->p, ctx, 
+    pmont)) goto err;
+
+  BN_to_montgomery(&F, &f, pmont, ctx);
+  BN_to_montgomery(&BETA, &beta, pmont, ctx);
+  if (!BN_mod_mul_montgomery(&BETA, &BETA, &F, pmont, ctx)) goto err;
+  BN_from_montgomery(&beta, &BETA, pmont, ctx);
+
+  /* Squirt out alpha, left padded to modulus size with zero bytes */
+  j = BN_num_bytes(&alpha);
+  i = BN_bn2bin(&alpha, &(to[num-j]));
+  for(k=0; k<(num-i); k++) to[k]=0;
+
+  /* Follow this with beta */
+  p = &(to[num]);
+  j = BN_num_bytes(&beta);
+  i = BN_bn2bin(&beta, &(p[num-j]));
+  for(k=0; k<(num-i); k++) p[k]=0;
+
+  r = num*2;
+
+ err:
+  if (ctx != NULL) BN_CTX_free(ctx);
+  if (pmont != NULL) BN_MONT_CTX_free(pmont);
+  BN_clear_free(&alpha);
+  BN_clear_free(&beta);
+  BN_clear_free(&beta);
+  BN_clear_free(&kappa);
+  BN_clear_free(&f);
+  BN_clear_free(&BETA);
+  BN_clear_free(&F);
+  if (buf != NULL) {
+    memset(buf, 0, num);
+    Free(buf);
+  }
+  return r;
+}
+
+int ElGamal_private_decrypt( int flen, unsigned char *from,
+			     unsigned char *to,
+			     DSA *dsa, int padding )
+{
+
+  BIGNUM alpha, beta, gamma, delta, p1a;
+  BIGNUM BETA, GAMMA, DELTA;
+  BN_CTX *ctx;
+  BN_MONT_CTX *pmont;
+  unsigned char *p, *buf = NULL;
+  int j, r = -1, num;
+
+  BN_init(&alpha);
+  BN_init(&beta);
+  BN_init(&gamma);
+  BN_init(&delta);
+  BN_init(&p1a);
+  BN_init(&BETA);
+  BN_init(&GAMMA);
+  BN_init(&DELTA);
+  if ((ctx = BN_CTX_new()) == NULL) goto err;
+  if ((pmont = BN_MONT_CTX_new()) == NULL) goto err;
+  if (! BN_MONT_CTX_set(pmont, dsa->p, ctx)) goto err;
+
+  num = BN_num_bytes(dsa->p);
+
+  /* set p1a to be equal to p-1-x, where x is the private key */
+  if (BN_copy(&p1a, dsa->p) == NULL) goto err;
+  if (! BN_sub_word(&p1a, 1)) goto err;
+  if (! BN_sub(&p1a, &p1a, dsa->priv_key)) goto err;
+
+  if ((buf = (unsigned char *)Malloc(num)) == NULL) {
+    ElGamalerr(ELGAMAL_F_ELGAMAL_PRIVATE_DECRYPT, ERR_R_MALLOC_FAILURE);
+    goto err;
+  }
+
+  if (flen > num*2) {
+    ElGamalerr(ELGAMAL_F_ELGAMAL_PRIVATE_DECRYPT, ELGAMAL_R_DATA_GREATER_THAN_MOD_LEN);
+    goto err;
+  }
+
+  /* Copy the cipher text into the two numbers alpha and beta */
+  if (BN_bin2bn(from, flen / 2, &alpha) == NULL) goto err;
+  if (BN_bin2bn(&(from[flen/2]), flen / 2, &beta) == NULL) goto err;
+  
+  if (! BN_mod_exp_mont(&gamma, &alpha, &p1a, dsa->p, ctx, pmont)) goto err;
+  BN_to_montgomery(&GAMMA, &gamma, pmont, ctx);
+  BN_to_montgomery(&BETA, &beta, pmont, ctx);
+  if (! BN_mod_mul_montgomery(&DELTA, &GAMMA, &BETA, pmont, ctx)) goto err;
+  BN_from_montgomery(&delta, &DELTA, pmont, ctx);
+
+  /* Now delta should contain the (possibly padded) plaintext */
+  p = buf;
+  j = BN_bn2bin(&delta, p);
+
+  switch( padding ) {
+  case ELGAMAL_PKCS1_PADDING:
+    r = RSA_padding_check_PKCS1_type_2(to, num, buf, j, num);
+    break;
+  case ELGAMAL_PKCS1_OAEP_PADDING:
+    r = RSA_padding_check_PKCS1_OAEP(to, num, buf, j, num, NULL, 0);
+    break;
+  case ELGAMAL_NO_PADDING:
+    r = RSA_padding_check_none(to, num, buf, j, num);
+    break;
+  default:
+    ElGamalerr(ELGAMAL_F_ELGAMAL_PRIVATE_DECRYPT, 
+      ELGAMAL_R_UNKNOWN_PADDING_TYPE);
+    goto err;
+  }
+
+  if (r < 0)
+    ElGamalerr(ELGAMAL_F_ELGAMAL_PRIVATE_DECRYPT, 
+      ELGAMAL_R_PADDING_CHECK_FAILED);
+
+ err:
+  if (ctx != NULL) BN_CTX_free(ctx);
+  if (pmont != NULL) BN_MONT_CTX_free(pmont);
+  BN_clear_free(&alpha);
+  BN_clear_free(&beta);
+  BN_clear_free(&gamma);
+  BN_clear_free(&delta);
+  BN_clear_free(&p1a);
+  BN_clear_free(&BETA);
+  BN_clear_free(&GAMMA);
+  BN_clear_free(&DELTA);
+  if (buf != NULL) {
+    memset(buf, 0, num);
+    Free(buf);
+  }
+  return r;
+}
+bool
+valid_ciphertext_length( const u_int32_t len, struct connection *c )
+{
+  EVP_PKEY *pk = c->key;
+  bool ret = FALSE;
+
+  if ((!pk) || (len == 0)) return FALSE;
+  switch(pk->type) {
+  case EVP_PKEY_RSA:
+    if (len % BN_num_bytes(pk->pkey.rsa->n) == 0) ret = TRUE;
+    break;
+  case EVP_PKEY_DSA:
+    if (len % (2 * BN_num_bytes(pk->pkey.dsa->p)) == 0) ret = TRUE;
+    break;
+  default:
+    return FALSE;
+  }
+
+  return ret;
+}
+
+static void
+alloc_ciphertext( const u_int32_t len,
+		  EVP_PKEY *pk,
+		  u_char **c,
+		  u_int32_t *ms,
+		  u_int32_t *bsize,
+		  u_int32_t *bl )
+{
+  int modsize, chunksize, blocks;
+  u_int32_t clen;
+
+  switch(pk->type)
+    {
+    case EVP_PKEY_RSA:
+      {
+	RSA *rsa = pk->pkey.rsa;
+	modsize = BN_num_bytes(rsa->n);
+      }
+      break;
+    case EVP_PKEY_DSA:
+      {
+	DSA *dsa = pk->pkey.dsa;
+	modsize = BN_num_bytes(dsa->p) * 2;
+      }
+      break;
+    }
+  chunksize = modsize - 2 * SHA1_DIGEST_SIZE - 1;
+  blocks = (len + chunksize - 1) / chunksize;
+  clen = blocks * modsize;
+  *c = malloc(clen);
+  memset(*c, 0, clen);
+  *bsize = chunksize - 1;
+  *bl = blocks;
+  *ms = modsize;
+}
+
+bool
+pubkey_encrypt_chunk( chunk_t *ch, struct state *st )
+{
+  struct connection *c = st->st_connection;
+  u_char *str = ch->ptr;
+  u_int32_t len = ch->len;
+  EVP_PKEY *pk = NULL;
+  u_char *ciph;
+  u_int32_t ms, bs, bl;
+  u_int16_t auth = st->st_oakley.auth;
+  int i;
+  long clen = 0;
+
+  switch(auth) {
+  case OAKLEY_RSA_ENC:
+  case OAKLEY_RSA_ENC_REV:
+    for(i=0; i<MAX_OTHER; i++) {
+      if ((c->other[i].type == EVP_PKEY_RSA) &&
+	  (c->other[i].cert != NULL)) {
+	pk = X509_get_pubkey((X509 *)c->other[i].cert);
+	break;
+      }
+    }
+    break;
+  case OAKLEY_ELGAMAL_ENC:
+  case OAKLEY_ELGAMAL_ENC_REV:
+    for(i=0; i<MAX_OTHER; i++) {
+      if ((c->other[i].type == EVP_PKEY_DSA) &&
+	  (c->other[i].cert != NULL)) {
+	pk = X509_get_pubkey((X509 *)c->other[i].cert);
+	break;
+      }
+    }
+    break;
+  default:
+    log("Non PK authentication scheme in state");
+    return FALSE;
+  }
+
+  if (!pk) {
+    log("Unable to select an encryption key");
+    return FALSE;
+  }
+
+  switch(pk->type) {
+  case EVP_PKEY_RSA:
+    {
+      alloc_ciphertext(len, pk, &ciph, &ms, &bs, &bl);
+    }
+    break;
+  case EVP_PKEY_DSA:
+    {
+      alloc_ciphertext(len, pk, &ciph, &ms, &bs, &bl);
+    }
+    break;
+  default:
+    log("Unknown key type: %d", pk->type);
+    break;
+  }
+
+    for(i=0; ((i<bl)&&(clen>=0)); i++) {
+    u_char *pst = &str[i * bs];
+    u_char *cst = &ciph[i * ms];
+    u_int32_t plen = (i < bl-1) ? bs : len % bs;
+
+    switch(pk->type) {
+    case EVP_PKEY_RSA:
+      {
+	RSA *rsa = pk->pkey.rsa;
+
+	clen = RSA_public_encrypt(plen, pst, cst, rsa, RSA_PKCS1_OAEP_PADDING);
+      }
+      break;
+    case EVP_PKEY_DSA:
+      {
+	DSA *dsa = pk->pkey.dsa;
+
+	clen = ElGamal_public_encrypt(plen, pst, cst, dsa, ELGAMAL_PKCS1_OAEP_PADDING);
+      }
+      break;
+    default:
+      log("Unknown cert type: %d", pk->type);
+      return FALSE;
+      break;
+    }
+  }
+
+  memset(ch->ptr, 0, ch->len);
+  if (clen < 0) {
+    log("Failed to encrypt payload with certificate's public key.");
+    return FALSE;
+  } else {
+    freeanychunk(*ch);
+    ch->len=bl*ms;
+    ch->ptr=ciph;
+    return TRUE;
+  }
+}
+
+bool
+privkey_decrypt_chunk( chunk_t *ch, struct state *st )
+{
+  u_int32_t i, bl, bs, clen;
+  struct connection *c = st->st_connection;
+  EVP_PKEY *pk = c->key;
+  u_char *str = ch->ptr;
+  u_char *pst;
+  u_int32_t ptr, plen;
+
+  switch(pk->type) {
+  case EVP_PKEY_RSA:
+    {
+      RSA *rsa = pk->pkey.rsa;
+      bs = BN_num_bytes(rsa->n);
+    }
+    break;
+  case EVP_PKEY_DSA:
+    {
+      DSA *dsa = pk->pkey.dsa;
+      bs = 2 * BN_num_bytes(dsa->p);
+    }
+    break;
+  default:
+    log("Unknown key type: %d", pk->type);
+    break;
+  }
+
+  clen = ch->len;
+  bl = clen / bs;
+
+  pst = malloc(clen);
+  ptr = 0;
+  plen = 0;
+	
+  for(i=0; ((i<bl)&&(plen >= 0)); i++) {
+    switch(pk->type) {
+    case EVP_PKEY_RSA:
+      {
+	RSA *rsa = pk->pkey.rsa;
+
+	if (clen >= bs) {
+/*
+ * int     RSA_private_decrypt(int flen, unsigned char *from, 
+ *               unsigned char *to, RSA *rsa,int padding);
+ *
+ *         This function implements RSA private decryption, the rsa variable
+ *         should be a private key.  'from_len' bytes are taken
+ *         from 'from' and decrypted.  The decrypted data is
+ *         put into 'to'.  The number of bytes encrypted is returned.  -1 is
+ *         returned to indicate an error. The operation performed is
+ *         to = from^rsa->d mod rsa->n.
+ */
+
+	  plen = RSA_private_decrypt( bs, &(str[i * bs]), &(pst[ptr]), rsa, 
+	     RSA_PKCS1_OAEP_PADDING );
+	  if (plen == -1) {
+	    log_err();
+	  }
+	} else /* Ciphertext is too short */
+	  plen = 0;
+      }
+      break;
+    case EVP_PKEY_DSA:
+      {
+	DSA *dsa = pk->pkey.dsa;
+	
+	if (clen >= bs) {
+	  plen = ElGamal_private_decrypt( bs, &str[i * bs], &pst[ptr], 
+	    dsa, ELGAMAL_PKCS1_OAEP_PADDING );
+	  if (plen == -1 ) {
+	    log_err();
+	  }
+	} else /* Short ciphertext - don't try and decrypt */
+	  plen = 0;
+      }
+      break;
+    default:
+      log("Unknown key type: %d", pk->type);
+      plen = 0;
+      break;
+    }
+    ptr += plen;
+  }
+
+  if (plen != -1) {
+    freeanychunk(*ch);
+    ch->ptr = pst;
+    ch->len = ptr;
+    return TRUE;
+  } else {
+    pfree(pst);
+    return FALSE;
+  }
+}
+
+bool
+use_openssl( struct connection *c )
+{
+	/* Using data from connection *c, we can determine if we are 
+	 * currently using the openssl-related functions or not.
+	 * ie: 
+	 *   c->cert
+	 *   c->key
+	 *   c->cert_options
+	 * 
+	 * also use c->policy to determine policy.
+	 * 
+	 * Return 0 if openssl, otherwise 1.
+	 */
+
+	if (c->policy & POLICY_OPENSSL) {
+		if ((c->cert != NULL) || 
+			(c->key != NULL) || 
+			(c->cert_options != 0)) 
+		{
+			// OPENSSL
+			return 1;
+		}
+		else
+		{
+			// RSASIG only
+			return 0;
+		}
+	}
+    else 
+	{
+		// PSK
+		return 0;
+	}
+}
+
+bool
+check_idtype_and_path( struct connection *c, const char *spec )
+{
+
+  return TRUE;
+}
+
+const struct RSA_public_key *
+fs_RSA ( EVP_PKEY *evp_pkey ) {
+  struct RSA_public_key *fs_rsa;
+
+ /*
+  * MP_INT:
+  * int _mp_alloc;
+  * int _mp_size;
+  * mp_limb_t *_mp_d;
+  */
+
+ /* BIGNUM
+  * BN_ULONG *d;
+  * int top;
+  * int max;
+  * int neg;
+  * int flags;
+  */
+
+/* So:
+    mp_limb_t *_mp_d = BN_ULONG *d 
+    int _mp_alloc = int max 
+    int _mp_size = int top
+*/
+
+/*   fs_rsa->n = (MP_INT)(evp_pkey->pkey.rsa->n); */
+  {
+  BIGNUM *temp_bignum;
+  MP_INT *temp_mp_int;
+
+  temp_bignum = evp_pkey->pkey.rsa->n;
+  temp_mp_int->_mp_d = (mp_limb_t *)&(temp_bignum->d);
+  temp_mp_int->_mp_alloc = temp_bignum->max;
+  temp_mp_int->_mp_size = temp_bignum->top;
+  fs_rsa->n = *(temp_mp_int);
+  }
+
+  {
+/*   fs_rsa->e = (MP_INT)(evp_pkey->pkey.rsa->e); */
+  BIGNUM *temp_bignum;
+  MP_INT *temp_mp_int;
+
+  temp_bignum = evp_pkey->pkey.rsa->e;
+  temp_mp_int->_mp_d = (mp_limb_t *)&(temp_bignum->d);
+  temp_mp_int->_mp_alloc = temp_bignum->max;
+  temp_mp_int->_mp_size = temp_bignum->top;
+  fs_rsa->e = *(temp_mp_int);
+  }
+
+  fs_rsa->k = mpz_sizeinbase(&fs_rsa->n, 2);        /* size in bits, for a start */
+  fs_rsa->k = (fs_rsa->k + BITS_PER_BYTE - 1) / BITS_PER_BYTE;      /* now octets */
+  
+  return fs_rsa;
+}
+
+
+#endif /* OPENSSL */
diff -bruN freeswan-1.9.orig/pluto/openssl.h freeswan-1.9/pluto/openssl.h
--- freeswan-1.9.orig/pluto/openssl.h	Wed Dec 31 19:00:00 1969
+++ freeswan-1.9/pluto/openssl.h	Wed May 16 10:57:20 2001
@@ -0,0 +1,101 @@
+#ifdef OPENSSL
+#ifndef OPENSSL_INC_H
+#define OPENSSL_INC_H
+
+#include <openssl/evp.h>
+#include <openssl/err.h>
+#include <openssl/pem.h>
+#include <openssl/x509.h>
+#include <openssl/x509v3.h>
+#include <openssl/safestack.h>
+
+#include <freeswan.h>
+
+#include "xmap.h"
+
+struct _x509_cert_node {
+  X509 *x;
+  struct _x509_cert_node *next;
+};
+
+typedef struct _x509_cert_node *X509_cert_list;
+
+typedef bool discrim_fn( X509 *x, STACK_OF(XMAP) *lu,
+			 struct payload_digest *const id_pld, bool strict);
+
+extern bool make_lookups(STACK_OF(XMAP) **lu, const char *spec );
+extern bool check_idtype_and_path( struct connection *c, const char *spec );
+
+extern void log_err( void );
+extern void load_cert_and_key( const char *cert, const char *key,
+			       X509 **x, EVP_PKEY **k );
+extern bool use_openssl( struct connection *c );
+extern STACK_OF(X509) *
+peer_cert_list( STACK_OF(XMAP) *lu,
+		int type,
+		X509 *cert, struct payload_digest *const id_pld,
+		bool strict );
+
+extern bool have_rsa_key( struct state *st );
+extern bool have_dss_key( struct state *st );
+extern bool have_rsa_keypair( struct state *st );
+extern bool have_elgamal_keypair( struct state *st );
+
+extern bool verify_certificate( X509 *x, STACK_OF(XMAP) *lu,
+				const char *path, bool strict );
+
+extern u_int32_t parse_options( const char *s );
+
+extern int DSA_sign_raw(unsigned char *dgst,int dlen,
+			unsigned char *sig, unsigned int *siglen, DSA *dsa);
+
+extern int DSA_verify_raw(const unsigned char *dgst,int dgst_len,
+			  unsigned char *sigbuf, int siglen, DSA *dsa);
+
+#define ERR_LIB_ELGAMAL 127
+
+#define ELGAMAL_F_ELGAMAL_PRIVATE_DECRYPT 100
+#define ELGAMAL_F_ELGAMAL_PUBLIC_ENCRYPT  101
+
+#define ELGAMAL_R_UNKNOWN_PADDING_TYPE      100
+#define ELGAMAL_R_DATA_GREATER_THAN_MOD_LEN 101
+#define ELGAMAL_R_PADDING_CHECK_FAILED      102
+
+#define ELGAMAL_PKCS1_PADDING RSA_PKCS1_PADDING
+#define ELGAMAL_PKCS1_OAEP_PADDING RSA_PKCS1_OAEP_PADDING
+#define ELGAMAL_NO_PADDING RSA_NO_PADDING
+
+#define ElGamalerr(f, r) ERR_PUT_error(ERR_LIB_ELGAMAL, (f), (r), ERR_file_name, __LINE__)
+
+void ERR_load_ElGamal_strings( void );
+int ElGamal_public_check( DSA *dsa );
+int ElGamal_public_encrypt( int flen, unsigned char *from,
+			    unsigned char *to,
+			    DSA *dsa, int padding );
+int ElGamal_private_decrypt( int flen, unsigned char *from,
+			     unsigned char *to,
+			     DSA *dsa, int padding );
+
+/* Function pointer pointing to an encryption routine */
+typedef void encryptor_fn( chunk_t *ch, struct state *c );
+
+extern bool valid_ciphertext_length( const u_int32_t len,
+				     struct connection *c );
+extern bool privkey_decrypt_chunk ( chunk_t *ch, struct state *c );
+extern bool pubkey_encrypt_chunk ( chunk_t *ch, struct state *c );
+
+/* get the other end's cert based */
+extern bool have_othercert( struct connection *c, int type );
+
+/* Macro to duplicate Private key. Used in unshare_connection_strings */
+#define EVP_PKEY_dup(pkey) \
+  (EVP_PKEY *)ASN1_dup((int (*)())i2d_PrivateKey, \
+  (char *(*)())d2i_AutoPrivateKey,(char *)pkey)
+
+/* convert EVP_PKEY to freeswan's RSA_public_key */
+extern const struct RSA_public_key *fs_RSA ( EVP_PKEY *evp_pkey );
+
+#endif
+#endif
+
+
diff -bruN freeswan-1.9.orig/pluto/openssl_defs.h freeswan-1.9/pluto/openssl_defs.h
--- freeswan-1.9.orig/pluto/openssl_defs.h	Wed Dec 31 19:00:00 1969
+++ freeswan-1.9/pluto/openssl_defs.h	Wed May 16 10:57:20 2001
@@ -0,0 +1,5 @@
+
+#define FILE_NAME_LIMIT 80
+#define PATH_NAME_LIMIT 256
+#define CERT_OPTIONS_LIMIT 128
+#define MAX_OTHER 2 /* only know about two type of certificate at the moment (RSA,DSA) */
diff -bruN freeswan-1.9.orig/pluto/packet.c freeswan-1.9/pluto/packet.c
--- freeswan-1.9.orig/pluto/packet.c	Fri Sep 15 05:09:26 2000
+++ freeswan-1.9/pluto/packet.c	Wed Jun  6 14:07:26 2001
@@ -12,7 +12,7 @@
  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  * for more details.
  *
- * RCSID $Id: packet.c,v 1.24 2000/09/15 09:09:26 dhr Exp $
+ * RCSID $Id: packet.c,v 1.26 2001/04/09 19:48:42 dhr Exp $
  */
 
 #include <stdio.h>
@@ -20,6 +20,8 @@
 #include <netinet/in.h>
 #include <string.h>
 
+#include <freeswan.h>
+
 #include "constants.h"
 #include "defs.h"
 #include "log.h"
@@ -663,23 +665,21 @@
  */
 
 bool
-in_struct(void *struct_ptr, struct_desc *sd,
-    pb_stream *ins, pb_stream *obj_pbs)
+in_struct(void *struct_ptr, struct_desc *sd
+, pb_stream *ins, pb_stream *obj_pbs)
 {
-    char ugh[100];	/* arbitrary limit on diagnostic length */
+    err_t ugh = NULL;
     u_int8_t *cur = ins->cur;
 
-    ugh[0] = '\0';
-
     if (ins->roof - cur < (ptrdiff_t)sd->size) {
-	snprintf(ugh, sizeof(ugh), "not enough room in input packet for %s", sd->name);
+	ugh = builddiag("not enough room in input packet for %s", sd->name);
     } else {
 	u_int8_t *roof = cur + sd->size;    /* may be changed by a length field */
 	u_int8_t *outp = struct_ptr;
 	bool immediate = FALSE;
 	field_desc *fp;
 
-	for (fp = sd->fields; ugh[0] == '\0'; fp++) {
+	for (fp = sd->fields; ugh == NULL; fp++) {
 	    size_t i = fp->size;
 
 	    passert(ins->roof - cur >= (ptrdiff_t)i);
@@ -687,15 +687,15 @@
 	    passert(outp - (cur - ins->cur) == struct_ptr);
 
 #if 0
-	    DBG(DBG_PARSING, DBG_log("%d %s",
-		(int) (cur - ins->cur), fp->name == NULL? "" : fp->name));
+	    DBG(DBG_PARSING, DBG_log("%d %s"
+		, (int) (cur - ins->cur), fp->name == NULL? "" : fp->name));
 #endif
 	    switch (fp->field_type) {
 	    case ft_mbz:	/* must be zero */
 		for (; i != 0; i--) {
 		    if (*cur++ != 0) {
-			snprintf(ugh, sizeof(ugh), "byte %d of %s must be zero, but is not",
-			    (int) (cur - ins->cur), sd->name);
+                       ugh = builddiag("byte %d of %s must be zero, but is not"
+                           , (int) (cur - ins->cur), sd->name);
 			break;
 		    }
 		    *outp++ = '\0';	/* probably redundant */
@@ -723,13 +723,11 @@
 			: immediate? sd->size : n + sd->size;
 
 		    if (len < sd->size) {
-			snprintf(ugh, sizeof(ugh),
-			    "%s of %s is smaller than minimum",
-			    fp->name, sd->name);
+                       ugh = builddiag("%s of %s is smaller than minimum"
+                           , fp->name, sd->name);
 		    } else if (pbs_left(ins) < len) {
-			snprintf(ugh, sizeof(ugh),
-			    "%s of %s is larger than can fit",
-			    fp->name, sd->name);
+                       ugh = builddiag("%s of %s is larger than can fit"
+                           , fp->name, sd->name);
 		    } else {
 			roof = ins->cur + len;
 		    }
@@ -741,18 +739,17 @@
 		    /* FALL THROUGH */
 		case ft_enum:	/* value from an enumeration */
 		    if (enum_name(fp->desc, n) == NULL) {
-			snprintf(ugh, sizeof(ugh),
-			    "%s of %s has an unknown value: %lu",
-			    fp->name, sd->name, (unsigned long)n);
+                       ugh = builddiag("%s of %s has an unknown value: %lu"
+                           , fp->name, sd->name, (unsigned long)n);
 		    }
 		    /* FALL THROUGH */
 		case ft_loose_enum:	/* value from an enumeration with only some names known */
 		    break;
 		case ft_set:	/* bits representing set */
 		    if (!testset(fp->desc, n)) {
-			snprintf(ugh, sizeof(ugh),
-			    "bitset %s of %s has unknown member(s): %s",
-			    fp->name, sd->name, bitnamesof(fp->desc, n));
+			ugh = builddiag("bitset %s of %s has unknown member(s): %s"
+                            , fp->name, sd->name, bitnamesof(fp->desc, n));
+
 		    }
 		    break;
 		default:
@@ -791,8 +788,8 @@
 		    obj_pbs->cur = cur;
 		}
 		ins->cur = roof;
-		DBG(DBG_PARSING,
-		    DBG_prefix_print_struct(ins, "parse ", struct_ptr, sd, TRUE));
+		DBG(DBG_PARSING
+		    , DBG_prefix_print_struct(ins, "parse ", struct_ptr, sd, TRUE));
 		return TRUE;
 
 	    default:
@@ -818,17 +815,17 @@
     {
 	if (bytes == NULL)
 	{
-	    DBG(DBG_PARSING,
-		DBG_log("skipping %u raw bytes of %s (%s)",
-		    (unsigned) len, ins->name, name);
+	    DBG(DBG_PARSING
+		, DBG_log("skipping %u raw bytes of %s (%s)"
+		    , (unsigned) len, ins->name, name);
 		DBG_dump(name, ins->cur, len));
 	}
 	else
 	{
 	    memcpy(bytes, ins->cur, len);
-	    DBG(DBG_PARSING,
-		DBG_log("parsing %u raw bytes of %s into %s",
-		    (unsigned) len, ins->name, name);
+	    DBG(DBG_PARSING
+		, DBG_log("parsing %u raw bytes of %s into %s"
+		    , (unsigned) len, ins->name, name);
 		DBG_dump(name, bytes, len));
 	}
 	ins->cur += len;
@@ -851,20 +848,19 @@
  */
 
 bool
-out_struct(const void *struct_ptr, struct_desc *sd,
-    pb_stream *outs, pb_stream *obj_pbs)
+out_struct(const void *struct_ptr, struct_desc *sd
+, pb_stream *outs, pb_stream *obj_pbs)
 {
-    char ugh[100];	/* arbitrary limit on diagnostic length */
+    err_t ugh = NULL;
     const u_int8_t *inp = struct_ptr;
     u_int8_t *cur = outs->cur;
 
-    DBG(DBG_EMITTING,
-	DBG_prefix_print_struct(outs, "emit ", struct_ptr, sd, obj_pbs==NULL));
+    DBG(DBG_EMITTING
+	, DBG_prefix_print_struct(outs, "emit ", struct_ptr, sd, obj_pbs==NULL));
 
-    ugh[0] = '\0';
     if (outs->roof - cur < (ptrdiff_t)sd->size) {
-	snprintf(ugh, sizeof(ugh)
-	    , "not enough room left in output packet to place %s", sd->name);
+	ugh = builddiag("not enough room left in output packet to place %s"
+	    , sd->name);
     } else {
 	bool immediate = FALSE;
 	pb_stream obj;
@@ -873,7 +869,7 @@
 	obj.lenfld = NULL;  /* until a length field is discovered */
 	obj.lenfld_desc = NULL;
 
-	for (fp = sd->fields; ugh[0] == '\0'; fp++) {
+	for (fp = sd->fields; ugh == NULL; fp++) {
 	    size_t i = fp->size;
 
 	    passert(outs->roof - cur >= (ptrdiff_t)i);
@@ -881,8 +877,8 @@
 	    passert(inp - (cur - outs->cur) == struct_ptr);
 
 #if 0
-	    DBG(DBG_EMITTING, DBG_log("%d %s",
-		(int) (cur - outs->cur), fp->name == NULL? "" : fp->name);
+	    DBG(DBG_EMITTING, DBG_log("%d %s"
+		, (int) (cur - outs->cur), fp->name == NULL? "" : fp->name);
 #endif
 	    switch (fp->field_type) {
 	    case ft_mbz:	/* must be zero */
@@ -934,18 +930,16 @@
 		    /* FALL THROUGH */
 		case ft_enum:	/* value from an enumeration */
 		    if (enum_name(fp->desc, n) == NULL) {
-			snprintf(ugh, sizeof(ugh),
-			    "%s of %s has an unknown value: %lu",
-			    fp->name, sd->name, (unsigned long)n);
+                       ugh = builddiag("%s of %s has an unknown value: %lu"
+			    , fp->name, sd->name, (unsigned long)n);
 		    }
 		    /* FALL THROUGH */
 		case ft_loose_enum:	/* value from an enumeration with only some names known */
 		    break;
 		case ft_set:	/* bits representing set */
 		    if (!testset(fp->desc, n)) {
-			snprintf(ugh, sizeof(ugh),
-			    "bitset %s of %s has unknown member(s): %s",
-			    fp->name, sd->name, bitnamesof(fp->desc, n));
+			ugh = builddiag("bitset %s of %s has unknown member(s): %s"
+			    , fp->name, sd->name, bitnamesof(fp->desc, n));
 		    }
 		    break;
 		default:
@@ -1002,8 +996,8 @@
 }
 
 bool
-out_generic(u_int8_t np, struct_desc *sd,
-    pb_stream *outs, pb_stream *obj_pbs)
+out_generic(u_int8_t np, struct_desc *sd
+, pb_stream *outs, pb_stream *obj_pbs)
 {
     struct isakmp_generic gen;
 
@@ -1013,8 +1007,8 @@
 }
 
 bool
-out_generic_raw(u_int8_t np, struct_desc *sd,
-    pb_stream *outs, void *bytes, size_t len, const char *name)
+out_generic_raw(u_int8_t np, struct_desc *sd
+, pb_stream *outs, void *bytes, size_t len, const char *name)
 {
     pb_stream pbs;
 
@@ -1030,15 +1024,15 @@
 {
     if (pbs_left(outs) < len)
     {
-	loglog(RC_LOG_SERIOUS, "not enough room left to place %lu bytes of %s in %s",
-	    (unsigned long) len, name, outs->name);
+	loglog(RC_LOG_SERIOUS, "not enough room left to place %lu bytes of %s in %s"
+	    , (unsigned long) len, name, outs->name);
 	return FALSE;
     }
     else
     {
-	DBG(DBG_EMITTING,
-	    DBG_log("emitting %u raw bytes of %s into %s",
-		(unsigned) len, name, outs->name);
+	DBG(DBG_EMITTING
+	    , DBG_log("emitting %u raw bytes of %s into %s"
+		, (unsigned) len, name, outs->name);
 	    DBG_dump(name, bytes, len));
 	memcpy(outs->cur, bytes, len);
 	outs->cur += len;
@@ -1056,8 +1050,8 @@
     }
     else
     {
-	DBG(DBG_EMITTING, DBG_log("emitting %u zero bytes of %s into %s",
-	    (unsigned) len, name, outs->name));
+	DBG(DBG_EMITTING, DBG_log("emitting %u zero bytes of %s into %s"
+	    , (unsigned) len, name, outs->name));
 	memset(outs->cur, 0x00, len);
 	outs->cur += len;
 	return TRUE;
@@ -1078,8 +1072,8 @@
 
 	if (pbs->lenfld_desc->field_type == ft_lv)
 	    len -= sizeof(struct isakmp_attribute);
-	DBG(DBG_EMITTING, DBG_log("emitting length of %s: %lu",
-	    pbs->name, (unsigned long) len));
+	DBG(DBG_EMITTING, DBG_log("emitting length of %s: %lu"
+	    , pbs->name, (unsigned long) len));
 	while (i-- != 0) {
 	    pbs->lenfld[i] = (u_int8_t)len;
 	    len >>= BITS_PER_BYTE;
diff -bruN freeswan-1.9.orig/pluto/packet.h freeswan-1.9/pluto/packet.h
--- freeswan-1.9.orig/pluto/packet.h	Fri Sep 15 05:09:26 2000
+++ freeswan-1.9/pluto/packet.h	Wed Jun  6 14:08:33 2001
@@ -12,7 +12,7 @@
  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  * for more details.
  *
- * RCSID $Id: packet.h,v 1.16 2000/09/15 09:09:26 dhr Exp $
+ * RCSID $Id: packet.h,v 1.17 2001/04/04 20:02:25 dhr Exp $
  */
 
 /* a struct_desc describes a structure for the struct I/O routines.
@@ -122,14 +122,36 @@
  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  * !                            Length                             !
  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * Although the drafts are a little unclear, all messages should
- * be padded with enough 0x00 bytes to make the length a multiple of
- * (a) a multiple of 4 octets in length (source:
- *     draft-ietf-ipsec-isakmp-09.txt 3, but ??? no padding value is
- *     specified), and
- * (b) the encryption block size (if encrypted) (source:
- *     draft-ietf-ipsec-isakmp-oakley-07, 5.3 and Appendix B)
- * ??? It is not clear that if (b) applies, (a) always makes sense.
+ * Although the drafts are a little unclear, there are a few
+ * places that specify that messages should be padded with 0x00
+ * octets (bytes) to make the length a multiple of something.
+ *
+ * RFC 2408 "ISAKMP" 3.6 specifies that all messages will be
+ * padded to be a multiple of 4 octets in length.
+ * ??? This looks vestigial, and we ignore this requirement.
+ *
+ * RFC 2409 "IKE" Appedix B specifies:
+ *     Each message should be padded up to the nearest block size
+ *     using bytes containing 0x00.
+ * ??? This does not appear to be limited to encrypted messages,
+ * but it surely must be: the block size is meant to be the encryption
+ * block size, and that is meaningless for a non-encrypted message.
+ *
+ * RFC 2409 "IKE" 5.3 specifies:
+ *     Encrypted payloads are padded up to the nearest block size.
+ *     All padding bytes, except for the last one, contain 0x00. The
+ *     last byte of the padding contains the number of the padding
+ *     bytes used, excluding the last one. Note that this means there
+ *     will always be padding.
+ * ??? This is nuts since payloads are not padded, messages are.
+ * It also contradicts Appendix B.  So we ignore it.
+ *
+ * Summary: we pad encrypted output messages with 0x00 to bring them
+ * up to a multiple of the encryption block size.  On input, we require
+ * that any encrypted portion of a message be a multiple of the encryption
+ * block size.   After any decryption, we ignore padding (any bytes after
+ * the first payload that specifies a next payload of none; we don't
+ * require them to be zero).
  */
 
 struct isakmp_hdr
diff -bruN freeswan-1.9.orig/pluto/preshared.c freeswan-1.9/pluto/preshared.c
--- freeswan-1.9.orig/pluto/preshared.c	Thu Feb 22 16:27:59 2001
+++ freeswan-1.9/pluto/preshared.c	Wed Jun  6 14:18:25 2001
@@ -11,7 +11,7 @@
  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  * for more details.
  *
- * RCSID $Id: preshared.c,v 1.42.2.2 2001/02/22 21:27:59 henry Exp $
+ * RCSID $Id: preshared.c,v 1.50 2001/04/09 19:48:42 dhr Exp $
  */
 
 #include <stdio.h>
@@ -176,8 +176,13 @@
 
 const char *shared_secrets_file = SHARED_SECRETS_FILE;
 
+struct id_list {
+    struct id id;
+    struct id_list *next;
+};
+
 struct secret {
-    struct id *ids;
+    struct id_list *ids;
     enum PrivateKeyKind kind;
     union {
 	chunk_t preshared_secret;
@@ -203,14 +208,11 @@
     unsigned int best_match = 0;
     struct secret *best = NULL;
     struct secret *s;
-    struct id
-	*my_id = &c->this.id,
-	rw_id,
-	*his_id = &c->that.id;
-
-    if (c->rw_state == rwcs_instance
-    && (c->that.id.kind == ID_IPV4_ADDR || c->that.id.kind == ID_IPV6_ADDR)
-    && sameaddr(&c->that.id.ip_addr, &c->that.host_addr))
+    struct id *my_id = &c->this.id
+       , rw_id
+       , *his_id = &c->that.id;
+
+    if (his_id_was_instantiated(c))
     {
 	/* roadwarrior: replace him with 0.0.0.0 */
 	rw_id.kind = c->that.id.kind;
@@ -234,14 +236,14 @@
 	    else
 	    {
 		/* check if both ends match ids */
-		struct id *i;
+		struct id_list *i;
 
 		for (i = s->ids; i != NULL; i = i->next)
 		{
-		    if (same_id(my_id, i))
+			if (same_id(my_id, &i->id))
 			match |= match_me;
 
-		    if (same_id(his_id, i))
+			if (same_id(his_id, &i->id))
 			match |= match_him;
 		}
 
@@ -544,8 +546,6 @@
 {
     char buf[2048];	/* limit on size of binary representation of key */
     err_t ugh = NULL;
-    err_t ugh_extra = "";
-    char ugh_space[100];	/* perhaps enough space */
 
     if (*tok == '"' || *tok == '\'')
     {
@@ -573,10 +573,7 @@
 	    if (ugh != NULL)
 	    {
 		/* atobytes didn't like PSK data */
-		snprintf(ugh_space, sizeof(ugh_space)
-		    , "PSK data malformed (%s): ", ugh);
-		ugh = ugh_space;
-		ugh_extra = tok;
+		ugh = builddiag("PSK data malformed (%s): %s", ugh, tok);
 	    }
 	    else
 	    {
@@ -613,8 +610,8 @@
 		}
 		else if (!tokeqword(p->name))
 		{
-		    ugh = p->name;
-		    ugh_extra = " keyword not found where expected in RSA key";
+		    ugh = builddiag("%s keyword not found where expected in RSA key"
+                       , p->name);
 		}
 		else if (!(shift()
 		&& (!tokeq(":") || shift())))	/* ignore optional ":" */
@@ -624,10 +621,7 @@
 		else if (NULL != (ugh = atobytes(tok, sfp->cur - tok, buf, sizeof(buf), &sz)))
 		{
 		    /* in RSA key, atobytes didn't like */
-		    snprintf(ugh_space, sizeof(ugh_space)
-			, "RSA data malformed (%s): ", ugh);
-		    ugh = ugh_space;
-		    ugh_extra = tok;
+		    ugh = builddiag("RSA data malformed (%s): %s", ugh, tok);
 		}
 		else
 		{
@@ -667,14 +661,13 @@
     }
     else
     {
-	ugh = "unrecognized key format: ";
-	ugh_extra = tok;
+	ugh = builddiag("unrecognized key format: %s", tok);
     }
 
     if (ugh != NULL)
     {
-	loglog(RC_LOG_SERIOUS, "\"%s\" line %d: %s%s"
-	    , sfp->filename, sfp->lino, ugh, ugh_extra);
+	loglog(RC_LOG_SERIOUS, "\"%s\" line %d: %s"
+	    , sfp->filename, sfp->lino, ugh);
     }
     else if (flushline("expected record boundary in key"))
     {
@@ -775,13 +768,13 @@
 
 		    if (tokeq("%any"))
 		    {
-			memset(&id, 0, sizeof(id));
+			id = empty_id;
 			id.kind = ID_IPV4_ADDR;
 			ugh = anyaddr(AF_INET, &id.ip_addr);
 		    }
 		    else if (tokeq("%any6"))
 		    {
-			memset(&id, 0, sizeof(id));
+			id = empty_id;
 			id.kind = ID_IPV6_ADDR;
 			ugh = anyaddr(AF_INET6, &id.ip_addr);
 		    }
@@ -797,8 +790,11 @@
 		    }
 		    else
 		    {
-			struct id *i = clone_id(&id);
+			struct id_list *i = alloc_thing(struct id_list
+                           , "id_list");
 
+                       i->id = id;
+                       unshare_id_content(&i->id);
 			i->next = s->ids;
 			s->ids = i;
 			/* DBG_log("id type %d: %s %.*s", i->kind, ip_str(&i->ip_addr), (int)i->name.len, i->name.ptr); */
@@ -888,6 +884,7 @@
 	(void) shift();	/* prime tok */
 	(void) flushline("file starts with indentation (continuation notation)");
 	process_secret_records();
+	fclose(pos.fp);
     }
 
     sfp = pos.previous;	/* restore old state */
@@ -904,13 +901,14 @@
 
 	for (s = secrets; s != NULL; s = ns)
 	{
-	    struct id *i, *ni;
+	    struct id_list *i, *ni;
 
 	    ns = s->next;	/* grab before freeing s */
 	    for (i = s->ids; i != NULL; i = ni)
 	    {
 		ni = i->next;	/* grab before freeing i */
-		free_id(i);
+		free_id_content(&i->id);
+                pfree(i);
 	    }
 	    switch (s->kind)
 	    {
@@ -946,7 +944,7 @@
 /* public key machinery */
 
 struct pubkeyrec {
-    struct id *id;
+    struct id id;
     enum pubkey_alg alg;
     union {
 	struct RSA_public_key rsa;
@@ -963,7 +961,7 @@
 
     pubkeys = p->next;
 
-    free_id(p->id);
+    free_id_content(&p->id);
 
     /* algorithm-specific freeing */
     switch (p->alg)
@@ -1062,7 +1060,7 @@
 
     for (pp = &pubkeys; (p = *pp) != NULL; pp = &p->next)
     {
-	if (same_id(id, p->id) && p->alg == alg)
+	if (same_id(id, &p->id) && p->alg == alg)
 	{
 	    /* we have a winner: bring it to front, return key */
 
@@ -1137,7 +1135,9 @@
 	passert(FALSE);
     }
 
-    p->id = clone_id(id);
+    p->id = *id;
+    unshare_id_content(&p->id);
+
     p->alg = alg;
 
     /* just before installing, delete any previous key of this type
diff -bruN freeswan-1.9.orig/pluto/preshared.h freeswan-1.9/pluto/preshared.h
--- freeswan-1.9.orig/pluto/preshared.h	Fri Aug 18 01:20:18 2000
+++ freeswan-1.9/pluto/preshared.h	Wed May 16 10:57:20 2001
@@ -29,7 +29,7 @@
 
 enum PrivateKeyKind {
     PPK_PSK,
-    /* PPK_DSS, */	/* not implemented */
+    /* PPK_DSS,     Still unsupported */
     PPK_RSA
 };
 
diff -bruN freeswan-1.9.orig/pluto/rnd.c freeswan-1.9/pluto/rnd.c
--- freeswan-1.9.orig/pluto/rnd.c	Tue Jul 25 11:21:26 2000
+++ freeswan-1.9/pluto/rnd.c	Wed Jun  6 15:04:46 2001
@@ -12,7 +12,7 @@
  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  * for more details.
  *
- * RCSID $Id: rnd.c,v 1.13 2000/07/25 15:21:26 dhr Exp $
+ * RCSID $Id: rnd.c,v 1.15 2001/03/23 23:17:51 dhr Exp $
  */
 
 /* A true random number generator (we hope)
@@ -57,6 +57,8 @@
 #include <sys/time.h>
 #include <fcntl.h>
 
+#include <freeswan.h>
+
 #include "sha1.h"
 #include "constants.h"
 #include "defs.h"
@@ -104,6 +106,14 @@
 
 #else /* !USE_DEV_RANDOM */
 
+/* Generate (what we hope is) a true random byte using the clock skew trick.
+ * Note: this code is not maintained!  In particular, LINUX signal(2)
+ * semantics changed with glibc2 (and not for the better).  It isn't clear
+ * that this code will work.  We keep the code because someday it might
+ * come in handy.
+ */
+# error "This code is not maintained.  Please define USE_DEV_RANDOM."
+
 static volatile sig_atomic_t i, j, k;
 
 /* timer signal handler */
@@ -118,7 +128,6 @@
 	signal(SIGVTALRM, rnd_handler);
 }
 
-/* Generate (what we hope is) a true random byte using the clock skew trick */
 static u_char
 generate_rnd_byte(void)
 {
diff -bruN freeswan-1.9.orig/pluto/routing.txt freeswan-1.9/pluto/routing.txt
--- freeswan-1.9.orig/pluto/routing.txt	Wed Dec 31 19:00:00 1969
+++ freeswan-1.9/pluto/routing.txt	Mon Jun  4 13:00:38 2001
@@ -0,0 +1,331 @@
+Routing and Erouting in Pluto
+=============================
+
+RCSID $Id: routing.txt,v 1.3 2001/05/29 18:39:57 dhr Exp $
+
+This is meant as internal documentation for Pluto.  As such, it
+presumes some understanding of Pluto's code.
+
+It also describes KLIPS 1 erouting, including details not otherwise
+documented.  KLIPS 1 documentation would be better included in KLIPS.
+
+Routing and erouting are complicated enough that the Pluto code needs
+a guide.  This document is meant to be that guide.
+
+
+Mechanisms available to Pluto
+-----------------------------
+
+All outbound packets that are to be processed by KLIPS 1 must be
+routed to an ipsecN network interface.  Pluto only uses normal routing
+(as opposed to "Advanced Routing"), so the selection of packets is
+made solely on the basis of the destination address.  (Since the
+actual routing commands are in the updown script, they could be
+changed by the administrator, but Pluto needs to understand what is
+going on, and it currently assumes normal routing is used.)
+
+When an outbound packet hits an ipsecN interface, KLIPS figures out
+how to process it by finding an eroute that applies to the source and
+destination addresses.  Eroutes are global: they are not specific to a
+particular ipsecN interface (routing needs to get the packets to any
+ipsecN interface; erouting takes it from there, ignoring issues of
+source IP address and nexthop (because nobody knows!)).  If multiple
+eroutes apply to the packet, among the ones with the most specific
+source subnet, the one with the most specific destination subset is
+chosen (RGB thinks).  If no eroute is discovered, KLIPS acts as if it
+was covered by a DROP eroute (this is the default behaviour; it can be
+changed).  At most one eroute can exist for a particular pair of
+client subnets.
+
+There are fundamentally two kinds of eroutes: "shunt" eroutes and ones
+that specify that a packet is to be processed by a group of IPSEC SAs.
+Shunt eroutes specify what is to be done with the packet.  Remember
+that these only apply to outbound packets.
+
+- TRAP: notify Pluto of the packet (presumably to attempt to negotiate
+  an appropriate group of IPSEC SAs).  At the same time, KLIPS
+  installs a HOLD shunt (see below) for the specific source and
+  destination addresses from the packet and retains the packet
+  for later reprocessing (KLIPS does not yet implement retention).
+  Beware: if the TRAP's subnets both contained a single IP address
+  then installing the HOLD would actually delete the TRAP.
+
+- PASS: let the packet through in the clear
+
+- DROP: discard the packet
+
+- REJECT: discard the packet and notify the sender 
+
+- HOLD: (automatically created by KLIPS when a TRAP fires) block
+  the packet, but retain it.  If there is already a retained
+  packet, drop the old one and retain the new.  When the HOLD
+  shunt is deleted or replaced, the retained packet is reinjected --
+  there might now be a tunnel.  Note that KLIPS doesn't yet
+  implement the retention part, so HOLD is really like a DROP.
+
+One consequence of there being only one eroute for a pair of clients
+is that KLIPS will only use one SA group for output for this pair,
+even though there could be several SA groups that are authorised and
+live.  Pluto chooses to make this the youngest such group.
+  
+  
+
+KLIPS lets through in the clear outbound UDP/500 packets that would
+otherwise be processed if they originate on this host and meet certain
+other conditions.  The actual test is
+	source == me
+	&& (no_eroute || dest == eroute.dest || isanyaddr(eroute.dest))
+	&& port == UDP/500
+The idea is that IKE packets between us and a peer should not be
+sent through an IPSEC tunnel negotiated between us.  Furthermore,
+our shunt eroutes should not apply to our IKE packets (shunt eroutes
+will generally have an eroute.dest of 0.0.0.0 or its IPv6 equivalent).
+
+Inbound behaviour is controlled in a quite different way.  KLIPS
+processes only those inbound packets of ESP or AH protocol, with a
+destination address for this machine's ipsecN interfaces. The
+processing is as dictated by the SAs involved.  Unfortunately, the
+decapsulated packet's source and destination address are not checked
+(part of "inbound policy checking").
+
+To prevent clear packets being accepted, firewall rules must be put in
+place.  This has nothing to do with KLIPS, but is nonetheless in
+important part of security.  It isn't clear what firewalling makes
+sense when Opportunism is allowed.
+
+
+For routing and firewalling, Pluto invokes the updown script.  Pluto
+installs eroutes via extended PF_KEY messages.
+
+
+Current Pluto Behaviour
+-----------------------
+
+Data Structures:
+
+Routes and most eroutes are associated with connections (struct
+connection, a potential connection description).  The enum routing_t
+field "routing" in struct connection records the state of routing and
+erouting for that connection.  The values are:
+    RT_UNROUTED,	/* unrouted */
+    RT_UNROUTED_HOLD,	/* unrouted, but HOLD shunt installed */
+    RT_ROUTED_PROSPECTIVE,	/* routed, and TRAP shunt installed */
+    RT_ROUTED_HOLD,	/* routed, and HOLD shunt installed */
+    RT_ROUTED_FAILURE,	/* routed, and failure-context shunt installed */
+    RT_ROUTED_TUNNEL	/* routed, and erouted to an IPSEC SA group */
+Notice that the routing and erouting are not independent: erouting
+(except for HOLD) implies that the connection is routed.
+
+Several struct connections may have the same destination subnet.  If
+they agree on what the route should be, they can share it -- any of
+them may have routing >= RT_ROUTED_PROSPECTIVE.  If they disagree,
+they cannot simultaneously be routed.
+
+invariant: for all struct connections c, d:
+    (c.that.client == d.that.client
+	    && c.routing >= RT_ROUTED_PROSPECTIVE
+	    && d.routing >= RT_ROUTED_PROSPECTIVE)
+    => c.interface == d.interface && c.this.nexthop == d.this.nexthop
+
+There are two kinds of eroutes: shunt eroutes and ones for an IPSEC SA
+Group.  Most eroutes are associated with and are represeented in a
+connection.  The exception is that some HOLD and PASS shunts do not
+correspond to connections; those are represented in the bare_shunt
+table.
+
+An eroute for an IPSEC SA Group is associated with the state object
+for that Group.  The existence of such an eroute is also represented
+by the "so_serial_t eroute_owner" field in the struct connection.  The
+value is the serial number of the state object for the Group.  The
+special value SOS_NOBODY means that there is no owner associated with
+this connection for the eroute and hence no normal eroute.  At most
+one eroute owner may exist for a particular (source subnet,
+destination subnet) pair.  A Pluto-managed eroute cannot be associated
+with an RT_UNROUTED connection.
+
+invariant: for all struct connection c:
+    c.routing == RT_EROUTED_TUNNEL || c.eroute_owner == SOS_NOBODY
+
+invariant: for all struct connections c, d:
+    c.this.client == d.this.client && c.that.client == d.that.client
+        && &c != &d
+    => c.routing == RT_UNROUTED || d.routing == RT_UNROUTED
+
+If no normal eroute is set for a particular (source subnet,
+destination subnet) pair for which a connection is routed, then a
+shunt eroute would have been installed.  This specifies what should
+happen to packets snared by the route.
+
+When Pluto is notified by KLIPS of a packet that has been TRAPped,
+there is no connection with which to associate the HOLD.  It is
+temporarily held in the "bare_shunt table".  If Opportunism is
+attempted but DNS doesn't provide Security Gateway information, Pluto
+will replace the HOLD with a PASS shunt.  Since this PASS isn't
+associated with a connection, it too will reside in the bare_shunt
+table.  If the HOLD can be associated with a connection, it will be
+removed from the bare_shunt table and represented in the connection.
+
+There are two contexts for which shunt eroutes are installed by Pluto
+for a particular connection.  The first context is with the prospect
+of dealing with packets before any negotiation has been attempted.  I
+call this context "prospective".  Currently is a TRAP shunt, used to
+catch packets for initiate opportunistic negotiation.  In the future,
+it might also be used to implement preordained PASS, DROP, or REJECT
+rules.
+
+The second context is after a failed negotiation.  I call this context
+"failure".  At this point a different kind of shunt eroute is
+appropriate.  Depending on policy, it could be PASS, DROP, or REJECT,
+but it is unlikely to be TRAP.  The shunt eroute should have a
+lifetime (this isn't yet implemented).  When the lifetime expires, the
+failure shunt eroute should be replaced by the prospective shunt
+eroute.
+
+The kind and duration of a failure shunt eroute should perhaps depend
+on the nature of the failure, at least as imperfectly detected by
+Pluto.  We haven't looked at this.  In particular, the mapping from
+observations to robust respose isn't obvious.
+
+The shunt eroute policies should be a function of the potential
+connection.  The failure shunt eroute can be specified for a
+particular connection with the flags --pass and --drop in a connection
+definition.  There are four combinations, and each has a distinct
+meaning.  The failure shunt eroute is incompletely implemented and
+cannot be represented in /etc/ipsec.conf.
+
+There is as yet no control over the prospective shunt eroute: it is
+always TRAP as far as Pluto is concerned.  This is probably
+reasonable: any other fate suggests that no negotiation will be done,
+and so a connection definition is inappropriate.  These should be
+implemented as manual conns.  There remains the issue of whether Pluto
+should be aware of them -- currently it is not.
+
+
+Routines:
+
+[in kernel.c]
+
+bool do_command(struct connection *c, const char *verb)
+    Run the updown script to perform such tasks as installing a route
+    and adjust the firewall.
+
+bool could_route(struct connection *c)
+    Check to see whether we could route and eroute the connection.
+    <- shunt_eroute_connection (to check if --route can be performed)
+    <- install_inbound_ipsec_sa (to see if it will be possible
+       to (later) install route and eroute the corresponding outbound SA)
+    <- install_ipsec_sa (to see if the outbound SA can be routed and erouted)
+
+bool trap_connection(struct connection *c)
+    Install a TRAP shunt eroute for this connection.  This implements
+    "whack --route", the way an admin can specify that packets for a
+    connection should be caught without first bringing it up.
+
+void unroute_connection(struct connection *c)
+    Delete any eroute for a connection and unroute it if route isn't shared.
+    <- release_connection
+    <- whack_handle (for "whack --unroute)
+
+bool eroute_connection(struct connection *c
+, ipsec_spi_t spi, unsigned int proto, unsigned int satype
+, unsigned int op, const char *opname UNUSED)
+    Issue PF_KEY commands to KLIPS to add, replace, or delete an eroute.
+    The verb is specified by op and described (for logging) by opname.
+    <- assign_hold
+    <- sag_eroute
+    <- shunt_eroute
+    
+bool assign_hold(struct connection *c
+, const ip_address *src, const ip_address *dst)
+    Take a HOLD from the bare_shunt table and assign it to a connection.
+    If the HOLD is broadened (i.e. the connection's source or destination
+    subnets contain more than one IP address), this will involve replacing
+    the HOLD with a different one.
+
+bool sag_eroute(struct state *st, unsigned op, const char *opname)
+    SA Group eroute manipulation.  The SA Group concerned is
+    identified with a state object.
+    <- route_and_eroute several times
+
+bool shunt_eroute(struct connection *c, unsigned int op, const char *opname)
+    shunt eroute manipulation.  Shunt eroutes are associated with
+    connections.
+    <- unroute_connection
+    <- route_and_eroute
+    <- delete_ipsec_sa
+
+bool route_and_eroute(struct connection *c, struct state *st)
+    Install a route and then a prospective shunt eroute or an SA group
+    eroute.  The code assumes that could_route had previously
+    given the go-ahead.  Any SA group to be erouted must already
+    exist.
+    <- shunt_eroute_connection
+    <- install_ipsec_sa
+
+void scan_proc_shunts(void)
+    Every SHUNT_SCAN_INTERVAL scan /proc/net/ipsec_eroute.
+    Delete any PASS eroute in the bare_shunt table that hasn't been used
+    within the last SHUNT_PATIENCE seconds.
+    For any HOLD for which Pluto hasn't received an ACQUIRE (possibly
+    lost due to congestion), act as if an ACQUIRE were received.
+
+[in connection.c]
+
+struct connection *route_owner(struct connection *c, struct connection **erop)
+    Find the connection to connection c's peer's client with the
+    largest value of .routing.  All other things being equal,
+    preference is given to c.  Return NULL if no connection is routed
+    at all.  If erop is non-null, sets it to a connection sharing both
+    our client subnet and peer's client subnet with the largest value
+    of .routing.
+    The return value is used to find other connections sharing
+    a route.  The value of *erop is used to find other connections
+    sharing an eroute.
+    <- could_route (to find any conflicting routes or eroutes)
+    <- unroute_connection (to find out if our route is still in use
+       after this connection is finished with it)
+    <- install_inbound_ipsec_sa (to find other IPSEC SAs for the
+       same peer clients; when we find them WE KILL THEM; a
+       kludge to deal with road warriors reconnecting)
+    <- route_and_eroute (to find all the connections from which the
+       route or eroute is being stolen)
+
+Uses:
+
+- setting up route & shunt eroute to TRAP packets for opportunism
+  (whack --route).  Perhaps also manually designating DROP, REJECT, or
+  PASS for certain packets.
+
+  whack_handle() responds to --route; calls route_connection()
+  
+
+- removing same (whack --unroute)
+
+  whack_handle() responds to --unroute; calls unroute_connection()
+
+- installing route & normal eroute for a newly negotiated group of
+  outbound IPSEC SAs
+
+  + perhaps an (additional) route is not needed: if the negotiation
+    was initiated by a TRAPped outgoing packet, then there must
+    already have been a route that got the packet to ipsecN.  Mind
+    you, it could have been the wrong N!
+
+  install_ipsec_sa()
+
+- updating a normal eroute when a new group of IPSEC SAs replaces
+  an old one due to rekeying.
+
+  install_ipsec_sa()
+
+- replacing an old eroute when a negotiation fails.  But this is
+  tricky.  If this was a rekeying, we should just leave the old
+  normal eroute be -- it might still work.  Otherwise, this was
+  an initial negotiation: we should replace the shunt eroute
+  with one appropriate for the failure context.
+
+- when a group of IPSEC SAs dies or is killed, and it had the eroute,
+  its normal eroute should be replaced by a shunt eroute.  If there
+  was an attempt to replace the group, the replacement is in the
+  failure context; otherwise the replacement is in the prospective
+  context.
diff -bruN freeswan-1.9.orig/pluto/server.c freeswan-1.9/pluto/server.c
--- freeswan-1.9.orig/pluto/server.c	Tue Jan 23 18:09:31 2001
+++ freeswan-1.9/pluto/server.c	Wed Jun  6 15:20:02 2001
@@ -12,7 +12,7 @@
  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  * for more details.
  *
- * RCSID $Id: server.c,v 1.55 2001/01/23 23:09:31 dhr Exp $
+ * RCSID $Id: server.c,v 1.60 2001/04/07 18:22:18 dhr Exp $
  */
 
 #include <stdio.h>
@@ -53,7 +53,6 @@
 #include "kernel_comm.h"
 #include "whack.h"	/* for RC_LOG_SERIOUS */
 
-#include <signal.h>
 #include <pfkeyv2.h>
 #include <pfkey.h>
 
@@ -116,6 +115,73 @@
 
 /* Initialize the interface sockets. */
 
+static void
+mark_ifaces_dead(void)
+{
+    struct iface *p;
+
+    for (p = interfaces; p != NULL; p = p->next)
+       p->change = IFN_DELETE;
+}
+
+static void
+free_dead_ifaces(void)
+{
+    struct iface *p;
+    bool some_dead = FALSE
+       , some_new = FALSE;
+
+    for (p = interfaces; p != NULL; p = p->next)
+    {
+       if (p->change == IFN_DELETE)
+       {
+           log("shutting down interface %s/%s %s"
+               , p->vname, p->rname, ip_str(&p->addr));
+           some_dead = TRUE;
+       }
+       else if (p->change == IFN_ADD)
+       {
+           some_new = TRUE;
+       }
+    }
+
+    if (some_dead)
+    {
+       struct iface **pp;
+
+       release_dead_interfaces();
+       for (pp = &interfaces; (p = *pp) != NULL; )
+       {
+           if (p->change == IFN_DELETE)
+           {
+               *pp = p->next;  /* advance *pp */
+               pfree(p->vname);
+               pfree(p->rname);
+               close(p->fd);
+               pfree(p);
+           }
+           else
+           {
+               pp = &p->next;  /* advance pp */
+           }
+       }
+    }
+
+    /* this must be done after the release_dead_interfaces
+     * in case some to the newly unoriented connections can
+     * become oriented here.
+     */
+    if (some_dead || some_new)
+       check_orientations();
+}
+
+void
+free_ifaces(void)
+{
+    mark_ifaces_dead();
+    free_dead_ifaces();
+}
+
 struct raw_iface {
     ip_address addr;
     char name[IFNAMSIZ + 20];	/* what would be a safe size? */
@@ -133,12 +199,9 @@
     struct ifconf ifconf;
     struct ifreq buf[300];	/* for list of interfaces -- arbitrary limit */
     struct raw_iface *rifaces = NULL;
+    int master_sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);    /* Get a UDP socket */
 
     /* get list of interfaces with assigned IPv4 addresses from system */
-    {
-	/* Get a UDP socket */
-	int master_sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
-	ip_address any;
 
 	if (master_sock == -1)
 	    exit_log_errno((e, "socket() failed in find_raw_ifaces4()"));
@@ -148,28 +211,30 @@
 	    exit_log_errno((e, "setsockopt() in find_raw_ifaces4()"));
 
 	/* bind the socket */
+    {
+       ip_address any;
+
 	(void)anyaddr(AF_INET, &any);
 	setportof(htons(pluto_port), &any);
 	if (bind(master_sock, sockaddrof(&any), sockaddrlenof(&any)) < 0)
 	    exit_log_errno((e, "bind() failed in find_raw_ifaces4()"));
+    }
 
-	/* Get local interfaces */
+    /* Get local interfaces.  See netdevice(7). */
 	ifconf.ifc_len = sizeof(buf);
 	ifconf.ifc_buf = (void *) buf;
-	memset(buf, '\0', sizeof(buf));
+    zero(buf);
 
 	if (ioctl(master_sock, SIOCGIFCONF, &ifconf) == -1)
 	    exit_log_errno((e, "ioctl(SIOCGIFCONF) in find_raw_ifaces4()"));
 
-	close(master_sock);
-    }
-
     /* Add an entry to rifaces for each interesting interface. */
     for (j = 0; (j+1) * sizeof(*buf) <= (size_t)ifconf.ifc_len; j++)
     {
 	struct raw_iface ri;
 	const struct sockaddr_in *rs = (struct sockaddr_in *) &buf[j].ifr_addr;
 	err_t ugh;
+	struct ifreq auxinfo;
 
 	/* ignore all but AF_INET interfaces */
 	if (rs->sin_family != AF_INET)
@@ -179,6 +244,16 @@
 	memcpy(ri.name, buf[j].ifr_name, IFNAMSIZ);
 	ri.name[IFNAMSIZ] = '\0';
 
+       /* Find out stuff about this interface.  See netdevice(7). */
+       zero(&auxinfo); /* paranoia */
+       memcpy(auxinfo.ifr_name, buf[j].ifr_name, IFNAMSIZ);
+       if (ioctl(master_sock, SIOCGIFFLAGS, &auxinfo) == -1)
+           exit_log_errno((e
+               , "ioctl(SIOCGIFFLAGS) for %s in find_raw_ifaces4()"
+               , ri.name));
+       if (!(auxinfo.ifr_flags & IFF_UP))
+           continue;   /* ignore an interface that isn't UP */
+
 	/* ignore unconfigured interfaces */
 	if (rs->sin_addr.s_addr == 0)
 	    continue;
@@ -193,6 +268,8 @@
 	rifaces = clone_thing(ri, "struct raw_iface");
     }
 
+    close(master_sock);
+
     return rifaces;
 }
 
@@ -244,9 +321,7 @@
 		, "%4hx%4hx%4hx%4hx%4hx%4hx%4hx%4hx"
 		  " %02x %02x %02x %02x %20s\n"
 		, xb+0, xb+1, xb+2, xb+3, xb+4, xb+5, xb+6, xb+7
-		, &if_idx, &plen
-		, &scope, &dad_status
-		, ri.name);
+		, &if_idx, &plen, &scope, &dad_status, ri.name);
 	    err_t ugh;
 
 	    /* ??? we should diagnose any problems */
@@ -275,10 +350,9 @@
     return rifaces;
 }
 
-static struct iface *
-process_raw_ifaces(struct iface *new_ifaces_tail, struct raw_iface *rifaces)
+static void
+process_raw_ifaces(struct raw_iface *rifaces)
 {
-    struct iface *new_ifaces = new_ifaces_tail;
     struct raw_iface *ifp;
 
     /* Find all virtual/real interface pairs.
@@ -430,8 +504,9 @@
 		    q->vname = clone_str(v->name, "virtual device name");
 		    q->addr = ifp->addr;
 		    q->fd = fd;
-		    q->next = new_ifaces;
-		    new_ifaces = q;
+                   q->next = interfaces;
+                   q->change = IFN_ADD;
+                   interfaces = q;
 		    log("adding interface %s/%s %s"
 			, q->vname, q->rname, ip_str(&q->addr));
 		    break;
@@ -442,10 +517,8 @@
 		&& streq(q->vname, v->name)
 		&& sameaddr(&q->addr, &ifp->addr))
 		{
-		    /* matches -- steal old entry */
-		    *p = q->next;
-		    q->next = new_ifaces;
-		    new_ifaces = q;
+                   /* matches -- rejuvinate old entry */
+                   q->change = IFN_KEEP;
 		    break;
 		}
 
@@ -463,42 +536,29 @@
 	rifaces = t->next;
 	pfree(t);
     }
-
-    return new_ifaces;
 }
 
 void
 find_ifaces(void)
 {
-    struct iface *new_ifaces = NULL;
+    mark_ifaces_dead();
+    process_raw_ifaces(find_raw_ifaces4());
+    process_raw_ifaces(find_raw_ifaces6());
 
-    new_ifaces = process_raw_ifaces(new_ifaces, find_raw_ifaces4());
-    new_ifaces = process_raw_ifaces(new_ifaces, find_raw_ifaces6());
+    free_dead_ifaces();            /* ditch remaining old entries */
 
-    free_ifaces();	    /* ditch remaining old entries */
-    interfaces = new_ifaces;
     if (interfaces == NULL)
 	loglog(RC_LOG_SERIOUS, "no public interfaces found");
 }
 
 void
-free_ifaces(void)
+show_ifaces_status(void)
 {
-    struct iface *p = interfaces;
-
-    while (p != NULL)
-    {
-	struct iface *q = p->next;
+    struct iface *p;
 
-	log("shutting down interface %s/%s %s"
+    for (p = interfaces; p != NULL; p = p->next)
+       whack_log(RC_COMMENT, "interface %s/%s %s"
 	    , p->vname, p->rname, ip_str(&p->addr));
-	release_interface(p);
-	pfree(p->vname);
-	pfree(p->rname);
-	close(p->fd);
-	pfree(p);
-	p = q;
-    }
 }
 
 static volatile sig_atomic_t hupflag = FALSE;
@@ -507,7 +567,6 @@
 huphandler(int sig UNUSED)
 {
     hupflag = TRUE;
-    (void)signal(SIGHUP, &huphandler);
 }
 
 /* call_server listens for incoming ISAKMP packets and Whack messages,
@@ -521,7 +580,16 @@
 
 
     /* dumb folks think poking any daemon with SIGHUP is polite */
-    (void)signal(SIGHUP, &huphandler);
+    {
+       int r;
+       struct sigaction act;
+
+       act.sa_handler = &huphandler;
+       sigemptyset(&act.sa_mask);
+       act.sa_flags = 0;       /* no SA_ONESHOT, no SA_RESTART, no nothing */
+       r = sigaction(SIGHUP, &act, NULL);
+       passert(r == 0);
+    }
 
     for (;;)
     {
diff -bruN freeswan-1.9.orig/pluto/server.h freeswan-1.9/pluto/server.h
--- freeswan-1.9.orig/pluto/server.h	Tue Jan 23 18:09:31 2001
+++ freeswan-1.9/pluto/server.h	Wed Jun  6 15:22:38 2001
@@ -11,7 +11,7 @@
  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  * for more details.
  *
- * RCSID $Id: server.h,v 1.13 2001/01/23 23:09:31 dhr Exp $
+ * RCSID $Id: server.h,v 1.15 2001/04/06 20:30:08 dhr Exp $
  */
 
 extern struct sockaddr_un ctl_addr;	/* address of control (whack) socket */
@@ -34,10 +34,12 @@
     ip_address addr;	/* interface IP address */
     int fd;	/* file descriptor of socket for IKE UDP messages */
     struct iface *next;
+    enum { IFN_ADD, IFN_KEEP, IFN_DELETE } change;
 };
 
 extern struct iface *interfaces;	/* public interfaces */
 
 extern void find_ifaces(void);
+extern void show_ifaces_status(void);
 extern void free_ifaces(void);
 extern void call_server(void);
diff -bruN freeswan-1.9.orig/pluto/spdb.c freeswan-1.9/pluto/spdb.c
--- freeswan-1.9.orig/pluto/spdb.c	Mon Feb 26 13:42:57 2001
+++ freeswan-1.9/pluto/spdb.c	Thu Jun  7 14:33:57 2001
@@ -11,7 +11,7 @@
  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  * for more details.
  *
- * RCSID $Id: spdb.c,v 1.63.2.1 2001/02/26 18:42:57 henry Exp $
+ * RCSID $Id: spdb.c,v 1.69 2001/04/09 19:48:43 dhr Exp $
  */
 
 #include <stdio.h>
@@ -39,6 +39,11 @@
 #include "md5.h"
 #include "crypto.h" /* requires sha1.h and md5.h */
 
+#ifdef OPENSSL
+#include "demux.h"
+#include "openssl.h"
+#endif
+
 #define AD(x) x, elemsof(x)	/* Array Description */
 #define AD_NULL NULL, 0
 
@@ -46,6 +51,12 @@
 
 /* arrays of attributes for transforms, preshared key */
 
+static struct db_attr otpsk1024desmd5[] = {
+	{ OAKLEY_ENCRYPTION_ALGORITHM, OAKLEY_DES_CBC },
+	{ OAKLEY_HASH_ALGORITHM, OAKLEY_MD5 },
+	{ OAKLEY_AUTHENTICATION_METHOD, OAKLEY_PRESHARED_KEY },
+	{ OAKLEY_GROUP_DESCRIPTION, OAKLEY_GROUP_MODP1024 },
+	};
 static struct db_attr otpsk1024des3md5[] = {
 	{ OAKLEY_ENCRYPTION_ALGORITHM, OAKLEY_3DES_CBC },
 	{ OAKLEY_HASH_ALGORITHM, OAKLEY_MD5 },
@@ -53,6 +64,12 @@
 	{ OAKLEY_GROUP_DESCRIPTION, OAKLEY_GROUP_MODP1024 },
 	};
 
+static struct db_attr otpsk1536desmd5[] = {
+	{ OAKLEY_ENCRYPTION_ALGORITHM, OAKLEY_DES_CBC },
+	{ OAKLEY_HASH_ALGORITHM, OAKLEY_MD5 },
+	{ OAKLEY_AUTHENTICATION_METHOD, OAKLEY_PRESHARED_KEY },
+	{ OAKLEY_GROUP_DESCRIPTION, OAKLEY_GROUP_MODP1536 },
+	};
 static struct db_attr otpsk1536des3md5[] = {
 	{ OAKLEY_ENCRYPTION_ALGORITHM, OAKLEY_3DES_CBC },
 	{ OAKLEY_HASH_ALGORITHM, OAKLEY_MD5 },
@@ -60,6 +77,12 @@
 	{ OAKLEY_GROUP_DESCRIPTION, OAKLEY_GROUP_MODP1536 },
 	};
 
+static struct db_attr otpsk1024dessha[] = {
+	{ OAKLEY_ENCRYPTION_ALGORITHM, OAKLEY_DES_CBC },
+	{ OAKLEY_HASH_ALGORITHM, OAKLEY_SHA },
+	{ OAKLEY_AUTHENTICATION_METHOD, OAKLEY_PRESHARED_KEY },
+	{ OAKLEY_GROUP_DESCRIPTION, OAKLEY_GROUP_MODP1024 },
+	};
 static struct db_attr otpsk1024des3sha[] = {
 	{ OAKLEY_ENCRYPTION_ALGORITHM, OAKLEY_3DES_CBC },
 	{ OAKLEY_HASH_ALGORITHM, OAKLEY_SHA },
@@ -67,6 +90,12 @@
 	{ OAKLEY_GROUP_DESCRIPTION, OAKLEY_GROUP_MODP1024 },
 	};
 
+static struct db_attr otpsk1536dessha[] = {
+	{ OAKLEY_ENCRYPTION_ALGORITHM, OAKLEY_DES_CBC },
+	{ OAKLEY_HASH_ALGORITHM, OAKLEY_SHA },
+	{ OAKLEY_AUTHENTICATION_METHOD, OAKLEY_PRESHARED_KEY },
+	{ OAKLEY_GROUP_DESCRIPTION, OAKLEY_GROUP_MODP1536 },
+	};
 static struct db_attr otpsk1536des3sha[] = {
 	{ OAKLEY_ENCRYPTION_ALGORITHM, OAKLEY_3DES_CBC },
 	{ OAKLEY_HASH_ALGORITHM, OAKLEY_SHA },
@@ -76,6 +105,12 @@
 
 /* arrays of attributes for transforms, RSA signatures */
 
+static struct db_attr otrsasig1024desmd5[] = {
+	{ OAKLEY_ENCRYPTION_ALGORITHM, OAKLEY_DES_CBC },
+	{ OAKLEY_HASH_ALGORITHM, OAKLEY_MD5 },
+	{ OAKLEY_AUTHENTICATION_METHOD, OAKLEY_RSA_SIG },
+	{ OAKLEY_GROUP_DESCRIPTION, OAKLEY_GROUP_MODP1024 },
+	};
 static struct db_attr otrsasig1024des3md5[] = {
 	{ OAKLEY_ENCRYPTION_ALGORITHM, OAKLEY_3DES_CBC },
 	{ OAKLEY_HASH_ALGORITHM, OAKLEY_MD5 },
@@ -83,6 +118,12 @@
 	{ OAKLEY_GROUP_DESCRIPTION, OAKLEY_GROUP_MODP1024 },
 	};
 
+static struct db_attr otrsasig1536desmd5[] = {
+	{ OAKLEY_ENCRYPTION_ALGORITHM, OAKLEY_DES_CBC },
+	{ OAKLEY_HASH_ALGORITHM, OAKLEY_MD5 },
+	{ OAKLEY_AUTHENTICATION_METHOD, OAKLEY_RSA_SIG },
+	{ OAKLEY_GROUP_DESCRIPTION, OAKLEY_GROUP_MODP1536 },
+	};
 static struct db_attr otrsasig1536des3md5[] = {
 	{ OAKLEY_ENCRYPTION_ALGORITHM, OAKLEY_3DES_CBC },
 	{ OAKLEY_HASH_ALGORITHM, OAKLEY_MD5 },
@@ -90,6 +131,12 @@
 	{ OAKLEY_GROUP_DESCRIPTION, OAKLEY_GROUP_MODP1536 },
 	};
 
+static struct db_attr otrsasig1024dessha[] = {
+	{ OAKLEY_ENCRYPTION_ALGORITHM, OAKLEY_DES_CBC },
+	{ OAKLEY_HASH_ALGORITHM, OAKLEY_SHA },
+	{ OAKLEY_AUTHENTICATION_METHOD, OAKLEY_RSA_SIG },
+	{ OAKLEY_GROUP_DESCRIPTION, OAKLEY_GROUP_MODP1024 },
+	};
 static struct db_attr otrsasig1024des3sha[] = {
 	{ OAKLEY_ENCRYPTION_ALGORITHM, OAKLEY_3DES_CBC },
 	{ OAKLEY_HASH_ALGORITHM, OAKLEY_SHA },
@@ -97,6 +144,12 @@
 	{ OAKLEY_GROUP_DESCRIPTION, OAKLEY_GROUP_MODP1024 },
 	};
 
+static struct db_attr otrsasig1536dessha[] = {
+	{ OAKLEY_ENCRYPTION_ALGORITHM, OAKLEY_DES_CBC },
+	{ OAKLEY_HASH_ALGORITHM, OAKLEY_SHA },
+	{ OAKLEY_AUTHENTICATION_METHOD, OAKLEY_RSA_SIG },
+	{ OAKLEY_GROUP_DESCRIPTION, OAKLEY_GROUP_MODP1536 },
+	};
 static struct db_attr otrsasig1536des3sha[] = {
 	{ OAKLEY_ENCRYPTION_ALGORITHM, OAKLEY_3DES_CBC },
 	{ OAKLEY_HASH_ALGORITHM, OAKLEY_SHA },
@@ -104,11 +157,305 @@
 	{ OAKLEY_GROUP_DESCRIPTION, OAKLEY_GROUP_MODP1536 },
 	};
 
+#ifdef OPENSSL /* OPENSSL */
+static struct db_attr ot1024desmd5_ds_rsa[] = {
+	{ OAKLEY_ENCRYPTION_ALGORITHM, OAKLEY_DES_CBC },
+	{ OAKLEY_HASH_ALGORITHM, OAKLEY_MD5 },
+	{ OAKLEY_AUTHENTICATION_METHOD, OAKLEY_RSA_SIG },
+	{ OAKLEY_GROUP_DESCRIPTION, OAKLEY_GROUP_MODP1024 },
+	};
+static struct db_attr ot1024des3md5_ds_rsa[] = {
+	{ OAKLEY_ENCRYPTION_ALGORITHM, OAKLEY_3DES_CBC },
+	{ OAKLEY_HASH_ALGORITHM, OAKLEY_MD5 },
+	{ OAKLEY_AUTHENTICATION_METHOD, OAKLEY_RSA_SIG },
+	{ OAKLEY_GROUP_DESCRIPTION, OAKLEY_GROUP_MODP1024 },
+	};
+
+static struct db_attr ot1024dessha_ds_rsa[] = {
+	{ OAKLEY_ENCRYPTION_ALGORITHM, OAKLEY_DES_CBC },
+	{ OAKLEY_HASH_ALGORITHM, OAKLEY_SHA },
+	{ OAKLEY_AUTHENTICATION_METHOD, OAKLEY_RSA_SIG },
+	{ OAKLEY_GROUP_DESCRIPTION, OAKLEY_GROUP_MODP1024 },
+	};
+static struct db_attr ot1024des3sha_ds_rsa[] = {
+	{ OAKLEY_ENCRYPTION_ALGORITHM, OAKLEY_3DES_CBC },
+	{ OAKLEY_HASH_ALGORITHM, OAKLEY_SHA },
+	{ OAKLEY_AUTHENTICATION_METHOD, OAKLEY_RSA_SIG },
+	{ OAKLEY_GROUP_DESCRIPTION, OAKLEY_GROUP_MODP1024 },
+	};
+
+static struct db_attr ot1024dessha_ds_dss[] = {
+	{ OAKLEY_ENCRYPTION_ALGORITHM, OAKLEY_DES_CBC },
+	{ OAKLEY_HASH_ALGORITHM, OAKLEY_SHA },
+	{ OAKLEY_AUTHENTICATION_METHOD, OAKLEY_DSS_SIG },
+	{ OAKLEY_GROUP_DESCRIPTION, OAKLEY_GROUP_MODP1024 },
+	};
+static struct db_attr ot1024des3sha_ds_dss[] = {
+	{ OAKLEY_ENCRYPTION_ALGORITHM, OAKLEY_3DES_CBC },
+	{ OAKLEY_HASH_ALGORITHM, OAKLEY_SHA },
+	{ OAKLEY_AUTHENTICATION_METHOD, OAKLEY_DSS_SIG },
+	{ OAKLEY_GROUP_DESCRIPTION, OAKLEY_GROUP_MODP1024 },
+	};
+
+static struct db_attr ot1024desmd5_pk_rsa[] = {
+	{ OAKLEY_ENCRYPTION_ALGORITHM, OAKLEY_DES_CBC },
+	{ OAKLEY_HASH_ALGORITHM, OAKLEY_MD5 },
+	{ OAKLEY_AUTHENTICATION_METHOD, OAKLEY_RSA_ENC },
+	{ OAKLEY_GROUP_DESCRIPTION, OAKLEY_GROUP_MODP1024 },
+	};
+static struct db_attr ot1024des3md5_pk_rsa[] = {
+	{ OAKLEY_ENCRYPTION_ALGORITHM, OAKLEY_3DES_CBC },
+	{ OAKLEY_HASH_ALGORITHM, OAKLEY_MD5 },
+	{ OAKLEY_AUTHENTICATION_METHOD, OAKLEY_RSA_ENC },
+	{ OAKLEY_GROUP_DESCRIPTION, OAKLEY_GROUP_MODP1024 },
+	};
+
+static struct db_attr ot1024dessha_pk_rsa[] = {
+	{ OAKLEY_ENCRYPTION_ALGORITHM, OAKLEY_DES_CBC },
+	{ OAKLEY_HASH_ALGORITHM, OAKLEY_SHA },
+	{ OAKLEY_AUTHENTICATION_METHOD, OAKLEY_RSA_ENC },
+	{ OAKLEY_GROUP_DESCRIPTION, OAKLEY_GROUP_MODP1024 },
+	};
+static struct db_attr ot1024des3sha_pk_rsa[] = {
+	{ OAKLEY_ENCRYPTION_ALGORITHM, OAKLEY_3DES_CBC },
+	{ OAKLEY_HASH_ALGORITHM, OAKLEY_SHA },
+	{ OAKLEY_AUTHENTICATION_METHOD, OAKLEY_RSA_ENC },
+	{ OAKLEY_GROUP_DESCRIPTION, OAKLEY_GROUP_MODP1024 },
+	};
+
+static struct db_attr ot1024dessha_pk_elgamal[] = {
+	{ OAKLEY_ENCRYPTION_ALGORITHM, OAKLEY_DES_CBC },
+	{ OAKLEY_HASH_ALGORITHM, OAKLEY_SHA },
+	{ OAKLEY_AUTHENTICATION_METHOD, OAKLEY_ELGAMAL_ENC },
+	{ OAKLEY_GROUP_DESCRIPTION, OAKLEY_GROUP_MODP1024 },
+	};
+static struct db_attr ot1024des3sha_pk_elgamal[] = {
+	{ OAKLEY_ENCRYPTION_ALGORITHM, OAKLEY_3DES_CBC },
+	{ OAKLEY_HASH_ALGORITHM, OAKLEY_SHA },
+	{ OAKLEY_AUTHENTICATION_METHOD, OAKLEY_ELGAMAL_ENC },
+	{ OAKLEY_GROUP_DESCRIPTION, OAKLEY_GROUP_MODP1024 },
+	};
+
+static struct db_attr ot1024desmd5_pk_elgamal[] = {
+	{ OAKLEY_ENCRYPTION_ALGORITHM, OAKLEY_DES_CBC },
+	{ OAKLEY_HASH_ALGORITHM, OAKLEY_MD5 },
+	{ OAKLEY_AUTHENTICATION_METHOD, OAKLEY_ELGAMAL_ENC },
+	{ OAKLEY_GROUP_DESCRIPTION, OAKLEY_GROUP_MODP1024 },
+	};
+static struct db_attr ot1024des3md5_pk_elgamal[] = {
+	{ OAKLEY_ENCRYPTION_ALGORITHM, OAKLEY_3DES_CBC },
+	{ OAKLEY_HASH_ALGORITHM, OAKLEY_MD5 },
+	{ OAKLEY_AUTHENTICATION_METHOD, OAKLEY_ELGAMAL_ENC },
+	{ OAKLEY_GROUP_DESCRIPTION, OAKLEY_GROUP_MODP1024 },
+	};
+
+static struct db_attr ot1024desmd5_rpk_rsa[] = {
+	{ OAKLEY_ENCRYPTION_ALGORITHM, OAKLEY_DES_CBC },
+	{ OAKLEY_HASH_ALGORITHM, OAKLEY_MD5 },
+	{ OAKLEY_AUTHENTICATION_METHOD, OAKLEY_RSA_ENC_REV },
+	{ OAKLEY_GROUP_DESCRIPTION, OAKLEY_GROUP_MODP1024 },
+	};
+static struct db_attr ot1024des3md5_rpk_rsa[] = {
+	{ OAKLEY_ENCRYPTION_ALGORITHM, OAKLEY_3DES_CBC },
+	{ OAKLEY_HASH_ALGORITHM, OAKLEY_MD5 },
+	{ OAKLEY_AUTHENTICATION_METHOD, OAKLEY_RSA_ENC_REV },
+	{ OAKLEY_GROUP_DESCRIPTION, OAKLEY_GROUP_MODP1024 },
+	};
+
+static struct db_attr ot1024dessha_rpk_rsa[] = {
+	{ OAKLEY_ENCRYPTION_ALGORITHM, OAKLEY_DES_CBC },
+	{ OAKLEY_HASH_ALGORITHM, OAKLEY_SHA },
+	{ OAKLEY_AUTHENTICATION_METHOD, OAKLEY_RSA_ENC_REV },
+	{ OAKLEY_GROUP_DESCRIPTION, OAKLEY_GROUP_MODP1024 },
+	};
+static struct db_attr ot1024des3sha_rpk_rsa[] = {
+	{ OAKLEY_ENCRYPTION_ALGORITHM, OAKLEY_3DES_CBC },
+	{ OAKLEY_HASH_ALGORITHM, OAKLEY_SHA },
+	{ OAKLEY_AUTHENTICATION_METHOD, OAKLEY_RSA_ENC_REV },
+	{ OAKLEY_GROUP_DESCRIPTION, OAKLEY_GROUP_MODP1024 },
+	};
+
+static struct db_attr ot1024dessha_rpk_elgamal[] = {
+	{ OAKLEY_ENCRYPTION_ALGORITHM, OAKLEY_DES_CBC },
+	{ OAKLEY_HASH_ALGORITHM, OAKLEY_SHA },
+	{ OAKLEY_AUTHENTICATION_METHOD, OAKLEY_ELGAMAL_ENC_REV },
+	{ OAKLEY_GROUP_DESCRIPTION, OAKLEY_GROUP_MODP1024 },
+	};
+static struct db_attr ot1024des3sha_rpk_elgamal[] = {
+	{ OAKLEY_ENCRYPTION_ALGORITHM, OAKLEY_3DES_CBC },
+	{ OAKLEY_HASH_ALGORITHM, OAKLEY_SHA },
+	{ OAKLEY_AUTHENTICATION_METHOD, OAKLEY_ELGAMAL_ENC_REV },
+	{ OAKLEY_GROUP_DESCRIPTION, OAKLEY_GROUP_MODP1024 },
+	};
+
+static struct db_attr ot1024desmd5_rpk_elgamal[] = {
+	{ OAKLEY_ENCRYPTION_ALGORITHM, OAKLEY_DES_CBC },
+	{ OAKLEY_HASH_ALGORITHM, OAKLEY_MD5 },
+	{ OAKLEY_AUTHENTICATION_METHOD, OAKLEY_ELGAMAL_ENC_REV },
+	{ OAKLEY_GROUP_DESCRIPTION, OAKLEY_GROUP_MODP1024 },
+	};
+static struct db_attr ot1024des3md5_rpk_elgamal[] = {
+	{ OAKLEY_ENCRYPTION_ALGORITHM, OAKLEY_3DES_CBC },
+	{ OAKLEY_HASH_ALGORITHM, OAKLEY_MD5 },
+	{ OAKLEY_AUTHENTICATION_METHOD, OAKLEY_ELGAMAL_ENC_REV },
+	{ OAKLEY_GROUP_DESCRIPTION, OAKLEY_GROUP_MODP1024 },
+	};
+
+static struct db_attr ot1536desmd5_ds_rsa[] = {
+	{ OAKLEY_ENCRYPTION_ALGORITHM, OAKLEY_DES_CBC },
+	{ OAKLEY_HASH_ALGORITHM, OAKLEY_MD5 },
+	{ OAKLEY_AUTHENTICATION_METHOD, OAKLEY_RSA_SIG },
+	{ OAKLEY_GROUP_DESCRIPTION, OAKLEY_GROUP_MODP1536 },
+	};
+static struct db_attr ot1536des3md5_ds_rsa[] = {
+	{ OAKLEY_ENCRYPTION_ALGORITHM, OAKLEY_3DES_CBC },
+	{ OAKLEY_HASH_ALGORITHM, OAKLEY_MD5 },
+	{ OAKLEY_AUTHENTICATION_METHOD, OAKLEY_RSA_SIG },
+	{ OAKLEY_GROUP_DESCRIPTION, OAKLEY_GROUP_MODP1536 },
+	};
+
+static struct db_attr ot1536dessha_ds_rsa[] = {
+	{ OAKLEY_ENCRYPTION_ALGORITHM, OAKLEY_DES_CBC },
+	{ OAKLEY_HASH_ALGORITHM, OAKLEY_SHA },
+	{ OAKLEY_AUTHENTICATION_METHOD, OAKLEY_RSA_SIG },
+	{ OAKLEY_GROUP_DESCRIPTION, OAKLEY_GROUP_MODP1536 },
+	};
+static struct db_attr ot1536des3sha_ds_rsa[] = {
+	{ OAKLEY_ENCRYPTION_ALGORITHM, OAKLEY_3DES_CBC },
+	{ OAKLEY_HASH_ALGORITHM, OAKLEY_SHA },
+	{ OAKLEY_AUTHENTICATION_METHOD, OAKLEY_RSA_SIG },
+	{ OAKLEY_GROUP_DESCRIPTION, OAKLEY_GROUP_MODP1536 },
+	};
+
+static struct db_attr ot1536dessha_ds_dss[] = {
+	{ OAKLEY_ENCRYPTION_ALGORITHM, OAKLEY_DES_CBC },
+	{ OAKLEY_HASH_ALGORITHM, OAKLEY_SHA },
+	{ OAKLEY_AUTHENTICATION_METHOD, OAKLEY_DSS_SIG },
+	{ OAKLEY_GROUP_DESCRIPTION, OAKLEY_GROUP_MODP1536 },
+	};
+static struct db_attr ot1536des3sha_ds_dss[] = {
+	{ OAKLEY_ENCRYPTION_ALGORITHM, OAKLEY_3DES_CBC },
+	{ OAKLEY_HASH_ALGORITHM, OAKLEY_SHA },
+	{ OAKLEY_AUTHENTICATION_METHOD, OAKLEY_DSS_SIG },
+	{ OAKLEY_GROUP_DESCRIPTION, OAKLEY_GROUP_MODP1536 },
+	};
+
+static struct db_attr ot1536desmd5_pk_rsa[] = {
+	{ OAKLEY_ENCRYPTION_ALGORITHM, OAKLEY_DES_CBC },
+	{ OAKLEY_HASH_ALGORITHM, OAKLEY_MD5 },
+	{ OAKLEY_AUTHENTICATION_METHOD, OAKLEY_RSA_ENC },
+	{ OAKLEY_GROUP_DESCRIPTION, OAKLEY_GROUP_MODP1536 },
+	};
+static struct db_attr ot1536des3md5_pk_rsa[] = {
+	{ OAKLEY_ENCRYPTION_ALGORITHM, OAKLEY_3DES_CBC },
+	{ OAKLEY_HASH_ALGORITHM, OAKLEY_MD5 },
+	{ OAKLEY_AUTHENTICATION_METHOD, OAKLEY_RSA_ENC },
+	{ OAKLEY_GROUP_DESCRIPTION, OAKLEY_GROUP_MODP1536 },
+	};
+
+static struct db_attr ot1536dessha_pk_rsa[] = {
+	{ OAKLEY_ENCRYPTION_ALGORITHM, OAKLEY_DES_CBC },
+	{ OAKLEY_HASH_ALGORITHM, OAKLEY_SHA },
+	{ OAKLEY_AUTHENTICATION_METHOD, OAKLEY_RSA_ENC },
+	{ OAKLEY_GROUP_DESCRIPTION, OAKLEY_GROUP_MODP1536 },
+	};
+static struct db_attr ot1536des3sha_pk_rsa[] = {
+	{ OAKLEY_ENCRYPTION_ALGORITHM, OAKLEY_3DES_CBC },
+	{ OAKLEY_HASH_ALGORITHM, OAKLEY_SHA },
+	{ OAKLEY_AUTHENTICATION_METHOD, OAKLEY_RSA_ENC },
+	{ OAKLEY_GROUP_DESCRIPTION, OAKLEY_GROUP_MODP1536 },
+	};
+
+static struct db_attr ot1536dessha_pk_elgamal[] = {
+	{ OAKLEY_ENCRYPTION_ALGORITHM, OAKLEY_DES_CBC },
+	{ OAKLEY_HASH_ALGORITHM, OAKLEY_SHA },
+	{ OAKLEY_AUTHENTICATION_METHOD, OAKLEY_ELGAMAL_ENC },
+	{ OAKLEY_GROUP_DESCRIPTION, OAKLEY_GROUP_MODP1536 },
+	};
+static struct db_attr ot1536des3sha_pk_elgamal[] = {
+	{ OAKLEY_ENCRYPTION_ALGORITHM, OAKLEY_3DES_CBC },
+	{ OAKLEY_HASH_ALGORITHM, OAKLEY_SHA },
+	{ OAKLEY_AUTHENTICATION_METHOD, OAKLEY_ELGAMAL_ENC },
+	{ OAKLEY_GROUP_DESCRIPTION, OAKLEY_GROUP_MODP1536 },
+	};
+
+static struct db_attr ot1536desmd5_pk_elgamal[] = {
+	{ OAKLEY_ENCRYPTION_ALGORITHM, OAKLEY_DES_CBC },
+	{ OAKLEY_HASH_ALGORITHM, OAKLEY_MD5 },
+	{ OAKLEY_AUTHENTICATION_METHOD, OAKLEY_ELGAMAL_ENC },
+	{ OAKLEY_GROUP_DESCRIPTION, OAKLEY_GROUP_MODP1536 },
+	};
+static struct db_attr ot1536des3md5_pk_elgamal[] = {
+	{ OAKLEY_ENCRYPTION_ALGORITHM, OAKLEY_3DES_CBC },
+	{ OAKLEY_HASH_ALGORITHM, OAKLEY_MD5 },
+	{ OAKLEY_AUTHENTICATION_METHOD, OAKLEY_ELGAMAL_ENC },
+	{ OAKLEY_GROUP_DESCRIPTION, OAKLEY_GROUP_MODP1536 },
+	};
+
+static struct db_attr ot1536desmd5_rpk_rsa[] = {
+	{ OAKLEY_ENCRYPTION_ALGORITHM, OAKLEY_DES_CBC },
+	{ OAKLEY_HASH_ALGORITHM, OAKLEY_MD5 },
+	{ OAKLEY_AUTHENTICATION_METHOD, OAKLEY_RSA_ENC_REV },
+	{ OAKLEY_GROUP_DESCRIPTION, OAKLEY_GROUP_MODP1536 },
+	};
+static struct db_attr ot1536des3md5_rpk_rsa[] = {
+	{ OAKLEY_ENCRYPTION_ALGORITHM, OAKLEY_3DES_CBC },
+	{ OAKLEY_HASH_ALGORITHM, OAKLEY_MD5 },
+	{ OAKLEY_AUTHENTICATION_METHOD, OAKLEY_RSA_ENC_REV },
+	{ OAKLEY_GROUP_DESCRIPTION, OAKLEY_GROUP_MODP1536 },
+	};
+
+static struct db_attr ot1536dessha_rpk_rsa[] = {
+	{ OAKLEY_ENCRYPTION_ALGORITHM, OAKLEY_DES_CBC },
+	{ OAKLEY_HASH_ALGORITHM, OAKLEY_SHA },
+	{ OAKLEY_AUTHENTICATION_METHOD, OAKLEY_RSA_ENC_REV },
+	{ OAKLEY_GROUP_DESCRIPTION, OAKLEY_GROUP_MODP1536 },
+	};
+static struct db_attr ot1536des3sha_rpk_rsa[] = {
+	{ OAKLEY_ENCRYPTION_ALGORITHM, OAKLEY_3DES_CBC },
+	{ OAKLEY_HASH_ALGORITHM, OAKLEY_SHA },
+	{ OAKLEY_AUTHENTICATION_METHOD, OAKLEY_RSA_ENC_REV },
+	{ OAKLEY_GROUP_DESCRIPTION, OAKLEY_GROUP_MODP1536 },
+	};
+
+static struct db_attr ot1536dessha_rpk_elgamal[] = {
+	{ OAKLEY_ENCRYPTION_ALGORITHM, OAKLEY_DES_CBC },
+	{ OAKLEY_HASH_ALGORITHM, OAKLEY_SHA },
+	{ OAKLEY_AUTHENTICATION_METHOD, OAKLEY_ELGAMAL_ENC_REV },
+	{ OAKLEY_GROUP_DESCRIPTION, OAKLEY_GROUP_MODP1536 },
+	};
+static struct db_attr ot1536des3sha_rpk_elgamal[] = {
+	{ OAKLEY_ENCRYPTION_ALGORITHM, OAKLEY_3DES_CBC },
+	{ OAKLEY_HASH_ALGORITHM, OAKLEY_SHA },
+	{ OAKLEY_AUTHENTICATION_METHOD, OAKLEY_ELGAMAL_ENC_REV },
+	{ OAKLEY_GROUP_DESCRIPTION, OAKLEY_GROUP_MODP1536 },
+	};
+
+static struct db_attr ot1536desmd5_rpk_elgamal[] = {
+	{ OAKLEY_ENCRYPTION_ALGORITHM, OAKLEY_DES_CBC },
+	{ OAKLEY_HASH_ALGORITHM, OAKLEY_MD5 },
+	{ OAKLEY_AUTHENTICATION_METHOD, OAKLEY_ELGAMAL_ENC_REV },
+	{ OAKLEY_GROUP_DESCRIPTION, OAKLEY_GROUP_MODP1536 },
+	};
+static struct db_attr ot1536des3md5_rpk_elgamal[] = {
+	{ OAKLEY_ENCRYPTION_ALGORITHM, OAKLEY_3DES_CBC },
+	{ OAKLEY_HASH_ALGORITHM, OAKLEY_MD5 },
+	{ OAKLEY_AUTHENTICATION_METHOD, OAKLEY_ELGAMAL_ENC_REV },
+	{ OAKLEY_GROUP_DESCRIPTION, OAKLEY_GROUP_MODP1536 },
+	};
+#endif /* OPENSSL */
+
 /* We won't accept this, but by proposing it, we get to test
  * our rejection.  We better not propose it to an IKE daemon
  * that will accept it!
  */
 #ifdef TEST_INDECENT_PROPOSAL
+static struct db_attr otpsk1024destiger[] = {
+	{ OAKLEY_ENCRYPTION_ALGORITHM, OAKLEY_DES_CBC },
+	{ OAKLEY_HASH_ALGORITHM, OAKLEY_TIGER },
+	{ OAKLEY_AUTHENTICATION_METHOD, OAKLEY_PRESHARED_KEY },
+	{ OAKLEY_GROUP_DESCRIPTION, OAKLEY_GROUP_MODP1024 },
+	};
 static struct db_attr otpsk1024des3tiger[] = {
 	{ OAKLEY_ENCRYPTION_ALGORITHM, OAKLEY_3DES_CBC },
 	{ OAKLEY_HASH_ALGORITHM, OAKLEY_TIGER },
@@ -119,6 +466,7 @@
 
 /* tables of transforms, in preference order (select based on AUTH) */
 
+
 static struct db_trans oakley_trans_psk[] = {
 #ifdef TEST_INDECENT_PROPOSAL
 	{ KEY_IKE, AD(otpsk1024des3tiger) },
@@ -127,6 +475,14 @@
 	{ KEY_IKE, AD(otpsk1024des3md5) },
 	{ KEY_IKE, AD(otpsk1536des3md5) },
 	{ KEY_IKE, AD(otpsk1536des3sha) },
+/* DES */
+#ifdef TEST_INDECENT_PROPOSAL
+	{ KEY_IKE, AD(otpsk1024destiger) },
+#endif
+	{ KEY_IKE, AD(otpsk1024dessha) },
+	{ KEY_IKE, AD(otpsk1024desmd5) },
+	{ KEY_IKE, AD(otpsk1536desmd5) },
+	{ KEY_IKE, AD(otpsk1536dessha) },
     };
 
 static struct db_trans oakley_trans_rsasig[] = {
@@ -134,8 +490,139 @@
 	{ KEY_IKE, AD(otrsasig1024des3md5) },
 	{ KEY_IKE, AD(otrsasig1536des3md5) },
 	{ KEY_IKE, AD(otrsasig1536des3sha) },
+/* DES */
+	{ KEY_IKE, AD(otrsasig1024dessha) },
+	{ KEY_IKE, AD(otrsasig1024desmd5) },
+	{ KEY_IKE, AD(otrsasig1536desmd5) },
+	{ KEY_IKE, AD(otrsasig1536dessha) },
     };
 
+#ifdef OPENSSL
+static struct db_trans oakley_trans_psk2[] = {
+#ifdef TEST_INDECENT_PROPOSAL
+	{ KEY_IKE, AD(otpsk1024des3tiger), NULL },
+#endif
+	{ KEY_IKE, AD(otpsk1024des3sha), NULL },
+	{ KEY_IKE, AD(otpsk1024des3md5), NULL },
+	{ KEY_IKE, AD(otpsk1536des3md5), NULL },
+	{ KEY_IKE, AD(otpsk1536des3sha), NULL },
+/* DES */
+#ifdef TEST_INDECENT_PROPOSAL
+	{ KEY_IKE, AD(otpsk1024destiger), NULL },
+#endif
+	{ KEY_IKE, AD(otpsk1024dessha), NULL },
+	{ KEY_IKE, AD(otpsk1024desmd5), NULL },
+	{ KEY_IKE, AD(otpsk1536desmd5), NULL },
+	{ KEY_IKE, AD(otpsk1536dessha), NULL },
+    };
+
+static struct db_trans oakley_trans_openssl[] = {
+	{ KEY_IKE, AD(ot1024des3sha_rpk_elgamal), have_elgamal_keypair },
+	{ KEY_IKE, AD(ot1024des3sha_rpk_rsa), have_rsa_keypair },
+	{ KEY_IKE, AD(ot1024des3md5_rpk_elgamal), have_elgamal_keypair },
+	{ KEY_IKE, AD(ot1024des3md5_rpk_rsa), have_rsa_keypair },
+	{ KEY_IKE, AD(ot1024des3sha_pk_elgamal), have_elgamal_keypair },
+	{ KEY_IKE, AD(ot1024des3sha_pk_rsa), have_rsa_keypair },
+	{ KEY_IKE, AD(ot1024des3md5_pk_elgamal), have_elgamal_keypair },
+	{ KEY_IKE, AD(ot1024des3md5_pk_rsa), have_rsa_keypair },
+	{ KEY_IKE, AD(ot1024des3sha_ds_dss), have_dss_key },
+	{ KEY_IKE, AD(ot1024des3sha_ds_rsa), have_rsa_key },
+	{ KEY_IKE, AD(ot1024des3md5_ds_rsa), have_rsa_key },
+	{ KEY_IKE, AD(ot1536des3sha_rpk_elgamal), have_elgamal_keypair },
+	{ KEY_IKE, AD(ot1536des3sha_rpk_rsa), have_rsa_keypair },
+	{ KEY_IKE, AD(ot1536des3md5_rpk_elgamal), have_elgamal_keypair },
+	{ KEY_IKE, AD(ot1536des3md5_rpk_rsa), have_rsa_keypair },
+	{ KEY_IKE, AD(ot1536des3sha_pk_elgamal), have_elgamal_keypair },
+	{ KEY_IKE, AD(ot1536des3sha_pk_rsa), have_rsa_keypair },
+	{ KEY_IKE, AD(ot1536des3md5_pk_elgamal), have_elgamal_keypair },
+	{ KEY_IKE, AD(ot1536des3md5_pk_rsa), have_rsa_keypair },
+	{ KEY_IKE, AD(ot1536des3sha_ds_dss), have_dss_key },
+	{ KEY_IKE, AD(ot1536des3sha_ds_rsa), have_rsa_key },
+	{ KEY_IKE, AD(ot1536des3md5_ds_rsa), have_rsa_key },
+/* DES */
+	{ KEY_IKE, AD(ot1024dessha_rpk_elgamal), have_elgamal_keypair },
+	{ KEY_IKE, AD(ot1024dessha_rpk_rsa), have_rsa_keypair },
+	{ KEY_IKE, AD(ot1024desmd5_rpk_elgamal), have_elgamal_keypair },
+	{ KEY_IKE, AD(ot1024desmd5_rpk_rsa), have_rsa_keypair },
+	{ KEY_IKE, AD(ot1024dessha_pk_elgamal), have_elgamal_keypair },
+	{ KEY_IKE, AD(ot1024dessha_pk_rsa), have_rsa_keypair },
+	{ KEY_IKE, AD(ot1024desmd5_pk_elgamal), have_elgamal_keypair },
+	{ KEY_IKE, AD(ot1024desmd5_pk_rsa), have_rsa_keypair },
+	{ KEY_IKE, AD(ot1024dessha_ds_dss), have_dss_key },
+	{ KEY_IKE, AD(ot1024dessha_ds_rsa), have_rsa_key },
+	{ KEY_IKE, AD(ot1024desmd5_ds_rsa), have_rsa_key },
+	{ KEY_IKE, AD(ot1536dessha_rpk_elgamal), have_elgamal_keypair },
+	{ KEY_IKE, AD(ot1536dessha_rpk_rsa), have_rsa_keypair },
+	{ KEY_IKE, AD(ot1536desmd5_rpk_elgamal), have_elgamal_keypair },
+	{ KEY_IKE, AD(ot1536desmd5_rpk_rsa), have_rsa_keypair },
+	{ KEY_IKE, AD(ot1536dessha_pk_elgamal), have_elgamal_keypair },
+	{ KEY_IKE, AD(ot1536dessha_pk_rsa), have_rsa_keypair },
+	{ KEY_IKE, AD(ot1536desmd5_pk_elgamal), have_elgamal_keypair },
+	{ KEY_IKE, AD(ot1536desmd5_pk_rsa), have_rsa_keypair },
+	{ KEY_IKE, AD(ot1536dessha_ds_dss), have_dss_key },
+	{ KEY_IKE, AD(ot1536dessha_ds_rsa), have_rsa_key },
+	{ KEY_IKE, AD(ot1536desmd5_ds_rsa), have_rsa_key },
+  };
+
+static struct db_trans oakley_trans_psk2openssl[] = {
+	{ KEY_IKE, AD(ot1024des3sha_rpk_elgamal), have_elgamal_keypair },
+	{ KEY_IKE, AD(ot1024des3sha_rpk_rsa), have_rsa_keypair },
+	{ KEY_IKE, AD(ot1024des3md5_rpk_elgamal), have_elgamal_keypair },
+	{ KEY_IKE, AD(ot1024des3md5_rpk_rsa), have_rsa_keypair },
+	{ KEY_IKE, AD(ot1024des3sha_pk_elgamal), have_elgamal_keypair },
+	{ KEY_IKE, AD(ot1024des3sha_pk_rsa), have_rsa_keypair },
+	{ KEY_IKE, AD(ot1024des3md5_pk_elgamal), have_elgamal_keypair },
+	{ KEY_IKE, AD(ot1024des3md5_pk_rsa), have_rsa_keypair },
+	{ KEY_IKE, AD(ot1024des3sha_ds_dss), have_dss_key },
+	{ KEY_IKE, AD(ot1024des3sha_ds_rsa), have_rsa_key },
+	{ KEY_IKE, AD(ot1024des3md5_ds_rsa), have_rsa_key },
+	{ KEY_IKE, AD(otpsk1024des3sha), NULL },
+	{ KEY_IKE, AD(otpsk1024des3md5), NULL },
+	{ KEY_IKE, AD(ot1536des3sha_rpk_elgamal), have_elgamal_keypair },
+	{ KEY_IKE, AD(ot1536des3sha_rpk_rsa), have_rsa_keypair },
+	{ KEY_IKE, AD(ot1536des3md5_rpk_elgamal), have_elgamal_keypair },
+	{ KEY_IKE, AD(ot1536des3md5_rpk_rsa), have_rsa_keypair },
+	{ KEY_IKE, AD(ot1536des3sha_pk_elgamal), have_elgamal_keypair },
+	{ KEY_IKE, AD(ot1536des3sha_pk_rsa), have_rsa_keypair },
+	{ KEY_IKE, AD(ot1536des3md5_pk_elgamal), have_elgamal_keypair },
+	{ KEY_IKE, AD(ot1536des3md5_pk_rsa), have_rsa_keypair },
+	{ KEY_IKE, AD(ot1536des3sha_ds_dss), have_dss_key },
+	{ KEY_IKE, AD(ot1536des3sha_ds_rsa), have_rsa_key },
+	{ KEY_IKE, AD(ot1536des3md5_ds_rsa), have_rsa_key },
+	{ KEY_IKE, AD(otpsk1536des3md5), NULL },
+	{ KEY_IKE, AD(otpsk1536des3sha), NULL },
+/* DES */
+	{ KEY_IKE, AD(ot1024dessha_rpk_elgamal), have_elgamal_keypair },
+	{ KEY_IKE, AD(ot1024dessha_rpk_rsa), have_rsa_keypair },
+	{ KEY_IKE, AD(ot1024desmd5_rpk_elgamal), have_elgamal_keypair },
+	{ KEY_IKE, AD(ot1024desmd5_rpk_rsa), have_rsa_keypair },
+	{ KEY_IKE, AD(ot1024dessha_pk_elgamal), have_elgamal_keypair },
+	{ KEY_IKE, AD(ot1024dessha_pk_rsa), have_rsa_keypair },
+	{ KEY_IKE, AD(ot1024desmd5_pk_elgamal), have_elgamal_keypair },
+	{ KEY_IKE, AD(ot1024desmd5_pk_rsa), have_rsa_keypair },
+	{ KEY_IKE, AD(ot1024dessha_ds_dss), have_dss_key },
+	{ KEY_IKE, AD(ot1024dessha_ds_rsa), have_rsa_key },
+	{ KEY_IKE, AD(ot1024desmd5_ds_rsa), have_rsa_key },
+	{ KEY_IKE, AD(otpsk1024dessha), NULL },
+	{ KEY_IKE, AD(otpsk1024desmd5), NULL },
+
+	{ KEY_IKE, AD(ot1536dessha_rpk_elgamal), have_elgamal_keypair },
+	{ KEY_IKE, AD(ot1536dessha_rpk_rsa), have_rsa_keypair },
+	{ KEY_IKE, AD(ot1536desmd5_rpk_elgamal), have_elgamal_keypair },
+	{ KEY_IKE, AD(ot1536desmd5_rpk_rsa), have_rsa_keypair },
+	{ KEY_IKE, AD(ot1536dessha_pk_elgamal), have_elgamal_keypair },
+	{ KEY_IKE, AD(ot1536dessha_pk_rsa), have_rsa_keypair },
+	{ KEY_IKE, AD(ot1536desmd5_pk_elgamal), have_elgamal_keypair },
+	{ KEY_IKE, AD(ot1536desmd5_pk_rsa), have_rsa_keypair },
+	{ KEY_IKE, AD(ot1536dessha_ds_dss), have_dss_key },
+	{ KEY_IKE, AD(ot1536dessha_ds_rsa), have_rsa_key },
+	{ KEY_IKE, AD(ot1536desmd5_ds_rsa), have_rsa_key },
+	{ KEY_IKE, AD(otpsk1536desmd5), NULL },
+	{ KEY_IKE, AD(otpsk1536dessha), NULL },
+  };
+#endif /* #ifdef OPENSSL */
+
+
 /* In this table, either PSK or RSA sig is accepted.
  * The order matters, but I don't know what would be best.
  */
@@ -151,6 +638,18 @@
 	{ KEY_IKE, AD(otpsk1536des3md5) },
 	{ KEY_IKE, AD(otrsasig1536des3sha) },
 	{ KEY_IKE, AD(otpsk1536des3sha) },
+/* DES */
+#ifdef TEST_INDECENT_PROPOSAL
+	{ KEY_IKE, AD(otpsk1024destiger) },
+#endif
+	{ KEY_IKE, AD(otrsasig1024dessha) },
+	{ KEY_IKE, AD(otpsk1024dessha) },
+	{ KEY_IKE, AD(otrsasig1024desmd5) },
+	{ KEY_IKE, AD(otpsk1024desmd5) },
+	{ KEY_IKE, AD(otrsasig1536desmd5) },
+	{ KEY_IKE, AD(otpsk1536desmd5) },
+	{ KEY_IKE, AD(otrsasig1536dessha) },
+	{ KEY_IKE, AD(otpsk1536dessha) },
     };
 
 /* array of proposals to be conjoined (can only be one for Oakley) */
@@ -164,6 +663,17 @@
 static struct db_prop oakley_pc_pskrsasig[] =
     { { PROTO_ISAKMP, AD(oakley_trans_pskrsasig) } };
 
+#ifdef OPENSSL
+static struct db_prop oakley_pc_psk2[] =
+    { { PROTO_ISAKMP, AD(oakley_trans_psk2) } };
+
+static struct db_prop oakley_pc_openssl[] =
+    { { PROTO_ISAKMP, AD(oakley_trans_openssl) } };
+
+static struct db_prop oakley_pc_psk2openssl[] =
+    { { PROTO_ISAKMP, AD(oakley_trans_psk2openssl) } };
+#endif
+
 /* array of proposal conjuncts (can only be one) */
 
 static struct db_prop_conj oakley_props_psk[] = { { AD(oakley_pc_psk) } };
@@ -172,6 +682,14 @@
 
 static struct db_prop_conj oakley_props_pskrsasig[] = { { AD(oakley_pc_pskrsasig) } };
 
+#ifdef OPENSSL
+static struct db_prop_conj oakley_props_psk2[] = { { AD(oakley_pc_psk2) } };
+
+static struct db_prop_conj oakley_props_openssl[] = { { AD(oakley_pc_openssl) } };
+
+static struct db_prop_conj oakley_props_psk2openssl[] = { { AD(oakley_pc_psk2openssl) } };
+#endif
+
 /* the sadb entry, subscripted by POLICY_PSK and POLICY_RSASIG bits */
 struct db_sa oakley_sadb[] = {
     { AD_NULL },	/* none */
@@ -180,6 +698,16 @@
     { AD(oakley_props_pskrsasig) },	/* POLICY_PSK + POLICY_RSASIG */
     };
 
+#ifdef OPENSSL
+/* the sadb entry, subscripted by POLICY_PSK and POLICY_OPENSSL bits */
+struct db_sa oakley_sadb2[] = {
+    { NULL, 0 },	/* none */
+    { AD(oakley_props_psk2) },	/* POLICY_PSK */
+    { AD(oakley_props_openssl) },	/* POLICY_OPENSSL */
+    { AD(oakley_props_psk2openssl) },	/* POLICY_PSK + POLICY_OPENSSL */
+    };
+#endif
+
 /**************** IPsec (quick mode) SA database ****************/
 
 /* arrays of attributes for transforms */
@@ -203,12 +731,22 @@
 /* arrays of transforms, each in in preference order */
 
 static struct db_trans espa_trans[] = {
+#ifndef OPENSSL
     { ESP_3DES, AD(espmd5_attr) },
     { ESP_3DES, AD(espsha1_attr) },
+    { ESP_DES, AD(espmd5_attr) },
+    { ESP_DES, AD(espsha1_attr) },
+#else
+    { ESP_3DES, AD(espmd5_attr), NULL },
+    { ESP_3DES, AD(espsha1_attr), NULL },
+    { ESP_DES, AD(espmd5_attr), NULL },
+    { ESP_DES, AD(espsha1_attr), NULL },
+#endif
     };
 
 static struct db_trans esp_trans[] = {
     { ESP_3DES, AD_NULL },
+    { ESP_DES, AD_NULL },
     };
 
 #ifdef SUPPORT_ESP_NULL
@@ -219,8 +757,13 @@
 #endif /* SUPPORT_ESP_NULL */
 
 static struct db_trans ah_trans[] = {
+#ifndef OPENSSL
     { AH_MD5, AD(ah_HMAC_MD5_attr) },
     { AH_SHA, AD(ah_HMAC_SHA1_attr) },
+#else
+    { AH_MD5, AD(ah_HMAC_MD5_attr), NULL },
+    { AH_SHA, AD(ah_HMAC_SHA1_attr), NULL },
+#endif
     };
 
 static struct db_trans ipcomp_trans[] = {
@@ -327,12 +870,11 @@
 
 /* output an attribute (within an SA) */
 static bool
-out_attr(
-	int type,
-	unsigned long val,
-	struct_desc *attr_desc,
-	enum_names **attr_val_descs UNUSED,
-	pb_stream *pbs)
+out_attr(int type
+, unsigned long val
+, struct_desc *attr_desc
+, enum_names **attr_val_descs UNUSED
+, pb_stream *pbs)
 {
     struct isakmp_attribute attr;
 
@@ -366,8 +908,8 @@
 	enum_names *d = attr_val_descs[type];
 
 	if (d != NULL)
-	    DBG_log("    [%lu is %s]",
-		val, enum_show(d, val)));
+	    DBG_log("    [%lu is %s]"
+		, val, enum_show(d, val)));
     return TRUE;
 }
 
@@ -375,19 +917,17 @@
  * This has the side-effect of allocating SPIs for us.
  */
 bool
-out_sa(
-    pb_stream *outs,
-    struct db_sa *sadb,
-    struct state *st,
-    bool oakley_mode,
-    u_int8_t np)
+out_sa(pb_stream *outs
+, struct db_sa *sadb
+, struct state *st
+, bool oakley_mode
+, u_int8_t np)
 {
     pb_stream sa_pbs;
     int pcn;
-    bool
-	ah_spi_generated = FALSE,
-	esp_spi_generated = FALSE,
-	ipcomp_cpi_generated = FALSE;
+    bool ah_spi_generated = FALSE
+	, esp_spi_generated = FALSE
+	, ipcomp_cpi_generated = FALSE;
 
     /* SA header out */
     {
@@ -437,7 +977,19 @@
 	    proposal.isap_spisize = oakley_mode ? 0
 		: p->protoid == PROTO_IPCOMP ? IPCOMP_CPI_SIZE
 		: IPSEC_DOI_SPI_SIZE;
+
+#ifndef OPENSSL
 	    proposal.isap_notrans = p->trans_cnt;
+#else
+	    proposal.isap_notrans = 0;
+	    for(tn = 0; tn < p->trans_cnt; tn++) {
+	      struct db_trans *t = &(p->trans[tn]);
+	      if (t->offer == NULL)
+	        proposal.isap_notrans++;
+	      else if ((t->offer(st))) /* only offer a propsal if we can carry it out */
+	        proposal.isap_notrans++;
+	    }
+#endif
 	    if (!out_struct(&proposal, &isakmp_proposal_desc, &sa_pbs, &proposal_pbs))
 		return FALSE;
 
@@ -536,6 +1088,14 @@
 
 		trans.isat_np = (tn == p->trans_cnt - 1)
 		    ? ISAKMP_NEXT_NONE : ISAKMP_NEXT_T;
+#ifdef OPENSSL
+		if ((t->offer != NULL) && ((t->offer)(st) == FALSE)) {
+		  DBG(DBG_PARSING,
+		  DBG_log("Skipping unavailable cipher: %d", tn);
+		  );
+		  continue; /* skip unavailable cipher */
+		}
+#endif
 		trans.isat_transnum = tn;
 		trans.isat_transid = t->transid;
 		if (!out_struct(&trans, trans_desc, &proposal_pbs, &trans_pbs))
@@ -648,6 +1208,180 @@
     return val;
 }
 
+#ifdef OPENSSL
+struct _trans_node {
+  struct oakley_trans_attrs ta;
+  struct isakmp_transform trans;
+  u_char *attr_start;
+  size_t attr_len;
+  bool elim; /* has this node been eliminated from the selection process */
+  struct _trans_node *next;
+};
+
+typedef struct _trans_node *trans_list;
+
+/* Free a list of Oakley transforms */
+static void
+trans_list_free( trans_list *l )
+{
+  trans_list p;
+
+  if (!l) return;
+  while (*l) {
+    p = *l;
+    *l = p->next;
+    pfree(p->attr_start);
+    pfree(p);
+  }
+}
+
+static void
+trans_list_append(trans_list *l,
+		  struct oakley_trans_attrs *ta,
+		  struct isakmp_transform *trans,
+		  u_char *attr_start,
+		  size_t attr_len) {
+  trans_list p, pp;
+
+  if (!l) return;
+  if ((p = alloc_bytes(sizeof(struct _trans_node),
+		       "transformation node")) == NULL) return;
+  p->ta = *ta;
+  p->trans = *trans;
+  p->attr_len = attr_len;
+  if ((p->attr_start = alloc_bytes(attr_len, "attribute")) == NULL) {
+    pfree(p);
+    return;
+  }
+  memcpy(p->attr_start, attr_start, attr_len);
+  p->elim = FALSE;
+  p->next = NULL;
+  if (*l == NULL) {
+    *l = p;
+  } else {
+    for(pp = *l; pp->next ; pp = pp->next);
+    pp->next = p;
+  }
+}
+
+static bool
+select_trans_candidate(trans_list l,
+		       struct oakley_trans_attrs *ta,
+		       struct isakmp_transform *trans,
+		       u_char **attr_start,
+		       size_t *attr_len,
+		       u_int32_t opts)
+{
+  bool ret = FALSE;
+  trans_list auth[OAKLEY_ELGAMAL_ENC_REV+1], p;
+  uint i, numprefs, pref[10];
+
+  if (!l) {
+    DBG(DBG_PARSING,
+    DBG_log("No candidate transforms to choose from");
+    );
+    return FALSE;
+  }
+
+  if ((!ta) || (!attr_len) || (!trans) || (!attr_start)) {
+    DBG(DBG_PARSING,
+    DBG_log("No space to store selected transform");
+    );
+    return FALSE;
+  }
+
+  /* Separate all elements of the list by authentication method */
+
+  for(i=OAKLEY_PRESHARED_KEY; i<=OAKLEY_ELGAMAL_ENC_REV; i++)
+    auth[i] = NULL;
+  for(p=l; p; p=p->next)
+    if ((p->ta.auth >= OAKLEY_PRESHARED_KEY) &&
+	(p->ta.auth <= OAKLEY_ELGAMAL_ENC_REV )) {
+      trans_list_append(&(auth[p->ta.auth]),
+			&(p->ta),
+			&(p->trans),
+			p->attr_start,
+			p->attr_len);
+    }
+
+  numprefs = 7;
+  pref[numprefs-1] = OAKLEY_PRESHARED_KEY;
+  DBG(DBG_PARSING | DBG_CRYPT,
+  DBG_log("select_trans_candidate: %08x", opts);
+  );
+  if (opts & CERT_OPTION_PK) {
+    if (opts & CERT_OPTION_REV) {
+      DBG(DBG_PARSING | DBG_CRYPT,
+      DBG_log("Preferring revised PK encryption schemes");
+      );
+      pref[0] = OAKLEY_ELGAMAL_ENC_REV;
+      pref[1] = OAKLEY_RSA_ENC_REV;
+      pref[2] = OAKLEY_ELGAMAL_ENC;
+      pref[3] = OAKLEY_RSA_ENC;
+      pref[4] = OAKLEY_RSA_SIG;
+      pref[5] = OAKLEY_DSS_SIG;
+    } else {
+      DBG(DBG_PARSING | DBG_CRYPT,
+      DBG_log("Preferring standard PK encryption schemes");
+      );
+      pref[0] = OAKLEY_ELGAMAL_ENC;
+      pref[1] = OAKLEY_RSA_ENC;
+      pref[2] = OAKLEY_ELGAMAL_ENC_REV;
+      pref[3] = OAKLEY_RSA_ENC_REV;
+      pref[4] = OAKLEY_RSA_SIG;
+      pref[5] = OAKLEY_DSS_SIG;
+    }
+  } else {
+    if (opts & CERT_OPTION_REV) {
+      DBG(DBG_PARSING | DBG_CRYPT,
+      DBG_log("Preferring digisig schemes, then revised pk");
+      );
+      pref[0] = OAKLEY_RSA_SIG;
+      pref[1] = OAKLEY_DSS_SIG;
+      pref[2] = OAKLEY_ELGAMAL_ENC_REV;
+      pref[3] = OAKLEY_RSA_ENC_REV;
+      pref[4] = OAKLEY_ELGAMAL_ENC;
+      pref[5] = OAKLEY_RSA_ENC;
+    } else {
+      DBG(DBG_PARSING | DBG_CRYPT,
+      DBG_log("Preferring digisig schemes, then standard pk");
+      );
+      pref[0] = OAKLEY_RSA_SIG;
+      pref[1] = OAKLEY_DSS_SIG;
+      pref[2] = OAKLEY_ELGAMAL_ENC;
+      pref[3] = OAKLEY_RSA_ENC;
+      pref[4] = OAKLEY_ELGAMAL_ENC_REV;
+      pref[5] = OAKLEY_RSA_ENC_REV;
+    }
+  }
+
+  for(i=0; ((i<numprefs) && (!ret)); i++) {
+    DBG(DBG_PARSING,
+    DBG_log("Trying out: %s", enum_show(&oakley_auth_names, pref[i]));
+    );
+    if ((pref[i]) && (auth[pref[i]])) {
+      ret = TRUE;
+      *ta = auth[pref[i]]->ta;
+      *trans = auth[pref[i]]->trans;
+      *attr_start = alloc_bytes(auth[pref[i]]->attr_len, "attribute");
+      if (*attr_start) {
+	*attr_len = auth[pref[i]]->attr_len;
+	memcpy(*attr_start, auth[pref[i]]->attr_start, *attr_len);
+      }
+      DBG(DBG_PARSING,
+      DBG_log("Candidate selected: %s", 
+        enum_show(&oakley_auth_names, pref[i]));
+      );
+    }
+}
+  
+  for(i=OAKLEY_PRESHARED_KEY; i<=OAKLEY_RSA_ENC_REV; i++) {
+    trans_list_free(&auth[i]);
+  }
+  return ret;
+}
+#endif
+
 /* Parse the body of an ISAKMP SA Payload (i.e. Phase 1 / Main Mode).
  * Various shortcuts are taken.  In particular, the policy, such as
  * it is, is hardwired.
@@ -677,6 +1411,12 @@
     struct isakmp_proposal proposal;
     unsigned no_trans_left;
     int last_transnum;
+    const struct connection *c = st->st_connection;
+    
+#ifdef OPENSSL
+    bool selected;
+    trans_list tl = NULL;
+#endif
 
     /* DOI */
     if (sa->isasa_doi != ISAKMP_DOI_IPSEC)
@@ -764,8 +1504,8 @@
 
     if (selection && proposal.isap_notrans != 1)
     {
-	loglog(RC_LOG_SERIOUS, "a single Transform is required in a selecting Oakley Proposal; found %u",
-	    (unsigned)proposal.isap_notrans);
+	loglog(RC_LOG_SERIOUS, "a single Transform is required in a selecting Oakley Proposal; found %u"
+	    , (unsigned)proposal.isap_notrans);
 	return BAD_PROPOSAL_SYNTAX;
     }
 
@@ -779,14 +1519,11 @@
 	u_char *attr_start;
 	size_t attr_len;
 	struct isakmp_transform trans;
-	lset_t
-	    seen_attrs = 0,
-	    seen_durations = 0;
+	lset_t seen_attrs = 0
+	    , seen_durations = 0;
 	u_int16_t life_type;
 	struct oakley_trans_attrs ta;
-	char ugh[100];	/* mailbox for diagnostics (arbitrary limit) */
-
-	ugh[0] = '\0';	/* empty mailbox */
+	err_t ugh = NULL;       /* set to diagnostic when problem detected */
 
 	/* initialize only optional field in ta */
 	ta.life_seconds = OAKLEY_ISAKMP_SA_LIFETIME_DEFAULT;	/* When this SA expires (seconds) */
@@ -854,10 +1591,10 @@
 			, (unsigned)val, enum_show(&oakley_attr_names, a.isaat_af_type));
 		    return ATTRIBUTES_NOT_SUPPORTED;
 		}
-		DBG(DBG_PARSING,
-		    if ((a.isaat_af_type & ISAKMP_ATTR_AF_MASK) == ISAKMP_ATTR_AF_TV)
-			DBG_log("   [%u is %s]",
-			    (unsigned)val, enum_show(vdesc, val)));
+		DBG(DBG_PARSING
+		    , if ((a.isaat_af_type & ISAKMP_ATTR_AF_MASK) == ISAKMP_ATTR_AF_TV)
+			DBG_log("   [%u is %s]"
+			    , (unsigned)val, enum_show(vdesc, val)));
 	    }
 
 	    switch (a.isaat_af_type)
@@ -865,15 +1602,28 @@
 		case OAKLEY_ENCRYPTION_ALGORITHM | ISAKMP_ATTR_AF_TV:
 		    switch (val)
 		    {
-#if 0	/* we don't feel DES is safe */
 		    case OAKLEY_DES_CBC:
-#endif
+			if ((c->block_cypher == ALL_BLOCK_CYPHER) ||
+			  (c->block_cypher == DES_BLOCK_CYPHER)) {
+			  ta.encrypt = val;
+			  ta.encrypter = &oakley_encrypter[val];
+			} else {
+                       ugh = builddiag("%s is not supported",
+			    enum_show(&oakley_enc_names, val));
+			}
+			break;
 		    case OAKLEY_3DES_CBC:
+			if ((c->block_cypher == ALL_BLOCK_CYPHER) ||
+			  (c->block_cypher == DES3_BLOCK_CYPHER)) {
 			ta.encrypt = val;
 			ta.encrypter = &oakley_encrypter[val];
+			} else {
+                       ugh = builddiag("%s is not supported",
+			    enum_show(&oakley_enc_names, val));
+			}
 			break;
 		    default:
-			snprintf(ugh, sizeof(ugh), "%s is not supported"
+                       ugh = builddiag("%s is not supported"
 			    , enum_show(&oakley_enc_names, val));
 		    }
 		    break;
@@ -887,36 +1637,100 @@
 			ta.hasher = &oakley_hasher[val];
 			break;
 		    default:
-			snprintf(ugh, sizeof(ugh), "%s is not supported",
-			    enum_show(&oakley_hash_names, val));
+                       ugh = builddiag("%s is not supported"
+			    , enum_show(&oakley_hash_names, val));
 		    }
 		    break;
 
 		case OAKLEY_AUTHENTICATION_METHOD | ISAKMP_ATTR_AF_TV:
+                   {
+                   /* check that authentication method is acceptable */
+                   lset_t iap = st->st_policy & POLICY_ID_AUTH_MASK;
+
+                   /* default policy is to accept any method */
+                   if (iap == LEMPTY)
+                       iap = POLICY_ID_AUTH_MASK;
+
 		    switch (val)
 		    {
 		    case OAKLEY_PRESHARED_KEY:
-			/* Accept if policy specifies PSK or is default */
-			if ((st->st_policy & POLICY_PSK)
-			|| (st->st_policy & POLICY_ISAKMP_MASK) == LEMPTY)
+                       if ((iap & POLICY_PSK) == LEMPTY)
 			{
-			    /* check that we can find a preshared secret */
-			    if (get_preshared_secret(st->st_connection) == NULL)
-				snprintf(ugh, sizeof(ugh)
-				    , "Can't authenticate: no preshared key");
-			    ta.auth = val;
+                           ugh = "policy does not allow OAKLEY_PRESHARED_KEY authentication";
 			}
 			else
 			{
-			    snprintf(ugh, sizeof(ugh)
-				, "policy does not allow OAKLEY_PRESHARED_KEY authentication");
+                            /* check that we can find a preshared secret */
+                            struct connection *c = st->st_connection;
+
+                           if (get_preshared_secret(c) == NULL)
+                           {
+                               char mid[IDTOA_BUF]
+                                   , hid[IDTOA_BUF];
+
+                               idtoa(&c->this.id, mid, sizeof(mid));
+                               if (his_id_was_instantiated(c))
+                                   strcpy(hid, "%any");
+                               else
+                                   idtoa(&c->that.id, hid, sizeof(hid));
+                               ugh = builddiag("Can't authenticate: no preshared key found for `%s' and `%s'"
+                                   , mid, hid);
+                           }
+                           ta.auth = val;
 			}
 			break;
 
+#ifdef OPENSSL
+                  case OAKLEY_DSS_SIG:
+                    if ((st->st_connection->key == NULL) ||
+                        (((EVP_PKEY *)(st->st_connection->key))->type != EVP_PKEY_DSA))
+                      ugh = builddiag(
+                      "OAKLEY_DSS_SIG requested, but no DSA key available to sign with. Still unsupported.");
+                    ta.auth = val;
+                    break;
+/*
+ *                case OAKLEY_RSA_SIG:
+ * see after #endif OPENSSL
+ */
+                  case OAKLEY_RSA_ENC:
+                    if (!have_rsa_keypair(st))
+                      ugh = builddiag(
+                      "OAKLEY_RSA_ENC requested, but no cert available to encrypt with");
+                    ta.auth = val;
+                    break;
+                  case OAKLEY_ELGAMAL_ENC:
+                    if (!have_elgamal_keypair(st))
+                      ugh = builddiag(
+                      "OAKLEY_ELGAMAL_ENC requested, but no cert available to encrypt with");
+                    ta.auth = val;
+                    break;
+                  case OAKLEY_RSA_ENC_REV:
+                    if (!have_rsa_keypair(st))
+                      ugh = builddiag(
+                      "OAKLEY_RSA_ENC_REV requested, but no cert available to encrypt with");
+                    ta.auth = val;
+                    break;
+                  case OAKLEY_ELGAMAL_ENC_REV:
+                    if (!have_elgamal_keypair(st))
+                      ugh = builddiag(
+                      "OAKLEY_ELGAMAL_ENC_REV requested, but no cert available to encrypt with");
+                    ta.auth = val;
+                    break;
+
 		    case OAKLEY_RSA_SIG:
+		    if (!use_openssl(st->st_connection))
+		    {
+#endif /* OPENSSL, !use_openssl */
 			/* Accept if policy specifies RSASIG or is default */
-			if ((st->st_policy & POLICY_RSASIG)
-			|| (st->st_policy & POLICY_ISAKMP_MASK) == LEMPTY)
+#ifndef OPENSSL
+                       if ((iap & POLICY_RSASIG) == LEMPTY)
+#else
+                       if ((iap & POLICY_OPENSSL) == LEMPTY)
+#endif
+                       {
+                           ugh = "policy does not allow OAKLEY_RSA_SIG authentication";
+                       }
+                       else
 			{
 			    /* We'd like to check that we can find a public
 			     * key for him and a private key for us that is
@@ -928,26 +1742,30 @@
 			     */
 			    ta.auth = val;
 			}
-			else
-			{
-			    snprintf(ugh, sizeof(ugh)
-				, "policy does not allow OAKLEY_RSA_SIG authentication");
+#ifdef OPENSSL
+		    } else { /* use_openssl */
+		      if ((st->st_connection->key == NULL) ||
+		        (((EVP_PKEY *)(st->st_connection->key))->type != EVP_PKEY_RSA))
+                      ugh = builddiag(
+		      "OAKLEY_RSA_SIG requested, but no key available to sign with");
+		      ta.auth = val;
 			}
+#endif
 			break;
 
 		    default:
-			snprintf(ugh, sizeof(ugh)
-			    , "Pluto does not support %s authentication"
+                       ugh = builddiag("Pluto does not support %s authentication"
 			    , enum_show(&oakley_auth_names, val));
 			break;
 		    }
+		    }
 		    break;
 
 		case OAKLEY_GROUP_DESCRIPTION | ISAKMP_ATTR_AF_TV:
 		    ta.group = lookup_group(val);
 		    if (ta.group == NULL)
 		    {
-			snprintf(ugh, sizeof(ugh), "only OAKLEY_GROUP_MODP1024 and OAKLEY_GROUP_MODP1536 supported");
+                       ugh = "only OAKLEY_GROUP_MODP1024 and OAKLEY_GROUP_MODP1536 supported";
 			break;
 		    }
 		    break;
@@ -969,8 +1787,7 @@
 		case OAKLEY_LIFE_DURATION | ISAKMP_ATTR_AF_TV:
 		    if ((seen_attrs & LELEM(OAKLEY_LIFE_TYPE)) == 0)
 		    {
-			snprintf(ugh, sizeof(ugh),
-			    "OAKLEY_LIFE_DURATION attribute not preceded by OAKLEY_LIFE_TYPE attribute");
+                       ugh = "OAKLEY_LIFE_DURATION attribute not preceded by OAKLEY_LIFE_TYPE attribute";
 			break;
 		    }
 		    seen_attrs &= ~(LELEM(OAKLEY_LIFE_DURATION) | LELEM(OAKLEY_LIFE_TYPE));
@@ -979,8 +1796,7 @@
 		    {
 			case OAKLEY_LIFE_SECONDS:
 			    if (val > OAKLEY_ISAKMP_SA_LIFETIME_MAXIMUM)
-				snprintf(ugh, sizeof(ugh),
-				    "peer requested %lu seconds"
+				ugh = builddiag("peer requested %lu seconds"
 				    " which exceeds our limit %d seconds"
 				    , (long) val
 				    , OAKLEY_ISAKMP_SA_LIFETIME_MAXIMUM);
@@ -1014,11 +1830,11 @@
 		case OAKLEY_GROUP_ORDER | ISAKMP_ATTR_AF_TLV:
 #endif
 		default:
-		    snprintf(ugh, sizeof(ugh), "unsupported OAKLEY attribute");
+                   ugh = "unsupported OAKLEY attribute";
 		    break;
 	    }
 
-	    if (ugh[0] != '\0')
+	    if (ugh != NULL)
 	    {
 		loglog(RC_LOG_SERIOUS, "%s.  Attribute %s"
 		    , ugh, enum_show(&oakley_attr_names, a.isaat_af_type));
@@ -1026,7 +1842,7 @@
 	    }
 	}
 
-	if (ugh[0] == '\0')
+	if (ugh == NULL)
 	{
 	    /* a little more checking is in order */
 	    {
@@ -1049,8 +1865,9 @@
 	     * Lets finish early and leave.
 	     */
 
-	    DBG(DBG_PARSING | DBG_CRYPT,
-		DBG_log("Oakley Transform %u accepted", trans.isat_transnum));
+#ifndef OPENSSL
+	    DBG(DBG_PARSING | DBG_CRYPT
+		, DBG_log("Oakley Transform %u accepted", trans.isat_transnum));
 
 	    if (r_sa_pbs != NULL)
 	    {
@@ -1087,6 +1904,7 @@
 		if (!out_struct(&r_trans, &isakmp_isakmp_transform_desc, &r_proposal_pbs, &r_trans_pbs))
 		    passert(FALSE);
 
+
 		if (!out_raw(attr_start, attr_len, &r_trans_pbs, "attributes"))
 		    passert(FALSE);
 		close_output_pbs(&r_trans_pbs);
@@ -1102,6 +1920,14 @@
 	    /* copy over the results */
 	    st->st_oakley = ta;
 	    return NOTHING_WRONG;
+#else
+	    /*
+	     * We store the ta result into the list of candidates
+	     * Afterwards, site policy dictates which of the
+	     * candidates we should select
+	     */
+	    trans_list_append(&tl, &ta, &trans, attr_start, attr_len);
+#endif
 	}
 
 	/* on to next transform */
@@ -1122,9 +1948,77 @@
 		, enum_show(&payload_names, proposal.isap_np));
 	    return BAD_PROPOSAL_SYNTAX;
 	}
-    }
+    } /* for */
+
+#ifndef OPENSSL
     loglog(RC_LOG_SERIOUS, "no acceptable Oakley Transform");
     return NO_PROPOSAL_CHOSEN;
+#else
+    /* We should have a list of hopefuls in the list tl */
+    { /* open scope */
+      u_char *attr_start;
+      size_t attr_len;
+      struct isakmp_transform trans;
+
+      selected = select_trans_candidate(tl, &st->st_oakley, &trans, 
+        &attr_start, &attr_len, st->st_connection->cert_options);
+      trans_list_free(&tl);
+      if (! selected) {
+        log("no acceptable Oakley Transform");
+        return NO_PROPOSAL_CHOSEN;
+      } else {
+        DBG(DBG_PARSING | DBG_CRYPT,
+        DBG_log("Oakley Transform %u accepted", trans.isat_transnum)
+        );
+
+        if (r_sa_pbs != NULL)
+        {
+          struct isakmp_proposal r_proposal = proposal;
+          pb_stream r_proposal_pbs;
+          struct isakmp_transform r_trans = trans;
+          pb_stream r_trans_pbs;
+
+          /* Situation */
+          if (!out_struct(&ipsecdoisit, &ipsec_sit_desc, r_sa_pbs, NULL))
+            passert(FALSE);
+
+          /* Proposal */
+#ifdef EMIT_ISAKMP_SPI
+          r_proposal.isap_spisize = COOKIE_SIZE;
+#else
+          r_proposal.isap_spisize = 0;
+#endif
+          r_proposal.isap_notrans = 1;
+          if (!out_struct(&r_proposal, &isakmp_proposal_desc, r_sa_pbs, &r_proposal_pbs))
+            passert(FALSE);
+
+          /* SPI */
+#ifdef EMIT_ISAKMP_SPI
+          if (!out_raw(my_cookie, COOKIE_SIZE, &r_proposal_pbs, "SPI"))
+            passert(FALSE);
+          r_proposal.isap_spisize = COOKIE_SIZE;
+#else
+          /* none (0) */
+#endif
+
+          /* Transform */
+          r_trans.isat_np = ISAKMP_NEXT_NONE;
+          if (!out_struct(&r_trans, &isakmp_isakmp_transform_desc, 
+            &r_proposal_pbs, &r_trans_pbs))
+            passert(FALSE);
+
+          if (!out_raw(attr_start, attr_len, &r_trans_pbs, "attributes"))
+            passert(FALSE);
+          if (attr_start) pfree(attr_start);
+
+          close_output_pbs(&r_trans_pbs);
+          close_output_pbs(&r_proposal_pbs);
+          close_output_pbs(r_sa_pbs);
+        }     /* if (r_sa_pbs != NULL) */
+      return NOTHING_WRONG;
+      }       /* if (! selected) */
+    }  /* end this scope */
+#endif        /* OPENSSL */
 }
 
 /* Parse the body of an IPsec SA Payload (i.e. Phase 2 / Quick Mode).
@@ -1175,9 +2069,8 @@
 , bool is_ipcomp
 , struct state *st)	/* current state object */
 {
-    lset_t
-	seen_attrs = 0,
-	seen_durations = 0;
+    lset_t seen_attrs = 0
+       , seen_durations = 0;
     u_int16_t life_type;
     const struct oakley_group_desc *pfs_group = NULL;
 
@@ -1249,10 +2142,10 @@
 		    , (unsigned)val, enum_show(&ipsec_attr_names, a.isaat_af_type));
 		return FALSE;
 	    }
-	    DBG(DBG_PARSING,
-		if ((a.isaat_af_type & ISAKMP_ATTR_AF_MASK) == ISAKMP_ATTR_AF_TV)
-		    DBG_log("   [%u is %s]",
-			(unsigned)val, enum_show(vdesc, val)));
+	    DBG(DBG_PARSING
+		, if ((a.isaat_af_type & ISAKMP_ATTR_AF_MASK) == ISAKMP_ATTR_AF_TV)
+		    DBG_log("   [%u is %s]"
+			, (unsigned)val, enum_show(vdesc, val)));
 	}
 
 	switch (a.isaat_af_type)
@@ -1553,7 +2446,7 @@
 		/* We store CPI in the low order of a network order
 		 * ipsec_spi_t.  So we start a couple of bytes in.
 		 */
-		memset(&next_spi, '\0', sizeof(next_spi));
+		zero(&next_spi);
 		if (!in_raw((u_char *)&next_spi
 		  + IPSEC_DOI_SPI_SIZE - IPCOMP_CPI_SIZE
 		, IPCOMP_CPI_SIZE, &next_proposal_pbs, "CPI"))
@@ -1759,8 +2652,8 @@
 		}
 		if (!ok_auth)
 		{
-		    DBG(DBG_CONTROL | DBG_CRYPT,
-			DBG_log("%s attribute unsupported"
+		    DBG(DBG_CONTROL | DBG_CRYPT
+			, DBG_log("%s attribute unsupported"
 			    " in %s Transform from %s"
 			    , enum_name(&auth_alg_names, ah_attrs.auth)
 			    , enum_show(&ah_transformid_names, ah_attrs.transid)
@@ -1797,9 +2690,7 @@
 
 		switch (esp_attrs.transid)
 		{
-#if 0	/* we don't feel single DES is safe */
 		    case ESP_DES:
-#endif
 		    case ESP_3DES:
 			break;
 
@@ -1812,8 +2703,8 @@
 			}
 			if (st->st_policy & POLICY_ENCRYPT)
 			{
-			    DBG(DBG_CONTROL | DBG_CRYPT,
-				    DBG_log("ESP_NULL Transform Proposal from %s"
+			    DBG(DBG_CONTROL | DBG_CRYPT
+				    , DBG_log("ESP_NULL Transform Proposal from %s"
 					" does not satisfy POLICY_ENCRYPT"
 					, ip_str(&c->that.host_addr)));
 			    continue;   /* try another */
@@ -1854,8 +2745,8 @@
 		if (ah_seen && ah_attrs.encapsulation != esp_attrs.encapsulation)
 		{
 		    /* ??? This should be an error, but is it? */
-		    DBG(DBG_CONTROL | DBG_CRYPT,
-			DBG_log("AH and ESP transforms disagree about encapsulation; TUNNEL presumed"));
+		    DBG(DBG_CONTROL | DBG_CRYPT
+			, DBG_log("AH and ESP transforms disagree about encapsulation; TUNNEL presumed"));
 		}
 
 		break;	/* we seem to be happy */
@@ -1946,13 +2837,13 @@
 		if (ah_seen && ah_attrs.encapsulation != ipcomp_attrs.encapsulation)
 		{
 		    /* ??? This should be an error, but is it? */
-		    DBG(DBG_CONTROL | DBG_CRYPT,
-			DBG_log("AH and IPCOMP transforms disagree about encapsulation; TUNNEL presumed"));
+		    DBG(DBG_CONTROL | DBG_CRYPT
+			, DBG_log("AH and IPCOMP transforms disagree about encapsulation; TUNNEL presumed"));
 		} else if (esp_seen && esp_attrs.encapsulation != ipcomp_attrs.encapsulation)
 		{
 		    /* ??? This should be an error, but is it? */
-		    DBG(DBG_CONTROL | DBG_CRYPT,
-			DBG_log("ESP and IPCOMP transforms disagree about encapsulation; TUNNEL presumed"));
+		    DBG(DBG_CONTROL | DBG_CRYPT
+			, DBG_log("ESP and IPCOMP transforms disagree about encapsulation; TUNNEL presumed"));
 		}
 
 		break;	/* we seem to be happy */
@@ -1974,33 +2865,33 @@
 
 	    /* AH proposal */
 	    if (ah_seen)
-		echo_proposal(ah_proposal,
-		    ah_trans,
-		    esp_seen || ipcomp_seen? ISAKMP_NEXT_P : ISAKMP_NEXT_NONE,
-		    r_sa_pbs,
-		    &st->st_ah,
-		    &isakmp_ah_transform_desc,
-		    &ah_trans_pbs);
+		echo_proposal(ah_proposal
+		    , ah_trans
+		    , esp_seen || ipcomp_seen? ISAKMP_NEXT_P : ISAKMP_NEXT_NONE
+		    , r_sa_pbs
+		    , &st->st_ah
+		    , &isakmp_ah_transform_desc
+		    , &ah_trans_pbs);
 
 	    /* ESP proposal */
 	    if (esp_seen)
-		echo_proposal(esp_proposal,
-		    esp_trans,
-		    ipcomp_seen? ISAKMP_NEXT_P : ISAKMP_NEXT_NONE,
-		    r_sa_pbs,
-		    &st->st_esp,
-		    &isakmp_esp_transform_desc,
-		    &esp_trans_pbs);
+		echo_proposal(esp_proposal
+		    , esp_trans
+		    , ipcomp_seen? ISAKMP_NEXT_P : ISAKMP_NEXT_NONE
+		    , r_sa_pbs
+		    , &st->st_esp
+		    , &isakmp_esp_transform_desc
+		    , &esp_trans_pbs);
 
 	    /* IPCOMP proposal */
 	    if (ipcomp_seen)
-		echo_proposal(ipcomp_proposal,
-		    ipcomp_trans,
-		    ISAKMP_NEXT_NONE,
-		    r_sa_pbs,
-		    &st->st_ipcomp,
-		    &isakmp_ipcomp_transform_desc,
-		    &ipcomp_trans_pbs);
+		echo_proposal(ipcomp_proposal
+		    , ipcomp_trans
+		    , ISAKMP_NEXT_NONE
+		    , r_sa_pbs
+		    , &st->st_ipcomp
+		    , &isakmp_ipcomp_transform_desc
+		    , &ipcomp_trans_pbs);
 
 	    close_output_pbs(r_sa_pbs);
 	}
diff -bruN freeswan-1.9.orig/pluto/spdb.h freeswan-1.9/pluto/spdb.h
--- freeswan-1.9.orig/pluto/spdb.h	Fri Sep 15 05:09:28 2000
+++ freeswan-1.9/pluto/spdb.h	Wed May 16 10:57:20 2001
@@ -24,11 +24,32 @@
     u_int16_t val;
 };
 
+#ifdef OPENSSL
+typedef bool offer_fn(struct state *st);
+/* Addition for OpenSSL: we don't want to offer cipher suites */
+/* which we aren't capable of generating, so I added a function */
+/* parameter 'offer', which takes the state as a parameter, and */
+/* returns either TRUE or FALSE, depending on whether the cipher */
+/* suite is supportable. For instance, there's no point in */
+/* offering to sign things with a DSA signature key, if all you've */
+/* got is an RSA one. */
+/* NB: If the function pointer is set to NULL, it means offer the */
+/* cipher suite under all conditions. The downside to this is that */
+/* another parameter must be added to all the IPsec cipher transforms */
+/* which is always NULL. I suppose we could embed policy information */
+/* within that parameter, e.g. If a pair of endpoints must have */
+/* a particular cipher between them. Trouble is, that information is */
+/* present within ipsec.conf, to some extent -- nd */
+#endif
+
 /* transform */
 struct db_trans {
     u_int8_t transid;	/* Transform-Id */
     struct db_attr *attrs;	/* array */
     int attr_cnt;	/* number of elements */
+#ifdef OPENSSL
+    offer_fn *offer;
+#endif
 };
 
 /* proposal */
@@ -56,9 +77,12 @@
 };
 
 /* The oakley sadb is subscripted by a bitset with members
- * from POLICY_PSK and POLICY_RSASIG.
+ * from POLICY_PSK and POLICY_RSASIG/OPENSSL.
  */
 extern struct db_sa oakley_sadb[1 << 2];
+#ifdef OPENSSL
+extern struct db_sa oakley_sadb2[1 << 2];
+#endif
 
 /* The ipsec sadb is subscripted by a bitset with members
  * from POLICY_ENCRYPT, POLICY_AUTHENTICATE, POLICY_COMPRESS
diff -bruN freeswan-1.9.orig/pluto/state.c freeswan-1.9/pluto/state.c
--- freeswan-1.9.orig/pluto/state.c	Tue Jan 30 16:58:36 2001
+++ freeswan-1.9/pluto/state.c	Thu Jun  7 14:47:11 2001
@@ -12,7 +12,7 @@
  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  * for more details.
  *
- * RCSID $Id: state.c,v 1.77 2001/01/30 21:58:36 dhr Exp $
+ * RCSID $Id: state.c,v 1.81 2001/05/08 05:37:24 dhr Exp $
  */
 
 #include <stdio.h>
@@ -162,12 +162,13 @@
 struct state *
 new_state(void)
 {
-    static struct state blank_state;	/* initialized all to zero & NULL */
+    static const struct state blank_state;     /* initialized all to zero & NULL */
+    static so_serial_t next_so = SOS_FIRST;
     struct state *st;
 
-    blank_state.st_serialno++;
-    passert(blank_state.st_serialno != SOS_NOBODY);	/* overflow can't happen! */
     st = clone_thing(blank_state, "struct state in new_state()");
+    st->st_serialno = next_so++;
+    passert(next_so > SOS_FIRST);      /* overflow can't happen! */
     st->st_whack_sock = NULL_FD;
     DBG(DBG_CONTROL, DBG_log("creating state object #%lu at %p",
 	st->st_serialno, (void *) st));
@@ -196,6 +197,8 @@
 struct state *
 state_with_serialno(so_serial_t sn)
 {
+    if (sn >= SOS_FIRST)
+    {
     struct state *st;
     int i;
 
@@ -203,6 +206,7 @@
 	for (st = statetable[i]; st != NULL; st = st->st_hashchain_next)
 	    if (st->st_serialno == sn)
 		return st;
+    }
     return NULL;
 }
 
@@ -291,6 +295,13 @@
 #endif
     passert(st->st_event == NULL);
 
+    /* Ditch anything pending on ISAKMP SA being established.
+     * Note: this must be done before the unhash_state to prevent
+     * flush_pending_by_state inadvertently and prematurely
+     * deleting our connection.
+     */
+    flush_pending_by_state(st);
+
     /* effectively, this deletes any ISAKMP SA that this state represents */
     unhash_state(st);
 
@@ -348,31 +359,34 @@
     pfreeany(st->st_esp.our_keymat);
     pfreeany(st->st_esp.peer_keymat);
 
+#ifdef OPENSSL
+    /* Clean out the stuff for revised PK encryption mode */
+    pfreeany(st->st_ne_i.ptr);
+    memset(&st->st_ks_i, 0, sizeof(st->st_ks_i));
+    memset(st->st_ne_i_iv, 0, MAX_DIGEST_LEN);
+    pfreeany(st->st_ne_r.ptr);
+    memset(&st->st_ks_r, 0, sizeof(st->st_ks_r));
+    memset(st->st_ne_r_iv, 0, MAX_DIGEST_LEN);
+#endif
+
     pfree(st);
 }
 
 
-/* If a connection will no longer be used, and it is temporary, delete it.
- * We must be careful to avoid circularity:
- * we don't touch it if it is rwcs_going_away.
- */
-void
-connection_discard(struct connection *c)
+/* Is a connection in use by some state? */
+bool
+states_use_connection(struct connection *c)
 {
-    if (c->rw_state == rwcs_instance)
-    {
 	/* are there any states still using it? */
 	struct state *st = NULL;
 	int i;
 
 	for (i = 0; st == NULL && i < STATE_TABLE_SIZE; i++)
-	    for (st = statetable[i]
-	    ; st != NULL && st->st_connection != c
-	    ; st = st->st_hashchain_next)
-		;
-	if (st == NULL)
-	    delete_connection(c);
-    }
+       for (st = statetable[i]; st != NULL; st = st->st_hashchain_next)
+           if (st->st_connection == c)
+               return TRUE;
+
+    return FALSE;
 }
 
 void
@@ -381,10 +395,10 @@
     int i;
 
     /* this kludge avoids an n^2 algorithm */
-    enum rwcs rws = c->rw_state;
+    enum connection_kind ck = c->kind;
 
-    if (rws == rwcs_instance)
-	c->rw_state = rwcs_going_away;
+    if (ck == CK_INSTANCE)
+       c->kind = CK_GOING_AWAY;
 
     for (i = 0; i < STATE_TABLE_SIZE; i++)
     {
@@ -421,9 +435,9 @@
 	}
     }
 
-    if (rws == rwcs_instance)
+    if (ck == CK_INSTANCE)
     {
-	c->rw_state = rws;
+	c->kind = ck;
 	delete_connection(c);
     }
 }
@@ -495,9 +509,10 @@
     return st;
 }
 
-/* Find newest ISAKMP SA state object that implements connection c */
+/* Find newest Phase 1 negotiation state object for suitable for connection c
+ */
 struct state *
-find_isakmp_sa(const struct connection *c)
+find_phase1_state(const struct connection *c)
 {
     struct state
 	*st,
@@ -506,7 +521,7 @@
 
     for (i = 0; i < STATE_TABLE_SIZE; i++)
 	for (st = statetable[i]; st != NULL; st = st->st_hashchain_next)
-	    if (IS_ISAKMP_SA_ESTABLISHED(st->st_state)
+	    if (IS_PHASE1(st->st_state)
 	    && c->host_pair == st->st_connection->host_pair
 	    && same_peer_ids(c, st->st_connection, NULL)
 	    && (best == NULL || best->st_serialno < st->st_serialno))
@@ -543,7 +558,7 @@
 	    passert(st->st_event != 0);
 
 	    him[0] = '\0';
-	    if (c->rw_state == rwcs_instance)
+	    if (c->kind == CK_INSTANCE)
 	    {
 		him[0] = ':';
 		addrtot(&c->that.host_addr, 0, him+1, sizeof(him)-1);
diff -bruN freeswan-1.9.orig/pluto/state.h freeswan-1.9/pluto/state.h
--- freeswan-1.9.orig/pluto/state.h	Tue Jan 30 16:58:36 2001
+++ freeswan-1.9/pluto/state.h	Wed Jun  6 15:52:29 2001
@@ -12,7 +12,7 @@
  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  * for more details.
  *
- * RCSID $Id: state.h,v 1.49 2001/01/30 21:58:36 dhr Exp $
+ * RCSID $Id: state.h,v 1.51 2001/03/02 03:19:46 dhr Exp $
  */
 
 #include <sys/types.h>
@@ -126,7 +126,6 @@
     u_int32_t          st_doi;                 /* Domain of Interpretation */
     u_int32_t          st_situation;
 
-    bool               st_pending_quick;       /* need to build IPsec SA after ISAKMP SA */
     lset_t             st_policy;              /* policy for IPsec SA */
 
     msgid_t            st_msgid;               /* MSG-ID from header.  Network Order! */
@@ -146,6 +145,15 @@
     u_int8_t           st_rcookie[COOKIE_SIZE];/* Responder Cookie */
     chunk_t            st_nr;                  /* Nr nonce */
 
+#ifdef OPENSSL
+    /* key material for revised public key information */
+    u_int8_t           st_ne_i_iv[MAX_DIGEST_LEN];
+    chunk_t            st_ne_i;                /* key for initiator payloads */
+    keysched           st_ks_i;
+    u_int8_t           st_ne_r_iv[MAX_DIGEST_LEN];
+    chunk_t            st_ne_r;                /* key for responder payloads */
+    keysched           st_ks_r;
+#endif
 
   /* my stuff */
 
@@ -180,7 +188,7 @@
                                                 * selected.
                                                 */
 
-    u_int16_t          st_state;               /* State of exchange */
+    enum state_kind    st_state;               /* State of exchange */
     u_int8_t           st_retransmit;          /* Number of retransmits */
     unsigned long      st_try;                 /* number of times rekeying attempted */
                                                /* 0 means the only time */
@@ -205,7 +213,7 @@
 
 extern u_int16_t pluto_port;	/* Pluto's port */
 
-extern void connection_discard(struct connection *c);
+extern bool states_use_connection(struct connection *c);
 
 /* state functions */
 
@@ -226,7 +234,7 @@
 	const ip_address *peer,
 	msgid_t msgid),
     *state_with_serialno(so_serial_t sn),
-    *find_isakmp_sa(const struct connection *c);
+    *find_phase1_state(const struct connection *c);
 
 extern void show_states_status(void);
 
diff -bruN freeswan-1.9.orig/pluto/timer.c freeswan-1.9/pluto/timer.c
--- freeswan-1.9.orig/pluto/timer.c	Sun Dec 17 17:05:12 2000
+++ freeswan-1.9/pluto/timer.c	Wed Jun  6 15:56:33 2001
@@ -12,7 +12,7 @@
  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  * for more details.
  *
- * RCSID $Id: timer.c,v 1.60 2000/12/17 22:05:12 dhr Exp $
+ * RCSID $Id: timer.c,v 1.64 2001/05/28 19:18:20 dhr Exp $
  */
 
 #include <stdio.h>
@@ -33,6 +33,7 @@
 #include "packet.h"
 #include "demux.h"  /* needs packet.h */
 #include "ipsec_doi.h"	/* needs demux.h and state.h */
+#include "kernel.h"
 #include "server.h"
 #include "log.h"
 #include "rnd.h"
@@ -69,7 +70,7 @@
  * This routine places an event in the event list.
  */
 void
-event_schedule(int type, time_t tm, struct state *st)
+event_schedule(enum event_type type, time_t tm, struct state *st)
 {
     struct event *ev = alloc_thing(struct event, "struct event in event_schedule()");
 
@@ -198,6 +199,11 @@
 	    init_secret();
 	    break;
 
+        case EVENT_SHUNT_SCAN:
+            passert(st == NULL);
+            scan_proc_shunts();
+            break;
+
 	case EVENT_RETRANSMIT:
 	    /* Time to retransmit, or give up.
 	     *
@@ -255,6 +261,8 @@
 		    case STATE_MAIN_I1:
 			details = ".  No acceptable response to our first IKE message";
 			break;
+		    default:
+                        break;
 		    }
 		    loglog(RC_NORETRANSMISSION
 			, "max number of retransmissions (%d) reached %s%s"
@@ -279,7 +287,7 @@
 			    /* Release whack because the observer will get bored. */
 			    loglog(RC_COMMENT, "%s, but releasing whack"
 				, story);
-			    release_whack(st);
+			    release_pending_whacks(st, story);
 			}
 			else
 			{
diff -bruN freeswan-1.9.orig/pluto/timer.h freeswan-1.9/pluto/timer.h
--- freeswan-1.9.orig/pluto/timer.h	Sun Aug 13 21:21:41 2000
+++ freeswan-1.9/pluto/timer.h	Wed Jun  6 15:57:55 2001
@@ -11,7 +11,7 @@
  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  * for more details.
  *
- * RCSID $Id: timer.h,v 1.11 2000/08/14 01:21:41 dhr Exp $
+ * RCSID $Id: timer.h,v 1.12 2001/05/28 19:18:20 dhr Exp $
  */
 
 extern time_t now(void);	/* careful version of time(2) */
@@ -26,7 +26,7 @@
     struct event   *ev_next;        /* Pointer to next event */
 };
 
-extern void event_schedule(int type, time_t tm, struct state *st);
+extern void event_schedule(enum event_type type, time_t tm, struct state *st);
 extern void event_handle(void);
 extern long next_event(void);
 extern void delete_event(struct state *st);
diff -bruN freeswan-1.9.orig/pluto/version.c freeswan-1.9/pluto/version.c
--- freeswan-1.9.orig/pluto/version.c	Mon Feb 26 18:56:08 2001
+++ freeswan-1.9/pluto/version.c	Thu Jun  7 14:54:02 2001
@@ -1,2 +1,2 @@
-/* silly pointless RCSID $Id: version.c,v 1.17.2.1 2001/02/26 23:56:08 henry Exp $ */
-static const char freeswan_version[] = "1.9";
+/* silly pointless RCSID $Id: version.c,v 1.19 2001/05/30 13:02:20 henry Exp $ */
+static const char freeswan_version[] = "FreeSWAN-1.9-pkix2";
diff -bruN freeswan-1.9.orig/pluto/whack.c freeswan-1.9/pluto/whack.c
--- freeswan-1.9.orig/pluto/whack.c	Wed Jan 31 20:54:09 2001
+++ freeswan-1.9/pluto/whack.c	Wed Jun  6 16:09:39 2001
@@ -1,4 +1,6 @@
 /* command interface to Pluto
+ *
+ * Modified by Luc Lanthier based on work from:
  * Copyright (C) 1997 Angelos D. Keromytis.
  * Copyright (C) 1998, 1999  D. Hugh Redelmeier.
  *
@@ -12,7 +14,7 @@
  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  * for more details.
  *
- * RCSID $Id: whack.c,v 1.72 2001/02/01 01:54:09 dhr Exp $
+ * RCSID $Id: whack.c,v 1.77 2001/05/14 20:37:48 dhr Exp $
  */
 
 #include <stdio.h>
@@ -82,6 +84,10 @@
 	    " [--compress]"
 	    " [--tunnel]"
 	    " [--pfs]"
+#ifdef OPENSSL
+	    " [--openssl]"
+#endif
+
 	    " \\\n   "
 	    " [--ikelifetime <seconds>]"
 	    " [--ipseclifetime <seconds>]"
@@ -90,6 +96,14 @@
 	    " [--reykeyfuzz <percentage>]"
 	    " \\\n   "
 	    " [--keyingtries <count>]"
+#ifdef OPENSSL
+	    " \\\n   "
+	    " [--certfile <file name>]"
+	    " [--certopts <[!]opt1,[!]opt2,...,[!]optN>]"
+	    " [--peerfile <file name>]"
+	    " [--keyfile <file name>]"
+	    " [--certpath <file name>]"
+#endif
 	    "\n\n"
 	"routing: whack"
 	    " (--route | --unroute)"
@@ -142,6 +156,9 @@
 	"shutdown: whack"
 	    " --shutdown"
 	    "\n\n"
+	"DES type: whack"
+	    " [--force_encrypt_cypher <des/3des>]"
+	    "\n\n"
 	"FreeS/WAN %s\n",
 	freeswan_version);
 }
@@ -203,6 +220,14 @@
     OPT_KEYID,
     OPT_PUBKEYRSA,
 
+#ifdef OPENSSL
+    OPT_CERTFILE,
+    OPT_CERTOPTS,
+    OPT_PEERFILE,
+    OPT_KEYFILE,
+    OPT_CERTPATH,
+#endif
+
     OPT_ROUTE,
     OPT_UNROUTE,
 
@@ -234,17 +259,26 @@
 
 #   define CD_POLICY_FIRST  CD_PSK
     CD_PSK,	/* same order as POLICY_* */
+#ifndef OPENSSL
     CD_RSASIG,	/* same order as POLICY_* */
+#else
+    CD_OPENSSL,	/* same order as POLICY_* */
+#endif
     CD_ENCRYPT,	/* same order as POLICY_* */
     CD_AUTHENTICATE,	/* same order as POLICY_* */
     CD_COMPRESS,	/* same order as POLICY_* */
     CD_TUNNEL,	/* same order as POLICY_* */
     CD_PFS,	/* same order as POLICY_* */
+
+    CD_FAIL_PASS,	/* same order as POLICY_* */
+    CD_FAIL_DROP,
     CD_TUNNELIPV4,
     CD_TUNNELIPV6,
     CD_CONNIPV4,
     CD_CONNIPV6,
 
+    CD_FORCE_ENCRYPT_CYPHER,   /* to force DES or 3DES only */
+
     CD_IKELIFETIME,
     CD_IPSECLIFETIME,
     CD_RKMARGIN,
@@ -317,7 +351,12 @@
     { "updown", required_argument, NULL, CD_UPDOWN + OO },
 
     { "psk", no_argument, NULL, CD_PSK + OO },
+#ifndef OPENSSL
     { "rsasig", no_argument, NULL, CD_RSASIG + OO },
+#else
+    { "rsasig", no_argument, NULL, CD_OPENSSL + OO },
+    { "openssl", no_argument, NULL, CD_OPENSSL + OO },
+#endif
 
     { "encrypt", no_argument, NULL, CD_ENCRYPT + OO },
     { "authenticate", no_argument, NULL, CD_AUTHENTICATE + OO },
@@ -326,6 +365,8 @@
     { "tunnelipv4", no_argument, NULL, CD_TUNNELIPV4 + OO },
     { "tunnelipv6", no_argument, NULL, CD_TUNNELIPV6 + OO },
     { "pfs", no_argument, NULL, CD_PFS + OO },
+    { "pass", no_argument, NULL, CD_FAIL_PASS + OO },
+    { "drop", no_argument, NULL, CD_FAIL_DROP + OO },
     { "ipv4", no_argument, NULL, CD_CONNIPV4 + OO },
     { "ipv6", no_argument, NULL, CD_CONNIPV6 + OO },
 
@@ -335,6 +376,16 @@
     { "rekeywindow", required_argument, NULL, CD_RKMARGIN + OO + NUMERIC_ARG },	/* OBSOLETE */
     { "rekeyfuzz", required_argument, NULL, CD_RKFUZZ + OO + NUMERIC_ARG },
     { "keyingtries", required_argument, NULL, CD_KTRIES + OO + NUMERIC_ARG },
+/* DES Support */
+    { "force_encrypt_cypher", required_argument, NULL, CD_FORCE_ENCRYPT_CYPHER + OO },
+
+#ifdef OPENSSL
+    { "certfile", required_argument, NULL, OPT_CERTFILE + OO },
+    { "certopts", required_argument, NULL, OPT_CERTOPTS + OO },
+    { "peerfile", required_argument, NULL, OPT_PEERFILE + OO },
+    { "keyfile", required_argument, NULL, OPT_KEYFILE + OO },
+    { "certpath", required_argument, NULL, OPT_CERTPATH + OO },
+#endif
 
 #ifdef DEBUG
     { "debug-none", no_argument, NULL, DBGOPT_NONE + OO },
@@ -418,7 +469,7 @@
     if (default_nexthop)
     {
 	if (isanyaddr(&that->host_addr))
-	    diag("nexthop must be specified when other host is a Road Warrior");
+	    diag("nexthop must be specified when other host is a %any or %opportunistic");
 	this->host_nexthop = that->host_addr;
     }
 
@@ -439,7 +490,11 @@
 	    /* client is 0.0.0.0/32: Opportunism connection */
 	    if (!isanyaddr(&this->host_addr))
 		diag("normal client network must not be 0.0.0.0/32 or 0::0/128");
+#ifndef OPENSSL
 	    if ((policy & (POLICY_PSK | POLICY_RSASIG)) != POLICY_RSASIG)
+#else
+	    if ((policy & (POLICY_PSK | POLICY_OPENSSL)) != POLICY_OPENSSL)
+#endif
 		diag("only RSASIG is supported for opportunism");
 	    if ((policy & POLICY_PFS) == 0)
 		diag("PFS required for opportunism");
@@ -449,14 +504,15 @@
     }
     else
     {
-	/* fill in unspec-unspec as client subnet */
+	/* fill in anyaddr-anyaddr as (missing) client subnet */
 	ip_address cn;
 
-	diagq(unspecaddr(caf, &cn), NULL);
+	diagq(anyaddr(caf, &cn), NULL);
 	diagq(rangetosubnet(&cn, &cn, &this->client), NULL);
     }
 }
 
+
 /* This is a hack for initiating ISAKMP exchanges. */
 
 int
@@ -471,7 +527,7 @@
 	*af_used_by = NULL,
 	*tunnel_af_used_by = NULL;
 
-    memset(&msg, '\0', sizeof(msg));
+    zero(&msg);
     msg.magic = WHACK_MAGIC;
     msg.right.host_port = IKE_UDP_PORT;
 
@@ -484,10 +540,11 @@
     msg.keyval.ptr = NULL;
 
     msg.sa_ike_life_seconds = OAKLEY_ISAKMP_SA_LIFETIME_DEFAULT;
-    msg.sa_ipsec_life_seconds = SA_LIFE_DURATION_DEFAULT;
+    msg.sa_ipsec_life_seconds = PLUTO_SA_LIFE_DURATION_DEFAULT;
     msg.sa_rekey_margin = SA_REPLACEMENT_MARGIN_DEFAULT;
     msg.sa_rekey_fuzz = SA_REPLACEMENT_FUZZ_DEFAULT;
     msg.sa_keying_tries = SA_REPLACEMENT_RETRIES_DEFAULT;
+    msg.block_cypher = FORCE_ENCRYPT_CYPHER_DEFAULT;
 
     msg.addr_family = AF_INET;
     msg.tunnel_addr_family = AF_INET;
@@ -668,6 +725,37 @@
 	    msg.whack_async = TRUE;
 	    continue;
 
+#ifdef OPENSSL
+      case OPT_CERTFILE:
+          if (strlen(optarg) >= FILE_NAME_LIMIT)
+              diagq("certificate file name too long", optarg);
+              strcpy(msg.whack_certfile, optarg);
+        continue;
+
+      case OPT_CERTOPTS:
+          if (strlen(optarg) >= CERT_OPTIONS_LIMIT)
+              diagq("certificate file name too long", optarg);
+              strcpy(msg.whack_certopts, optarg);
+        continue;
+
+      case OPT_PEERFILE:
+          if (strlen(optarg) >= FILE_NAME_LIMIT)
+              diagq("peer certificate file name too long", optarg);
+              strcpy(msg.whack_peerfile, optarg);
+        continue;
+
+      case OPT_KEYFILE:
+          if (strlen(optarg) >= FILE_NAME_LIMIT)
+              diagq("key file name too long", optarg);
+              strcpy(msg.whack_keyfile, optarg);
+        continue;
+
+      case OPT_CERTPATH:
+          if (strlen(optarg) >= PATH_NAME_LIMIT)
+              diagq("certificate path name too long", optarg);
+              strcpy(msg.whack_certpath, optarg);
+        continue;
+#endif
 
 	/* Connection Description options */
 
@@ -737,7 +825,7 @@
 	    if ((cd_seen & LELEM(CD_HOST-CD_FIRST)) == 0)
 		diag("connection missing --host before --to");
 	    msg.left = msg.right;
-	    memset(&msg.right, '\0', sizeof(msg.right));
+	    zero(&msg.right);
 	    msg.right.id = NULL;
 	    msg.right.updown = NULL;
 	    msg.right.host_port = IKE_UDP_PORT;
@@ -746,12 +834,18 @@
 	    continue;
 
 	case CD_PSK:		/* --psk */
+#ifndef OPENSSL
 	case CD_RSASIG:	/* --rsasig */
+#else
+	case CD_OPENSSL:	/* --rsasig */
+#endif
 	case CD_ENCRYPT:	/* --encrypt */
 	case CD_AUTHENTICATE:	/* --authenticate */
 	case CD_COMPRESS:	/* --compress */
 	case CD_TUNNEL:	/* --tunnel */
-	case CD_PFS:	/* -- pfs */
+	case CD_PFS:	/* --pfs */
+	case CD_FAIL_PASS:	/* --pass */
+	case CD_FAIL_DROP:	/* --drop */
 	    msg.policy |= LELEM(c - CD_POLICY_FIRST);
 	    continue;
 
@@ -775,6 +869,20 @@
 	    msg.sa_keying_tries = opt_whole;
 	    continue;
 
+	/* DES support */
+	case CD_FORCE_ENCRYPT_CYPHER:   /* --force_encrypt_cypher <des/3des> */
+	if (strcmp("des", optarg) == 0) {
+	  msg.block_cypher = DES_BLOCK_CYPHER;
+	}
+	if (strcmp("3des", optarg) == 0) {
+	  msg.block_cypher = DES3_BLOCK_CYPHER;
+	}
+	/* else */
+	if ((strcmp("3des", optarg) != 0) && (strcmp("des", optarg) != 0)) {
+	  diag("--force_encrypt_cypher must have a parameter of either 'des' or '3des'");
+	}
+	continue;
+
 	case OPT_KEYID:	/* --keyid <identity> */
 	    msg.whack_key = TRUE;
 	    msg.keyid = optarg;	/* decoded by Pluto */
@@ -862,6 +970,7 @@
      * required information was supplied.
      */
 
+    /* check opportunistic initiation simulation request */
     switch (opts_seen & (LELEM(OPT_OPPO_HERE) | LELEM(OPT_OPPO_THERE)))
     {
     case LELEM(OPT_OPPO_HERE):
@@ -873,6 +982,7 @@
 	break;
     }
 
+    /* check connection description */
     if (opts_seen & LELEM(OPT_CD))
     {
 	if (!LALLIN(cd_seen, LELEM(CD_TO-CD_FIRST)))
@@ -893,6 +1003,10 @@
 
 	if (subnettypeof(&msg.left.client) != subnettypeof(&msg.right.client))
 	    diag("endpoints clash: one is IPv4 and the other is IPv6");
+
+       if (!HAS_IPSEC_POLICY(msg.policy)
+       && (msg.left.has_client || msg.right.has_client))
+           diag("must not specify clients for ISAKMP-only connection");
 
 	msg.whack_connection = TRUE;
     }
diff -bruN freeswan-1.9.orig/pluto/whack.h freeswan-1.9/pluto/whack.h
--- freeswan-1.9.orig/pluto/whack.h	Sun Jan 28 16:03:05 2001
+++ freeswan-1.9/pluto/whack.h	Wed Jun  6 16:10:04 2001
@@ -16,6 +16,10 @@
 
 #include <freeswan.h>
 
+#ifdef OPENSSL
+#include "openssl_defs.h"
+#endif
+
 /*
  * Since the message remains on one host, native representation is used.
  * Think of this as horizontal microcode: all selected operations are
@@ -83,6 +87,14 @@
     enum pubkey_alg pubkey_alg;
     chunk_t keyval;	/* chunk */
 
+#ifdef OPENSSL
+    char whack_certfile[FILE_NAME_LIMIT];
+    char whack_certopts[CERT_OPTIONS_LIMIT];
+    char whack_peerfile[FILE_NAME_LIMIT];
+    char whack_keyfile[FILE_NAME_LIMIT];
+    char whack_certpath[PATH_NAME_LIMIT];
+#endif
+
     /* for WHACK_ROUTE: */
     bool whack_route;
 
@@ -110,6 +122,10 @@
 
     /* for WHACK_SHUTDOWN */
     bool whack_shutdown;
+
+    /* for des type to use */
+    lset_t block_cypher;
+
 
     /* space for strings (hope there is enough room):
      * Note that pointers don't travel on wire.
diff -bruN freeswan-1.9.orig/pluto/x_sobj.c freeswan-1.9/pluto/x_sobj.c
--- freeswan-1.9.orig/pluto/x_sobj.c	Wed Dec 31 19:00:00 1969
+++ freeswan-1.9/pluto/x_sobj.c	Wed May 16 10:57:20 2001
@@ -0,0 +1,36 @@
+#ifdef OPENSSL
+#include "x_sobj.h"
+
+IMPLEMENT_STACK_OF(X509_OBJECT)
+
+X509_OBJECT *
+X509_OBJECT_new( const int type, void *p )
+{
+  X509_OBJECT *ret = Malloc(sizeof(X509_OBJECT));
+
+  if (ret == NULL) return ret;
+  switch(type) {
+  case X509_LU_X509:
+    ret->type = type;
+    ret->data.x509 = (X509 *)p;
+    break;
+  case X509_LU_CRL:
+    ret->type = type;
+    ret->data.crl = (X509_CRL *)p;
+    break;
+  default: /* Unknown type */
+    Free((char *)ret);
+    ret = NULL;
+    break;
+  }
+  return ret;
+}
+
+void
+X509_OBJECT_free(X509_OBJECT *x)
+{
+  if (!x) return;
+  X509_OBJECT_free_contents(x);
+  Free((char *)x);
+}
+#endif /* OPENSSL */
diff -bruN freeswan-1.9.orig/pluto/x_sobj.h freeswan-1.9/pluto/x_sobj.h
--- freeswan-1.9.orig/pluto/x_sobj.h	Wed Dec 31 19:00:00 1969
+++ freeswan-1.9/pluto/x_sobj.h	Wed May 16 10:57:20 2001
@@ -0,0 +1,12 @@
+#ifndef X_SOBJ_H
+#define X_SOBJ_H
+
+#include <openssl/x509.h>
+#include <openssl/x509_vfy.h>
+
+DECLARE_STACK_OF(X509_OBJECT)
+
+X509_OBJECT *X509_OBJECT_new( const int type, void *ptr );
+void X509_OBJECT_free(X509_OBJECT *x);
+
+#endif
diff -bruN freeswan-1.9.orig/pluto/xmap.c freeswan-1.9/pluto/xmap.c
--- freeswan-1.9.orig/pluto/xmap.c	Wed Dec 31 19:00:00 1969
+++ freeswan-1.9/pluto/xmap.c	Wed May 16 10:57:20 2001
@@ -0,0 +1,401 @@
+#ifdef OPENSSL
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include <openssl/stack.h>
+#include <openssl/asn1.h>
+#include <openssl/safestack.h>
+#include <openssl/pem.h>
+#include <openssl/x509.h>
+#include <openssl/x509v3.h>
+
+#include "x_sobj.h"
+#include "xmap_file.h"
+#include "xmap_dir.h"
+#include "xmap_db.h"
+#include "xmap_ldap.h"
+#include "xmap.h"
+
+#include <freeswan.h> /* needed by constants.h */
+#include "constants.h"
+#include "defs.h"
+#include "log.h"
+
+static XMAP_METHOD_LIST *xmth = NULL;
+
+XMAP *XMAP_new(const char *spec);
+STACK_OF(X509_OBJECT) *
+XMAP_lookup( XMAP *xm, const int type, const char *index, void *p );
+void XMAP_free(XMAP *xm);
+void XMAP_dump(XMAP *xm);
+
+int
+XMAP_register(XMAP_METHOD *meth)
+{
+  XMAP_METHOD_LIST *p;
+  int found;
+
+  for(p=xmth,found=0; ((!found) && (p)); p=p->next)
+    if (strcasecmp(meth->prefix, p->meth->prefix) == 0) found=1;
+
+  if (found) {
+    return 0;
+  } else {
+    p = malloc(sizeof(XMAP_METHOD_LIST));
+    if (p) {
+      p->next = xmth;
+      p->meth = meth;
+      xmth = p;
+    } else
+      return 0;
+  }
+  return 1;
+}
+
+void
+XMAP_METHOD_LIST_free( void )
+{
+  XMAP_METHOD_LIST *p, *q;
+
+  for(p=xmth; p;) {
+    q = p->next;
+    free(p);
+    q = p;
+  }
+}
+
+int
+XMAP_unregister(const char *prefix)
+{
+  XMAP_METHOD_LIST *p, *q;
+  int found;
+
+  for(p = xmth, found = 0; ((!found) && (p)); )
+    if (strcasecmp(p->meth->prefix, prefix) == 0)
+      found = 1;
+    else
+      p=p->next;
+
+  if (!found)
+    return 0;
+  else {
+    if ( p == xmth ) {
+      xmth = xmth->next;
+      free(p);
+    } else {
+      for(q = xmth; q->next != p; q = q->next);
+      q->next = p->next;
+      free(p);
+    }
+  }
+  return 1;
+}
+
+XMAP *
+XMAP_new(const char *spec)
+{
+  XMAP *ret;
+  char *s;
+
+  if ((ret = malloc(sizeof(XMAP))) == NULL) goto end;
+  if ((ret->spec = strdup(spec)) == NULL) goto end;
+  ret->methp = NULL;
+
+  if ((s = strchr(spec, DICT_SEPARATOR)) == NULL) {
+    log("No type prefix");
+  } else {
+    int l = (int)(s - spec) + 1;
+    XMAP_METHOD_LIST *p;
+    int found;
+
+    for(p=xmth, found = 0; ((!found) && (p));) {
+      if (strncasecmp(p->meth->prefix, spec, l-1) == 0)
+	found = 1;
+      else
+	p = p->next;
+    }
+
+    if (found) {
+      ret->pmap = p->meth->new(&s[1]);
+      if (! ret->pmap) goto end;
+      ret->methp = p;
+    } else {
+      log("Unknown map type spec: %s", spec);
+      goto end;
+    }
+  }
+  return ret;
+ end:
+  if (ret->spec) free(ret->spec);
+  if (ret) free(ret);
+  return NULL;
+}
+
+static int
+check_methp(XMAP *xm)
+{
+  XMAP_METHOD_LIST *p;
+
+  for(p = xmth; p; p = p->next)
+    if (xm->methp == p) {
+      return 1;
+    }
+
+  return 0;
+}
+
+STACK_OF(X509_OBJECT) *
+XMAP_lookup( XMAP *xm, const int type, const char *index, void *p )
+{
+  if ((!xm) || (!check_methp(xm)) || (! xm->methp->meth->lookup) )
+  {
+    return NULL;
+  }
+  return xm->methp->meth->lookup(xm->pmap, type, index, p);
+}
+
+void
+XMAP_free(XMAP *xm)
+{
+  if (!xm) return;
+  if (!xm->pmap) return;
+  if (!check_methp(xm)) return;
+  if (xm->methp->meth->free) xm->methp->meth->free(xm->pmap);
+  if (xm->spec) free(xm->spec);
+  free(xm);
+}
+
+void
+XMAP_dump(XMAP *xm)
+{
+  if (! xm->pmap) return;
+  if (!check_methp(xm)) return;
+  if (! xm->methp->meth->dump) return;
+  xm->methp->meth->dump(xm->pmap);
+}
+
+int
+X509_subjAltName_check_dns(X509 *x, const char *dns)
+{
+  int i, loc, ret;
+  X509_EXTENSION *ext;
+  u_char *p;
+  STACK_OF(GENERAL_NAME) *nsk = NULL;
+  GENERAL_NAME *gn;
+
+  ret = 0;
+  if ((loc = X509_get_ext_by_NID(x, NID_subject_alt_name, -1)) >= 0) {
+    if ((ext = X509_get_ext(x, loc)) != NULL) {
+      p = ext->value->data;
+      d2i_GENERAL_NAMES(&nsk, &p, ext->value->length);
+      if (nsk) {
+	for(i=0; i < sk_GENERAL_NAME_num(nsk); i++) {
+	  gn = sk_GENERAL_NAME_value(nsk, i);
+	  
+	  if (gn->type == GEN_DNS) {
+	    if (strncasecmp(dns, gn->d.ia5->data, gn->d.ia5->length) == 0) {
+	      ret = 1;
+	      break;
+	    }
+	  }
+	}
+	sk_GENERAL_NAME_free(nsk);
+	nsk = NULL;
+      }
+    }
+  }
+  return ret;
+}
+
+int
+X509_subjAltName_check_ip(X509 *x, const struct in_addr ip)
+{
+  int i, loc, ret;
+  X509_EXTENSION *ext;
+  u_char *p;
+  STACK_OF(GENERAL_NAME) *nsk = NULL;
+  GENERAL_NAME *gn;
+
+  ret = 0;
+  if ((loc = X509_get_ext_by_NID(x, NID_subject_alt_name, -1)) >= 0) {
+	if ((ext = X509_get_ext(x, loc)) != NULL) {
+		p = ext->value->data;
+		d2i_GENERAL_NAMES(&nsk, &p, ext->value->length);
+		if (nsk) {
+			for(i=0; i < sk_GENERAL_NAME_num(nsk); i++) {
+				gn = sk_GENERAL_NAME_value(nsk, i);
+	  
+				if (gn->type == GEN_IPADD) {
+					if (memcmp(&ip.s_addr, gn->d.ip->data, gn->d.ip->length) == 0) {
+						ret = 1;
+						break;
+					}
+				}
+			}
+			sk_GENERAL_NAME_free(nsk);
+			nsk = NULL;
+		}
+ 	 }
+  }
+  return ret;
+}
+
+
+/* some cloning procedures. needed to unshare connection
+ * for road warrior support.
+ */
+
+STACK_OF(XMAP) 
+*clone_sk_XMAP ( STACK_OF(XMAP) *sk_xm )
+{
+	/* declare new stack */
+	STACK_OF(XMAP) *temp_sk_xm;
+	int i;
+
+	/* clone contents of stack. Memory pointers stay the same
+	 * so further cloning for each sub-structure is needed.
+	 *
+	 * typedef struct stack_st
+	 * {
+	 *  int num;
+	 *  char **data;
+	 *  int sorted;
+	 *  int num_alloc;
+	 *  int (*comp)();
+	 * } STACK;
+	 */
+
+	temp_sk_xm = sk_XMAP_new_null();
+	for (i=0; i<sk_XMAP_num(sk_xm); i++) {
+	  XMAP *xm = sk_XMAP_value(sk_xm, i);
+
+	  /* clone XMAP */
+	  xm = clone_XMAP(xm);
+
+	  sk_XMAP_push(temp_sk_xm, xm);
+	}
+
+	/* return the newly cloned STACK_OF(XMAP) */
+	return temp_sk_xm;     
+}
+
+XMAP 
+*clone_XMAP ( XMAP *xm )
+{
+	XMAP *temp_xm;
+	/* cloning of XMAP....... 
+	 * typedef struct _xmap_st {
+	 *   char *spec;
+	 *   void *pmap;
+	 *   XMAP_METHOD_LIST *methp;
+	 * } XMAP;
+	 */
+
+	temp_xm = malloc(sizeof(XMAP));
+
+	temp_xm->spec = clone_str(xm->spec, "cloning XMAP spec");
+	temp_xm->pmap = clone_XMAP_pmap(xm->pmap, xm->spec);
+
+	/* let's try without cloning the XMAP_METHOD_LIST, so that
+	 * check_methp will work.
+	 * temp_xm->methp = clone_XMAP_METHOD_LIST(xm->methp);
+	 */ 
+	temp_xm->methp = xm->methp;
+
+	return temp_xm;
+}
+
+XMAP_METHOD_LIST 
+*clone_XMAP_METHOD_LIST ( XMAP_METHOD_LIST *xm_l )
+{
+	XMAP_METHOD_LIST *temp_xm_l;
+
+	/*
+	 * typedef struct _xmap_method_list_st {
+	 *   XMAP_METHOD *meth;
+	 *   struct _xmap_method_list_st *next;
+	 * } XMAP_METHOD_LIST;
+	 *
+	 * Recursive cloning...
+	 */
+
+	temp_xm_l = malloc(sizeof(XMAP_METHOD_LIST));
+	if (xm_l->next) {
+		temp_xm_l->next = clone_XMAP_METHOD_LIST(xm_l->next);
+	} else {
+		temp_xm_l->next = NULL;
+	}
+
+	temp_xm_l->meth = clone_XMAP_METHOD(xm_l->meth);
+	return temp_xm_l;
+}
+
+
+XMAP_METHOD
+*clone_XMAP_METHOD ( XMAP_METHOD *xm_m )
+{
+	XMAP_METHOD *temp_xm_m;
+
+	/*
+	 * typedef struct _xmap_method_st {
+	 *   char *prefix;
+	 *     STACK_OF(X509_OBJECT) *(*lookup)( void *this, 
+	 *        const int type, const char *index, void *p );
+	 *   void (*dump)(void *pmap);
+	 *   void (*free)(void *pmap);
+	 *   void *(*new) (const char *spec);
+	 * } XMAP_METHOD;
+	 */
+
+
+	temp_xm_m = malloc(sizeof(XMAP_METHOD));
+
+	if (xm_m->prefix) {
+		temp_xm_m->prefix = clone_str(xm_m->prefix, 
+			"cloning XMAP_METHOD prefix");
+	}
+
+	/* don't clone the following */
+	temp_xm_m->lookup = xm_m->lookup;
+	temp_xm_m->dump = xm_m->dump;
+	temp_xm_m->free = xm_m->free;
+	temp_xm_m->new = xm_m->new;
+
+	return temp_xm_m;
+}
+
+void
+*clone_XMAP_pmap ( void *pmap, char *spec )
+{
+	void *t_pmap;
+	char *s;
+	int l, found;
+	XMAP_METHOD_LIST *p;
+
+	s = strchr(spec, DICT_SEPARATOR);
+	l = (int)(s - spec) + 1;
+
+	for(p=xmth, found = 0; ((!found) && (p));) {
+	  if (strncasecmp(p->meth->prefix, spec, l-1) == 0) {
+	    found = 1;
+	   } else {
+	    p = p->next;
+           }
+	}
+
+	if (found) {
+	  t_pmap = p->meth->new(&s[1]);
+	}
+
+	return t_pmap;
+}
+
+
+IMPLEMENT_STACK_OF(XMAP)
+#endif /* OPENSSL */
diff -bruN freeswan-1.9.orig/pluto/xmap.h freeswan-1.9/pluto/xmap.h
--- freeswan-1.9.orig/pluto/xmap.h	Wed Dec 31 19:00:00 1969
+++ freeswan-1.9/pluto/xmap.h	Wed May 16 10:57:20 2001
@@ -0,0 +1,62 @@
+#ifndef XMAP_H
+#define XMAP_H
+
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include <openssl/safestack.h>
+#include <openssl/x509.h>
+#include <openssl/x509_vfy.h>
+
+#include "x_sobj.h"
+
+typedef struct _xmap_method_st {
+  char *prefix;
+    STACK_OF(X509_OBJECT) *(*lookup)( void *this, const int type, const char *index, void *p );
+  void (*dump)(void *pmap);
+  void (*free)(void *pmap);
+  void *(*new) (const char *spec);
+} XMAP_METHOD;
+
+typedef struct _xmap_method_list_st {
+  XMAP_METHOD *meth;
+  struct _xmap_method_list_st *next;
+} XMAP_METHOD_LIST;
+
+typedef struct _xmap_st {
+  char *spec;
+  void *pmap;
+  XMAP_METHOD_LIST *methp;
+} XMAP;
+
+DECLARE_STACK_OF(XMAP)
+
+#ifndef DICT_SEPARATOR
+#define DICT_SEPARATOR ':'
+#endif
+
+#define XMAP_UNKNOWN_TYPE 0
+#define XMAP_FILE_TYPE    1
+#define XMAP_DIR_TYPE     2
+#define XMAP_DB_TYPE      3
+
+int XMAP_register(XMAP_METHOD *meth);
+void XMAP_METHOD_LIST_free( void );
+int XMAP_unregister(const char *prefix);
+
+int X509_subjAltName_check_dns(X509 *x, const char *dns);
+int X509_subjAltName_check_ip(X509 *x, const struct in_addr in);
+
+XMAP *XMAP_new(const char *spec);
+STACK_OF(X509_OBJECT) *XMAP_lookup( XMAP *xm, const int type, const char *index, void *p );
+void XMAP_free(XMAP *xm);
+void XMAP_dump(XMAP *xm);
+
+extern STACK_OF(XMAP) *clone_sk_XMAP ( STACK_OF(XMAP) *sk_xm );
+extern XMAP *clone_XMAP ( XMAP *xm );
+extern void *clone_XMAP_pmap ( void *pmap, char *spec );
+extern XMAP_METHOD_LIST *clone_XMAP_METHOD_LIST ( XMAP_METHOD_LIST *xm_l );
+extern XMAP_METHOD *clone_XMAP_METHOD ( XMAP_METHOD *xm_m );
+
+#endif /* XMAP_H */
diff -bruN freeswan-1.9.orig/pluto/xmap_db.c freeswan-1.9/pluto/xmap_db.c
--- freeswan-1.9.orig/pluto/xmap_db.c	Wed Dec 31 19:00:00 1969
+++ freeswan-1.9/pluto/xmap_db.c	Wed May 16 10:57:20 2001
@@ -0,0 +1,574 @@
+#ifdef OPENSSL
+#if defined(HAVE_DB) || (HAVE_DB185)
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <errno.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#ifdef HAVE_DB185
+#include <db_185.h>
+#else
+#include <db.h>
+#endif
+
+#include <openssl/bio.h>
+#include <openssl/pem.h>
+#include <openssl/x509v3.h>
+
+#include "xmap_db.h"
+
+#include <freeswan.h> /* needed by constants.h */
+#include "constants.h"
+#include "defs.h"
+#include "log.h"
+
+static void XMAP_DB_dump(void *this);
+static void XMAP_DB_free(void *this);
+static void *XMAP_DB_new(const char *dbname);
+static STACK_OF(X509_OBJECT) *
+XMAP_DB_lookup( void *this, const int type, const char *index, void *p );
+static STACK_OF(X509_OBJECT) *
+XMAP_DB_lookup_cert_by_subject( XMAP_DB *xm, X509_NAME *name );
+static STACK_OF(X509_OBJECT) *
+XMAP_DB_lookup_cert_by_issuer( XMAP_DB *xm, X509_NAME *name );
+static STACK_OF(X509_OBJECT) *
+XMAP_DB_lookup_crl_by_issuer( XMAP_DB *xm, X509_NAME *name );
+static STACK_OF(X509_OBJECT) *
+XMAP_DB_lookup_cert_by_uid( XMAP_DB *xm, const char *uid );
+static STACK_OF(X509_OBJECT) *
+XMAP_DB_lookup_cert_by_dns( XMAP_DB *xm, const char *dns );
+static STACK_OF(X509_OBJECT) *
+XMAP_DB_lookup_cert_by_ip( XMAP_DB *xm, const struct in_addr ip);
+static STACK_OF(X509_OBJECT) *
+XMAP_DB_lookup_ca_certs( XMAP_DB *xm );
+
+#define TAGLEN 4
+
+static unsigned char tag_cert[] = { 0x00, 0x00, 0x00, 0x00 };
+static unsigned char tag_subj[] = { 0x00, 0x00, 0x00, 0x01 };
+static unsigned char tag_csub[] = { 0x00, 0x00, 0x00, 0x02 };
+static unsigned char tag_uid[] = { 0x00, 0x00, 0x00, 0x03 };
+static unsigned char tag_crl[] = { 0x00, 0x00, 0x00, 0x04 };
+static unsigned char tag_ca[] = { 0x00, 0x00, 0x00, 0x05 };
+static unsigned char tag_dns[] = { 0x00, 0x00, 0x00, 0x06 };
+static unsigned char tag_ip[] = { 0x00, 0x00, 0x00, 0x07 };
+
+#define DBZ(x) memset(&(x), 0, sizeof((x)))
+
+static XMAP_METHOD xmap_db_methods = {
+  "db",
+  XMAP_DB_lookup,
+  XMAP_DB_dump,
+  XMAP_DB_free,
+  XMAP_DB_new
+};
+
+void *
+XMAP_DB_new(const char *dbname)
+{
+  XMAP_DB *ret;
+
+  if ((ret = alloc_thing(XMAP_DB, "xmap_db")) == NULL) goto end;
+  if ((ret->dbname = clone_bytes(dbname, strlen(dbname)+1, "dbname")) == NULL)
+    goto end;
+  if ((ret->db = dbopen(dbname, O_RDONLY, 0, DB_HASH, NULL)) == NULL)
+    goto end;
+
+  ret->meth = &xmap_db_methods;
+
+  return (void *)ret;
+ end:
+  if (ret->db) ret->db->close(ret->db);
+  if (ret->dbname) pfree(ret->dbname);
+  if (ret) pfree(ret);
+  return NULL;
+}
+
+static STACK_OF(X509_OBJECT) *
+XMAP_DB_lookup( void *this, const int type, const char *index, void *p )
+{
+  XMAP_DB *xm = (XMAP_DB *)this;
+
+  switch(type) {
+  case X509_LU_X509:
+    if (strcasecmp(index, "subject") == 0)
+      return XMAP_DB_lookup_cert_by_subject( xm, (X509_NAME *)p);
+    if (strcasecmp(index, "issuer") == 0)
+      return XMAP_DB_lookup_cert_by_issuer( xm, (X509_NAME *)p);
+    else if (strcasecmp(index, "uid") == 0)
+      return XMAP_DB_lookup_cert_by_uid( xm, (char  *)p);
+    else if (strcasecmp(index, "dns") == 0)
+      return XMAP_DB_lookup_cert_by_dns( xm, (char  *)p);
+    else if (strcasecmp(index, "ip") == 0)
+      return XMAP_DB_lookup_cert_by_ip( xm, *((struct in_addr *)p));
+    else if (strcasecmp(index, "ca") == 0)
+      return XMAP_DB_lookup_ca_certs( xm );
+    else
+      return NULL;
+    break;
+  case X509_LU_CRL:
+    if (strcasecmp(index, "issuer") == 0)
+      return XMAP_DB_lookup_crl_by_issuer( xm, (X509_NAME *)p);
+    else
+      return NULL;
+    break;
+  default:
+    return NULL;
+  }
+}
+
+static STACK_OF(X509_OBJECT) *
+XMAP_DB_lookup_cert_by_subject(XMAP_DB *xm, X509_NAME *name)
+{
+  STACK_OF(X509_OBJECT) *sk = sk_X509_OBJECT_new_null();
+  DBT k, v;
+  unsigned char *d, *dum;
+  unsigned int i, dlen;
+
+  DBZ(k);
+  DBZ(v);
+  if (!xm->db) goto end;
+  dlen = i2d_X509_NAME(name, NULL);
+  if ((d = alloc_bytes(dlen + TAGLEN, "ASN.1 name")) == NULL) goto end;
+  dum = &d[TAGLEN];
+  memcpy(d, tag_subj, TAGLEN);
+  i2d_X509_NAME(name, &dum);
+  k.data = d;
+  k.size = dlen + TAGLEN;
+  if (xm->db->get(xm->db, &k, &v, 0) == 0) {
+    u_int32_t c1, c2;
+
+    memcpy((unsigned char *)&c1, v.data, sizeof(c1));
+    c2 = ntohl(c1);
+    pfree(d); d = NULL;
+    dlen = SHA_DIGEST_LENGTH + TAGLEN;
+    if ((d = alloc_bytes(dlen, "SHA-1 tag")) == NULL) goto end;
+    memcpy(d, tag_cert, TAGLEN);
+    for(i=0; i<c2; i++) {
+      unsigned char *vv = v.data;
+      DBT v2;
+
+      DBZ(v2);
+      memcpy(&(d[TAGLEN]), &vv[i*SHA_DIGEST_LENGTH+TAGLEN], SHA_DIGEST_LENGTH);
+      k.data = d;
+      k.size = dlen;
+      if (xm->db->get(xm->db, &k, &v2, 0) == 0) {
+	X509 *x;
+	dum = (unsigned char *)v2.data;
+	if ((x = d2i_X509(NULL, &dum, v2.size)) != NULL) {
+	  X509_OBJECT *xo = X509_OBJECT_new( X509_LU_X509, x);
+	  if (x)
+	    sk_X509_OBJECT_push(sk, xo);
+	  else
+	    X509_free(x);
+	}
+      }
+    }
+    pfree(d); d = NULL;
+  }
+ end:
+  if (d) pfree(d);
+  return sk;
+}
+
+static STACK_OF(X509_OBJECT) *
+XMAP_DB_lookup_cert_by_issuer(XMAP_DB *xm, X509_NAME *name)
+{
+  STACK_OF(X509_OBJECT) *sk = sk_X509_OBJECT_new_null();
+  DBT k, v;
+  unsigned char *d, *dum;
+  unsigned int i, dlen;
+
+  DBZ(k);
+  DBZ(v);
+  if (!xm->db) goto end;
+  dlen = i2d_X509_NAME(name, NULL);
+  if ((d = alloc_bytes(dlen + TAGLEN, "ASN.1 name")) == NULL) goto end;
+  dum = &d[TAGLEN];
+  memcpy(d, tag_subj, TAGLEN);
+  i2d_X509_NAME(name, &dum);
+  k.data = d;
+  k.size = dlen + TAGLEN;
+  if (xm->db->get(xm->db, &k, &v, 0) == 0) {
+    u_int32_t c1, c2;
+
+    memcpy((unsigned char *)&c1, v.data, sizeof(c1));
+    c2 = ntohl(c1);
+    pfree(d); d = NULL;
+    dlen = SHA_DIGEST_LENGTH + TAGLEN;
+    if ((d = alloc_bytes(dlen, "SHA-1 tag")) == NULL) goto end;
+    memcpy(d, tag_cert, TAGLEN);
+    for(i=0; i<c2; i++) {
+      unsigned char *vv = v.data;
+      DBT v2;
+
+      DBZ(v2);
+      memcpy(&(d[TAGLEN]), &vv[i*SHA_DIGEST_LENGTH+TAGLEN], SHA_DIGEST_LENGTH);
+      k.data = d;
+      k.size = dlen;
+      if (xm->db->get(xm->db, &k, &v2, 0) == 0) {
+	X509 *x;
+	dum = (unsigned char *)v2.data;
+	if ((x = d2i_X509(NULL, &dum, v2.size)) != NULL) {
+	  X509_OBJECT *xo = X509_OBJECT_new( X509_LU_X509, x);
+	  if (x)
+	    sk_X509_OBJECT_push(sk, xo);
+	  else
+	    X509_free(x);
+	}
+      }
+    }
+    pfree(d); d = NULL;
+  }
+ end:
+  if (d) pfree(d);
+  return sk;
+}
+
+static int
+isCA( X509 *x )
+{
+  X509_EXTENSION *ext;
+  BASIC_CONSTRAINTS *p = NULL;
+  int loc;
+  
+  loc = X509_get_ext_by_NID(x, NID_basic_constraints, -1);
+  if (loc >= 0) {
+    ext = X509_get_ext(x, loc);
+    if (ext) {
+      p = X509V3_EXT_d2i(ext);
+      if (! p->ca) {
+	BASIC_CONSTRAINTS_free(p);
+	return 0;
+      } else {
+	BASIC_CONSTRAINTS_free(p);
+	return 1; /* This is a CA certificate */
+      }
+    } else
+      return 0;
+  } else
+    return 0;
+}
+
+static STACK_OF(X509_OBJECT) *
+XMAP_DB_lookup_crl_by_issuer(XMAP_DB *xm, X509_NAME *name)
+{
+  STACK_OF(X509_OBJECT) *sk = sk_X509_OBJECT_new_null();
+  DBT k, v;
+  unsigned char *d, *dum;
+  unsigned int i, dlen;
+
+  DBZ(k);
+  DBZ(v);
+  if (!xm->db) goto end;
+  dlen = i2d_X509_NAME(name, NULL);
+  if ((d = alloc_bytes(dlen + TAGLEN, "ASN.1 name")) == NULL) goto end;
+  dum = &d[TAGLEN];
+  memcpy(d, tag_csub, TAGLEN);
+  i2d_X509_NAME(name, &dum);
+  k.data = d;
+  k.size = dlen + TAGLEN;
+  if (xm->db->get(xm->db, &k, &v, 0) == 0) {
+    u_int32_t c1, c2;
+
+    memcpy((unsigned char *)&c1, v.data, sizeof(c1));
+    c2 = ntohl(c1);
+    pfree(d); d = NULL;
+    dlen = SHA_DIGEST_LENGTH + TAGLEN;
+    if ((d = alloc_bytes(dlen, "SHA-1 tag")) == NULL) goto end;
+    memcpy(d, tag_crl, TAGLEN);
+    for(i=0; i<c2; i++) {
+      unsigned char *vv = v.data;
+      DBT v2;
+
+      DBZ(v2);
+      memcpy(&(d[TAGLEN]), &vv[i*SHA_DIGEST_LENGTH+TAGLEN], SHA_DIGEST_LENGTH);
+      k.data = d;
+      k.size = dlen;
+      if (xm->db->get(xm->db, &k, &v2, 0) == 0) {
+	X509_CRL *c;
+	dum = (unsigned char *)v2.data;
+	if ((c = d2i_X509_CRL(NULL, &dum, v2.size)) != NULL) {
+	  X509_OBJECT *xo = X509_OBJECT_new(X509_LU_CRL, c);
+
+	  if (xo)
+	    sk_X509_OBJECT_push(sk, xo);
+	  else
+	    X509_CRL_free(c);
+	}
+      }
+    }
+    pfree(d); d = NULL;
+  }
+ end:
+  if (d) pfree(d);
+  return sk;
+}
+
+static STACK_OF(X509_OBJECT) *
+XMAP_DB_lookup_ca_certs( XMAP_DB *xm )
+{
+  STACK_OF(X509_OBJECT) *sk = sk_X509_OBJECT_new_null();
+  DBT k, v;
+  unsigned char *d, *dum;
+  unsigned int i, dlen;
+
+  DBZ(k);
+  DBZ(v);
+  if (!xm->db) goto end;
+  if ((d = alloc_bytes(TAGLEN, "CA tag")) == NULL) goto end;
+  memcpy(d, tag_ca, TAGLEN);
+  k.data = d;
+  k.size = TAGLEN;
+  if (xm->db->get(xm->db, &k, &v, 0) == 0) {
+    u_int32_t c1, c2;
+
+    memcpy((unsigned char *)&c1, v.data, sizeof(c1));
+    c2 = ntohl(c1);
+    pfree(d); d = NULL;
+    dlen = SHA_DIGEST_LENGTH + TAGLEN;
+    if ((d = alloc_bytes(dlen, "SHA-1 tag")) == NULL) goto end;
+    memcpy(d, tag_cert, TAGLEN);
+    for(i=0; i<c2; i++) {
+      unsigned char *vv = v.data;
+      DBT v2;
+
+      DBZ(v2);
+      memcpy(&(d[TAGLEN]), &vv[(i*SHA_DIGEST_LENGTH)+TAGLEN],
+	     SHA_DIGEST_LENGTH);
+      k.data = d;
+      k.size = dlen;
+      if (xm->db->get(xm->db, &k, &v2, 0) == 0) {
+	X509 *x;
+	dum = (unsigned char *)v2.data;
+	if (((x = d2i_X509(NULL, &dum, v2.size)) != NULL) && (isCA(x))) {
+	  X509_OBJECT *xo = X509_OBJECT_new( X509_LU_X509, x);
+
+	  if (xo) 
+	    sk_X509_OBJECT_push(sk, xo);
+	  else
+	    X509_free(x);
+	}
+      }
+    }
+    pfree(d); d = NULL;
+  }
+ end:
+  if (d) pfree(d);
+  return sk;
+}
+
+static STACK_OF(X509_OBJECT) *
+XMAP_DB_lookup_cert_by_uid(XMAP_DB *xm, const char *uid)
+{
+  STACK_OF(X509_OBJECT) *sk = sk_X509_OBJECT_new_null();
+  DBT k, v;
+  unsigned char *d, *dum;
+  unsigned int i, ulen, dlen;
+
+  DBZ(k);
+  DBZ(v);
+  if (!xm->db) goto end;
+  ulen = strlen(uid);
+  if ((d = alloc_bytes(ulen + TAGLEN, "uid tag")) == NULL) goto end;
+  memcpy(d, tag_uid, TAGLEN);
+  strncpy(&d[TAGLEN], uid, ulen);
+  k.data = d;
+  k.size = ulen + TAGLEN;
+  if (xm->db->get(xm->db, &k, &v, 0) == 0) {
+    u_int32_t c1, c2;
+
+    memcpy((unsigned char *)&c1, v.data, sizeof(c1));
+    c2 = ntohl(c1);
+    pfree(d); d = NULL;
+    dlen = SHA_DIGEST_LENGTH + TAGLEN;
+    if ((d = alloc_bytes(dlen, "SHA-1 tag")) == NULL) goto end;
+    memcpy(d, tag_cert, TAGLEN);
+    for(i=0; i<c2; i++) {
+      unsigned char *vv = v.data;
+      DBT v2;
+
+      DBZ(v2);
+      memcpy(&(d[TAGLEN]), &vv[(i*SHA_DIGEST_LENGTH)+TAGLEN],
+	     SHA_DIGEST_LENGTH);
+      k.data = d;
+      k.size = dlen;
+      if (xm->db->get(xm->db, &k, &v2, 0) == 0) {
+	X509 *x;
+	dum = (unsigned char *)v2.data;
+	if ((x = d2i_X509(NULL, &dum, v2.size)) != NULL) {
+	  X509_OBJECT *xo = X509_OBJECT_new( X509_LU_X509, x);
+
+	  if (xo) 
+	    sk_X509_OBJECT_push(sk, xo);
+	  else
+	    X509_free(x);
+	}
+      }
+    }
+    pfree(d); d = NULL;
+  }
+ end:
+  if (d) pfree(d);
+  return sk;
+}
+
+static STACK_OF(X509_OBJECT) *
+XMAP_DB_lookup_cert_by_dns(XMAP_DB *xm, const char *dns)
+{
+  STACK_OF(X509_OBJECT) *sk = sk_X509_OBJECT_new_null();
+  DBT k, v;
+  unsigned char *d, *dum;
+  unsigned int i, ulen, dlen;
+
+  DBZ(k);
+  DBZ(v);
+  if (!xm->db) goto end;
+  ulen = strlen(dns);
+  if ((d = alloc_bytes(ulen + TAGLEN, "dns tag")) == NULL) goto end;
+  memcpy(d, tag_dns, TAGLEN);
+  strncpy(&d[TAGLEN], dns, ulen);
+  k.data = d;
+  k.size = ulen + TAGLEN;
+  if (xm->db->get(xm->db, &k, &v, 0) == 0) {
+    u_int32_t c1, c2;
+
+    memcpy((unsigned char *)&c1, v.data, sizeof(c1));
+    c2 = ntohl(c1);
+    pfree(d); d = NULL;
+    dlen = SHA_DIGEST_LENGTH + TAGLEN;
+    if ((d = alloc_bytes(dlen, "SHA-1 tag")) == NULL) goto end;
+    memcpy(d, tag_cert, TAGLEN);
+    for(i=0; i<c2; i++) {
+      unsigned char *vv = v.data;
+      DBT v2;
+
+      DBZ(v2);
+      memcpy(&(d[TAGLEN]), &vv[(i*SHA_DIGEST_LENGTH)+TAGLEN],
+	     SHA_DIGEST_LENGTH);
+      k.data = d;
+      k.size = dlen;
+      if (xm->db->get(xm->db, &k, &v2, 0) == 0) {
+	X509 *x;
+	dum = (unsigned char *)v2.data;
+	if ((x = d2i_X509(NULL, &dum, v2.size)) != NULL) {
+	  if (X509_subjAltName_check_dns(x, dns)) {
+	    X509_OBJECT *xo = X509_OBJECT_new( X509_LU_X509, x);
+	    
+	    if (xo) 
+	      sk_X509_OBJECT_push(sk, xo);
+	    else
+	      X509_free(x);
+	  } else 
+	    X509_free(x);
+	}
+      }
+    }
+    pfree(d); d = NULL;
+  }
+ end:
+  if (d) free(d);
+  return sk;
+}
+
+static STACK_OF(X509_OBJECT) *
+XMAP_DB_lookup_cert_by_ip(XMAP_DB *xm, const struct in_addr ip)
+{
+  STACK_OF(X509_OBJECT) *sk = sk_X509_OBJECT_new_null();
+  DBT k, v;
+  unsigned char *d, *dum;
+  unsigned int i, ulen, dlen;
+
+  DBZ(k);
+  DBZ(v);
+  if (!xm->db) goto end;
+  ulen = sizeof(ip.s_addr);
+  if ((d = alloc_bytes(ulen + TAGLEN, "ip tag")) == NULL) goto end;
+  memcpy(d, tag_ip, TAGLEN);
+  memcpy(&d[TAGLEN], &ip.s_addr, ulen);
+  k.data = d;
+  k.size = ulen + TAGLEN;
+  if (xm->db->get(xm->db, &k, &v, 0) == 0) {
+    u_int32_t c1, c2;
+
+    memcpy((unsigned char *)&c1, v.data, sizeof(c1));
+    c2 = ntohl(c1);
+    pfree(d); d = NULL;
+    dlen = SHA_DIGEST_LENGTH + TAGLEN;
+    if ((d = alloc_bytes(dlen, "SHA-1 tag")) == NULL) goto end;
+    memcpy(d, tag_cert, TAGLEN);
+    for(i=0; i<c2; i++) {
+      unsigned char *vv = v.data;
+      DBT v2;
+
+      DBZ(v2);
+      memcpy(&(d[TAGLEN]), &vv[(i*SHA_DIGEST_LENGTH)+TAGLEN],
+	     SHA_DIGEST_LENGTH);
+      k.data = d;
+      k.size = dlen;
+      if (xm->db->get(xm->db, &k, &v2, 0) == 0) {
+	X509 *x;
+	dum = (unsigned char *)v2.data;
+
+        DBG(DBG_PARSING | DBG_RAW,
+        DBG_log("** v2 length: %d", v2.size);
+        );
+        DBG(DBG_RAW,
+        DBG_dump("** v2: ", v2.data, v2.size);
+        );
+
+	if ((x = d2i_X509(NULL, &dum, v2.size)) != NULL) {
+	  if (X509_subjAltName_check_ip(x, ip)) {
+	    X509_OBJECT *xo = X509_OBJECT_new( X509_LU_X509, x);
+	    
+	    if (xo) 
+	      sk_X509_OBJECT_push(sk, xo);
+	    else
+	      X509_free(x);
+	  }
+	} else
+	  X509_free(x);
+      }
+    }
+    pfree(d); d = NULL;
+  }
+ end:
+  if (d) pfree(d);
+  return sk;
+}
+
+static void
+XMAP_DB_dump(void *this)
+{
+  XMAP_DB *xm = (XMAP_DB *)this;
+  DBG(DBG_PARSING,
+  DBG_log("XMAP_DB: %s", xm->dbname);
+  );
+}
+
+static void
+XMAP_DB_free(void *this)
+{
+  XMAP_DB *xm = (XMAP_DB *)this;
+
+  if (!xm) return;
+  if (xm->dbname) pfree(xm->dbname);
+  if (xm->db) xm->db->close(xm->db);
+  pfree(xm);
+}
+
+XMAP_METHOD *
+XMAP_METHOD_db( void )
+{
+  return (&xmap_db_methods);
+}
+#endif /* HAVE_DB */
+#endif /* OPENSSL */
diff -bruN freeswan-1.9.orig/pluto/xmap_db.h freeswan-1.9/pluto/xmap_db.h
--- freeswan-1.9.orig/pluto/xmap_db.h	Wed Dec 31 19:00:00 1969
+++ freeswan-1.9/pluto/xmap_db.h	Wed May 16 10:57:20 2001
@@ -0,0 +1,27 @@
+#ifndef XMAP_DB_H
+#define XMAP_DB_H
+
+#if defined(HAVE_DB) || defined(HAVE_DB185)
+
+#include <openssl/safestack.h>
+#include <openssl/x509.h>
+
+#ifdef HAVE_DB185
+#include <db_185.h>
+#else
+#include <db.h>
+#endif
+
+#include "x_sobj.h"
+#include "xmap.h"
+
+typedef struct xmap_db_st {
+  char *dbname;
+  DB *db;
+  XMAP_METHOD *meth;
+} XMAP_DB;
+
+XMAP_METHOD *XMAP_METHOD_db( void );
+
+#endif /* HAVE_DB */
+#endif /* XMAP_DB_H */
diff -bruN freeswan-1.9.orig/pluto/xmap_dir.c freeswan-1.9/pluto/xmap_dir.c
--- freeswan-1.9.orig/pluto/xmap_dir.c	Wed Dec 31 19:00:00 1969
+++ freeswan-1.9/pluto/xmap_dir.c	Wed May 16 10:57:20 2001
@@ -0,0 +1,545 @@
+#ifdef OPENSSL
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <dirent.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <errno.h>
+
+#include <openssl/bio.h>
+#include <openssl/pem.h>
+#include <openssl/err.h>
+#include <openssl/x509.h>
+#include <openssl/x509v3.h>
+
+#include "xmap_dir.h"
+#include "xmap.h"
+
+#include <freeswan.h> /* needed by constants.h */
+#include "constants.h"
+#include "defs.h"
+#include "log.h"
+
+static void XMAP_DIR_dump(void *this);
+static void XMAP_DIR_free(void *this);
+static void *XMAP_DIR_new(const char *dir);
+static STACK_OF(X509_OBJECT) *
+XMAP_DIR_lookup( void *this, const int type, const char *index, void *p );
+static STACK_OF(X509_OBJECT) *
+XMAP_DIR_lookup_cert_by_subject( XMAP_DIR *xm, X509_NAME *name );
+static STACK_OF(X509_OBJECT) *
+XMAP_DIR_lookup_cert_by_issuer( XMAP_DIR *xm, X509_NAME *name );
+static STACK_OF(X509_OBJECT) *
+XMAP_DIR_lookup_crl_by_issuer( XMAP_DIR *xm, X509_NAME *name );
+static STACK_OF(X509_OBJECT) *
+XMAP_DIR_lookup_cert_by_uid( XMAP_DIR *xm, const char *uid );
+static STACK_OF(X509_OBJECT) *
+XMAP_DIR_lookup_cert_by_dns( XMAP_DIR *xm, const char *dns );
+static STACK_OF(X509_OBJECT) *
+XMAP_DIR_lookup_cert_by_ip( XMAP_DIR *xm, const struct in_addr ip );
+static STACK_OF(X509_OBJECT) *
+XMAP_DIR_lookup_ca_certs( XMAP_DIR *xm );
+
+static XMAP_METHOD xmap_dir_methods = {
+  "dir",
+  XMAP_DIR_lookup,
+  XMAP_DIR_dump,
+  XMAP_DIR_free,
+  XMAP_DIR_new
+};
+
+static void *
+XMAP_DIR_new(const char *dir)
+{
+  XMAP_DIR *ret;
+
+  if ((ret = alloc_thing(XMAP_DIR, "xmap_dir")) == NULL) goto end;
+  if ((ret->dir = clone_bytes(dir, strlen(dir)+1, "directory name")) == NULL)
+    goto end;
+  ret->meth = &xmap_dir_methods;
+
+  return (void *)ret;
+ end:
+  if (ret->dir) pfree(ret->dir);
+  if (ret) pfree(ret);
+  return NULL;
+}
+
+static int
+isCA( X509 *x )
+{
+  X509_EXTENSION *ext;
+  BASIC_CONSTRAINTS *p = NULL;
+  int loc;
+  
+  loc = X509_get_ext_by_NID(x, NID_basic_constraints, -1);
+  if (loc >= 0) {
+    ext = X509_get_ext(x, loc);
+    if (ext) {
+      p = X509V3_EXT_d2i(ext);
+      if (! p->ca) {
+	BASIC_CONSTRAINTS_free(p);
+	return 0;
+      } else {
+	BASIC_CONSTRAINTS_free(p);
+	return 1; /* This is a CA certificate */
+      }
+    } else
+      return 0;
+  } else
+    return 0;
+}
+
+static STACK_OF(X509_OBJECT) *
+XMAP_DIR_lookup( void *this, const int type, const char *index, void *p )
+{
+  XMAP_DIR *xm = (XMAP_DIR *)this;
+
+  switch(type) {
+  case X509_LU_X509:
+    if (strcasecmp(index, "subject") == 0)
+      return XMAP_DIR_lookup_cert_by_subject( xm, (X509_NAME *)p);
+    if (strcasecmp(index, "issuer") == 0)
+      return XMAP_DIR_lookup_cert_by_issuer( xm, (X509_NAME *)p);
+    else if (strcasecmp(index, "uid") == 0)
+      return XMAP_DIR_lookup_cert_by_uid( xm, (char  *)p);
+    else if (strcasecmp(index, "dns") == 0)
+      return XMAP_DIR_lookup_cert_by_dns( xm, (char  *)p);
+    else if (strcasecmp(index, "ip") == 0)
+      return XMAP_DIR_lookup_cert_by_ip( xm, *(struct in_addr *)p);
+    else if (strcasecmp(index, "ca") == 0)
+      return XMAP_DIR_lookup_ca_certs( xm );
+    else
+      return NULL;
+    break;
+  case X509_LU_CRL:
+    if (strcasecmp(index, "issuer") == 0)
+      return XMAP_DIR_lookup_crl_by_issuer( xm, (X509_NAME *)p);
+    else
+      return NULL;
+    break;
+  default:
+    return NULL;
+  }
+}
+
+static char hashval[PATH_MAX+1] = "";
+static char dirname[PATH_MAX+1] = "";
+
+static int
+hash_select(const struct dirent *de)
+{
+  int l = strlen(hashval);
+
+  if (strncmp(de->d_name, hashval, l) == 0) {
+    return 1;
+  } else {
+    return 0;
+  }
+}
+
+static int
+select_files(const struct dirent *de)
+{
+  struct stat st;
+  char path[PATH_MAX+1];
+  
+  snprintf(path, sizeof(path), "%s/%s", dirname, de->d_name);
+  if (lstat(path, &st) == 0) {
+    if (S_ISREG(st.st_mode))
+      return 1;
+    else
+      return 0;
+  } else {
+    log("error in stat: %s", strerror(errno));
+    return 0;
+  }     
+}
+
+static STACK_OF(X509_OBJECT) *
+XMAP_DIR_lookup_cert_by_subject( XMAP_DIR *xm, X509_NAME *name )
+{
+  char path[PATH_MAX+1];
+  int n;
+  STACK_OF(X509_OBJECT) *sk = sk_X509_OBJECT_new_null();
+  struct dirent **flist;
+
+  if (!sk) return sk;
+  snprintf(hashval, sizeof(hashval)-1, "%08lx.cert", X509_NAME_hash(name));
+  n = scandir(xm->dir, &flist, hash_select, alphasort);
+  if (n < 0)
+    log("error on scandir: %s", strerror(errno));
+  else {
+    int i;
+
+    for(i=0; i<n; i++) {
+      BIO *b;
+
+      snprintf(path, sizeof(path)-1, "%s/%s", xm->dir, flist[i]->d_name);
+      
+      if ((b = BIO_new_file(path, "r")) != NULL) {
+	X509 *x;
+
+	/* Try a PEM load first, then try DER if it fails */
+	if ((x = PEM_read_bio_X509(b, NULL, NULL, NULL)) == NULL) {
+	  BIO_ctrl(b, BIO_CTRL_RESET, 0, NULL);
+	  x = d2i_X509_bio(b, NULL); /* Try DER loading */
+	}
+
+	if (x) {
+	  if (X509_NAME_cmp(X509_get_subject_name(x), name) == 0) {
+	    X509_OBJECT *xo = X509_OBJECT_new(X509_LU_X509, x);
+
+	    if (x) {
+	      sk_X509_OBJECT_push(sk, xo);
+	    } else
+	      X509_free(x);
+	  } else
+	    X509_free(x);
+	}
+
+	BIO_free(b);
+      } else {
+	ERR_print_errors_fp(stderr);
+      }
+    }
+    if (n > 0) free(flist);
+  }
+  return sk;
+}
+
+static STACK_OF(X509_OBJECT) *
+XMAP_DIR_lookup_cert_by_issuer( XMAP_DIR *xm, X509_NAME *name )
+{
+  char path[PATH_MAX+1];
+  int n;
+  STACK_OF(X509_OBJECT) *sk = sk_X509_OBJECT_new_null();
+  struct dirent **flist;
+
+  if (!sk) return sk;
+  snprintf(hashval, sizeof(hashval)-1, "%08lx.cert", X509_NAME_hash(name));
+  n = scandir(xm->dir, &flist, hash_select, alphasort);
+  if (n < 0)
+    log("error on scandir: %s", strerror(errno));
+  else {
+    int i;
+
+    for(i=0; i<n; i++) {
+      BIO *b;
+
+      snprintf(path, sizeof(path)-1, "%s/%s", xm->dir, flist[i]->d_name);
+      
+      if ((b = BIO_new_file(path, "r")) != NULL) {
+	X509 *x;
+
+	/* Try a PEM load first, then try DER if it fails */
+	if ((x = PEM_read_bio_X509(b, NULL, NULL, NULL)) == NULL) {
+	  BIO_ctrl(b, BIO_CTRL_RESET, 0, NULL);
+	  x = d2i_X509_bio(b, NULL); /* Try DER loading */
+	}
+
+	if (x) {
+	  if (X509_NAME_cmp(X509_get_issuer_name(x), name) == 0) {
+	    X509_OBJECT *xo = X509_OBJECT_new(X509_LU_X509, x);
+
+	    if (x) {
+	      sk_X509_OBJECT_push(sk, xo);
+	    } else
+	      X509_free(x);
+	  } else
+	    X509_free(x);
+	}
+
+	BIO_free(b);
+      } else {
+	ERR_print_errors_fp(stderr);
+      }
+    }
+    if (n > 0) free(flist);
+  }
+  return sk;
+}
+
+static STACK_OF(X509_OBJECT) *
+XMAP_DIR_lookup_ca_certs( XMAP_DIR *xm )
+{
+  char path[PATH_MAX+1];
+  int n;
+  STACK_OF(X509_OBJECT) *sk = sk_X509_OBJECT_new_null();
+  struct dirent **flist;
+
+  if (!sk) return sk;
+  strncpy(dirname, xm->dir, sizeof(dirname)-1);
+  n = scandir(xm->dir, &flist, select_files, alphasort);
+  if (n < 0)
+    log("error in scandir: %s", strerror(errno));
+  else {
+    int i;
+
+    for(i=0; i<n; i++) {
+      BIO *b;
+
+      snprintf(path, sizeof(path)-1, "%s/%s", xm->dir, flist[i]->d_name);
+      
+      if ((b = BIO_new_file(path, "r")) != NULL) {
+	X509 *x;
+
+	/* Try a PEM load first, then try DER if it fails */
+	if ((x = PEM_read_bio_X509(b, NULL, NULL, NULL)) == NULL) {
+	  BIO_ctrl(b, BIO_CTRL_RESET, 0, NULL);
+	  x = d2i_X509_bio(b, NULL); /* Try DER loading */
+	}
+
+	if (x) {
+	  if (isCA(x)) {
+	    X509_OBJECT *xo = X509_OBJECT_new(X509_LU_X509, x);
+
+	    if (xo) {
+	      sk_X509_OBJECT_push(sk, xo);
+	    } else
+	      X509_free(x);
+	  } else
+	    X509_free(x);
+	}
+
+	BIO_free(b);
+      } else {
+	ERR_print_errors_fp(stderr);
+      }
+    }
+    if (n > 0) free(flist);
+  }
+  return sk;
+}
+
+static STACK_OF(X509_OBJECT) *
+XMAP_DIR_lookup_crl_by_issuer( XMAP_DIR *xm, X509_NAME *name )
+{
+  char path[PATH_MAX+1];
+  int n;
+  STACK_OF(X509_OBJECT) *sk = sk_X509_OBJECT_new_null();
+  struct dirent **flist;
+
+  if (!sk) return sk;
+  snprintf(hashval, sizeof(hashval)-1, "%08lx.crl", X509_NAME_hash(name));
+  n = scandir(xm->dir, &flist, hash_select, alphasort);
+  if (n < 0)
+    log("error in scandir: %s", strerror(errno));
+  else {
+    int i;
+
+    for(i=0; i<n; i++) {
+      BIO *b;
+
+      snprintf(path, sizeof(path)-1, "%s/%s", xm->dir, flist[i]->d_name);
+
+      if ((b = BIO_new_file(path, "r")) != NULL) {
+	X509_CRL *c;
+
+	/* Try a PEM load first, then try DER if it fails */
+	if ((c = PEM_read_bio_X509_CRL(b, NULL, NULL, NULL)) == NULL) {
+	  BIO_ctrl(b, BIO_CTRL_RESET, 0, NULL);
+	  c = d2i_X509_CRL_bio(b, NULL); /* Try DER loading */
+	}
+
+	if (c) {
+	  if (X509_NAME_cmp(X509_CRL_get_issuer(c), name) == 0) {
+	    X509_OBJECT *xo = X509_OBJECT_new(X509_LU_CRL, c);
+	    if (xo)
+	      sk_X509_OBJECT_push(sk, xo);
+	    else
+	      X509_CRL_free(c);
+	  } else
+	    X509_CRL_free(c);
+	}
+
+	BIO_free(b);
+      } else {
+	ERR_print_errors_fp(stderr);
+      }
+    }
+    if (n > 0) free(flist);
+  }
+  return sk;
+}
+
+static STACK_OF(X509_OBJECT) *
+XMAP_DIR_lookup_cert_by_uid( XMAP_DIR *xm, const char *uid )
+{
+  char path[PATH_MAX+1];
+  int n;
+  STACK_OF(X509_OBJECT) *sk = sk_X509_OBJECT_new_null();
+  struct dirent **flist;
+
+  if (!sk) return sk;
+  snprintf(hashval, sizeof(hashval)-1, "uid-%s", uid);
+  n = scandir(xm->dir, &flist, hash_select, alphasort);
+  if (n < 0)
+    log("error in scandir: %s", strerror(errno));
+  else {
+    int i;
+
+    for(i=0; i<n; i++) {
+      BIO *b;
+
+      snprintf(path, sizeof(path)-1, "%s/%s", xm->dir, flist[i]->d_name);
+      
+      if ((b = BIO_new_file(path, "r")) != NULL) {
+	X509 *x;
+
+	/* Try a PEM load first, then try DER if it fails */
+	if ((x = PEM_read_bio_X509(b, NULL, NULL, NULL)) == NULL) {
+	  BIO_ctrl(b, BIO_CTRL_RESET, 0, NULL);
+	  x = d2i_X509_bio(b, NULL); /* Try DER loading */
+	}
+
+	if (x) {
+	  X509_OBJECT *xo = X509_OBJECT_new(X509_LU_X509, x);
+	  if (xo)
+	    sk_X509_OBJECT_push(sk, xo);
+	  else 
+	    X509_free(x);
+	}
+
+	BIO_free(b);
+      } else {
+	ERR_print_errors_fp(stderr);
+      }
+    }
+    if (n > 0) free(flist);
+  }
+  return sk;
+}
+
+static STACK_OF(X509_OBJECT) *
+XMAP_DIR_lookup_cert_by_dns( XMAP_DIR *xm, const char *dns )
+{
+  char path[PATH_MAX+1];
+  int n;
+  STACK_OF(X509_OBJECT) *sk = sk_X509_OBJECT_new_null();
+  struct dirent **flist;
+
+  if (!sk) return sk;
+  snprintf(hashval, sizeof(hashval)-1, "dns-%s", dns);
+  n = scandir(xm->dir, &flist, hash_select, alphasort);
+  if (n < 0)
+    log("error in scandir: %s", strerror(errno));
+  else {
+    int i;
+
+    for(i=0; i<n; i++) {
+      BIO *b;
+
+      snprintf(path, sizeof(path)-1, "%s/%s", xm->dir, flist[i]->d_name);
+      
+      if ((b = BIO_new_file(path, "r")) != NULL) {
+	X509 *x;
+
+	/* Try a PEM load first, then try DER if it fails */
+	if ((x = PEM_read_bio_X509(b, NULL, NULL, NULL)) == NULL) {
+	  BIO_ctrl(b, BIO_CTRL_RESET, 0, NULL);
+	  x = d2i_X509_bio(b, NULL); /* Try DER loading */
+	}
+
+	if (x) {
+	  if (X509_subjAltName_check_dns(x, dns)) {
+	    X509_OBJECT *xo = X509_OBJECT_new(X509_LU_X509, x);
+	    if (xo)
+	      sk_X509_OBJECT_push(sk, xo);
+	    else 
+	      X509_free(x);
+	  }
+	} else {
+	  X509_free(x);
+	}
+
+	BIO_free(b);
+      } else {
+	ERR_print_errors_fp(stderr);
+      }
+    }
+    if (n > 0) free(flist);
+  }
+  return sk;
+}
+
+static STACK_OF(X509_OBJECT) *
+XMAP_DIR_lookup_cert_by_ip( XMAP_DIR *xm, const struct in_addr ip )
+{
+  char path[PATH_MAX+1];
+  int n;
+  STACK_OF(X509_OBJECT) *sk = sk_X509_OBJECT_new_null();
+  struct dirent **flist;
+
+  if (!sk) return sk;
+  
+  snprintf(hashval, sizeof(hashval)-1, "ip-%s", inet_ntoa(ip));
+  n = scandir(xm->dir, &flist, hash_select, alphasort);
+  if (n < 0)
+    log("error in scandir: %s", strerror(errno));
+  else {
+    int i;
+
+    for(i=0; i<n; i++) {
+      BIO *b;
+
+      snprintf(path, sizeof(path)-1, "%s/%s", xm->dir, flist[i]->d_name);
+      
+      if ((b = BIO_new_file(path, "r")) != NULL) {
+	X509 *x;
+
+	/* Try a PEM load first, then try DER if it fails */
+	if ((x = PEM_read_bio_X509(b, NULL, NULL, NULL)) == NULL) {
+	  BIO_ctrl(b, BIO_CTRL_RESET, 0, NULL);
+	  x = d2i_X509_bio(b, NULL); /* Try DER loading */
+	}
+
+	if (x) {
+	  if (X509_subjAltName_check_ip(x, ip)) {
+	    X509_OBJECT *xo = X509_OBJECT_new(X509_LU_X509, x);
+	    if (xo)
+	      sk_X509_OBJECT_push(sk, xo);
+	    else 
+	      X509_free(x);
+	  }
+	} else {
+	  X509_free(x);
+	}
+
+	BIO_free(b);
+      } else {
+	ERR_print_errors_fp(stderr);
+      }
+    }
+    if (n > 0) free(flist);
+  }
+  return sk;
+}
+
+static void
+XMAP_DIR_dump(void *this)
+{
+  XMAP_DIR *xm = (XMAP_DIR *)this;
+  DBG_log("XMAP_DIR: %s", xm->dir);
+}
+
+static void
+XMAP_DIR_free(void *this)
+{
+  XMAP_DIR *xm = (XMAP_DIR *)this;
+
+  if (!xm) return;
+  if (xm->dir) pfree(xm->dir);
+  free(xm);
+}
+
+XMAP_METHOD *
+XMAP_METHOD_dir( void )
+{
+  return (&xmap_dir_methods);
+}
+#endif /* OPENSSL */
diff -bruN freeswan-1.9.orig/pluto/xmap_dir.h freeswan-1.9/pluto/xmap_dir.h
--- freeswan-1.9.orig/pluto/xmap_dir.h	Wed Dec 31 19:00:00 1969
+++ freeswan-1.9/pluto/xmap_dir.h	Wed May 16 10:57:20 2001
@@ -0,0 +1,17 @@
+#ifndef XMAP_DIR_H
+#define XMAP_DIR_H
+
+#include <openssl/safestack.h>
+#include <openssl/x509.h>
+
+#include "x_sobj.h"
+#include "xmap.h"
+
+typedef struct xmap_dir_st {
+  char *dir;
+  XMAP_METHOD *meth;
+} XMAP_DIR;
+
+XMAP_METHOD *XMAP_METHOD_dir( void );
+
+#endif /* XMAP_DIR_H */
diff -bruN freeswan-1.9.orig/pluto/xmap_file.c freeswan-1.9/pluto/xmap_file.c
--- freeswan-1.9.orig/pluto/xmap_file.c	Wed Dec 31 19:00:00 1969
+++ freeswan-1.9/pluto/xmap_file.c	Wed May 16 10:57:20 2001
@@ -0,0 +1,359 @@
+#ifdef OPENSSL
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include <regex.h>
+
+#include <openssl/bio.h>
+#include <openssl/pem.h>
+#include <openssl/x509v3.h>
+
+#include "xmap.h"
+#include "xmap_file.h"
+
+#include <freeswan.h> /* needed by constants.h */
+#include "constants.h"
+#include "defs.h"
+#include "log.h"
+
+static void XMAP_FILE_dump(void *this);
+static void XMAP_FILE_free(void *this);
+static void *XMAP_FILE_new(const char *file);
+static int isCA( X509 *x );
+static STACK_OF(X509_OBJECT) *
+XMAP_FILE_lookup( void *this, const int type, const char *index, void *p );
+static STACK_OF(X509_OBJECT) *
+XMAP_FILE_lookup_cert_by_subject( XMAP_FILE *xm, X509_NAME *name );
+static STACK_OF(X509_OBJECT) *
+XMAP_FILE_lookup_cert_by_issuer( XMAP_FILE *xm, X509_NAME *name );
+static STACK_OF(X509_OBJECT) *
+XMAP_FILE_lookup_crl_by_issuer( XMAP_FILE *xm, X509_NAME *name );
+static STACK_OF(X509_OBJECT) *
+XMAP_FILE_lookup_cert_by_uid( XMAP_FILE *xm, const char *uid );
+static STACK_OF(X509_OBJECT) *
+XMAP_FILE_lookup_cert_by_dns( XMAP_FILE *xm, const char *dns );
+static STACK_OF(X509_OBJECT) *
+XMAP_FILE_lookup_cert_by_ip( XMAP_FILE *xm, const struct in_addr ip );
+static STACK_OF(X509_OBJECT) *
+XMAP_FILE_lookup_ca_certs( XMAP_FILE *xm );
+
+static XMAP_METHOD xmap_file_methods = {
+  "file",
+  XMAP_FILE_lookup,
+  XMAP_FILE_dump,
+  XMAP_FILE_free,
+  XMAP_FILE_new
+};
+
+/* Pattern is (ignoring lower/upper case --
+ * <whitespace>uid:<whitespace><alphanumeric user id><whitespace>
+ */
+#define UID_REGEX \
+"^[[:space:]]*[Uu][Ii][Dd]:[[:space:]]*([[:alnum:]]+)[[:space:]]$"
+
+static int
+isCA( X509 *x )
+{
+  X509_EXTENSION *ext;
+  BASIC_CONSTRAINTS *p = NULL;
+  int loc;
+  
+  loc = X509_get_ext_by_NID(x, NID_basic_constraints, -1);
+  if (loc >= 0) {
+    ext = X509_get_ext(x, loc);
+    if (ext) {
+      p = X509V3_EXT_d2i(ext);
+      if (! p->ca) {
+	BASIC_CONSTRAINTS_free(p);
+	return 0;
+      } else {
+	BASIC_CONSTRAINTS_free(p);
+	return 1; /* This is a CA certificate */
+      }
+    } else
+      return 0;
+  } else
+    return 0;
+}
+
+XMAP_METHOD *
+XMAP_METHOD_file( void )
+{
+  return (&xmap_file_methods);
+}
+
+static void *
+XMAP_FILE_new(const char *file)
+{
+  XMAP_FILE *ret;
+  int re_code;
+  char errbuf[257];
+
+  if ((ret = alloc_thing(XMAP_FILE, "xmap_file")) == NULL) goto end;
+  if ((ret->file = clone_bytes(file, strlen(file)+1, "file name")) == NULL)
+    goto end;
+  if ((ret->bio = BIO_new_file(ret->file, "r")) == NULL) goto end;
+
+  if ((re_code = regcomp(&ret->uidreg, UID_REGEX, REG_EXTENDED)) != 0) {
+    regerror(re_code, &ret->uidreg, errbuf, sizeof(errbuf-1));
+    log("Regex Error: %s", errbuf);
+    goto end;
+  }
+
+  ret->meth = &xmap_file_methods;
+  return (void *)ret;
+ end:
+  if (ret->bio) BIO_free(ret->bio);
+  if (ret->file) pfree(ret->file);
+  if (ret) pfree(ret);
+  return NULL;
+}
+
+static STACK_OF(X509_OBJECT) *
+XMAP_FILE_lookup( void *this, const int type, const char *index, void *p )
+{
+  XMAP_FILE *xm = (XMAP_FILE *)this;
+
+  switch(type) {
+  case X509_LU_X509:
+    if (strcasecmp(index, "issuer") == 0)
+	{
+		return XMAP_FILE_lookup_cert_by_issuer( xm, (X509_NAME *)p);
+	}
+    if (strcasecmp(index, "subject") == 0)
+	{
+		return XMAP_FILE_lookup_cert_by_subject( xm, (X509_NAME *)p);
+	}
+    else if (strcasecmp(index, "uid") == 0)
+	{
+		return XMAP_FILE_lookup_cert_by_uid( xm, (char  *)p);
+	}
+    else if (strcasecmp(index, "dns") == 0)
+	{
+		return XMAP_FILE_lookup_cert_by_dns( xm, (char  *)p);
+	}
+    else if (strcasecmp(index, "ip") == 0)
+	{
+		return XMAP_FILE_lookup_cert_by_ip( xm, *((struct in_addr *)p));
+	}
+    else if (strcasecmp(index, "ca") == 0)
+	{
+		return XMAP_FILE_lookup_ca_certs( xm );
+	}
+    else
+	{
+		return NULL;
+	}
+    break;
+  case X509_LU_CRL:
+    if (strcasecmp(index, "issuer") == 0)
+      return XMAP_FILE_lookup_crl_by_issuer( xm, (X509_NAME *)p);
+    else
+      return NULL;
+    break;
+  default:
+    return NULL;
+  }
+}
+
+static STACK_OF(X509_OBJECT) *
+XMAP_FILE_lookup_cert_by_subject( XMAP_FILE *xm, X509_NAME *name )
+{
+  X509 *x;
+  STACK_OF(X509_OBJECT) *sk = sk_X509_OBJECT_new_null();
+
+  if (sk == NULL) return sk;
+  BIO_ctrl(xm->bio, BIO_CTRL_RESET, 0, NULL);
+  while ((x = PEM_read_bio_X509(xm->bio, NULL, NULL, NULL)) != NULL) {
+    if (X509_NAME_cmp(X509_get_subject_name(x), name) == 0) {
+      X509_OBJECT *xo = X509_OBJECT_new(X509_LU_X509, x);
+      if (xo) {
+	sk_X509_OBJECT_push(sk, xo);
+      } else
+	X509_free(x);
+    } else
+      X509_free(x);
+  }
+  return sk;
+}
+
+static STACK_OF(X509_OBJECT) *
+XMAP_FILE_lookup_cert_by_issuer( XMAP_FILE *xm, X509_NAME *name )
+{
+  X509 *x;
+  STACK_OF(X509_OBJECT) *sk = sk_X509_OBJECT_new_null();
+
+  if (sk == NULL) return sk;
+  BIO_ctrl(xm->bio, BIO_CTRL_RESET, 0, NULL);
+  while ((x = PEM_read_bio_X509(xm->bio, NULL, NULL, NULL)) != NULL) {
+    if (X509_NAME_cmp(X509_get_issuer_name(x), name) == 0) {
+      X509_OBJECT *xo = X509_OBJECT_new(X509_LU_X509, x);
+      if (xo) {
+	sk_X509_OBJECT_push(sk, xo);
+      } else
+	X509_free(x);
+    } else
+      X509_free(x);
+  }
+  return sk;
+}
+
+static STACK_OF(X509_OBJECT) *
+XMAP_FILE_lookup_ca_certs( XMAP_FILE *xm  )
+{
+  X509 *x;
+  STACK_OF(X509_OBJECT) *sk = sk_X509_OBJECT_new_null();
+
+  if (sk == NULL) return sk;
+  BIO_ctrl(xm->bio, BIO_CTRL_RESET, 0, NULL);
+  while ((x = PEM_read_bio_X509(xm->bio, NULL, NULL, NULL)) != NULL) {
+    if (isCA(x)) {
+      X509_OBJECT *xo = X509_OBJECT_new(X509_LU_X509, x);
+      if (xo) {
+	sk_X509_OBJECT_push(sk, xo);
+      } else
+	X509_free(x);
+    } else
+      X509_free(x);
+  }
+  return sk;
+}
+
+static STACK_OF(X509_OBJECT) *
+XMAP_FILE_lookup_crl_by_issuer( XMAP_FILE *xm, X509_NAME *name )
+{
+  X509_CRL *c;
+  STACK_OF(X509_OBJECT) *sk = sk_X509_OBJECT_new_null();
+
+  if (sk == NULL) return sk;
+  BIO_ctrl(xm->bio, BIO_CTRL_RESET, 0, NULL);
+  while ((c = PEM_read_bio_X509_CRL(xm->bio, NULL, NULL, NULL)) != NULL) {
+    if (X509_NAME_cmp(X509_CRL_get_issuer(c), name) == 0) {
+      X509_OBJECT *xo = X509_OBJECT_new(X509_LU_CRL, c);
+      if (xo) {
+	sk_X509_OBJECT_push(sk, xo);
+      } else
+	X509_CRL_free(c);
+    } else
+      X509_CRL_free(c);
+  }
+  return sk;
+}
+
+static STACK_OF(X509_OBJECT) *
+XMAP_FILE_lookup_cert_by_uid( XMAP_FILE *xm, const char *uid )
+{
+  char line[BUFSIZ+1], user[BUFSIZ+1];
+  regmatch_t pmatch[2];
+  STACK_OF(X509_OBJECT) *sk = sk_X509_OBJECT_new_null();
+  X509 *x;
+
+  if (sk == NULL) return sk;
+  BIO_ctrl(xm->bio, BIO_CTRL_RESET, 0, NULL);
+  while (BIO_gets(xm->bio, line, sizeof(line)-1)) {
+    if (!regexec(&xm->uidreg, line, 2, pmatch, 0))
+      if ((pmatch[1].rm_so != -1) && (pmatch[1].rm_eo != -1)) {
+	memset(user, 0, sizeof(user));
+	strncpy(user, &line[pmatch[1].rm_so],
+		pmatch[1].rm_eo - pmatch[1].rm_so);
+	if (strcmp(uid, user) == 0) {
+	  /* Found a match for the user id */
+	  if ((x = PEM_read_bio_X509(xm->bio, NULL, NULL, NULL)) != NULL) {
+	    X509_OBJECT *xo = X509_OBJECT_new( X509_LU_X509, x);
+	    if (xo) {
+	      sk_X509_OBJECT_push(sk, xo);
+	    } else 
+	      X509_free(x);
+	  }
+	}
+      }
+  }
+
+  return sk;
+}
+
+static STACK_OF(X509_OBJECT) *
+XMAP_FILE_lookup_cert_by_dns( XMAP_FILE *xm, const char *dns )
+{
+  STACK_OF(X509_OBJECT) *sk = sk_X509_OBJECT_new_null();
+  X509 *x;
+  int zap;
+  X509_OBJECT *xo;
+
+  if (sk == NULL) return sk;
+  BIO_ctrl(xm->bio, BIO_CTRL_RESET, 0, NULL);
+  while ((x = PEM_read_bio_X509(xm->bio, NULL, NULL, NULL)) != NULL) {
+    zap = X509_subjAltName_check_dns(x, dns) ? 0 : 1;
+    
+    if (zap)
+      X509_free(x);
+    else {
+      xo = X509_OBJECT_new( X509_LU_X509, x);
+      if (xo)
+	sk_X509_OBJECT_push(sk, xo);
+      else 
+	X509_free(x);
+    }
+  }
+
+  return sk;
+}
+
+static STACK_OF(X509_OBJECT) *
+XMAP_FILE_lookup_cert_by_ip( XMAP_FILE *xm, struct in_addr ip )
+{
+  STACK_OF(X509_OBJECT) *sk = sk_X509_OBJECT_new_null();
+  X509 *x;
+  int zap;
+  X509_OBJECT *xo;
+
+  if (sk == NULL) {
+    DBG(DBG_PARSING,
+    DBG_log("sk is NULL, returning NULL.");
+    );
+	return sk;
+  }
+  BIO_ctrl(xm->bio, BIO_CTRL_RESET, 0, NULL);
+  while ((x = PEM_read_bio_X509(xm->bio, NULL, NULL, NULL)) != NULL) {
+    zap = X509_subjAltName_check_ip(x, ip) ? 0 : 1;
+
+    if (zap)
+      X509_free(x);
+    else {
+      xo = X509_OBJECT_new( X509_LU_X509, x);
+      if (xo)
+		sk_X509_OBJECT_push(sk, xo);
+      else 
+		X509_free(x);
+    }
+  }
+
+  return sk;
+}
+
+static void
+XMAP_FILE_dump(void *this)
+{
+  XMAP_FILE *xm = (XMAP_FILE *)this;
+  DBG(DBG_CONTROL | DBG_PARSING,
+  DBG_log("XMAP_FILE: %s\n", xm->file);
+  );
+}
+
+static void
+XMAP_FILE_free(void *this)
+{
+  XMAP_FILE *xm = (XMAP_FILE *)this;
+
+  if (!xm) return;
+  regfree(&xm->uidreg);
+  if (xm->bio) BIO_free(xm->bio);
+  if (xm->file) pfree(xm->file);
+  pfree(xm);
+}
+#endif /* OPENSSL */
diff -bruN freeswan-1.9.orig/pluto/xmap_file.h freeswan-1.9/pluto/xmap_file.h
--- freeswan-1.9.orig/pluto/xmap_file.h	Wed Dec 31 19:00:00 1969
+++ freeswan-1.9/pluto/xmap_file.h	Wed May 16 10:57:20 2001
@@ -0,0 +1,28 @@
+#ifndef XMAP_FILE_H
+#define XMAP_FILE_H
+
+#include <regex.h>
+
+#include <openssl/safestack.h>
+#include <openssl/bio.h>
+#include <openssl/x509.h>
+#include <openssl/x509_vfy.h>
+
+#include "x_sobj.h"
+#include "xmap.h"
+
+typedef struct xmap_file_st {
+  char *file;
+  BIO *bio;
+  regex_t uidreg;
+  regex_t ipreg;
+  XMAP_METHOD *meth;
+} XMAP_FILE;
+
+XMAP_METHOD *XMAP_METHOD_file( void );
+#endif /* XMAP_FILE_H */
+
+
+
+
+
diff -bruN freeswan-1.9.orig/pluto/xmap_ldap.c freeswan-1.9/pluto/xmap_ldap.c
--- freeswan-1.9.orig/pluto/xmap_ldap.c	Wed Dec 31 19:00:00 1969
+++ freeswan-1.9/pluto/xmap_ldap.c	Wed May 16 11:18:56 2001
@@ -0,0 +1,1369 @@
+#ifdef OPENSSL
+#ifdef HAVE_LDAP
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <setjmp.h>
+#include <signal.h>
+#include <ctype.h>
+#include <errno.h>
+#include <sys/time.h>
+#include <regex.h>
+
+#include <lber.h>
+#include <ldap.h>
+
+#include "x_sobj.h"
+#include "xmap.h"
+#include "xmap_ldap.h"
+
+#include <openssl/x509v3.h>
+
+#include <freeswan.h> /* needed by constants.h */
+#include "constants.h"
+#include "defs.h"
+#include "log.h"
+#include "whack.h"
+
+static void XMAP_LDAP_dump(void *this);
+static void XMAP_LDAP_free(void *this);
+static void *XMAP_LDAP_new(const char *ldap);
+static STACK_OF(X509_OBJECT) *
+XMAP_LDAP_lookup( void *this, const int type, const char *index, void *p );
+static STACK_OF(X509_OBJECT) *
+XMAP_LDAP_lookup_cert_by_subject( XMAP_LDAP *xm, X509_NAME *name );
+static STACK_OF(X509_OBJECT) *
+XMAP_LDAP_lookup_cert_by_issuer( XMAP_LDAP *xm, X509_NAME *name );
+static STACK_OF(X509_OBJECT) *
+XMAP_LDAP_lookup_crl_by_issuer( XMAP_LDAP *xm, X509_NAME *name );
+static STACK_OF(X509_OBJECT) *
+XMAP_LDAP_lookup_cert_by_uid( XMAP_LDAP *xm, const char *uid );
+static STACK_OF(X509_OBJECT) *
+XMAP_LDAP_lookup_cert_by_dns( XMAP_LDAP *xm, const char *dns );
+static STACK_OF(X509_OBJECT) *
+XMAP_LDAP_lookup_cert_by_ip( XMAP_LDAP *xm, const struct in_addr ip );
+static STACK_OF(X509_OBJECT) *
+XMAP_LDAP_lookup_ca_certs( XMAP_LDAP *xm );
+static char **make_attrs( const char *a );
+static void attrs_free( char **attrs );
+
+char *find_filter( const char *index, const int type, flist *fl );
+char **find_attrs( const char *index, const int type, alist *al );
+
+static XMAP_METHOD xmap_ldap_methods = {
+  "ldap",
+  XMAP_LDAP_lookup,
+  XMAP_LDAP_dump,
+  XMAP_LDAP_free,
+  XMAP_LDAP_new
+};
+
+#define HOST_REGEX "^([[:alnum:]]+)_host_name[[:space:]]*=[[:space:]]*([[:punct:][:alnum:]]+)"
+#define PORT_REGEX "^([[:alnum:]]+)_port[[:space:]]*=[[:space:]]*([[:digit:]]+)"
+#define BASE_REGEX "^([[:alnum:]]+)_base[[:space:]]*=[[:space:]]*([^[:space:]].*)"
+#define TIMEOUT_REGEX "^([[:alnum:]]+)_timeout[[:space:]]*=[[:space:]]*([[:digit:]]+)"
+#define BINDDN_REGEX "^([[:alnum:]]+)_bind_dn[[:space:]]*=[[:space:]]*([^[:space:]].*)"
+#define BINDPW_REGEX "^([[:alnum:]]+)_password[[:space:]]*=[[:space:]]*([^[:space:]].*)"
+#define FILTER_REGEX "^([[:alnum:]]+)_filter(:(([\\*[:alnum:]]+)(:([[:alnum:]]+))?))?[[:space:]]*=[[:space:]]*([^[:space:]].*)"
+#define ATTRS_REGEX "^([[:alnum:]]+)_attributes(:(([\\*[:alnum:]]+)(:([[:alnum:]]+))?))?[[:space:]]*=[[:space:]]*([^[:space:]].*)"
+
+static void
+insert_filter( const char *index, const int type, const char *filter, flist *fl )
+{
+  int i;
+  char *f, *in;
+
+  for(i=0; ((i < MAXFLIST) && (fl[i].index)) ;i++)
+    if ((strcasecmp(index, fl[i].index) == 0) && (fl[i].type == type)) break;
+
+  if (i == MAXFLIST) return; /* No more room */
+  if (fl[i].index) {
+    /* A replacement operation */
+    if ((f = clone_bytes(filter, strlen(filter)+1, "filter")) == NULL) return;
+    pfree(fl[i].filter);
+    fl[i].filter = f;
+  } else {
+    if ((in = clone_bytes(index, strlen(index)+1, "index string")) == NULL)
+      return;
+    if ((f = clone_bytes(filter, strlen(filter)+1, "filter string")) == NULL)
+      { pfree(in); return; }
+    fl[i].index = in;
+    fl[i].type = type;
+    fl[i].filter = f;
+
+    DBG(DBG_PARSING,
+    DBG_log("Insert filter: %d (%s,%d,%s)", i+1, in, type, f);
+    );
+  }
+}
+
+static void
+insert_attrs( const char *index, const int type, const char *attr, alist *al )
+{
+  int i, j;
+  char **af, *in;
+
+  for(i=0; ((i < MAXFLIST) && (al[i].index)) ;i++) {
+    if ((strcasecmp(index, al[i].index) == 0) && (al[i].type == type)) {
+      break;
+    }
+  }
+
+  if (i == MAXFLIST) return; /* No more room */
+  if (al[i].index) {
+    /* A replacement operation */
+    if ((af = make_attrs(attr)) == NULL) return;
+    attrs_free(al[i].attrs);
+    al[i].attrs = af;
+  } else {
+    if ((in = clone_bytes(index, strlen(index)+1, "index string")) == NULL)
+      return;
+    if ((af = make_attrs(attr)) == NULL) { pfree(in); return; }
+    al[i].index = in;
+    al[i].type = type;
+    al[i].attrs = af;
+    DBG(DBG_PARSING,
+    DBG_log("Insert attribute: %d (%s,%d)", i+1, in, type);
+    );
+    for(j=0; af[j]; j++)
+      DBG(DBG_PARSING,
+      DBG_log("Attribute %d: %s", j+1, af[j]);
+      );
+  }
+}
+
+char *
+find_filter( const char *index, const int type, flist *fl )
+{
+  int i, OKind;
+  unsigned char OK, indOK, typeOK;
+
+  OK = 0x00;
+  for(i=0, OKind=0; ((i < MAXFLIST) && (fl[i].index)); i++) {
+    typeOK = (fl[i].type == X509_LU_FAIL) ? 0x01 :
+      ((fl[i].type == type) ? 0x04 : 0);
+    indOK = (strcasecmp(fl[i].index, "*") == 0) ? 0x02 :
+      ((strcasecmp(fl[i].index, index) == 0) ? 0x08 : 0);
+    if ((typeOK | indOK) > OK) { OKind = i; OK = typeOK | indOK; }
+  }
+
+  return fl[OKind].filter;
+}
+
+char **
+find_attrs( const char *index, const int type, alist *al )
+{
+  int i, OKind;
+  unsigned char OK, indOK, typeOK;
+
+  OK = 0x00;
+  for(i=0, OKind=0; ((i < MAXFLIST) && (al[i].index)); i++) {
+    typeOK = (al[i].type == X509_LU_FAIL) ? 0x01 :
+      ((al[i].type == type) ? 0x04 : 0);
+    indOK = (strcasecmp(al[i].index, "*") == 0) ? 0x02 :
+      ((strcasecmp(al[i].index, index) == 0) ? 0x08 : 0);
+    if ((typeOK | indOK) > OK) { OKind = i; OK = typeOK | indOK; }
+  }
+
+  return al[OKind].attrs;
+}
+
+static void
+extract_re_sub( const char *buf, regmatch_t *rm, char **lv)
+{
+  if (!buf || !lv || !rm) return;
+  if (*lv) return;
+  if ((rm->rm_so == -1) || (rm->rm_eo == -1)) return;
+  if ((*lv = alloc_bytes(rm->rm_eo - rm->rm_so + 1, "subexpression")) == NULL)
+    return;
+  strncpy(*lv, &buf[rm->rm_so], rm->rm_eo - rm->rm_so);
+  (*lv)[rm->rm_eo - rm->rm_so] = '\0';
+}
+
+static char **
+make_attrs( const char *a )
+{
+  char *s = clone_bytes(a, strlen(a)+1, "attribute list");
+  char *at;
+  int i = 0, j;
+  char **ret = NULL;
+  const char *delim = ", ";
+
+  if (!s) return NULL;
+  at = strtok(s, delim);
+  while (at != NULL) {
+    i++;
+    at = strtok(NULL, delim);
+  }
+  ret = alloc_bytes((i+1) * sizeof(char *), "attribute array");
+  if (!ret) { pfree(s); return NULL; }
+  for(j=0; j<=i; j++) ret[j] = NULL;
+  pfree(s);
+
+  if ((s = clone_bytes(a, strlen(a)+1, "attribute list")) == NULL) return NULL;
+  at = strtok(s, delim);
+  i = 0;
+  while (at != NULL) {
+    if ((ret[i++] = clone_bytes(at, strlen(at)+1, "attribute")) == NULL) {
+      for(i=0; ret[i]; i++) pfree(ret[i]);
+      pfree(ret);
+      pfree(s);
+      return NULL;
+    }
+    at = strtok(NULL, delim);
+  }
+  
+  pfree(s);
+  return ret;
+}
+
+static void
+attrs_free( char **attrs )
+{
+  int i=0;
+
+  for(i=0; attrs[i]; i++) pfree(attrs[i]);
+  pfree(attrs);
+}
+
+static jmp_buf env;
+static void
+ldap_timeout(int unused_sig __attribute__((unused)))
+{
+  longjmp(env, 1);
+}
+
+static int
+open_bind( XMAP_LDAP *xm )
+{
+  void (*saved_alarm)(int);
+
+  if ((saved_alarm = signal(SIGALRM, ldap_timeout)) == SIG_ERR) {
+    log("signal: %s", strerror(errno));
+    return 0;
+  }
+
+  alarm(xm->ldap_timeout);
+  if (setjmp(env) == 0) {
+    if ((xm->ld = ldap_open(xm->ldap_host, xm->ldap_port)) == NULL) {
+      alarm(0); /* turn it off */
+      DBG(DBG_PARSING,
+      DBG_log("Open to %s:%d failed", xm->ldap_host, xm->ldap_port);
+      );
+      loglog(RC_LOG_SERIOUS, "ldap_open: %s", strerror(errno));
+      return 0;
+    }
+  } else {
+    DBG(DBG_PARSING,
+    DBG_log("Open to %s:%d failed", xm->ldap_host, xm->ldap_port);
+    );
+    loglog(RC_LOG_SERIOUS, "ldap_open: Connection timed out.");
+    return 0;
+  }
+  alarm(0);
+
+  if ((ldap_bind_s(xm->ld, xm->ldap_bindDN, xm->ldap_bindPW,
+		   LDAP_AUTH_SIMPLE)) != LDAP_SUCCESS) return 0;
+
+  return 1;
+}
+
+void *
+XMAP_LDAP_new(const char *ldapspec)
+{
+  char *ls = NULL, *s, *ldapvar = NULL, *ldapfile;
+  FILE *fp;
+  XMAP_LDAP *ret = NULL;
+  int i, re_code;
+  char re_err[256];
+  regmatch_t re_match[10];
+
+  regex_t host_re;
+  regex_t port_re;
+  regex_t timeout_re;
+  regex_t base_re;
+  regex_t binddn_re;
+  regex_t bindpw_re;
+  regex_t filter_re;
+  regex_t attrs_re;
+
+  /* Default values */
+  char *ldap_host = clone_bytes("localhost", strlen("localhost")+1,
+				"ldap_host");
+  int ldap_port = LDAP_PORT;
+  int ldap_timeout = 10; /* seconds */
+  char *ldap_bindDN = clone_bytes("", 1, "bindDN");
+  char *ldap_bindPW = clone_bytes("", 1, "bindPW");
+  char *ldap_base = NULL;
+  flist ldap_filter[MAXFLIST];
+  alist ldap_attrs[MAXFLIST];
+
+  memset(ldap_filter, 0, sizeof(ldap_filter));
+  insert_filter("*", X509_LU_FAIL, "(cn=%s)", ldap_filter);
+
+  memset(ldap_attrs, 0, sizeof(ldap_attrs));
+  insert_attrs("*", X509_LU_FAIL, "usercertificate, usercertificate;binary, cacertificate, cacertificate;binary", ldap_attrs);
+
+  if ((re_code = regcomp(&host_re, HOST_REGEX, REG_EXTENDED)) != 0) {
+    regerror(re_code, &host_re, re_err, sizeof(re_err));
+    log("Regex error: %s", re_err);
+    goto end;
+  }
+
+  if ((re_code = regcomp(&port_re, PORT_REGEX, REG_EXTENDED)) != 0) {
+    regerror(re_code, &port_re, re_err, sizeof(re_err));
+    log("Regex error: %s", re_err);
+    goto end;
+  }
+
+  if ((re_code = regcomp(&base_re, BASE_REGEX, REG_EXTENDED)) != 0) {
+    regerror(re_code, &base_re, re_err, sizeof(re_err));
+    log("Regex error: %s", re_err);
+    goto end;
+  }
+
+  if ((re_code = regcomp(&timeout_re, TIMEOUT_REGEX, REG_EXTENDED)) != 0) {
+    regerror(re_code, &timeout_re, re_err, sizeof(re_err));
+    log("Regex error: %s", re_err);
+    goto end;
+  }
+
+  if ((re_code = regcomp(&binddn_re, BINDDN_REGEX, REG_EXTENDED)) != 0) {
+    regerror(re_code, &binddn_re, re_err, sizeof(re_err));
+    log("Regex error: %s", re_err);
+    goto end;
+  }
+
+  if ((re_code = regcomp(&bindpw_re, BINDPW_REGEX, REG_EXTENDED)) != 0) {
+    regerror(re_code, &bindpw_re, re_err, sizeof(re_err));
+    log("Regex error: %s", re_err);
+    goto end;
+  }
+
+  if ((re_code = regcomp(&filter_re, FILTER_REGEX, REG_EXTENDED)) != 0) {
+    regerror(re_code, &filter_re, re_err, sizeof(re_err));
+    log("Regex error: %s", re_err);
+    goto end;
+  }
+
+  if ((re_code = regcomp(&attrs_re, ATTRS_REGEX, REG_EXTENDED)) != 0) {
+    regerror(re_code, &attrs_re, re_err, sizeof(re_err));
+    log("Regex error: %s", re_err);
+    goto end;
+  }
+
+  if ((!ldap_host) || (!ldap_bindDN) || (!ldap_bindPW) ||
+      (!ldap_filter) || (!ldap_attrs)) goto end;
+
+  if (!ldapspec) goto end;
+  ls = clone_bytes(ldapspec, strlen(ldapspec)+1, "ldap spec");
+  if (!ls) goto end;
+  s = strchr(ls, ':');
+  ldapfile = ls;
+  if (s) {
+    ldapvar = clone_bytes(&s[1], strlen(&s[1])+1, "ldap name");
+    *s = '\0';
+  } else {
+    ldapvar = NULL;
+  }
+
+  fp = fopen( ldapfile, "r" );
+  if (!fp) {
+    perror("fopen");
+    goto end;
+  }
+
+  while (!feof(fp)) {
+    char buf[BUFSIZ], *ptr;
+
+    if (fgets(buf, sizeof(buf), fp)) {
+      int l;
+
+      for(ptr = buf; ((*ptr) && (isspace(*ptr))); ptr++);
+      if (! *ptr) continue; /* Blank Line */
+      if (*ptr == '#') continue; /* Comment */
+      l = strlen(buf)-1;
+      while ((l > 0) && (isspace(buf[l]))) { buf[l] = '\0'; l--; }
+
+      /* Check for host name spec */
+      if ((re_code = regexec(&host_re, buf, 10, re_match, 0)) == 0) {
+	char *lv = NULL;
+
+	extract_re_sub(buf, &re_match[1], &lv);
+	if (!ldapvar) extract_re_sub(buf, &re_match[1], &ldapvar);
+	if (strcmp(ldapvar, lv) == 0) {
+	  if (ldap_host) { pfree(ldap_host); ldap_host = NULL; }
+	  extract_re_sub(buf, &re_match[2], &ldap_host);
+	}
+	pfree(lv);
+      }
+
+      /* Check for port spec */
+      if ((re_code = regexec(&port_re, buf, 10, re_match, 0)) == 0) {
+	char *lv = NULL;
+
+	extract_re_sub(buf, &re_match[1], &lv);
+	if (!ldapvar) extract_re_sub(buf, &re_match[1], &ldapvar);
+	if (strcmp(ldapvar, lv) == 0) {
+	  char *ps = NULL;
+
+	  extract_re_sub(buf, &re_match[2], &ps);
+	  ldap_port = atoi(ps);
+	  pfree(ps);
+	}
+	pfree(lv);
+      }
+
+      /* Check for base spec */
+      if ((re_code = regexec(&base_re, buf, 10, re_match, 0)) == 0) {
+	char *lv = NULL;
+
+	extract_re_sub(buf, &re_match[1], &lv);
+	if (!ldapvar) extract_re_sub(buf, &re_match[1], &ldapvar);
+	if (strcmp(ldapvar, lv) == 0) {
+	  if (ldap_base) { free(ldap_base); ldap_base = NULL; }
+	  extract_re_sub(buf, &re_match[2], &ldap_base);
+	}
+	pfree(lv);
+      }
+
+      /* Check for timeout spec */
+      if ((re_code = regexec(&timeout_re, buf, 10, re_match, 0)) == 0) {
+	char *lv = NULL;
+
+	extract_re_sub(buf, &re_match[1], &lv);
+	if (!ldapvar) extract_re_sub(buf, &re_match[1], &ldapvar);
+	if (strcmp(ldapvar, lv) == 0) {
+	  char *to = NULL;
+
+	  extract_re_sub(buf, &re_match[2], &to);
+	  ldap_timeout = atoi(to);
+	  free(to);
+	}
+	pfree(lv);
+      }
+
+      /* Check for bind DN spec */
+      if ((re_code = regexec(&binddn_re, buf, 10, re_match, 0)) == 0) {
+	char *lv = NULL;
+
+	extract_re_sub(buf, &re_match[1], &lv);
+	if (!ldapvar) extract_re_sub(buf, &re_match[1], &ldapvar);
+	if (strcmp(ldapvar, lv) == 0) {
+	  if (ldap_bindDN) { free(ldap_bindDN); ldap_bindDN = NULL; }
+	  extract_re_sub(buf, &re_match[2], &ldap_bindDN);
+	}
+	pfree(lv);
+      }
+
+      /* Check for bind PW spec */
+      if ((re_code = regexec(&bindpw_re, buf, 10, re_match, 0)) == 0) {
+	char *lv = NULL;
+
+	extract_re_sub(buf, &re_match[1], &lv);
+	if (!ldapvar) extract_re_sub(buf, &re_match[1], &ldapvar);
+	if (strcmp(ldapvar, lv) == 0) {
+	  if (ldap_bindPW) { free(ldap_bindPW); ldap_bindPW = NULL; }
+	  extract_re_sub(buf, &re_match[2], &ldap_bindPW);
+	}
+	pfree(lv);
+      }
+
+      /* Check for filter spec */
+      if ((re_code = regexec(&filter_re, buf, 10, re_match, 0)) == 0) {
+	char *lv = NULL;
+
+	extract_re_sub(buf, &re_match[1], &lv);
+	if (!ldapvar) extract_re_sub(buf, &re_match[1], &ldapvar);
+	if (strcmp(ldapvar, lv) == 0) {
+	  char *filt = NULL, *sf = NULL, *ssf = NULL;
+	  int ssftype = X509_LU_FAIL; /* Use this as a catchall */
+
+	  if (re_match[2].rm_so != -1) {
+	    extract_re_sub(buf, &re_match[4], &sf);
+	    if (re_match[5].rm_so != -1) {
+	      extract_re_sub(buf, &re_match[6], &ssf);
+	      if (strcasecmp(ssf, "cert") == 0)
+		ssftype = X509_LU_X509;
+	      else if (strcasecmp(ssf, "crl") == 0)
+		ssftype = X509_LU_CRL;
+	      else
+		ssftype = X509_LU_RETRY; /* Use as an "invalid" value */
+	      pfree(ssf);
+	    }
+	  }
+	  extract_re_sub(buf, &re_match[7], &filt);
+	  if (ssftype != X509_LU_RETRY)
+	    insert_filter((sf == NULL) ? "*" : sf, ssftype, filt, ldap_filter);
+	  else
+	    if (filt) pfree(filt);
+	  if (sf) pfree(sf);
+	}
+	pfree(lv);
+      }
+
+      /* Check for attributes spec */
+      if ((re_code = regexec(&attrs_re, buf, 10, re_match, 0)) == 0) {
+	char *lv = NULL;
+
+	extract_re_sub(buf, &re_match[1], &lv);
+	if (!ldapvar) extract_re_sub(buf, &re_match[1], &ldapvar);
+	if (strcmp(ldapvar, lv) == 0) {
+	  char *attr = NULL;
+	  char *sf = NULL, *ssf = NULL;
+	  int ssftype = X509_LU_FAIL; /* Use this as a catchall */
+
+	  if (re_match[2].rm_so != -1) {
+	    extract_re_sub(buf, &re_match[4], &sf);
+	    if (re_match[5].rm_so != -1) {
+	      extract_re_sub(buf, &re_match[6], &ssf);
+	      if (strcasecmp(ssf, "cert") == 0)
+		ssftype = X509_LU_X509;
+	      else if (strcasecmp(ssf, "crl") == 0)
+		ssftype = X509_LU_CRL;
+	      else if (strcasecmp(ssf, "*") == 0)
+		ssftype = X509_LU_FAIL;
+	      else
+		ssftype = X509_LU_RETRY; /* Use as an "invalid" value */
+	      pfree(ssf);
+	    }
+	  }
+	  extract_re_sub(buf, &re_match[7], &attr);
+	  if (ssftype != X509_LU_RETRY)
+	    insert_attrs((sf == NULL) ? "*" : sf, ssftype, attr, ldap_attrs);
+	  else
+	    if (attr) pfree(attr);
+	  if (sf) pfree(sf);
+	}
+	pfree(lv);
+      }
+
+    }
+  }
+
+  if (!ldap_base) goto end; /* No search base - and we can't default to one */
+
+  if ((ret = alloc_thing(XMAP_LDAP, "xmap_ldap")) == NULL) goto end;
+
+  ret->ldapsource = ldapvar;
+  ret->ldap_host = ldap_host;
+  ret->ldap_port = ldap_port;
+  ret->ldap_base = ldap_base;
+  ret->ldap_timeout = ldap_timeout;
+  ret->ldap_bindDN = ldap_bindDN;
+  ret->ldap_bindPW = ldap_bindPW;
+  memcpy(ret->ldap_filter, ldap_filter, MAXFLIST * sizeof(flist));
+  memcpy(ret->ldap_attrs, ldap_attrs, MAXFLIST * sizeof(alist));
+  
+  fclose(fp); fp = NULL;
+
+  if (!open_bind(ret)) goto end;
+
+  if (ls) pfree(ls);
+  return (void *)ret;
+
+ end:
+  if (ldap_host) pfree(ldap_host);
+  if (ldap_base) pfree(ldap_base);
+  if (ldap_bindDN) pfree(ldap_bindDN);
+  if (ldap_bindPW) pfree(ldap_bindPW);
+  for(i=0; ldap_filter[i].index; i++)
+    { pfree(ldap_filter[i].index); pfree(ldap_filter[i].filter); }
+  for(i=0; ldap_attrs[i].index; i++)
+    { pfree(ldap_attrs[i].index); attrs_free(ldap_attrs[i].attrs); }
+  if (ldapvar) pfree(ldapvar);
+  if (ls) pfree(ls);
+  if (fp) fclose(fp);
+  return NULL;
+}
+
+static STACK_OF(X509_OBJECT) *
+XMAP_LDAP_lookup( void *this, const int type, const char *index, void *p )
+{
+  XMAP_LDAP *xm = (XMAP_LDAP *)this;
+
+  if (type == X509_LU_X509) {
+    if (strcasecmp(index, "subject") == 0)
+      return XMAP_LDAP_lookup_cert_by_subject(xm, (X509_NAME *)p);
+    if (strcasecmp(index, "issuer") == 0)
+      return XMAP_LDAP_lookup_cert_by_issuer(xm, (X509_NAME *)p);
+    else if (strcasecmp(index, "uid") == 0)
+      return XMAP_LDAP_lookup_cert_by_uid(xm, (char *)p);
+    else if (strcasecmp(index, "dns") == 0)
+      return XMAP_LDAP_lookup_cert_by_dns(xm, (char *)p);
+    else if (strcasecmp(index, "ip") == 0)
+      return XMAP_LDAP_lookup_cert_by_ip(xm, *((struct in_addr *)p));
+    else if (strcasecmp(index, "ca") == 0)
+      return XMAP_LDAP_lookup_ca_certs( xm );
+    else
+      return NULL;
+  } else if (type == X509_LU_CRL) {
+    if (strcasecmp(index, "issuer") == 0)
+      return XMAP_LDAP_lookup_crl_by_issuer(xm, (X509_NAME *)p);
+    else
+      return NULL;
+  } else {
+    log("Unknown search type");
+    return NULL;
+  }
+}
+
+static int
+ASN1_UTCTIME_cmp(ASN1_UTCTIME *a, ASN1_UTCTIME *b)
+{
+  char buff1[14],buff2[14],*p;
+  int i,j;
+ 
+  /* Degenerate cases */
+  if (!a && !b) return 0;
+  if (a && !b) return 1;
+  if (!a && b) return -1;
+ 
+  memset(buff1, 0, sizeof(buff1));
+  memset(buff2, 0, sizeof(buff2));
+ 
+  p=buff1;
+  i=a->length;
+  if ((i < 11) || (i > 17)) return(0);
+  memcpy(p,a->data,12);
+ 
+  p=buff2;
+  j=b->length;
+  if ((j < 11) || (j > 17)) return(0);
+  memcpy(p,b->data,12);
+ 
+  /* Correct for Y2K */
+  i=(buff1[0]-'0')*10+(buff1[1]-'0');
+  if (i < 50) i+=100; /* cf. RFC 2459 */
+  j=(buff2[0]-'0')*10+(buff2[1]-'0');
+  if (j < 50) j+=100;
+ 
+  if (i < j) return (-1);
+  if (i > j) return (1);
+ 
+  i=strcmp(buff1,buff2);
+ 
+  if (i == 0)
+    return 0;
+  else if (i < 0)
+    return(-1);
+  else
+    return(1);
+}
+
+static STACK_OF(X509_OBJECT) *
+XMAP_LDAP_lookup_cert_by_subject( XMAP_LDAP *xm, X509_NAME *name )
+{
+  STACK_OF(X509_OBJECT) *sk = sk_X509_OBJECT_new_null();
+  char *str, *s1, *ff, **af;
+  int i, j, tlen, rc;
+  LDAPMessage *res = NULL, *ent = NULL;
+  struct timeval tv;
+  struct berval **bv;
+
+  if (!sk) return NULL;
+  if (!xm->ld)
+    if (!open_bind(xm)) return NULL;
+
+/*
+ * Searching by 'common name' alone is wrong. Will let the code
+ * from the original author remain until a better solution is found.
+ * 
+ *  // First find the 'common name' attribute from the subject
+ *  for(i=0; i<sk_X509_NAME_ENTRY_num(ns); i++) {
+ *    X509_NAME_ENTRY *ne = sk_X509_NAME_ENTRY_value(ns, i);
+ *    int nid = OBJ_obj2nid(ne->object);
+ * 
+ *    if (nid == NID_commonName) {
+ *      if (!(str = alloc_bytes(ASN1_STRING_length(ne->value)+1, "common name")))
+ * return sk;
+ *      memset(str, 0, ASN1_STRING_length(ne->value)+1);
+ *      memcpy(str, ASN1_STRING_data(ne->value),
+ *             ASN1_STRING_length(ne->value));
+ *      break; 
+ *    }
+ *  }
+ */
+
+/* Use the whole DN */
+  str = X509_NAME_oneline(name, NULL, 0);
+
+  ff = find_filter("subject", X509_LU_X509, xm->ldap_filter);
+  af = find_attrs("subject", X509_LU_X509, xm->ldap_attrs);
+  tlen = strlen(ff) + strlen(str);
+  if ((s1 = alloc_bytes(tlen, "filter pattern")) != NULL) {
+    snprintf(s1, tlen, ff, str);
+    tv.tv_sec = xm->ldap_timeout; tv.tv_usec = 0;
+    rc = ldap_search_st(xm->ld, xm->ldap_base, LDAP_SCOPE_SUBTREE,
+			s1, af, 0,
+			&tv, &res);
+    if (rc == LDAP_SUCCESS) {
+      for(ent = ldap_first_entry(xm->ld, res); ent ;
+	  ent = ldap_next_entry(xm->ld, ent)) {
+	for(i = 0; af[i]; i++) {
+	  bv = ldap_get_values_len(xm->ld, ent, af[i]);
+	  if (bv) {
+	    for(j=0; bv[j]; j++) {
+	      unsigned char *p;
+	      X509 *x;
+
+
+	      p = bv[j]->bv_val;
+	      x = d2i_X509(NULL, &p, bv[j]->bv_len);
+	      if (x) {
+
+		if (X509_NAME_cmp(X509_get_subject_name(x), name) == 0) {
+		  X509_OBJECT *xo = X509_OBJECT_new(X509_LU_X509, x);
+		  if (xo) {
+		    int i, found = 0;
+
+		    for(i=0; (!found) && (i<sk_X509_OBJECT_num(sk)); i++) {
+		      X509_OBJECT *o = sk_X509_OBJECT_value(sk, i);
+
+		      if (X509_issuer_and_serial_cmp(x, o->data.x509) == 0)
+			found = 1;
+		    }
+		    if (!found)
+		      sk_X509_OBJECT_push(sk, xo);
+		    else {
+		      X509_free(x); /* duplicate of existing item */
+		    }
+		  } else {
+		    X509_free(x); /* cannot allocate X509_OBJECT */
+		  }
+		} else {
+		  X509_free(x); /* subject name doesn't match */
+		}
+	      }
+	    }
+	    ldap_value_free_len(bv);
+	  }
+	}
+      }
+    } else {
+      log("ldap_search_st error: %s", ldap_err2string(rc));
+      ldap_unbind(xm->ld);
+      xm->ld = NULL;
+    }
+    pfree(s1);
+  }
+  pfree(str);
+  return sk;
+}
+
+static STACK_OF(X509_OBJECT) *
+XMAP_LDAP_lookup_cert_by_issuer( XMAP_LDAP *xm, X509_NAME *name )
+{
+  STACK_OF(X509_OBJECT) *sk = sk_X509_OBJECT_new_null();
+  char *str, *s1, *ff, **af;
+  int i, j, tlen, rc;
+  LDAPMessage *res = NULL, *ent = NULL;
+  struct timeval tv;
+  struct berval **bv;
+
+  if (!sk) return NULL;
+  if (!xm->ld)
+    if (!open_bind(xm)) return NULL;
+
+  str = X509_NAME_oneline(name, NULL, 0);
+
+  ff = find_filter("issuer", X509_LU_X509, xm->ldap_filter);
+  af = find_attrs("issuer", X509_LU_X509, xm->ldap_attrs);
+  tlen = strlen(ff) + strlen(str);
+  if ((s1 = alloc_bytes(tlen, "filter pattern")) != NULL) {
+    snprintf(s1, tlen, ff, str);
+    tv.tv_sec = xm->ldap_timeout; tv.tv_usec = 0;
+    rc = ldap_search_st(xm->ld, xm->ldap_base, LDAP_SCOPE_SUBTREE,
+			s1, af, 0,
+			&tv, &res);
+    if (rc == LDAP_SUCCESS) {
+      for(ent = ldap_first_entry(xm->ld, res); ent ;
+	  ent = ldap_next_entry(xm->ld, ent)) {
+	for(i = 0; af[i]; i++) {
+	  bv = ldap_get_values_len(xm->ld, ent, af[i]);
+	  if (bv) {
+	    for(j=0; bv[j]; j++) {
+	      unsigned char *p;
+	      X509 *x;
+
+
+	      p = bv[j]->bv_val;
+	      x = d2i_X509(NULL, &p, bv[j]->bv_len);
+	      if (x) {
+
+		if (X509_NAME_cmp(X509_get_issuer_name(x), name) == 0) {
+		  X509_OBJECT *xo = X509_OBJECT_new(X509_LU_X509, x);
+		  if (xo) {
+		    int i, found = 0;
+
+		    for(i=0; (!found) && (i<sk_X509_OBJECT_num(sk)); i++) {
+		      X509_OBJECT *o = sk_X509_OBJECT_value(sk, i);
+
+		      if (X509_issuer_and_serial_cmp(x, o->data.x509) == 0)
+			found = 1;
+		    }
+		    if (!found)
+		      sk_X509_OBJECT_push(sk, xo);
+		    else {
+		      X509_free(x); /* duplicate of existing item */
+		    }
+		  } else {
+		    X509_free(x); /* cannot allocate X509_OBJECT */
+		  }
+		} else {
+		  X509_free(x); /* subject name doesn't match */
+		}
+	      }
+	    }
+	    ldap_value_free_len(bv);
+	  }
+	}
+      }
+    } else {
+      log("ldap_search_st error: %s", ldap_err2string(rc));
+      ldap_unbind(xm->ld);
+      xm->ld = NULL;
+    }
+    pfree(s1);
+  }
+  pfree(str);
+  return sk;
+}
+
+static int
+isCA( X509 *x )
+{
+  X509_EXTENSION *ext;
+  BASIC_CONSTRAINTS *p = NULL;
+  int loc;
+  
+  loc = X509_get_ext_by_NID(x, NID_basic_constraints, -1);
+  if (loc >= 0) {
+    ext = X509_get_ext(x, loc);
+    if (ext) {
+      p = X509V3_EXT_d2i(ext);
+      if (! p->ca) {
+	BASIC_CONSTRAINTS_free(p);
+	return 0;
+      } else {
+	BASIC_CONSTRAINTS_free(p);
+	return 1; /* This is a CA certificate */
+      }
+    } else
+      return 0;
+  } else
+    return 0;
+}
+
+static STACK_OF(X509_OBJECT) *
+XMAP_LDAP_lookup_ca_certs( XMAP_LDAP *xm )
+{
+  STACK_OF(X509_OBJECT) *sk = sk_X509_OBJECT_new_null();
+  char *ff, **af;
+  int i, j, rc;
+  LDAPMessage *res = NULL, *ent = NULL;
+  struct timeval tv;
+  struct berval **bv;
+
+  if (!sk) return NULL;
+  if (!xm->ld)
+    if (!open_bind(xm)) return NULL;
+
+  ff = find_filter("ca", X509_LU_X509, xm->ldap_filter);
+  af = find_attrs("ca", X509_LU_X509, xm->ldap_attrs);
+  tv.tv_sec = xm->ldap_timeout; tv.tv_usec = 0;
+  rc = ldap_search_st(xm->ld, xm->ldap_base, LDAP_SCOPE_SUBTREE,
+		      ff, af, 0, &tv, &res);
+  if (rc == LDAP_SUCCESS) {
+    for(ent = ldap_first_entry(xm->ld, res); ent ;
+	ent = ldap_next_entry(xm->ld, ent)) {
+      for(i = 0; af[i]; i++) {
+	bv = ldap_get_values_len(xm->ld, ent, af[i]);
+	if (bv) {
+	  for(j=0; bv[j]; j++) {
+	    unsigned char *p;
+	    X509 *x;
+	    
+	    p = bv[j]->bv_val;
+	    x = d2i_X509(NULL, &p, bv[j]->bv_len);
+	    if ((x) && (isCA(x))) {
+	      X509_OBJECT *xo = X509_OBJECT_new(X509_LU_X509, x);
+	      if (xo) {
+		int i, found = 0;
+		
+		for(i=0; (!found) && (i<sk_X509_OBJECT_num(sk)); i++) {
+		  X509_OBJECT *o = sk_X509_OBJECT_value(sk, i);
+		  
+		  if (X509_issuer_and_serial_cmp(x, o->data.x509) == 0)
+		    found = 1;
+		}
+		if (!found)
+		  sk_X509_OBJECT_push(sk, xo);
+		else
+		  X509_free(x); /* duplicate of existing item */
+	      } else
+		X509_free(x); /* cannot allocate X509_OBJECT */
+	    } else
+	      X509_free(x); /* subject name doesn't match */
+	  }
+	  ldap_value_free_len(bv);
+	}
+      }
+    }
+  } else {
+    log("ldap_search_st error: %s", ldap_err2string(rc));
+    ldap_unbind(xm->ld);
+    xm->ld = NULL;
+  }
+  return sk;
+}
+
+static STACK_OF(X509_OBJECT) *
+XMAP_LDAP_lookup_crl_by_issuer( XMAP_LDAP *xm, X509_NAME *name )
+{
+  STACK_OF(X509_OBJECT) *sk = sk_X509_OBJECT_new_null();
+  STACK_OF(X509_NAME_ENTRY) *ns = name->entries;
+  char *str, *s1, *ff, **af;
+  int i, j, tlen, rc;
+  LDAPMessage *res = NULL, *ent = NULL;
+  struct timeval tv;
+  struct berval **bv;
+
+  if (!sk) return NULL;
+  if (!xm->ld)
+    if (!open_bind(xm)) return NULL;
+
+  /* First find the 'common name' attribute from the subject */
+  for(i=0; i<sk_X509_NAME_ENTRY_num(ns); i++) {
+    X509_NAME_ENTRY *ne = sk_X509_NAME_ENTRY_value(ns, i);
+    int nid = OBJ_obj2nid(ne->object);
+
+    if (nid == NID_commonName) {
+      if (!(str = alloc_bytes(ASN1_STRING_length(ne->value)+1,
+			      "common name")))
+	return sk;
+      memset(str, 0, ASN1_STRING_length(ne->value)+1);
+      memcpy(str, ASN1_STRING_data(ne->value),
+             ASN1_STRING_length(ne->value));
+      break; 
+    }
+  }
+  ff = find_filter("issuer", X509_LU_CRL, xm->ldap_filter);
+  af = find_attrs("issuer", X509_LU_CRL, xm->ldap_attrs);
+  tlen = strlen(ff) + strlen(str);
+  if ((s1 = alloc_bytes(tlen, "filter pattern")) != NULL) {
+    snprintf(s1, tlen, ff, str);
+    tv.tv_sec = xm->ldap_timeout; tv.tv_usec = 0;
+    DBG(DBG_PARSING,
+    DBG_log("LDAP search: \"%s\"", s1);
+    );
+    for(i=0; af[i]; i++) {
+      DBG(DBG_PARSING,
+      DBG_log("Attr %d: %s", i+1, af[i]);
+      );
+    }
+    rc = ldap_search_st(xm->ld, xm->ldap_base, LDAP_SCOPE_SUBTREE,
+			s1, af, 0,
+			&tv, &res);
+    if (rc == LDAP_SUCCESS) {
+      for(ent = ldap_first_entry(xm->ld, res); ent ;
+	  ent = ldap_next_entry(xm->ld, ent)) {
+	for(i = 0; af[i]; i++) {
+	  bv = ldap_get_values_len(xm->ld, ent, af[i]);
+	  if (bv) {
+	    for(j=0; bv[j]; j++) {
+	      unsigned char *p;
+	      X509_CRL *x;
+	      
+	      p = bv[j]->bv_val;
+	      x = d2i_X509_CRL(NULL, &p, bv[j]->bv_len);
+	      if (x) {
+		if (X509_NAME_cmp(X509_CRL_get_issuer(x), name) == 0) {
+		  X509_OBJECT *xo = X509_OBJECT_new(X509_LU_CRL, x);
+
+		  if (xo) {
+		    int i, found = 0;
+
+		    for(i=0; (!found) && (i<sk_X509_OBJECT_num(sk)); i++) {
+		      X509_OBJECT *o = sk_X509_OBJECT_value(sk, i);
+
+		      if ((X509_CRL_cmp(o->data.crl, x) == 0) &&
+			  (ASN1_UTCTIME_cmp(X509_CRL_get_lastUpdate(o->data.crl),
+					    X509_CRL_get_lastUpdate(x)) == 0) &&
+			  (ASN1_UTCTIME_cmp(X509_CRL_get_nextUpdate(o->data.crl),
+					    X509_CRL_get_nextUpdate(x)) == 0))
+			  found = 1;
+		    }
+		    if (!found)
+		      sk_X509_OBJECT_push(sk, xo);
+		    else
+		      X509_CRL_free(x); /* duplicate of existing item */
+		  } else
+		    X509_CRL_free(x); /* cannot allocate X509_OBJECT */
+		} else
+		  X509_CRL_free(x); /* subject name doesn't match */
+	      }
+	    }
+	    ldap_value_free_len(bv);
+	  }
+	}
+      }
+    } else {
+      log("ldap_search_st error: %s", ldap_err2string(rc));
+      ldap_unbind(xm->ld);
+      xm->ld = NULL;
+    }
+    pfree(s1);
+  }
+  pfree(str);
+  return sk;
+}
+
+static STACK_OF(X509_OBJECT) *
+XMAP_LDAP_lookup_cert_by_uid( XMAP_LDAP *xm, const char *uid )
+{
+  STACK_OF(X509_OBJECT) *sk = sk_X509_OBJECT_new_null();
+  char *s1, *ff, **af;
+  int i, j, tlen, rc;
+  LDAPMessage *res = NULL, *ent = NULL;
+  struct timeval tv;
+  struct berval **bv;
+
+  if (!sk) return NULL;
+  if (!xm->ld)
+    if (!open_bind(xm)) return NULL;
+
+  ff = find_filter("uid", X509_LU_X509, xm->ldap_filter);
+  af = find_attrs("uid", X509_LU_X509, xm->ldap_attrs);
+  tlen = strlen(ff) + strlen(uid);
+  if ((s1 = alloc_bytes(tlen, "filter pattern")) != NULL) {
+    snprintf(s1, tlen, ff, uid);
+    tv.tv_sec = xm->ldap_timeout; tv.tv_usec = 0;
+    rc = ldap_search_st(xm->ld, xm->ldap_base, LDAP_SCOPE_SUBTREE,
+			s1, af, 0,
+			&tv, &res);
+    if (rc == LDAP_SUCCESS) {
+      for(ent = ldap_first_entry(xm->ld, res); ent ;
+	  ent = ldap_next_entry(xm->ld, ent)) {
+	for(i = 0; af[i]; i++) {
+	  bv = ldap_get_values_len(xm->ld, ent, af[i]);
+	  if (bv) {
+	    for(j=0; bv[j]; j++) {
+	      unsigned char *p;
+	      X509 *x;
+	      
+	      p = bv[j]->bv_val;
+	      x = d2i_X509(NULL, &p, bv[j]->bv_len);
+	      if (x) {
+		X509_OBJECT *xo = X509_OBJECT_new(X509_LU_X509, x);
+		if (xo) {
+		  int i, found = 0;
+		  
+		  for(i=0; (!found) && (i<sk_X509_OBJECT_num(sk)); i++) {
+		    X509_OBJECT *o = sk_X509_OBJECT_value(sk, i);
+		    
+		    if (X509_issuer_and_serial_cmp(x, o->data.x509) == 0)
+		      found = 1;
+		  }
+		  if (!found)
+		    sk_X509_OBJECT_push(sk, xo);
+		  else
+		    X509_free(x); /* duplicate of existing item */
+		} else
+		  X509_free(x); /* cannot allocate X509_OBJECT */
+	      }
+	    }
+	    ldap_value_free_len(bv);
+	  }
+	}
+      }
+    } else {
+      log("ldap_search_st error: %s", ldap_err2string(rc));
+      ldap_unbind(xm->ld);
+      xm->ld = NULL;
+    }
+    pfree(s1);
+  }
+  return sk;
+}
+
+static STACK_OF(X509_OBJECT) *
+XMAP_LDAP_lookup_cert_by_dns( XMAP_LDAP *xm, const char *dns )
+{
+  STACK_OF(X509_OBJECT) *sk = sk_X509_OBJECT_new_null();
+  char *s1, *ff, **af;
+  int i, j, tlen, rc;
+  LDAPMessage *res = NULL, *ent = NULL;
+  struct timeval tv;
+  struct berval **bv;
+
+  if (!sk) return NULL;
+  if (!xm->ld)
+    if (!open_bind(xm)) return NULL;
+
+  ff = find_filter("dns", X509_LU_X509, xm->ldap_filter);
+  af = find_attrs("dns", X509_LU_X509, xm->ldap_attrs);
+  tlen = strlen(ff) + strlen(dns);
+  if ((s1 = alloc_bytes(tlen, "filter patten")) != NULL) {
+    snprintf(s1, tlen, ff, dns);
+    tv.tv_sec = xm->ldap_timeout; tv.tv_usec = 0;
+    rc = ldap_search_st(xm->ld, xm->ldap_base, LDAP_SCOPE_SUBTREE,
+			s1, af, 0,
+			&tv, &res);
+    if (rc == LDAP_SUCCESS) {
+      for(ent = ldap_first_entry(xm->ld, res); ent ;
+	  ent = ldap_next_entry(xm->ld, ent)) {
+	for(i = 0; af[i]; i++) {
+	  bv = ldap_get_values_len(xm->ld, ent, af[i]);
+	  if (bv) {
+	    for(j=0; bv[j]; j++) {
+	      unsigned char *p;
+	      X509 *x;
+	      
+	      p = bv[j]->bv_val;
+	      x = d2i_X509(NULL, &p, bv[j]->bv_len);
+	      if (x) {
+		if (X509_subjAltName_check_dns(x, dns)) {
+		  X509_OBJECT *xo = X509_OBJECT_new(X509_LU_X509, x);
+		  if (xo) {
+		    int i, found = 0;
+		    
+		    for(i=0; (!found) && (i<sk_X509_OBJECT_num(sk)); i++) {
+		      X509_OBJECT *o = sk_X509_OBJECT_value(sk, i);
+		      
+		      if (X509_issuer_and_serial_cmp(x, o->data.x509) == 0)
+			found = 1;
+		    }
+		    if (!found)
+		      sk_X509_OBJECT_push(sk, xo);
+		    else
+		      X509_free(x); /* duplicate of existing item */
+		  } else
+		    X509_free(x); /* cannot allocate X509_OBJECT */
+		} else
+		  X509_free(x); /* subjAltName mismatch */
+	      }
+	    }
+	    ldap_value_free_len(bv);
+	  }
+	}
+      }
+    } else {
+      log("ldap_search_st error: %s", ldap_err2string(rc));
+      ldap_unbind(xm->ld);
+      xm->ld = NULL;
+    }
+    pfree(s1);
+  }
+  return sk;
+}
+
+static STACK_OF(X509_OBJECT) *
+XMAP_LDAP_lookup_cert_by_ip( XMAP_LDAP *xm, const struct in_addr ip )
+{
+  STACK_OF(X509_OBJECT) *sk = sk_X509_OBJECT_new_null();
+  char *s1, *ff, **af, *ipt;
+  int i, j, tlen, rc;
+  LDAPMessage *res = NULL, *ent = NULL;
+  struct timeval tv;
+  struct berval **bv;
+
+  if (!sk) return NULL;
+  if (!xm->ld)
+    if (!open_bind(xm)) return NULL;
+
+  if ((ipt = inet_ntoa(ip)) == NULL) return NULL;
+  ff = find_filter("ip", X509_LU_X509, xm->ldap_filter);
+  af = find_attrs("ip", X509_LU_X509, xm->ldap_attrs);
+  
+  tlen = strlen(ff) + strlen(ipt);
+  if ((s1 = alloc_bytes(tlen, "filter pattern")) != NULL) {
+    snprintf(s1, tlen, ff, ipt);
+    tv.tv_sec = xm->ldap_timeout; tv.tv_usec = 0;
+
+    DBG(DBG_PARSING, 
+    DBG_log("xm->ldap_base: %s -- s1: %s -- *af: %s", xm->ldap_base, s1, *af);
+    );
+
+    rc = ldap_search_st(xm->ld, xm->ldap_base, LDAP_SCOPE_SUBTREE,
+			s1, af, 0,
+			&tv, &res);
+    if (rc == LDAP_SUCCESS) {
+      for(ent = ldap_first_entry(xm->ld, res); ent ;
+	  ent = ldap_next_entry(xm->ld, ent)) {
+        for(i = 0; af[i]; i++) {
+          DBG(DBG_PARSING,
+          DBG_log("af[%d]: [%s]", i, af[i]);
+          );
+
+          bv = ldap_get_values_len(xm->ld, ent, af[i]);
+	  if (bv) {
+	    for(j=0; bv[j]; j++) {
+	      unsigned char *p;
+	      X509 *x;
+	      
+          DBG(DBG_PARSING,
+          DBG_log("** We got LDAP. Trying to process. j=%d.", j);
+          );
+
+          DBG(DBG_PARSING | DBG_RAW,
+          DBG_log("** length of X509 cert: %d", (int )bv[j]->bv_len);
+          );
+          DBG(DBG_RAW,
+          DBG_dump("** p: ", bv[j]->bv_val, bv[j]->bv_len);
+          );
+
+	      p = bv[j]->bv_val;
+	      x = d2i_X509(NULL, &p, bv[j]->bv_len);
+	      if (x) {
+            if (X509_subjAltName_check_ip(x, ip)) {
+              X509_OBJECT *xo = X509_OBJECT_new(X509_LU_X509, x);
+              if (xo) {
+                int i, found = 0;
+		    
+                for(i=0; (!found) && (i<sk_X509_OBJECT_num(sk)); i++) {
+                  X509_OBJECT *o = sk_X509_OBJECT_value(sk, i);
+		      
+                  if (X509_issuer_and_serial_cmp(x, o->data.x509) == 0)
+                    found = 1;
+                } /* end for */
+                if (!found)
+                  sk_X509_OBJECT_push(sk, xo);
+                else
+                  X509_free(x); /* duplicate of existing item */
+              }  /* end if (xo) */
+              else
+                X509_free(x); /* cannot allocate X509_OBJECT */
+            } /* end if (X509_subjAltName_check_ip(x, ip)) */
+            else
+              X509_free(x); /* SubjectAltName mismatch */
+          } /* end if (x) */
+          else
+          {
+          }
+        }
+        ldap_value_free_len(bv);
+      }
+    }
+  }
+    } else {
+      DBG(DBG_PARSING,
+      DBG_log("ldap_search_st error: %s", ldap_err2string(rc));
+      );
+      ldap_unbind(xm->ld);
+      xm->ld = NULL;
+    }
+    pfree(s1);
+  }
+  return sk;
+}
+
+static void
+sanitize(const char *buf, char *buf2, int buf2len)
+{
+  int l = strlen(buf), i, nl, p;
+  char *b;
+
+  for(i=0, nl=l; i<l; i++) if (buf[i] == '%') nl++;
+  b = alloc_bytes(nl+1, "temporary string");
+  memset(b, 0, nl+1);
+  for(i=0, p=0; i < nl; i++) {
+    if (buf[i] == '%') {
+      b[p] = '%';
+      b[p+1] = '%';
+      p++;
+    } else {
+      b[p] = buf[i];
+    }
+    p++;
+  }
+  strncpy(buf2, b, buf2len-1);
+  pfree(b);
+}
+
+static void
+XMAP_LDAP_dump(void *this)
+{
+  char buf[256];
+  XMAP_LDAP *xm = (XMAP_LDAP *)this;
+  int i, j;
+
+  DBG(DBG_PARSING,
+  DBG_log("XMAP_LDAP: %s", xm->ldapsource);
+  DBG_log("Host = %s:%d (Timeout = %d seconds)",
+	  xm->ldap_host, xm->ldap_port, xm->ldap_timeout);
+  DBG_log("Search base = %s", xm->ldap_base);
+  DBG_log("Bind = (\"%s\", \"%s\")", xm->ldap_bindDN, xm->ldap_bindPW);
+  );
+  for(i=0; ((i < MAXFLIST) && (xm->ldap_filter[i].index)); i++) {
+    snprintf(buf, sizeof(buf)-1, "Filter[%d] (%s,",
+	     i+1, xm->ldap_filter[i].index);
+    switch(xm->ldap_filter[i].type) {
+      case X509_LU_X509: strncat(buf, "Cert", sizeof(buf)-1); break;
+      case X509_LU_CRL: strncat(buf, "CRL", sizeof(buf)-1); break;
+      default: strncat(buf, "*", sizeof(buf)-1); break;
+    }
+    strncat(buf, ") ", sizeof(buf)-1);
+    strncat(buf, xm->ldap_filter[i].filter, sizeof(buf)-1);
+    sanitize(buf, buf, sizeof(buf)-1);
+    DBG(DBG_PARSING,
+    DBG_log(buf);
+    );
+  }
+  for(i=0; ((i < MAXFLIST) && (xm->ldap_attrs[i].index)); i++) {
+    snprintf(buf, sizeof(buf), "Attributes[%d] (%s,",
+	     i+1, xm->ldap_attrs[i].index);
+    switch(xm->ldap_attrs[i].type) {
+      case X509_LU_X509: strncat(buf, "Cert", sizeof(buf)-1); break;
+      case X509_LU_CRL: strncat(buf, "CRL", sizeof(buf)-1); break;
+      default: strncat(buf, "*", sizeof(buf)-1); break;
+    }
+    strncat(buf, ") ", sizeof(buf)-1);
+    for(j=0; xm->ldap_attrs[i].attrs[j]; j++) {
+      strncat(buf, ",", sizeof(buf)-1);
+      strncat(buf, xm->ldap_attrs[i].attrs[j], sizeof(buf)-1);
+    }
+    sanitize(buf, buf, sizeof(buf)-1);
+    DBG(DBG_PARSING,
+    DBG_log(buf);
+    );
+  }
+}
+
+static void
+XMAP_LDAP_free(void *this)
+{
+  XMAP_LDAP *xm = (XMAP_LDAP *)this;
+  int i;
+
+  if (!xm) return;
+  if (xm->ld) ldap_unbind(xm->ld);
+  if (xm->ldapsource) pfree(xm->ldapsource);
+  if (xm->ldap_host) pfree(xm->ldap_host);
+  if (xm->ldap_base) pfree(xm->ldap_base);
+  if (xm->ldap_bindDN) pfree(xm->ldap_bindDN);
+  if (xm->ldap_bindPW) pfree(xm->ldap_bindPW);
+
+  for(i=0; ((i < MAXFLIST) && (xm->ldap_filter[i].index)); i++) {
+    pfree(xm->ldap_filter[i].index);
+    pfree(xm->ldap_filter[i].filter);
+  }
+  
+  for(i=0; ((i < MAXFLIST) && (xm->ldap_attrs[i].index)); i++) {
+    pfree(xm->ldap_attrs[i].index);
+    attrs_free(xm->ldap_attrs[i].attrs);
+  }
+
+  pfree(xm);
+}
+
+XMAP_METHOD *
+XMAP_METHOD_ldap( void )
+{
+  return (&xmap_ldap_methods);
+}
+
+#endif /* HAVE_LDAP */
+#endif /* OPENSSL */
diff -bruN freeswan-1.9.orig/pluto/xmap_ldap.h freeswan-1.9/pluto/xmap_ldap.h
--- freeswan-1.9.orig/pluto/xmap_ldap.h	Wed Dec 31 19:00:00 1969
+++ freeswan-1.9/pluto/xmap_ldap.h	Wed May 16 10:57:20 2001
@@ -0,0 +1,49 @@
+#ifndef XMAP_LDAP_H
+#define XMAP_LDAP_H
+
+#ifdef HAVE_LDAP
+
+#include <openssl/safestack.h>
+#include <openssl/x509.h>
+
+#include <lber.h>
+#include <ldap.h>
+
+#include "x_sobj.h"
+#include "xmap.h"
+
+typedef struct _flist_st {
+  char *index;
+  int type;
+  char *filter;
+} flist;
+
+#define MAXFLIST 10
+
+typedef struct _alist_st {
+  char *index;
+  int type;
+  char **attrs;
+} alist;
+
+typedef struct xmap_ldap_st {
+  char *ldapsource;
+  char *ldap_host;
+  int ldap_port;
+  char *ldap_base;
+  int ldap_timeout;
+  char *ldap_bindDN;
+  char *ldap_bindPW;
+  flist ldap_filter[MAXFLIST];
+  alist ldap_attrs[MAXFLIST];
+
+  LDAP *ld;
+
+  XMAP_METHOD *meth;
+} XMAP_LDAP;
+
+XMAP_METHOD *XMAP_METHOD_ldap( void );
+
+#endif /* HAVE_LDAP */
+
+#endif /* XMAP_LDAP_H */
diff -bruN freeswan-1.9.orig/utils/Makefile freeswan-1.9/utils/Makefile
--- freeswan-1.9.orig/utils/Makefile	Tue Feb  6 13:11:41 2001
+++ freeswan-1.9/utils/Makefile	Thu Jun  7 14:52:06 2001
@@ -17,16 +17,24 @@
 PUBDIR=/usr/local/sbin
 PRIVDIR=/usr/local/lib/ipsec
 REALPRIVDIR=/usr/local/lib/ipsec
+FINALPRIVDIR=/usr/local/lib/ipsec
 RCDIR=/etc/rc.d/init.d
 REALRCDIR=/etc/rc.d/init.d
 CONFDIR=/etc
-MANTREE=/usr/local/man
+MANTREE=/usr/man
 
 FMANDIR=$(MANTREE)/man5
 CMANDIR=$(MANTREE)/man8
 PUBS=ipsec
-BINS=ranbits rsasigkey
+
+ifeq "$(USEOPENSSL)" "1"
+SCRIPTS=barf manual auto look showdefaults showhostkey rehashcertdir rsakeygen updown.firewall
+BINS=ranbits rsasigkey fswcert
+else
 SCRIPTS=barf manual auto look showdefaults showhostkey
+BINS=ranbits rsasigkey
+endif
+
 INTERNALS=_include _confread _keycensor _secretcensor _updown
 PRIVS=$(PUBS) $(SCRIPTS) $(INTERNALS) $(BINS)
 GENDFILES=secrets.eg conf.eg
@@ -47,6 +55,10 @@
 
 all:	$(PUBS) $(PRIVS) $(GENDFILES) $(LOCALS)
 
+fswcert: fswcert-0.4/fswcert.c
+	cd fswcert-0.4; $(MAKE)
+	cp fswcert-0.4/fswcert .
+
 ranbits:	ranbits.o
 	$(CC) $(CFLAGS) ranbits.o $(LIB) -o $@
 
@@ -64,7 +76,7 @@
 
 ipsec:	ipsec.in
 	VER=`sed -n '/"/s/^[^"]*"//p' ../version.c | sed 's/".*//'` ; \
-	sed "s/xxx/$$VER/" ipsec.in | sed "s:@IPSECDIR@:$(REALPRIVDIR):" >$@
+	sed "s/xxx/$$VER/" ipsec.in | sed "s:@IPSEC_DIR@:$(REALPRIVDIR):" >$@
 	chmod +x $@
 
 # generate sample secret (obfuscating it so that people don't get confused
@@ -98,41 +110,46 @@
 	./randomize conf.proto | egrep -v RCSI >$@
 
 install:	$(PUBS) $(PRIVS) $(MANS) $(GENDFILES)
-	mkdir -p $(PUBDIR) $(PRIVDIR) $(FMANDIR) $(CMANDIR) $(CONFDIR)
-	$(INSTALL) $(PUBS) $(PUBDIR)
-	$(INSTALL) $(PRIVS) $(PRIVDIR)
-	$(INSTALL) $(PUB) ipsec.conf.5 $(FMANDIR)
-	$(INSTALL) $(PUB) $(PLAIN_MANS) $(CMANDIR)
+	mkdir -p $(PREFIX)/$(PUBDIR) $(PREFIX)/$(PRIVDIR) 
+	mkdir -p $(PREFIX)/$(FMANDIR) $(PREFIX)/$(CMANDIR) 
+	mkdir -p $(PREFIX)/$(CONFDIR)
+	$(INSTALL) $(PUBS) $(PREFIX)/$(PUBDIR)
+	$(INSTALL) $(PRIVS) $(PREFIX)/$(PRIVDIR)
+	$(INSTALL) $(PUB) ipsec.conf.5 $(PREFIX)/$(FMANDIR)
+	$(INSTALL) $(PUB) $(PLAIN_MANS) $(PREFIX)/$(CMANDIR)
 	for f in $(IPSEC_CMANS) ; \
 	do \
-		$(INSTALL) $(PUB) $$f $(CMANDIR)/ipsec_$$f || exit 1 ; \
-		./manlink $(CMANDIR) ipsec_$$f ; \
+		$(INSTALL) $(PUB) $$f $(PREFIX)/$(CMANDIR)/ipsec_$$f || exit 1 ; \
+		./manlink $(PREFIX)/$(CMANDIR) ipsec_$$f ; \
 	done
-	test -f $(CONFDIR)/ipsec.secrets || \
-		$(INSTALL) $(PRIV) secrets.eg $(CONFDIR)/ipsec.secrets
-	test -f $(CONFDIR)/ipsec.conf || \
-		$(INSTALL) $(PUB) conf.eg $(CONFDIR)/ipsec.conf
+	test -d $(PREFIX)/$(CONFDIR) || $(INSTALL) -d $(PREFIX)/$(CONFDIR)
+	test -f $(PREFIX)/$(CONFDIR)/ipsec.secrets || \
+		$(INSTALL) $(PRIV) secrets.eg $(PREFIX)/$(CONFDIR)/ipsec.secrets
+	test -f $(PREFIX)/$(CONFDIR)/ipsec.conf || \
+		$(INSTALL) $(PUB) conf.eg $(PREFIX)/$(CONFDIR)/ipsec.conf
 	# main copy must go in RCDIR, PRIVDIR may not be mounted at boot time
-	mkdir -p $(RCDIR)
-	$(INSTALL) setup $(RCDIR)/ipsec
-	rm -f $(PRIVDIR)/setup
-	ln -s $(REALRCDIR)/ipsec $(PRIVDIR)/setup
-	if test " $(DESTDIR)" != " " ; \
-	then : do nothing ; \
-	elif which chkconfig >/dev/null 2>&1 ; \
+	test -d $(PREFIX)/$(RCDIR) || mkdir -p $(PREFIX)/$(RCDIR)
+	$(INSTALL) setup $(PREFIX)/$(RCDIR)/ipsec
+	rm -f $(PREFIX)/$(PRIVDIR)/setup
+	ln -s $(PREFIX)/$(REALRCDIR)/ipsec $(PREFIX)/$(PRIVDIR)/setup
+	# Only turn on the service if doing default install
+	if [ $(PREFIX) = '/' ] ; then \
+		if which chkconfig >/dev/null 2>&1 ; \
 	then chkconfig --add ipsec ; \
 	else $(MAKE) setup4 ; \
+		fi ; \
 	fi
 
+
 setup4:	$(RCDIR)/ipsec
 	# fallback rc install -- on in run states 2345, off in 016
-	-cd $(RCDIR)/../rc0.d ; ln -s ../init.d/ipsec K35ipsec
-	-cd $(RCDIR)/../rc1.d ; ln -s ../init.d/ipsec K35ipsec
-	-cd $(RCDIR)/../rc2.d ; ln -s ../init.d/ipsec S35ipsec
-	-cd $(RCDIR)/../rc3.d ; ln -s ../init.d/ipsec S35ipsec
-	-cd $(RCDIR)/../rc4.d ; ln -s ../init.d/ipsec S35ipsec
-	-cd $(RCDIR)/../rc5.d ; ln -s ../init.d/ipsec S35ipsec
-	-cd $(RCDIR)/../rc6.d ; ln -s ../init.d/ipsec K35ipsec
+	-test -d $(RCDIR) && cd $(RCDIR)/../rc0.d ; ln -s ../init.d/ipsec K35ipsec
+	-test -d $(RCDIR) && cd $(RCDIR)/../rc1.d ; ln -s ../init.d/ipsec K35ipsec
+	-test -d $(RCDIR) && cd $(RCDIR)/../rc2.d ; ln -s ../init.d/ipsec S35ipsec
+	-test -d $(RCDIR) && cd $(RCDIR)/../rc3.d ; ln -s ../init.d/ipsec S35ipsec
+	-test -d $(RCDIR) && cd $(RCDIR)/../rc4.d ; ln -s ../init.d/ipsec S35ipsec
+	-test -d $(RCDIR) && cd $(RCDIR)/../rc5.d ; ln -s ../init.d/ipsec S35ipsec
+	-test -d $(RCDIR) && cd $(RCDIR)/../rc6.d ; ln -s ../init.d/ipsec K35ipsec
 
 clean:
 	rm -f *.o $(BINS) $(GENDFILES) $(GENDSCRIPTS) $(LOCALS)
diff -bruN freeswan-1.9.orig/utils/_confread freeswan-1.9/utils/_confread
--- freeswan-1.9.orig/utils/_confread	Wed Mar 14 19:05:54 2001
+++ freeswan-1.9/utils/_confread	Mon Jun  4 10:40:36 2001
@@ -12,7 +12,7 @@
 # or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 # for more details.
 #
-# RCSID $Id: _confread,v 1.33.2.4 2001/03/15 00:05:54 henry Exp $
+# RCSID $Id: _confread,v 1.39 2001/06/01 15:49:13 henry Exp $
 #
 # Extract configuration info from /etc/ipsec.conf, repackage as assignments
 # to shell variables or tab-delimited fields.  Success or failure is reported
@@ -47,6 +47,7 @@
 fieldfmt=yes
 prefix=
 search=
+me="ipsec _confread"
 
 for dummy
 do
@@ -58,6 +59,7 @@
 			prefix="$2"
 			shift			;;
 	--search)	search="$2" ; shift	;;
+	--version)      echo "$me $IPSEC_VERSION" ; exit 0      ;;
 	--)		shift ; break		;;
 	-*)		echo "$0: unknown option \`$1'" >&2 ; exit 2	;;
 	*)		break			;;
@@ -115,10 +117,11 @@
 			fail("invalid section name " bq na[i] eq)
 	}
 
-	good = "also type auto authby"
+	good = "also type auto authby force_encrypt_cypher"
 	left = " left leftsubnet leftnexthop leftfirewall leftupdown"
 	akey = " keyexchange auth pfs keylife rekeymargin rekeyfuzz compress"
 	obs = " lifetime rekeystart rekeytries"
+	cert = " certfile keyfile peerfile certopts certpath"
 	akey = akey " keyingtries ikelifetime" obs
 	mkey = " spibase spi esp espenckey espauthkey espreplay_window"
 	left = left " leftespenckey leftespauthkey leftahkey"
@@ -126,7 +129,7 @@
 	mkey = mkey " ah ahkey ahreplay_window"
 	right = left
 	gsub(/left/, "right", right)
-	n = split(good left right akey mkey, g)
+	n = split(good left right akey mkey cert, g)
 	for (i = 1; i <= n; i++)
 		goodnames["conn:" g[i]] = 1
 
@@ -159,7 +162,9 @@
 function output(code, v1, v2) {
 	if (code == o_parm && v2 == "")		# suppress empty parameters
 		return
-	if (code == o_parm && !privatename(v1) && v2 ~ badchar)
+	if (privatename(v1))			# and private ones
+		return
+	if (code == o_parm && v2 ~ badchar)
 		fail("parameter value " bq v2 eq " contains unprintable character")
 
 	if (fieldfmt)
@@ -319,7 +324,7 @@
 			searchfound(sectionname)
 	} else {
 		# rather a kludge, but must check this somewhere
-		if (search == "auto" && rest !~ /^(add|start|ignore)$/)
+		if (search == "auto" && rest !~ /^(add|start|ignore|background)$/)
 			fail("illegal auto value " bq rest eq)
 	}
 	next
diff -bruN freeswan-1.9.orig/utils/_include freeswan-1.9/utils/_include
--- freeswan-1.9.orig/utils/_include	Tue Mar 14 19:38:50 2000
+++ freeswan-1.9/utils/_include	Mon Jun  4 10:42:33 2001
@@ -12,7 +12,7 @@
 # or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 # for more details.
 #
-# RCSID $Id: _include,v 1.13 2000/03/15 00:38:50 henry Exp $
+# RCSID $Id: _include,v 1.14 2001/06/01 15:49:13 henry Exp $
 #
 # Output includes marker lines for file changes:
 #	"#< filename lineno" signals entry into that file
@@ -24,13 +24,14 @@
 # Lines which look like marker and report lines are never passed through.
 
 usage="Usage: $0 file ..."
+me="ipsec _include"
 
 for dummy
 do
 	case "$1" in
 	--inband)				;;	# back compatibility
 	--help)		echo "$usage" ; exit 0	;;
-	--version)	echo 1 ; exit 0		;;
+	--version)	echo "$me $IPSEC_VERSION" ; exit 0		;;
 	--)		shift ; break		;;
 	-*)		echo "$0: unknown option \`$1'" >&2 ; exit 2	;;
 	*)		break			;;
diff -bruN freeswan-1.9.orig/utils/_keycensor freeswan-1.9/utils/_keycensor
--- freeswan-1.9.orig/utils/_keycensor	Thu Jun  1 18:20:24 2000
+++ freeswan-1.9/utils/_keycensor	Mon Jun  4 10:42:45 2001
@@ -12,15 +12,16 @@
 # or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 # for more details.
 #
-# RCSID $Id: _keycensor,v 1.5 2000/06/01 22:20:24 henry Exp $
+# RCSID $Id: _keycensor,v 1.6 2001/06/01 15:49:13 henry Exp $
 
 usage="Usage: $0 [file ...]"
+me="ipsec _keycensor"
 
 for dummy
 do
 	case "$1" in
 	--help)		echo "$usage" ; exit 0	;;
-	--version)	echo 1 ; exit 0		;;
+	--version)	echo "$me $IPSEC_VERSION" ; exit 0		;;
 	--)		shift ; break		;;
 	-*)		echo "$0: unknown option \`$1'" >&2 ; exit 2	;;
 	*)		break			;;
diff -bruN freeswan-1.9.orig/utils/_secretcensor freeswan-1.9/utils/_secretcensor
--- freeswan-1.9.orig/utils/_secretcensor	Thu Jun  1 18:19:52 2000
+++ freeswan-1.9/utils/_secretcensor	Mon Jun  4 10:42:55 2001
@@ -12,15 +12,16 @@
 # or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 # for more details.
 #
-# RCSID $Id: _secretcensor,v 1.6 2000/06/01 22:19:52 henry Exp $
+# RCSID $Id: _secretcensor,v 1.7 2001/06/01 15:49:13 henry Exp $
 
 usage="Usage: $0 [file ...]"
+me="ipsec _secretcensor"
 
 for dummy
 do
 	case "$1" in
 	--help)		echo "$usage" ; exit 0	;;
-	--version)	echo 1 ; exit 0		;;
+	--version)	echo "$me $IPSEC_VERSION" ; exit 0		;;
 	--)		shift ; break		;;
 	-*)		echo "$0: unknown option \`$1'" >&2 ; exit 2	;;
 	*)		break			;;
diff -bruN freeswan-1.9.orig/utils/_updown freeswan-1.9/utils/_updown
--- freeswan-1.9.orig/utils/_updown	Tue Mar 27 15:53:31 2001
+++ freeswan-1.9/utils/_updown	Wed May 16 10:57:20 2001
@@ -12,7 +12,7 @@
 # or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 # for more details.
 #
-# RCSID $Id: _updown,v 1.11.2.2 2001/03/27 20:53:31 henry Exp $
+# RCSID $Id: _updown,v 1.14 2001/04/07 22:42:54 henry Exp $
 
 
 
@@ -57,8 +57,15 @@
 }
 doroute() {
 	parms="-net $PLUTO_PEER_CLIENT_NET netmask $PLUTO_PEER_CLIENT_MASK"
-	parms="$parms dev $PLUTO_INTERFACE gw $PLUTO_NEXT_HOP"
-	route $1 $parms
+	parms2="dev $PLUTO_INTERFACE gw $PLUTO_NEXT_HOP"
+	case "$PLUTO_PEER_CLIENT_NET/$PLUTO_PEER_CLIENT_MASK" in
+	"0.0.0.0/0.0.0.0")
+		# horrible kludge for obscure routing bug with opportunistic
+		route $1 -net 0.0.0.0 netmask 128.0.0.0 $parms2 &&
+			route $1 -net 128.0.0.0 netmask 128.0.0.0 $parms2
+		;;
+	*)	route $1 $parms $parms2	;;
+	esac
 	st=$?
 	if test $st -ne 0
 	then
@@ -74,15 +81,25 @@
 case "$PLUTO_VERB:$1" in
 prepare-host:*|prepare-client:*)
 	# delete possibly-existing route (preliminary to adding a route)
+	case "$PLUTO_PEER_CLIENT_NET/$PLUTO_PEER_CLIENT_MASK" in
+	"0.0.0.0/0.0.0.0")
+		# horrible kludge for obscure routing bug with opportunistic
+		parms1="-net 0.0.0.0 netmask 128.0.0.0"
+		parms2="-net 128.0.0.0 netmask 128.0.0.0"
+		oops="`route del $parms1 2>&1 ; route del $parms2 2>&1`"
+		;;
+	*)
 	parms="-net $PLUTO_PEER_CLIENT_NET netmask $PLUTO_PEER_CLIENT_MASK"
 	oops="`route del $parms 2>&1`"
+		;;
+	esac
 	status="$?"
 	if test " $oops" = " " -a " $status" != " 0"
 	then
 		oops="silent error, exit status $status"
 	fi
 	case "$oops" in
-	'SIOCDELRT: No such process')
+	'SIOCDELRT: No such process'*)
 		# This is what route (currently -- not documented!) gives
 		# for "could not find such a route".
 		oops=
diff -bruN freeswan-1.9.orig/utils/auto freeswan-1.9/utils/auto
--- freeswan-1.9.orig/utils/auto	Mon Feb  5 20:13:18 2001
+++ freeswan-1.9/utils/auto	Mon Jun  4 10:44:49 2001
@@ -12,7 +12,7 @@
 # or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 # for more details.
 #
-# RCSID $Id: auto,v 1.55 2001/02/06 01:13:18 henry Exp $
+# RCSID $Id: auto,v 1.59 2001/05/04 05:31:50 henry Exp $
 
 me='ipsec auto'
 usage="Usage:
@@ -37,7 +37,7 @@
 do
 	case "$1" in
 	--help)		echo "$usage" ; exit 0	;;
-	--version)	echo 2 ; exit 0		;;
+	--version)      echo "$me $IPSEC_VERSION" ; exit 0      ;;
 	--show)		shopts=-x		;;
 	--showonly)	showonly=yes		;;
 	--config)	config="$2" ; shift	;;
@@ -222,11 +222,13 @@
 		return s[k]
 	}
 	function whackkey(dir,   rk) {
+		if (id(dir) == "%opportunistic")
+			return
 		rk = s[dir "rsasigkey"]
-		if (rk != "%dns")
-			print "ipsec whack --keyid", id(dir), "--pubkeyrsa", rk
-		else
+		if (rk == "%dns")
 			print "ipsec whack --keyid", id(dir)
+		else if (rk != "")
+			print "ipsec whack --keyid", id(dir), "--pubkeyrsa", rk
 	}
 	function output() {
 		if (!seensome)
@@ -288,8 +290,8 @@
 		}
 		duration("ikelifetime")
 
-		default("leftnexthop", s["right"])
-		default("rightnexthop", s["left"])
+		default("leftnexthop", "%direct")
+		default("rightnexthop", "%direct")
 		if (s["leftnexthop"] == s["left"])
 			fail("left and leftnexthop must not be the same")
 		if (s["rightnexthop"] == s["right"])
@@ -321,17 +323,56 @@
 			s["rightupdown"] = s["rightupdown"] " ipfwadm"
 
 		default("authby", "secret")
+		authbyfound = "0"
 		authtype = "--psk"
 		if (s["authby"] == "rsasig") {
+			authbyfound = "1"
 			authtype = "--rsasig"
 			need("leftrsasigkey")
 			need("rightrsasigkey")
-			if (id("left") ~ /^%/)
+			if (id("left") == "%any")
 				fail("ID \"" id("left") "\" cannot have RSA key")
-			if (id("right") ~ /^%/)
+			if (id("right") == "%any")
 				fail("ID \"" id("right") "\" cannot have RSA key")
-		} else if (s["authby"] != "secret")
+		}
+
+
+		if (s["authby"] == "cert") {
+			authbyfound = "1"
+			default("certfile", "")
+			default("certopts", "send")
+			default("keyfile", "")
+			default("certpath", "")
+			authtype = "--openssl"
+			need("certfile")
+			need("certopts")
+			need("keyfile")
+			need("certpath")
+		}
+
+		if (s["authby"] != "secret") {
+		  if (s["authby"] != "psk") {
+			if (authbyfound != "1") {
 			fail("unknown authby value \"" s["authby"] "\"")
+			}
+		  }
+		}
+
+		default("force_encrypt_cypher", "")
+		if ("force_encrypt_cypher" in s) {
+			if (s["force_encrypt_cypher"] == "des") {
+				force_encrypt_cypher = "des"
+			}
+			if (s["force_encrypt_cypher"] == "DES") {
+				force_encrypt_cypher = "des"
+			}
+			if (s["force_encrypt_cypher"] == "3des") {
+				force_encrypt_cypher = "3des"
+			}
+			if (s["force_encrypt_cypher"] == "3DES") {
+				force_encrypt_cypher = "3des"
+			}
+		}
 
 		settings = "--encrypt"
 		if (s["type"] != "transport")
@@ -366,6 +407,17 @@
 		if ("rekeyfuzz" in s)
 			fuzz = "--rekeyfuzz " s["rekeyfuzz"]
 
+		if (authtype == "--openssl") {
+			if ("certfile" in s)
+				certfile = "--certfile " s["certfile"]
+			if ("certopts" in s)
+				certopts = "--certopts " s["certopts"]
+			if ("keyfile" in s)
+				keyfile = "--keyfile " s["keyfile"]
+			if ("certpath" in s)
+				certpath = "--certpath " s["certpath"]
+		}
+
 		print "ipsec whack --name", name, settings, "\\"
 		print "\t--host", s["left"], lc,
 				"--nexthop", s["leftnexthop"], lud, lid, "\\"
@@ -373,8 +425,23 @@
 				"--nexthop", s["rightnexthop"], rud, rid, "\\"
 		print "\t--ipseclifetime", s["keylife"],
 			"--rekeywindow", s["rekeymargin"], "\\"
+		if (authtype == "--openssl") {
+			if (certfile != "--certfile ")
+				print certfile, "\\"
+			if (certopts != "--certopts ")
+				print certopts, "\\"
+			if (keyfile != "--keyfile ")
+				print keyfile, "\\"
+			if (certpath != "--certpath ")
+				print certpath, "\\"
+		}
+
+		if (force_encrypt_cypher != "") {
+			print "\t--force_encrypt_cypher", s["force_encrypt_cypher"], "\\"
+		}
+
 		print "\t--keyingtries", s["keyingtries"], fuzz
-		if (authtype != "--psk") {
+		if (authtype == "--rsasig") {
 			whackkey("left")
 			whackkey("right")
 		}
diff -bruN freeswan-1.9.orig/utils/auto.8 freeswan-1.9/utils/auto.8
--- freeswan-1.9.orig/utils/auto.8	Fri Mar 23 12:43:47 2001
+++ freeswan-1.9/utils/auto.8	Mon Jun  4 10:37:03 2001
@@ -1,5 +1,5 @@
-.TH IPSEC_AUTO 8 "23 March 2001"
-.\" RCSID $Id: auto.8,v 1.35.2.1 2001/03/23 17:43:47 henry Exp $
+.TH IPSEC_AUTO 8 "31 May 2001"
+.\" RCSID $Id: auto.8,v 1.38 2001/05/31 21:57:32 henry Exp $
 .SH NAME
 ipsec auto \- control automatically-keyed IPsec connections
 .SH SYNOPSIS
@@ -155,7 +155,7 @@
 .I pluto
 to re-read the
 .I /etc/ipsec.secrets
-shared-secrets file,
+secret-keys file,
 which it normally reads only at startup time.
 (This is currently a synonym for
 .BR \-\-ready ,
@@ -233,7 +233,7 @@
 ipsec.conf(5), ipsec(8), ipsec_pluto(8), ipsec_whack(8), ipsec_manual(8)
 .SH HISTORY
 Written for the FreeS/WAN project
-<http://www.xs4all.nl/~freeswan/>
+<http://www.freeswan.org>
 by Henry Spencer.
 .SH BUGS
 Although an
diff -bruN freeswan-1.9.orig/utils/barf freeswan-1.9/utils/barf
--- freeswan-1.9.orig/utils/barf	Mon Dec 11 09:51:45 2000
+++ freeswan-1.9/utils/barf	Mon Jun  4 10:45:44 2001
@@ -12,15 +12,21 @@
 # or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 # for more details.
 #
-# RCSID $Id: barf,v 1.45 2000/12/11 14:51:45 henry Exp $
+# RCSID $Id: barf,v 1.47 2001/06/01 15:49:13 henry Exp $
 
 KERNSRC=${KERNSRC-/usr/src/linux}
 LOGS=${LOGS-/var/log}
+me="ipsec barf"
 
 # message patterns that start relevant parts of logs
 fstart='Starting FreeS.WAN'
 pstart='Starting Pluto'
 
+case "$1" in
+--help)		echo "Usage: ipsec barf" ; exit 0	;;
+--version)	echo "$me $IPSEC_VERSION" ; exit 0	;;
+esac
+
 # make sure output is in English
 unset LANG LANGUAGE LC_ALL LC_MESSAGES
 
@@ -32,7 +38,7 @@
 	# try the suggested files first
 	for f in $*
 	do
-		if test -r $LOGS/$f && egrep -q "$s" $LOGS/$f
+		if test -r $LOGS/$f -a ! -d $LOGS/$f && egrep -q "$s" $LOGS/$f
 		then
 			# aha, this one has it
 			findlog_result=$LOGS/$f
@@ -42,7 +48,7 @@
 	# nope, resort to a search, newest first, of uncompressed logs
 	for f in `ls -t $LOGS | egrep -v '\.(gz|Z)$'`
 	do
-		if test -r $LOGS/$f && egrep -q "$s" $LOGS/$f
+		if test -r $LOGS/$f -a ! -d $LOGS/$f && egrep -q "$s" $LOGS/$f
 		then
 			# found it
 			findlog_result=$LOGS/$f
@@ -103,11 +109,11 @@
 _________________________
 ipsec _include /etc/ipsec.secrets | ipsec _secretcensor
 _________________________
-ls -l ${IPSECDIR-/usr/local/lib/ipsec}
+ls -l ${IPSEC_DIR-/usr/local/lib/ipsec}
 _________________________
-for f in `ls ${IPSECDIR-/usr/local/lib/ipsec} | egrep updown`
+for f in `ls ${IPSEC_DIR-/usr/local/lib/ipsec} | egrep updown`
 do
-	cat ${IPSECDIR-/usr/local/lib/ipsec}/$f
+	cat ${IPSEC_DIR-/usr/local/lib/ipsec}/$f
 done
 _________________________
 cat /proc/net/dev
diff -bruN freeswan-1.9.orig/utils/barf.8 freeswan-1.9/utils/barf.8
--- freeswan-1.9.orig/utils/barf.8	Sun Dec  3 17:11:30 2000
+++ freeswan-1.9/utils/barf.8	Mon Jun  4 10:37:04 2001
@@ -1,5 +1,5 @@
-.TH IPSEC_BARF 8 "1 June 2000"
-.\" RCSID $Id: barf.8,v 1.16 2000/12/03 22:11:30 henry Exp $
+.TH IPSEC_BARF 8 "31 May 2001"
+.\" RCSID $Id: barf.8,v 1.18 2001/05/31 21:57:32 henry Exp $
 .SH NAME
 ipsec barf \- spew out collected IPsec debugging information
 .br
@@ -46,10 +46,15 @@
 not programs,
 and the output format is subject to change without warning.
 .SH FILES
-/proc/net/*, /var/log/*
+.nf
+/proc/net/*
+/var/log/*
+/etc/ipsec.conf
+/etc/ipsec.secrets
+.fi
 .SH HISTORY
 Written for the Linux FreeS/WAN project
-<http://www.xs4all.nl/~freeswan/>
+<http://www.freeswan.org>
 by Henry Spencer.
 .SH BUGS
 .I Barf
diff -bruN freeswan-1.9.orig/utils/conf.proto freeswan-1.9/utils/conf.proto
--- freeswan-1.9.orig/utils/conf.proto	Sun Dec  3 17:16:23 2000
+++ freeswan-1.9/utils/conf.proto	Mon Jun  4 10:46:06 2001
@@ -1,8 +1,8 @@
 # /etc/ipsec.conf - FreeS/WAN IPsec configuration file
-# RCSID $Id: conf.proto,v 1.28 2000/12/03 22:16:23 henry Exp $
+# RCSID $Id: conf.proto,v 1.29 2001/06/01 17:55:20 henry Exp $
 
 # More elaborate and more varied sample configurations can be found
-# in FreeS/WAN's doc/examples file.
+# in FreeS/WAN's doc/examples file, and in the HTML documentation.
 
 
 
@@ -26,12 +26,6 @@
 conn %default
 	# How persistent to be in (re)keying negotiations (0 means very).
 	keyingtries=0
-	# Parameters for manual-keying testing (DON'T USE OPERATIONALLY).
-	# Note:  only one test connection at a time can use these parameters!
-	spi=0x200
-	esp=3des-md5-96
-	espenckey=0x01234567_89abcdef_02468ace_13579bdf_12345678_9abcdef0
-	espauthkey=0x12345678_9abcdef0_2468ace0_13579bdf
 	# RSA authentication with keys from DNS.
 	authby=rsasig
 	leftrsasigkey=%dns
@@ -39,7 +33,17 @@
 
 
 
-# sample connection
+# connection description for (experimental!) opportunistic encryption
+# (requires KEY record in your DNS reverse map; see doc/opportunism.howto)
+conn me-to-anyone
+	left=%defaultroute
+	right=%opportunistic
+	# uncomment to enable incoming; change to auto=route for outgoing
+	#auto=add
+
+
+
+# sample VPN connection
 conn sample
 	# Left security gateway, subnet behind it, next hop toward right.
 	left=10.0.0.1
diff -bruN freeswan-1.9.orig/utils/errcheck freeswan-1.9/utils/errcheck
--- freeswan-1.9.orig/utils/errcheck	Wed Sep 20 10:31:50 2000
+++ freeswan-1.9/utils/errcheck	Mon Jun  4 10:46:19 2001
@@ -12,13 +12,15 @@
 # or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 # for more details.
 #
-# RCSID $Id: errcheck,v 1.6 2000/09/20 14:31:50 henry Exp $
+# RCSID $Id: errcheck,v 1.9 2001/05/24 01:22:37 henry Exp $
 
 # the errors.[och] stuff is for math emulation
 # the HiSax nonsense is due to a Red Hat 5.2 botch
-oops="`sed '/errors*\.[och]/s/errors*\./eror./g' $* |
-		sed '/#error .HiSax: No cards configured/s/error/eror/' |
-		egrep -i 'error|\*\*\*'`"
+# Red Hat's 2.2.19 whines about function read_rx_long_length_errors in e100.c
+oops="`sed -e '/errors*\.[och]/s/errors*\./eror./g' \
+	   -e '/#error .HiSax: No cards configured/s/error/eror/' \
+	   -e '/^e100.c: In function/s/length_errors/length_erors/' $* |
+	egrep -i 'error|\*\*\*' | egrep -v ': warning:'`"
 if test " $oops" != " "
 then
 	echo
diff -bruN freeswan-1.9.orig/utils/fswcert-0.4/Makefile freeswan-1.9/utils/fswcert-0.4/Makefile
--- freeswan-1.9.orig/utils/fswcert-0.4/Makefile	Wed Dec 31 19:00:00 1969
+++ freeswan-1.9/utils/fswcert-0.4/Makefile	Wed May 16 10:57:20 2001
@@ -0,0 +1,26 @@
+###################################################
+# Adjust SSLDIR before make ...
+SSLDIR=/usr/ssl
+
+# Adjust IPSECDIR before make install ...
+IPSECDIR=/usr/lib/ipsec
+###################################################
+
+VERSION = 0.4
+
+CFLAGS = -g -Wall -O2 -DVERSION=\"$(VERSION)\" -I$(SSLDIR)/include -I$(OPENSSLROOT)/include
+LDFLAGS = -g -L$(SSLDIR)/lib -L$(OPENSSLROOT)/lib
+LDLIBS = -lcrypto
+
+DISTFILES=Makefile README fswcert.c _confread.patch
+
+all : fswcert
+
+fswcert : fswcert.o
+	$(CC) $(LDFLAGS) -o fswcert fswcert.o $(LDLIBS)
+
+fswcert.o: fswcert.c
+	$(CC) $(CFLAGS) -c fswcert.c
+
+clean :
+	rm -f fswcert fswcert.o
diff -bruN freeswan-1.9.orig/utils/fswcert-0.4/README freeswan-1.9/utils/fswcert-0.4/README
--- freeswan-1.9.orig/utils/fswcert-0.4/README	Wed Dec 31 19:00:00 1969
+++ freeswan-1.9/utils/fswcert-0.4/README	Wed May 16 10:57:20 2001
@@ -0,0 +1,94 @@
+fswcert Utility
+===============
+
+
+This replaces the grabkey and grabsubject utilities from the
+FreeS/WAN X.509 patch, and supports the new configuration
+options leftcert=... and rightcert=...
+
+Dependencies:
+  fswcert requires the openssl 0.9.5a package.
+
+Bugs:
+  Due to openssl, the fswcert binary is HUGE.
+
+
+These are the options supported:
+--------------------------------
+
+-c --certificate	print certificate data
+
+	Prints the certificate data needed for FreeS/WAN's
+	ipsec.conf. Input can be from an X.509 file in PEM
+	or DER format, or from a PKCS12 (*.p12) file.
+
+-k --key	print private RSA key data
+
+	Prints the private key data needed for FreeS/WAN's
+	ipsec.secrets. Input can be from an RSA private key
+	file, or from a PKCS12 (*.p12) file.
+
+-l --left	left-side parameters for ipsec.conf
+
+	Prefix certificate data with `left'
+
+-r --right	right-side parameters for ipsec.conf
+
+	Prefix certificate data with `left'
+
+--type=[x509|rsa|pkcs12]	select input file type
+
+	Select input file type. Defaults to x509.
+
+--format=[PEM|DER]	select input file format
+
+	Select input file format. Defaults to PEM.
+
+-C --directory=dir	change into dir first
+
+	Change into dir at startup. (Files are then
+	read relative to this directory).
+
+-q --quiet	single line error messages to stdout
+
+	This is a hack to better integrate with _confread.
+	Don't use manually.
+
+-d --der-output		outputs DN in DER binary format
+
+	This is also a hack. Useful to give the CA the DN in DER
+	so that it can insert the 'subject' search field in its
+	LDAP tables. 
+
+-v --version	returns version of fswcert
+
+Either --key or --certificate is required. It makes no sense to
+specify both --left and --right; the last option wins.
+
+
+To use X.509 PEM-encoded certificates with FreeS/WAN directly, do this:
+-----------------------------------------------------------------------
+
+- Adjust the IPSECDIR and SSLDIR in Makefile
+
+- Build fswcert with `make'
+
+- Install fswcert with `make install'
+
+- Patch FreeS/WAN's _confread with the patch provided
+
+- Put all the certificates you want to use with FreeS/WAN
+  in the /etc/ipsec.d/ directory
+
+
+Then you can use these new options in ipsec.conf and includes:
+--------------------------------------------------------------
+
+leftcert=filename.pem
+	Reads the identity and public key from filename.pem
+	(Replaces both leftid=@~... and leftrsasigkex=0x...)
+
+rightcert=filename.pem
+	Reads the identity and public key from filename.pem
+	(Replaces both rightid=@~... and rightrsasigkex=0x...)
+
diff -bruN freeswan-1.9.orig/utils/fswcert-0.4/_confread.patch freeswan-1.9/utils/fswcert-0.4/_confread.patch
--- freeswan-1.9.orig/utils/fswcert-0.4/_confread.patch	Wed Dec 31 19:00:00 1969
+++ freeswan-1.9/utils/fswcert-0.4/_confread.patch	Wed May 16 10:57:20 2001
@@ -0,0 +1,51 @@
+--- freeswan-1.5/utils/_confread	Wed May 31 14:10:40 2000
++++ freeswan-1.5-x509/utils/_confread	Tue Sep 19 16:29:42 2000
+@@ -42,6 +42,7 @@
+ # fi
+ 
+ config=/etc/ipsec.conf
++fswcert="$IPSECDIR/fswcert --directory /etc/ipsec.d"
+ include=yes
+ type=conn
+ fieldfmt=yes
+@@ -71,7 +72,7 @@
+ else
+ 	cat $config
+ fi |
+-awk 'BEGIN {
++awk -v "fswcert=$fswcert" 'BEGIN {
+ 	type = "'"$type"'"
+ 	names = "'"$*"'"
+ 	prefix = "'"$prefix"'"
+@@ -122,6 +123,7 @@
+ 	mkey = " spibase spi esp espenckey espauthkey espreplay_window"
+ 	left = left " leftespenckey leftespauthkey leftahkey"
+ 	left = left " leftespspi leftahspi leftid leftrsasigkey"
++	left = left " leftcert"
+ 	mkey = mkey " ah ahkey ahreplay_window"
+ 	right = left
+ 	gsub(/left/, "right", right)
+@@ -313,6 +315,23 @@
+ 	value = substr($0, equal+1)
+ 	if (value ~ /^"/)
+ 		value = substr(value, 2, length(value)-2)
++}
++name ~ /^(left|right)cert$/ {
++	side = name
++	gsub(/cert$/, "", side)
++	pipe = fswcert " --quiet --cert " value
++	pipe | getline ID
++	pipe | getline RSASIGKEY
++	if (close(pipe) != 0)
++		fail(ID);
++	gsub(/^.*id=/, "", ID)
++	gsub(/^.*rsasigkey=/, "", RSASIGKEY)
++	seen[side "cert"] = 1
++	seen[side "id"] = 1
++	seen[side "rsasigkey"] = 1
++	output(o_parm, side "id", ID)
++	output(o_parm, side "rsasigkey", RSASIGKEY)
++	next
+ }
+ indefault {
+ 	if (name in default)
diff -bruN freeswan-1.9.orig/utils/fswcert-0.4/fswcert.c freeswan-1.9/utils/fswcert-0.4/fswcert.c
--- freeswan-1.9.orig/utils/fswcert-0.4/fswcert.c	Wed Dec 31 19:00:00 1969
+++ freeswan-1.9/utils/fswcert-0.4/fswcert.c	Wed May 16 11:20:34 2001
@@ -0,0 +1,550 @@
+/* Certificate and Private Key Format Conversions for FreeS/WAN
+ *
+ * Copyright (C) 2000 Andreas Gruenbacher, <a.gruenbacher@computer.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.
+ */
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+#include <unistd.h>
+
+#define _GNU_SOURCE
+#include <getopt.h>
+
+#include <termio.h>
+
+#include <openssl/crypto.h>
+#include <openssl/buffer.h>
+#include <openssl/bio.h>
+#include <openssl/err.h>
+#include <openssl/pkcs12.h>
+#include <openssl/pem.h>
+#include <openssl/rsa.h>
+
+struct option long_options[] = {
+	{"certificate",   0, 0, 'c'},
+	{"key",           0, 0, 'k'},
+	{"left",          0, 0, 'l'},
+	{"right",         0, 0, 'r'},
+	{"type",          1, 0,  1 },
+	{"format",        1, 0,  2 },
+	{"quiet",         0, 0, 'q'},
+	{"der-output",    0, 0, 'd'},
+	{"directory",     1, 0, 'C'},
+	{"version",       0, 0, 'v'},
+	{"help",          0, 0, 'h'},
+	{NULL,            0, 0,  0 }
+};
+
+int prompt_for_passwords = 0;
+const char *peer_prefix = NULL;
+int opt_quiet = 0;
+int der_output = 0;
+int der_binary = 0;
+const char *input_file = NULL;
+
+#define DUMP_CERTIFICATE	1
+#define DUMP_KEY		2
+int opt_what = 0;
+
+BIO *bio_err = NULL;
+
+enum input_file_type { IN_PKCS12 = 1, IN_X509 = 2, IN_RSA = 3 };
+enum input_format { FORMAT_ASN1 = 1, FORMAT_PEM = 3 };
+
+void print_errors(int ssl, const char *fmt, ...)
+{
+	if (fmt) {
+		va_list args;
+	
+		va_start(args, fmt);
+		if (input_file)
+			fprintf(stderr, "%s: ", input_file);
+		fprintf(stderr, "Error ");
+		vfprintf(stderr, fmt, args);
+		fprintf(stderr, "\n");
+		va_end(args);
+	}
+	if (ssl && !opt_quiet)
+		ERR_print_errors(bio_err);
+}
+
+const char *read_password(void)
+{
+	static char password[1024];
+	struct termio saved, no_echo;
+
+	printf("Password: ");
+
+	(void) ioctl(0, TCGETA, &saved);
+	no_echo = saved;
+	no_echo.c_lflag &= ~ECHO;
+	(void) ioctl(0, TCSETA, &no_echo);
+	fgets(password, sizeof(password), stdin);
+	(void) ioctl(0, TCSETA, &saved);
+	puts("");
+
+	if (strchr(password, '\n'))
+		*strchr(password, '\n') = '\0';
+	return password;
+}
+
+void BN_print_0(BIGNUM *num)
+{
+	int bits = BN_num_bits(num);
+
+	if ((bits-1) % 8 < 3)
+		putchar('0');
+	BN_print_fp(stdout, num);
+}
+
+#define print(what, num) do { \
+	printf("\t%s: 0x", what); \
+	BN_print_0(num); \
+	putchar('\n'); \
+	} while(0)
+
+int dump_rsa_private_key(RSA *rsa)
+{
+	if (rsa->d == NULL) {
+		print_errors(0, "no private exponent");
+		return 1;
+	}
+	if (opt_what & DUMP_KEY) {
+		print("Modulus", rsa->n);
+		print("PublicExponent", rsa->e);
+		print("PrivateExponent", rsa->d);
+		print("Prime1", rsa->p);
+		print("Prime2", rsa->q);
+		print("Exponent1", rsa->dmp1);
+		print("Exponent2", rsa->dmq1);
+		print("Coefficient", rsa->iqmp);
+	}
+	return 0;
+}
+
+#undef print
+
+int dump_x509_certificate(X509 *x509)
+{
+	BUF_MEM *subject;
+	EVP_PKEY *pkey;
+	RSA *rsa;
+	int i, error = 0;
+	char derbuf[256];
+	
+	if (!x509->cert_info || !x509->cert_info->subject ||
+            !x509->cert_info->subject->bytes) {
+		fprintf(stderr, "Certificate contains no subject\n");
+		return 1;
+	}
+	subject = &x509->cert_info->subject->bytes[0];
+
+	if (opt_what & DUMP_CERTIFICATE) {
+		if (!der_output) {
+			printf("\t%sid=@~", peer_prefix);
+			for (i = 0; i < subject->length; i++)
+				printf("%02X", (unsigned char)subject->data[i]);
+			printf("\n");
+		} else if (der_output) {
+			int derlen;
+			unsigned char *derbytes, *derout;
+
+			derlen=i2d_X509_NAME(x509->cert_info->subject, NULL);
+			derbytes=malloc(derlen);
+			derout=(unsigned char *)derbytes;
+
+			derlen=i2d_X509_NAME(X509_get_subject_name(x509), &derout);
+			derout=(unsigned char *)derbytes;
+
+			if (der_binary) {
+				for (i = 0; i < derlen; i++)
+					printf("%c", derout[i]);
+			} else {
+				X509_NAME_oneline(x509->cert_info->subject,
+					derbuf, 256);
+				printf("\t#%s DN: %s\n", peer_prefix, derbuf);
+				printf("\t%sid=@~", peer_prefix);
+				for (i = 0; i < derlen; i++)
+					printf("%02X", (unsigned char)derout[i]);
+				printf("\n");
+
+#if 0
+{ /* DEBUGGING ON */
+  X509_NAME *xn = X509_NAME_new();
+  char dnout[256];
+  if (xn == NULL) {
+    printf("\t#Unable to malloc X509_NAME *xn");
+  }
+
+  printf("\t#derlen = %d\n", derlen);
+  printf("\t#certlen = %d\n", certlen);
+
+  /* X509_NAME * d2i_X509_NAME(X509_NAME **a,unsigned char **pp,long length); 
+   */
+  xn = d2i_X509_NAME(&xn, &(derout), (long)derlen);
+
+  if (xn != NULL) {
+    X509_NAME_oneline(xn,dnout,256);
+    printf("\t#DNtest == %s\n", dnout);
+  } else {
+    printf("\t#Invalid DER string\n");
+  }
+} /* DEBUGGING OFF */
+#endif
+
+			}
+
+			free(derbytes);
+		}
+	}
+
+	pkey = X509_get_pubkey(x509);
+	if (pkey == NULL) {
+		print_errors(1, "getting public key");
+		return 1;
+	}
+	if (pkey->type != EVP_PKEY_RSA) {
+		print_errors(0, "not an RSA public key");
+		error = 1;
+		goto cleanup;
+	}
+	rsa = pkey->pkey.rsa;
+	
+#if 0
+	if (opt_what & DUMP_CERTIFICATE) {
+		int bytes = BN_num_bytes(rsa->e);
+		printf("\t%srsasigkey=0x%02X", peer_prefix, bytes);
+		BN_print_0(rsa->e);
+		BN_print_0(rsa->n);
+		putchar('\n');
+	}
+#endif
+
+cleanup:
+	EVP_PKEY_free(pkey);
+	return 0;
+}
+
+int read_pkcs12_safebag(PKCS12_SAFEBAG *bag, const char *password)
+{
+	PKCS8_PRIV_KEY_INFO *p8;
+	EVP_PKEY *pkey;
+	X509 *x509;
+	RSA *rsa;
+	int error = 0;
+	
+	switch (M_PKCS12_bag_type(bag)) {
+		case NID_keyBag:
+			p8 = bag->value.keybag;
+			pkey = EVP_PKCS82PKEY(p8);
+			if (!pkey) {
+				print_errors(1, "grabbing private key");
+				return 1;
+			}
+			rsa = EVP_PKEY_get1_RSA(pkey);
+			EVP_PKEY_free(pkey);
+			if (!rsa) {
+				print_errors(1, "getting RSA key");
+				return 1;
+			}
+			error = dump_rsa_private_key(rsa);
+			RSA_free(rsa);
+			break;
+
+		case NID_pkcs8ShroudedKeyBag:
+			p8 = M_PKCS12_decrypt_skey(bag, password, -1);
+			if (!p8) {
+				print_errors(1, "decrypting private key");
+				return 1;
+			}
+			pkey = EVP_PKCS82PKEY(p8);
+			PKCS8_PRIV_KEY_INFO_free(p8);
+			if (!pkey) {
+				print_errors(1, "grabbing private key");
+				return 1;
+			}
+			rsa = EVP_PKEY_get1_RSA(pkey);
+			EVP_PKEY_free(pkey);
+			if (!rsa) {
+				print_errors(1, "getting RSA private key");
+				return 1;
+			}
+			error = dump_rsa_private_key(rsa);
+			RSA_free(rsa);
+			break;
+
+		case NID_certBag:
+			if (M_PKCS12_cert_bag_type(bag) != NID_x509Certificate){
+				print_errors(0, "not an X.509 certificate");
+				return 1;
+			}
+			/* only dump the key's certificate */
+			if (!PKCS12_get_attr(bag, NID_localKeyID))
+				return 0;
+			x509 = M_PKCS12_certbag2x509(bag);
+			if (!x509) {
+				print_errors(1, "grabbing certificate");
+				return 1;
+			}
+			if (dump_x509_certificate(x509))
+				return 1;
+			X509_free(x509);
+			break;
+
+		default:
+			/* other bag entry */
+	}
+	return error;
+}
+
+int read_pkcs12_file(BIO *bio_in)
+{
+	const char *password = "\0";
+	PKCS12 *p12;
+	STACK /* _OF(PKCS7) */ *asafes = NULL;
+	PKCS7 *p7;
+	int i;
+
+	p12 = d2i_PKCS12_bio (bio_in, NULL);
+	if (!p12) {
+		print_errors(1, "reading PKCS12 file");
+		return 1;
+	}
+	if (!PKCS12_verify_mac(p12, password, 0)) {
+		if (prompt_for_passwords)
+			password = read_password();
+		if (!prompt_for_passwords ||
+		    !PKCS12_verify_mac(p12, password, -1)) {
+			print_errors(1, "verifying MAC: wrong password?");
+			return 1;
+		}
+	}
+
+	/* Unpack PKCS12 file */
+	asafes = M_PKCS12_unpack_authsafes (p12);
+	if (!asafes) {
+		print_errors(1, "unpacking PKCS12 file");
+		return 1;
+	}
+	for (i = 0; i < sk_num(asafes); i++) {
+		int bagnid, j;
+		STACK /* _OK(PKCS12) */ *bags;
+
+		p7 = (PKCS7 *) sk_value(asafes, i);
+		bagnid = OBJ_obj2nid(p7->type);
+		if (bagnid == NID_pkcs7_data)
+			bags = M_PKCS12_unpack_p7data(p7);
+		else if (bagnid == NID_pkcs7_encrypted)
+			bags = M_PKCS12_unpack_p7encdata(p7, password, -1);
+		else
+			continue;
+		if (!bags) {
+			print_errors(1, "unpacking PKCS12 file");
+			return 1;
+		}
+		for (j = 0; j < sk_num(bags); j++) {
+			PKCS12_SAFEBAG *bag =
+				(PKCS12_SAFEBAG *)sk_value(bags, j);
+			if (read_pkcs12_safebag(bag, password))
+				return 1;
+		}
+		sk_pop_free(bags, PKCS12_SAFEBAG_free);
+	}
+	sk_pop_free(asafes, PKCS7_free);
+	return 0;
+}
+
+int read_x509_file(BIO *bio_in, enum input_format input_format)
+{
+	X509 *x509 = NULL;
+	int error;
+
+	if (input_format == FORMAT_PEM)
+		x509 = PEM_read_bio_X509(bio_in, NULL, NULL, NULL);
+	else if (input_format == FORMAT_ASN1)
+		x509 = d2i_X509_bio(bio_in, NULL);
+	if (!x509) {
+		print_errors(1, "reading X509 certificate");
+		return 1;
+	}
+	error = dump_x509_certificate(x509);
+	X509_free(x509);
+
+	return error;
+}
+
+int read_rsa_file(BIO *bio_in, enum input_format input_format)
+{
+	RSA *rsa = NULL;
+	int error;
+
+	if (input_format == FORMAT_PEM)
+		rsa = PEM_read_bio_RSAPrivateKey(bio_in, NULL, NULL, NULL);
+	else if (input_format == FORMAT_ASN1)
+		rsa = d2i_RSAPrivateKey_bio(bio_in, NULL);
+	if (!rsa) {
+                print_errors(1, "reading RSA private key");
+                return 1;
+        }
+	error = dump_rsa_private_key(rsa);
+	RSA_free(rsa);
+	return error;
+}
+
+int main(int argc, char *argv[])
+{
+	enum input_file_type input_file_type = 0;
+	enum input_format input_format = 0;
+	int error = 0, opt;
+
+	prompt_for_passwords = isatty(0) && isatty(1);
+
+	while ((opt = getopt_long(argc, argv, "cklrqd:C:hv",
+	                          long_options, NULL)) != -1) {
+		switch(opt) {
+			case 1:  /* input file type */
+				if (!strcmp(optarg, "pkcs12"))
+					input_file_type = IN_PKCS12;
+				else if (!strcmp(optarg, "x509"))
+					input_file_type = IN_X509;
+				else if (!strcmp(optarg, "rsa"))
+					input_file_type = IN_RSA;
+				else
+					goto synopsis;
+				break;
+
+			case 2:  /* input format */
+				if (!strcmp(optarg, "PEM"))
+					input_format = FORMAT_PEM;
+				else if (!strcmp(optarg, "DER"))
+					input_format = FORMAT_ASN1;
+				else
+					goto synopsis;
+				break;
+
+			case 'c':  /* certificate */
+				opt_what |= DUMP_CERTIFICATE;
+				if (!input_file_type)
+					input_file_type = IN_X509;
+				break;
+
+			case 'k':  /* key */
+				opt_what |= DUMP_KEY;
+				if (!input_file_type)
+					input_file_type = IN_RSA;
+				break;
+
+			case 'l':  /* left */
+				if (!opt_what)
+					opt_what = DUMP_CERTIFICATE;
+				peer_prefix = "left";
+				break;
+
+			case 'r':  /* right */
+				if (!opt_what)
+					opt_what = DUMP_CERTIFICATE;
+				peer_prefix = "right";
+				break;
+
+			case 'C':  /* change directory */
+				if (chdir(optarg) && errno) {
+					perror(optarg);
+					error = 1;
+				}
+				break;
+
+			case 'v':  /* print version and exit */
+				printf("%s " VERSION "\n", argv[0]);
+				return 0;
+
+			case 'q':  /* quiet */
+				opt_quiet = 1;
+				break;
+
+			case 'd':  /* output in DER */
+				der_output = 1;
+				if (!strcmp(optarg, "a")) { 
+					/* ascii */
+					der_binary = 0;
+				} else if (!strcmp(optarg, "b")) {
+					der_binary = 1;
+				} else {
+					goto synopsis;
+				}
+				break;
+
+			default:
+				goto synopsis;
+		}
+	}
+	if (peer_prefix == NULL)
+		peer_prefix = "";
+
+	if (optind+1 != argc || !opt_what)
+		goto synopsis;
+
+	if (!input_file_type)
+		input_file_type = IN_X509;
+	if (!input_format)
+		input_format = FORMAT_PEM;
+
+	if (opt_quiet)
+		dup2(1,2);  /* stderr is stdout (awk hack) */
+
+	ERR_load_crypto_strings();
+	SSLeay_add_all_algorithms();
+	bio_err = BIO_new_fp (stderr, BIO_NOCLOSE);
+	
+	while (optind < argc) {
+		BIO *bio_in;
+
+		input_file = argv[optind];
+		bio_in = BIO_new_file(input_file, "rb");
+		if (!bio_in) {
+			perror(input_file);
+			error = 1;
+		} else {
+			if (input_file_type == IN_PKCS12)
+				error |= read_pkcs12_file(bio_in);
+			else if (input_file_type == IN_X509)
+				error |= read_x509_file(bio_in, input_format);
+			else if (input_file_type == IN_RSA)
+				error |= read_rsa_file(bio_in, input_format);
+			BIO_free(bio_in);
+		}
+		optind++;
+	}
+
+	BIO_free(bio_err);
+
+	return error;
+
+synopsis:
+	fprintf(stderr, "SYNOPSIS: %s --cert|--key [--left|--right] "
+	        "options file\n", argv[0]);
+	if (!opt_quiet) {
+		fprintf(stderr, "\t-c --cert\tprint certificate data\n"
+		        "\t-k --key\tprint private RSA key data\n"
+		        "\t-l --left\tleft-side parameters for ipsec.conf\n"
+		        "\t-r --right\tright-side parameters for ipsec.conf\n"
+		        "\t   --type=[x509|rsa|pkcs12]\tselect input file type\n"
+		        "\t   --format=[PEM|DER]\tselect input file format\n"
+		        "\t-C --directory=dir\tchange into dir first\n"
+		        "\t-d [ab]\tprints out the DER\n"
+			
+		        "\t-q --quiet\tsingle line error messages to stdout\n");
+	}
+	return error;
+}
+
diff -bruN freeswan-1.9.orig/utils/ipsec.8 freeswan-1.9/utils/ipsec.8
--- freeswan-1.9.orig/utils/ipsec.8	Mon Dec 11 09:49:58 2000
+++ freeswan-1.9/utils/ipsec.8	Mon Jun  4 10:37:04 2001
@@ -1,5 +1,5 @@
-.TH IPSEC 8 "11 Dec 2000"
-.\" RCSID $Id: ipsec.8,v 1.11 2000/12/11 14:49:58 henry Exp $
+.TH IPSEC 8 "1 June 2001"
+.\" RCSID $Id: ipsec.8,v 1.14 2001/06/01 15:48:36 henry Exp $
 .SH NAME
 ipsec \- invoke IPsec utilities
 .SH SYNOPSIS
@@ -33,18 +33,24 @@
 supplies the invoked
 .I command
 with a suitable PATH environment variable,
-and also provides an IPSECDIR environment variable containing
-the full pathname of the directory where the IPsec utilities are stored.
+and also provides IPSEC_DIR and IPSEC_VERSION environment variables,
+containing respectively
+the full pathname of the directory where the IPsec utilities are stored
+and the IPsec version number.
 .PP
 .B "ipsec \-\-help"
 lists the available commands.
 Most have their own manual pages, e.g.
-.IR ipsec_manual (8)
+.IR ipsec_auto (8)
 for
-.IR manual .
+.IR auto .
 .PP
 .B "ipsec \-\-version"
 supplies the version number of Linux FreeS/WAN.
+A version number of the form ``U\fIxxx\fR/K\fIyyy\fR''
+indicates that the user-level utilities are version \fIxxx\fR
+but the kernel portion appears to be version \fIyyy\fR
+(this form is used only if the two disagree).
 .PP
 .B "ipsec \-\-copyright"
 supplies boring copyright details.
@@ -52,16 +58,28 @@
 .B "ipsec \-\-directory"
 reports where
 .I ipsec
-thinkgs the IPsec utilities are stored.
+thinks the IPsec utilities are stored.
 .SH FILES
-/usr/local/lib/ipsec	utilities directory (default location)
+/usr/local/lib/ipsec	usual utilities directory
 .SH SEE ALSO
 .hy 0
-ipsec_manual(8), ipsec_auto(8),
-ipsec_klipsdebug(8), ipsec_barf(8)
+.na
+ipsec.conf(5), ipsec.secrets(5),
+ipsec_auto(8),
+ipsec_barf(8),
+ipsec_setup(8),
+ipsec_showdefaults(8),
+ipsec_showhostkey(8)
+.ad
+.hy
+.PP
+HTML documentation shipped with the release, starting with
+.IR doc/index.html .
+.I <http://www.freeswan.org/doc.html>
+may also be of use.
 .SH HISTORY
-Written for the Linux FreeS/WAN project
-<http://www.xs4all.nl/~freeswan/>
+Written for Linux FreeS/WAN
+<http://www.freeswan.org>
 by Henry Spencer.
 .SH BUGS
 The provision of centralized services,
diff -bruN freeswan-1.9.orig/utils/ipsec.conf.5 freeswan-1.9/utils/ipsec.conf.5
--- freeswan-1.9.orig/utils/ipsec.conf.5	Sun Mar 11 23:03:59 2001
+++ freeswan-1.9/utils/ipsec.conf.5	Mon Jun  4 10:47:28 2001
@@ -1,5 +1,5 @@
-.TH IPSEC.CONF 5 "9 March 2001"
-.\" RCSID $Id: ipsec.conf.5,v 1.57.2.2 2001/03/12 04:03:59 henry Exp $
+.TH IPSEC.CONF 5 "29 May 2001"
+.\" RCSID $Id: ipsec.conf.5,v 1.68 2001/05/31 21:57:33 henry Exp $
 .SH NAME
 ipsec.conf \- IPsec configuration and connections
 .SH DESCRIPTION
@@ -82,9 +82,10 @@
 (note the mandatory preceding white space).
 There can be white space on either side of the
 .BR = .
-The parameter names are specific to a section type.
+Parameter names follow the same syntax as section names,
+and are specific to a section type.
 Unless otherwise explicitly specified,
-no parameter may appear more than once in a section.
+no parameter name may appear more than once in a section.
 .PP
 An empty
 .I value
@@ -259,29 +260,6 @@
 .B no
 (the default).
 .TP
-.B auto
-what operation, if any, should be done automatically at IPsec startup;
-currently-accepted values are
-.B add
-(signifying an
-.I ipsec_auto
-.BR add ),
-.B start
-(signifying an
-.I ipsec_auto
-.BR start ),
-and
-.B ignore
-(also the default) (signifying no automatic startup operation).
-This parameter is ignored unless the
-.B plutoload
-or
-.B plutostart
-configuration parameter is set suitably; see the
-.B config
-.B setup
-discussion below.
-.TP
 .B left
 (required)
 the IP address of the left participant's public-network interface,
@@ -333,7 +311,9 @@
 next-hop gateway IP address for the left participant's connection
 to the public network;
 defaults to
-.IR right .
+.B %direct
+(meaning
+.IR right ).
 If the value is to be overridden by the
 .B left=%defaultroute
 method (see above),
@@ -415,6 +395,33 @@
 the default and currently the only accepted value is
 .B ike
 .TP
+.B auto
+what operation, if any, should be done automatically at IPsec startup;
+currently-accepted values are
+.B add
+(signifying an
+.B ipsec auto
+.BR \-\-add ),
+.B route
+(signifying that plus an
+.B ipsec auto
+.BR \-\-route ),
+.B start
+(signifying that plus an
+.B ipsec auto
+.BR \-\-up ),
+and
+.B ignore
+(also the default) (signifying no automatic startup operation).
+This parameter is ignored unless the
+.B plutoload
+or
+.B plutostart
+configuration parameter is set suitably; see the
+.B config
+.B setup
+discussion below.
+.TP
 .B auth
 whether authentication should be done as part of
 ESP encryption, or separately using the AH protocol;
@@ -918,28 +925,37 @@
 .B no
 (the default).
 .TP
-.B no_eroute_pass
-whether a packet which reaches KLIPS (via a route into a virtual interface)
-but does not match any eroute should be passed in plaintext,
-rather than discarded;
-acceptable values are
-.B yes
-(\fIinsecure unless you really know what you're doing!!!\fR)
-and
-.B no
-(the default).
-This overrides
-.BR opportunistic .
+.B packetdefault
+what should be done with
+a packet which reaches KLIPS (via a route into a virtual interface)
+but does not match any eroute;
+acceptable values are
+.B pass
+(\fIinsecure unless you really know what you're doing!!!\fR),
+.B drop
+(the default),
+and
+.B reject
+(currently same as
+.BR drop ,
+but eventually it will send an ICMP notification back
+to the sender).
 .TP
-.B opportunistic
-whether a packet which reaches KLIPS (via a route into a virtual interface)
-but does not match any eroute should cause an attempt to signal
-.I ipsec_pluto
-to create a connection for it;
+.B no_eroute_pass
+obsolete parameter similar to
+.B packetdefault
+but with more limited functionality;
+ignored if
+.B packetdefault
+is set;
 acceptable values are
 .B yes
+(synonymous with
+.BR packetdefault=pass )
 and
 .B no
+(synonymous with
+.BR packetdefault=drop )
 (the default).
 .TP
 .B hidetos
@@ -973,7 +989,7 @@
 ipsec(8), ipsec_ttoaddr(8), ipsec_auto(8), ipsec_manual(8), ipsec_rsasigkey(8)
 .SH HISTORY
 Designed for the FreeS/WAN project
-<http://www.xs4all.nl/~freeswan/>
+<http://www.freeswan.org>
 by Henry Spencer.
 .SH BUGS
 Including attributes of the keying channel
diff -bruN freeswan-1.9.orig/utils/ipsec.in freeswan-1.9/utils/ipsec.in
--- freeswan-1.9.orig/utils/ipsec.in	Mon Dec 11 09:49:58 2000
+++ freeswan-1.9/utils/ipsec.in	Mon Jun  4 10:47:36 2001
@@ -1,6 +1,6 @@
 #! /bin/sh
 # prefix command to run stuff from our programs directory
-# Copyright (C) 1998, 1999, 2000  Henry Spencer.
+# Copyright (C) 1998, 1999, 2000, 2001  Henry Spencer.
 # 
 # This program is free software; you can redistribute it and/or modify it
 # under the terms of the GNU General Public License as published by the
@@ -12,11 +12,11 @@
 # or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 # for more details.
 #
-# RCSID $Id: ipsec.in,v 1.13 2000/12/11 14:49:58 henry Exp $
+# RCSID $Id: ipsec.in,v 1.16 2001/06/01 15:48:36 henry Exp $
 
-# where the private directory is (exported in case other things want it)
-IPSECDIR=@IPSECDIR@
-export IPSECDIR
+# where the private directory is
+IPSEC_DIR=@IPSEC_DIR@
+export IPSEC_DIR
 
 # standardize PATH, and export it for everything else's benefit
 PATH=/usr/local/sbin:/sbin:/usr/sbin:/usr/local/bin:/bin:/usr/bin
@@ -27,7 +27,7 @@
 
 # Caution:  setup knows the format of $version
 version="xxx"
-copyright="Copyright (C) 1999, 2000  Henry Spencer, Richard Guy Briggs,
+copyright="Copyright (C) 1999, 2000, 2001  Henry Spencer, Richard Guy Briggs,
 	D. Hugh Redelmeier, Sandy Harris, Claudia Schmeing,
 	Angelos D. Keromytis, John Ioannidis.
 
@@ -40,13 +40,16 @@
    WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
    or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    (file COPYING in the distribution) for more details."
+IPSEC_VERSION="$version"
+export IPSEC_VERSION
 
 case "$1" in
 --help|'')
 	echo "Usage: ipsec command argument ..."
 	echo "where command is one of:"
-	ls $IPSECDIR | egrep -v -i "$DONTMENTION" | sed 's/^/	/'
+	ls $IPSEC_DIR | egrep -v -i "$DONTMENTION" | sed 's/^/	/'
 	echo
+	echo "Most of these have their own manual pages, e.g. ipsec_auto(8)."
 	echo "See also <http://www.freeswan.org> or the ipsec(8) manual page."
 	exit 0
 	;;
@@ -68,7 +71,7 @@
 	exit 0
 	;;
 --directory)
-	echo "$IPSECDIR"
+	echo "$IPSEC_DIR"
 	exit 0
 	;;
 --*)
@@ -79,7 +82,7 @@
 
 cmd="$1"
 shift
-path="$IPSECDIR/$cmd"
+path="$IPSEC_DIR/$cmd"
 
 if test ! -x "$path"
 then
diff -bruN freeswan-1.9.orig/utils/look freeswan-1.9/utils/look
--- freeswan-1.9.orig/utils/look	Sun Dec  3 17:16:24 2000
+++ freeswan-1.9/utils/look	Mon Jun  4 10:48:05 2001
@@ -12,9 +12,15 @@
 # or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 # for more details.
 #
-# RCSID $Id: look,v 1.23 2000/12/03 22:16:24 henry Exp $
+# RCSID $Id: look,v 1.26 2001/06/01 16:44:11 henry Exp $
 
 info=/var/run/ipsec.info
+me="ipsec look"
+
+case "$1" in
+--help)		echo "Usage: ipsec look" ; exit 0	;;
+--version)	echo "$me $IPSEC_VERSION" ; exit 0	;;
+esac
 
 # clear out variables that have strange effects on sort etc.
 unset LANG LANGUAGE LC_ALL LC_MESSAGES
@@ -37,7 +43,7 @@
 
 # combine spigrp and eroute
 cat /proc/net/ipsec_spigrp /proc/net/ipsec_eroute |
-	awk '	$2 != "->" { tun[$1] = $0 }
+	awk '
 		function pad(subnet) {
 			sub("/", ".", subnet)
 			split(subnet, d, ".")
@@ -45,13 +51,23 @@
 							d[3], d[4], d[5])
 		}
 		$2 == "->" {
-			printf "%s:%-18s -> %-18s => %s\n", (pad($1) pad($3)),
-				$1, $3, tun[$5]
-		}' | sort | sed 's/^[^:]*://'
+			printf "%s:%-18s -> %-18s => %s\n",
+				(pad($1) pad($3)),
+				$1, $3, (($5 in tun) ? tun[$5] : $5)
+			next
+		}
+		$3 == "->" {
+			printf "%s:%-18s -> %-18s => %s (%s)\n",
+				(pad($2) pad($4)),
+				$2, $4, (($6 in tun) ? tun[$6] : $6), $1
+			next
+		}
+		{ tun[$1] = $0 }
+	' | sort | sed 's/^[^:]*://'
 
 # tncfg (mostly as a divider line)
-egrep -v NULL /proc/net/ipsec_tncfg | paste -d % | sed 's/%/   /g' |
-	sed 's/ -> /->/g'
+egrep -v 'NULL[ \t]+mtu=0\(0\)[ \t]+->[ \t]+0' /proc/net/ipsec_tncfg |
+	paste -d % | sed 's/%/   /g' | sed 's/ -> /->/g'
 
 # SAs
 sort /proc/net/ipsec_spi
diff -bruN freeswan-1.9.orig/utils/manual freeswan-1.9/utils/manual
--- freeswan-1.9.orig/utils/manual	Sun Dec  3 17:16:24 2000
+++ freeswan-1.9/utils/manual	Mon Jun  4 10:48:17 2001
@@ -12,7 +12,7 @@
 # or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 # for more details.
 #
-# RCSID $Id: manual,v 1.76 2000/12/03 22:16:24 henry Exp $
+# RCSID $Id: manual,v 1.78 2001/06/01 15:49:13 henry Exp $
 
 me='ipsec manual'
 usage="Usage:
@@ -39,7 +39,7 @@
 do
 	case "$1" in
 	--help)		echo "$usage" ; exit 0	;;
-	--version)	echo 2 ; exit 0		;;
+	--version)	echo "$me $IPSEC_VERSION" ; exit 0	;;
 	--show)		shopts=-x		;;
 	--showonly)	showonly=yes		;;
 	--other)	other=1			;;
@@ -544,7 +544,7 @@
 		print "ipsec eroute --label", q(names),
 						"--eraf inet --replace", "\\"
 		if (pass)
-			p = "%passthrough"
+			p = "%pass"
 		else {
 			if (s["type"] == "tunnel")
 				p = "tun"
diff -bruN freeswan-1.9.orig/utils/ranbits.8 freeswan-1.9/utils/ranbits.8
--- freeswan-1.9.orig/utils/ranbits.8	Tue Aug 22 20:20:27 2000
+++ freeswan-1.9/utils/ranbits.8	Mon Jun  4 10:48:31 2001
@@ -1,5 +1,5 @@
 .TH IPSEC_RANBITS 8 "22 Aug 2000"
-.\" RCSID $Id: ranbits.8,v 1.6 2000/08/23 00:20:27 henry Exp $
+.\" RCSID $Id: ranbits.8,v 1.7 2001/05/31 21:57:33 henry Exp $
 .SH NAME
 ipsec ranbits \- generate random bits in ASCII form
 .SH SYNOPSIS
@@ -61,7 +61,7 @@
 ipsec_datatot(3), random(4)
 .SH HISTORY
 Written for the Linux FreeS/WAN project
-<http://www.xs4all.nl/~freeswan/>
+<http://www.freeswan.org>
 by Henry Spencer.
 .SH BUGS
 There is an internal limit on
diff -bruN freeswan-1.9.orig/utils/ranbits.c freeswan-1.9/utils/ranbits.c
--- freeswan-1.9.orig/utils/ranbits.c	Tue Aug 22 20:20:27 2000
+++ freeswan-1.9/utils/ranbits.c	Mon Jun  4 10:48:31 2001
@@ -12,7 +12,7 @@
  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  * for more details.
  *
- * RCSID $Id: ranbits.c,v 1.6 2000/08/23 00:20:27 henry Exp $
+ * RCSID $Id: ranbits.c,v 1.7 2001/05/30 06:16:05 henry Exp $
  */
 
 #include <sys/types.h>
@@ -51,7 +51,7 @@
 char me[] = "ipsec ranbits";	/* for messages */
 
 char buf[MAXBITS/CHAR_BIT];
-char outbuf[2*sizeof(buf)+10];
+char outbuf[3*sizeof(buf)];
 
 main(argc, argv)
 int argc;
diff -bruN freeswan-1.9.orig/utils/rehashcertdir freeswan-1.9/utils/rehashcertdir
--- freeswan-1.9.orig/utils/rehashcertdir	Wed Dec 31 19:00:00 1969
+++ freeswan-1.9/utils/rehashcertdir	Wed May 16 10:57:20 2001
@@ -0,0 +1,38 @@
+#!/bin/sh 
+if [ "$1" = "" ];
+then 
+  echo "Error: No directory to process."
+  echo "Usage: $0 <directory>"
+  echo
+  exit 1
+fi
+
+if [ ! -d $1 ];
+then
+  echo "Error: "$1" is not a directory."
+  echo "Usage: $0 <directory>"
+  echo
+  exit 2
+fi
+
+cd $1
+for ii in *.pem; do
+  if [ "`basename $ii`" = "crl.pem" ];
+  then
+    ln -fs $ii `openssl crl -noout -hash -in crl.pem`.crl.0
+  else
+    ln -fs $ii `openssl x509 -noout -hash -in $ii`.cert.0
+    perl -e "open(IN, \"openssl x509 -in $ii -noout -text \|\"); \
+      @IN = <IN>; \
+      foreach (@IN) { \
+        if (/IP Address:(\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3})/) { \
+          system(\"ln -sf $ii `dirname $ii`/ip-\$1.cert.0\"); \
+        } \
+        if (/DNS:([^, ]*).*$/) { \
+          system(\"ln -sf $ii `dirname $ii`/dns-\$1.cert.0\"); \
+        } \
+      };"
+  fi
+done
+
+
diff -bruN freeswan-1.9.orig/utils/rsakeygen freeswan-1.9/utils/rsakeygen
--- freeswan-1.9.orig/utils/rsakeygen	Wed Dec 31 19:00:00 1969
+++ freeswan-1.9/utils/rsakeygen	Wed May 16 13:09:59 2001
@@ -0,0 +1,32 @@
+#!/bin/sh
+# use command line specified directory for rsakeys and publickey files,
+# otherwise use the current directory
+KEYDIR=/usr/local/lib/ipsec
+if [ $# -eq 1 ]
+then 
+  KEYDIR=$1
+fi
+
+# define variables
+KEYFILE=$KEYDIR/rsakeys
+PUBKEY=$KEYDIR/publickey
+IPSEC_SECRETS=/etc/ipsec.secrets
+
+
+# generate rsa keys 
+touch $KEYFILE
+chmod 600 $KEYFILE
+ipsec rsasigkey --random /dev/urandom 1024 > $KEYFILE
+chmod 400 $KEYFILE
+
+# extract public key to write to publickey file
+awk 'NR==3 {print $0}' $KEYFILE | cut -d= -f2 > $PUBKEY
+
+# write the rest part including private key to the ipsec.secrets file
+touch ${IPSEC_SECRETS}
+chmod 600 ${IPSEC_SECRETS}
+echo ": rsa {" > ${IPSEC_SECRETS}
+awk 'NR>3 {print $0}' $KEYFILE >> ${IPSEC_SECRETS}
+echo "	}" >> ${IPSEC_SECRETS}
+chmod 400 ${IPSEC_SECRETS}
+exit 0
diff -bruN freeswan-1.9.orig/utils/rsasigkey.8 freeswan-1.9/utils/rsasigkey.8
--- freeswan-1.9.orig/utils/rsasigkey.8	Wed Mar 14 17:54:50 2001
+++ freeswan-1.9/utils/rsasigkey.8	Mon Jun  4 10:49:07 2001
@@ -1,5 +1,5 @@
-.TH IPSEC_RSASIGKEY 8 "23 Feb 2001"
-.\" RCSID $Id: rsasigkey.8,v 1.12.2.3 2001/03/14 22:54:50 henry Exp $
+.TH IPSEC_RSASIGKEY 8 "14 May 2001"
+.\" RCSID $Id: rsasigkey.8,v 1.17 2001/05/31 21:57:33 henry Exp $
 .SH NAME
 ipsec rsasigkey \- generate RSA signature key
 .SH SYNOPSIS
@@ -128,7 +128,7 @@
 .nf
 	# RSA 2048 bits   xy.example.com   Sat Apr 15 13:53:22 2000
 	# for signatures only, UNSAFE FOR ENCRYPTION
-	#pubkey=0x0103cc2a86fcf440...cf1011abb82d1
+	#pubkey=0sAQOF8tZ2NZt...Y1P+buFuFn/
 	#IN KEY 0x4200 4 1 AQOF8tZ2NZt...Y1P+buFuFn/
 	# (0x4200 = auth-only host-level, 4 = IPSec, 1 = RSA)
 	Modulus: 0xcc2a86fcf440...cf1011abb82d1
@@ -142,12 +142,19 @@
 	Coefficient: 0xafb761d001...0c13e98d98
 .fi
 .PP
+The first (comment) line,
+indicating the nature and date of the key,
+and giving a host name,
+is used by
+.IR ipsec_showhostkey (8)
+when generating some forms of key output.
+.PP
 The commented-out
 .B pubkey=
 line contains the public key\(emthe public exponent and the modulus\(emcombined
 in approximately RFC 2537 format
-(the one deviation is that the combined value is given in hex with a
-.B 0x
+(the one deviation is that the combined value is given with a
+.B 0s
 prefix, rather than in unadorned base-64),
 suitable for use in the
 .I ipsec.conf
@@ -227,7 +234,7 @@
 .SH FILES
 /dev/random
 .SH SEE ALSO
-random(4)
+random(4), ipsec_showhostkey(8)
 .br
 \fIApplied Cryptography\fR, 2nd. ed., by Bruce Schneier, Wiley 1996.
 .br
@@ -237,7 +244,7 @@
 by Torbj Granlund.
 .SH HISTORY
 Written for the Linux FreeS/WAN project
-<http://www.xs4all.nl/~freeswan/>
+<http://www.freeswan.org>
 by Henry Spencer.
 .SH BUGS
 There is an internal limit on
diff -bruN freeswan-1.9.orig/utils/rsasigkey.c freeswan-1.9/utils/rsasigkey.c
--- freeswan-1.9.orig/utils/rsasigkey.c	Thu Feb 22 17:11:30 2001
+++ freeswan-1.9/utils/rsasigkey.c	Mon Jun  4 10:49:07 2001
@@ -12,7 +12,7 @@
  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  * for more details.
  *
- * RCSID $Id: rsasigkey.c,v 1.14.2.2 2001/02/22 22:11:30 henry Exp $
+ * RCSID $Id: rsasigkey.c,v 1.16 2001/05/14 23:09:30 henry Exp $
  */
 
 #include <stdio.h>
@@ -353,7 +353,7 @@
 							/* ctime provides \n */
 	printf("\t# for signatures only, UNSAFE FOR ENCRYPTION\n");
 	bundp = bundle(E, n, &bs);
-	printf("\t#pubkey=%s\n", conv(bundp, bs, 'x'));	/* RFC2537ish format */
+	printf("\t#pubkey=%s\n", conv(bundp, bs, 's'));	/* RFC2537ish format */
 	printf("\t#IN KEY 0x4200 4 1 %s\n",
 			conv(bundp, bs, 's')+2);	/* RFC2537 */
 	printf("\t# (0x4200 = auth-only host-level, 4 = IPSec, 1 = RSA)\n");
diff -bruN freeswan-1.9.orig/utils/secrets.proto freeswan-1.9/utils/secrets.proto
--- freeswan-1.9.orig/utils/secrets.proto	Sun Mar 11 23:03:48 2001
+++ freeswan-1.9/utils/secrets.proto	Mon Jun  4 10:49:40 2001
@@ -1,16 +1,11 @@
-# RCSID $Id: secrets.proto,v 1.12.2.1 2001/03/12 04:03:48 henry Exp $
+# RCSID $Id: secrets.proto,v 1.14 2001/05/23 15:12:37 henry Exp $
 # This file holds shared secrets or RSA private keys for inter-Pluto
 # authentication.  See ipsec_pluto(8) manpage, and HTML documentation.
 
-# Shared secret (an arbitrary character string, which should be both long
-# and hard to guess, enclosed in quotes) for a pair of negotiating hosts.
-# Must be same on both; generate on one and copy to the other.
-10.0.0.1 10.12.12.1 : PSK "xxx"
-
 # RSA private key for this host, authenticating it to any other host
-# which knows the public part.  Put ONLY the "pubkey" part into connection
-# descriptions on the other host(s); it need not be kept secret, and can
-# be extracted conveniently with "ipsec showhostkey".
+# which knows the public part.  Suitable public keys, for ipsec.conf, DNS,
+# or configuration of other implementations, can be extracted conveniently
+# with "ipsec showhostkey".
 : RSA	{
 	# yyy
 	}
diff -bruN freeswan-1.9.orig/utils/setup freeswan-1.9/utils/setup
--- freeswan-1.9.orig/utils/setup	Wed Mar 14 18:52:41 2001
+++ freeswan-1.9/utils/setup	Mon Jun  4 11:29:01 2001
@@ -12,7 +12,7 @@
 # or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 # for more details.
 #
-# RCSID $Id: setup,v 1.90.2.3 2001/03/14 23:52:41 henry Exp $
+# RCSID $Id: setup,v 1.105 2001/06/01 15:49:14 henry Exp $
 #
 # ipsec         init.d script for starting and stopping
 #               the IPsec security subsystem (KLIPS and Pluto).
@@ -30,7 +30,7 @@
 # description: IPsec provides encrypted and authenticated communications; \
 # KLIPS is the kernel half of it, Pluto is the user-level management daemon.
 
-if test " $IPSECDIR" = " "	# if we were not called by the ipsec command
+if test " $IPSEC_DIR" = " "	# if we were not called by the ipsec command
 then
 	# we must establish a suitable PATH ourselves
 	PATH=/usr/local/sbin:/sbin:/usr/sbin:/usr/local/bin:/bin:/usr/bin
@@ -62,7 +62,7 @@
 done
 if ! test "$found"
 then
-	echo "cannot find ipsec command -- IPsec startup aborted" |
+	echo "cannot find ipsec command -- \`$1' aborted" |
 		logger -s -p daemon.error -t ipsec_setup
 	exit 1
 fi
@@ -72,7 +72,7 @@
 eval `ipsec _confread --varprefix IPSEC --type config setup`
 if test " $IPSEC_confreadstatus" != " "
 then
-	echo "$IPSEC_confreadstatus -- IPsec startup aborted" |
+	echo "$IPSEC_confreadstatus -- \`$1' aborted" |
 		logger -s -p daemon.error -t ipsec_setup
 	exit 1
 fi
@@ -82,6 +82,7 @@
 subsyslock=/var/lock/subsys/ipsec
 info=/var/run/ipsec.info
 sysflags=/proc/sys/net/ipsec
+modules=/proc/modules
 # full rp_filter path is $rpfilter1/interface/$rpfilter2
 rpfilter1=/proc/sys/net/ipv4/conf
 rpfilter2=rp_filter
@@ -100,8 +101,11 @@
 	# load module if necessary
 	if test ! -f $ipsecversion
 	then
+		if test -r $modules		# kernel does have modules
+		then
 		unset MODPATH MODULECONF	# no user overrides!
 		depmod -a >/dev/null 2>&1 && modprobe ipsec
+		fi
 		if test ! -f $ipsecversion
 		then
 			echo "Fatal error, kernel appears to lack KLIPS."
@@ -130,8 +134,8 @@
 	then
 		sysflag "$IPSECfragicmp" "fragicmp" no icmp
 		echo 1 >$sysflags/inbound_policy_check	# no debate
-		sysflag "$IPSECno_eroute_pass" "no_eroute_pass" no no_eroute_pass
-		sysflag "$IPSECopportunistic" "opportunistic" no opportunistic
+		sysflag no "no_eroute_pass" no no_eroute_pass	# obsolete parm
+		sysflag no "opportunistic" no opportunistic	# obsolete parm
 		sysflag "$IPSEChidetos" "hidetos" yes tos
 	else
 		echo "Cannot adjust kernel flags, no $sysflags directory!"
@@ -151,6 +155,26 @@
 			;;
 		esac
 	done
+
+	# set up default eroute if necessary
+	if test " $IPSECpacketdefault" = " "
+	then
+		case "$IPSECno_eroute_pass" in
+		''|no)	IPSECpacketdefault=drop	;;
+		yes)	IPSECpacketdefault=pass	;;
+		*)	echo "$me: unknown (not yes/no) no_eroute_pass value \`$IPSECno_eroute_pass'" >&2
+			IPSECpacketdefault=drop
+			;;
+		esac
+	fi
+	case "$IPSECpacketdefault" in
+	pass|reject)
+		ipsec eroute --label "packetdefault" --replace --eraf inet \
+			--src 0/0 --dst 0/0 --said "%$IPSECpacketdefault"
+		;;
+	drop)	;;
+	*)	echo "$me: unknown packetdefault value \`$IPSECpacketdefault'" >&2 ;;
+	esac
 }
 
 # set up a system flag based on a variable
@@ -160,6 +184,17 @@
 	'')	v="$3"	;;
 	*)	v="$1"	;;
 	esac
+	if test ! -f $sysflags/$4
+	then
+		if test " $v" != " $3"
+		then
+			echo "$me: cannot implement $2=$v because" >&2
+			echo "	$sysflags/$4 does not exist" >&2
+			return 1
+		else
+			return 0	# can't set it, but it's default anyway
+		fi
+	fi
 	case "$v" in
 	yes)	echo 1 >$sysflags/$4	;;
 	no)	echo 0 >$sysflags/$4	;;
@@ -281,7 +316,7 @@
 	# searches, if needed
 	if test " $IPSECplutoload" = " %search"
 	then
-		eval `ipsec _confread --varprefix PLUTO --search auto add start`
+		eval `ipsec _confread --varprefix PLUTO --search auto add start background`
 		if test " $PLUTO_confreadstatus" != " "
 		then
 			echo "plutoload: $PLUTO_confreadstatus" | logit
@@ -304,10 +339,25 @@
 		fi
 	fi
 
-	# ensure plutoload is a superset of plutostart
+	# ensure plutoload > plutoroute > plutostart
 	for s in $IPSECplutostart
 	do
 		found=
+		for lo in $IPSECplutoroute
+		do
+			if test " $lo" = " $s"
+			then
+				found=yes
+			fi
+		done
+		if test ! "$found"
+		then
+			IPSECplutoroute="$IPSECplutoroute $s"
+		fi
+	done
+	for s in $IPSECplutoroute
+	do
+		found=
 		for lo in $IPSECplutoload
 		do
 			if test " $lo" = " $s"
@@ -391,9 +441,10 @@
 	fi
 
 	# quickly establish routing
-	if test " $IPSECplutostart" != " "
+	if test " $IPSECplutoroute" != " "
 	then
-		echo "$IPSECplutostart" | tr ' ' '\n' | column -x -c 100 |
+		echo "$IPSECplutoroute" | 
+			tr ' ' '\n' | column -x -c 100 |
 			tr -s '\t ' '  ' |
 			while read bunch
 			do
@@ -449,6 +500,13 @@
 case "$1" in
   start|--start)
 	# Start things rolling.
+	# First, does it seem to be going already?
+	if test -f $info
+	then
+		echo "FreeS/WAN IPsec apparently already running, start aborted!" | logit
+		exit 1
+	fi
+	# announcement
 	# (Warning, changes to this log message may affect barf.)
 	version="`ipsec --version | awk 'NR == 1 { print $3 }'`"
 	echo "Starting FreeS/WAN IPsec $version..." | logit
@@ -466,10 +524,16 @@
 		exit 1
 	fi
 	>$info
+	if test ! -r $info
+	then
+		echo "...unable to create $info, aborting start!" | logit
+		exit 1
+	fi
 	startklips 2>&1 | logit
 	if test ! -f $ipsecversion	# hard to test startklips exit status
 	then
-		echo "Cannot continue IPsec startup."
+		echo "No KLIPS, cannot continue IPsec startup!"
+		rm -f $info
 		exit 1
 	fi
 	if test -d `dirname $subsyslock`
@@ -508,14 +572,23 @@
 	fore)	plutogo 2>&1 | logit	;;
 	esac
 	echo "...FreeS/WAN IPsec started" | logonly
+
+	echo "Starting background tunnels..." | logit
+	$0 --startbacktunnels
 	;;
 
   stop|--stop)
 	# Shut things down.
-	echo "Stopping FreeS/WAN IPsec..." | logit
 	if test -r $info
 	then
+		echo "Stopping FreeS/WAN IPsec..." | logit
+		status=0
 		. $info
+	else
+		echo "Stop ordered, but IPsec does not appear to be running!" |
+									logit
+		echo "Doing cleanup anyway..." | logit
+		status=1
 	fi
 	if test " $IPSECforwardcontrol" = " yes" -a " $ipforwardingwas" = " 0"
 	then
@@ -531,8 +604,21 @@
 		rm -f $plutopid
 	elif kill -0 `cat $plutopid` 2>/dev/null
 	then
+	  (
+		# kill pluto in 30 secs no matter what.
+		(
+			sleep 30
+			echo "30 second timeout expired. Killing Pluto." | logit
+			kill -9 $plutopid &> /dev/null
+		) &> /dev/null &
+		killpid=$!
 		ipsec whack --shutdown | awk '$1 != "002"' | logit
 		sleep 1			# general paranoia
+		# kill the killpid if we still need to.
+		if kill -0 $killpid &> /dev/null ; then
+			kill -9 $killpid &> /dev/null
+		fi
+	  ) 2> /dev/null
 		if test -s $plutopid
 		then
 			echo "Pluto did not go away!  Killing it:" | logit
@@ -563,6 +649,7 @@
 	fi
 	rm -f $info
 	echo "...FreeS/WAN IPsec stopped" | logonly
+	exit $status
 	;;
 
   restart|--restart)
@@ -570,18 +657,129 @@
 	$0 start
 	;;
 
+  status|--status)
+	if test -f $info
+	then
+		hasinfo=yes
+	fi
+
+	if test -f $subsyslock
+	then
+		haslock=yes
+	fi
+
+	if test -s $plutopid
+	then
+		if ps -p `cat $plutopid` >/dev/null
+		then
+			haspluto=yes
+			plutokind=normal
+		elif ps -C pluto >/dev/null
+		then
+			haspluto=yes
+			plutokind=illicit
+		fi
+	elif ps -C pluto >/dev/null
+	then
+		haspluto=yes
+		plutokind=orphaned
+	fi
+
+	if test -r /proc/net/ipsec_eroute -a \
+		" `wc -l </proc/net/ipsec_eroute`" -gt 0
+	then
+		eroutes=yes
+	fi
+
+	if test -r $ipsecversion
+	then
+		klips=yes
+	elif test -r $modules
+	then
+		klips=maybe
+	else
+		klips=none
+	fi
+               
+	if test "$hasinfo"
+	then
+		echo "started"
+		# might not be a subsystem lock dir, ignore that issue
+		if test "$plutokind" = "normal" -a "$klips" = "yes"
+		then
+			exit 0
+		fi
+		echo "but..."
+		if test ! "$haspluto"
+		then
+			echo "no Pluto running!"
+		else
+			echo "$plutokind Pluto running!"
+		fi
+		case $klips in
+		maybe)  echo "KLIPS module is not loaded!"      ;;
+		none)   echo "no KLIPS in kernel!"              ;;
+		esac
+		if test "$eroutes"
+		then
+		echo "some eroutes exist"
+		fi
+		exit 1
+	else
+		echo "stopped"
+		if test ! "$haslock" -a ! "$haspluto" -a ! "$eroutes"
+		then
+			exit 0
+		fi
+		echo "but..."
+		if test "$haslock"
+		then
+			echo "has subsystem lock!"
+		fi
+		if test "$haspluto"
+		then
+			echo "$plutokind Pluto is running!"
+		fi
+		if test "$eroutes"
+		then
+		echo "some eroutes exist!"
+		fi
+		exit 1
+	fi
+	;;
+
   --version)
-	echo "1"
+	echo "$me $IPSEC_VERSION"
 	exit 0
 	;;
 
   --help)
-	echo "Usage: $me {--start|--stop|--restart}"
+	echo "Usage: $me {--start|--stop|--restart|--status}"
 	exit 0
 	;;
 
+  startbacktunnels|--startbacktunnels)
+	(
+	eval `ipsec _confread --varprefix PLUTO --search auto background`
+	if test " $PLUTO_confreadstatus" != " "
+	then
+		echo "$PLUTO_confreadstatus (start search) -- aborting" |
+								logit
+		exit 1
+	fi
+	IPSECplutobackground="$PLUTO_confreadnames"
+
+	(
+	for TUNNEL in $IPSECplutobackground ; 
+	do
+	  ipsec auto --up $TUNNEL 
+	done
+	) &>/dev/null 
+	) &
+	;;
+
   *)
-	echo "Usage: $me {--start|--stop|--restart}" >&2
+	echo "Usage: $me {--start|--stop|--restart|--status}" >&2
 	exit 2
 esac
 
diff -bruN freeswan-1.9.orig/utils/setup.8 freeswan-1.9/utils/setup.8
--- freeswan-1.9.orig/utils/setup.8	Sun Dec  3 17:11:30 2000
+++ freeswan-1.9/utils/setup.8	Mon Jun  4 10:37:06 2001
@@ -1,5 +1,5 @@
-.TH IPSEC_SETUP 8 "28 Nov 2000"
-.\" RCSID $Id: setup.8,v 1.24 2000/12/03 22:11:30 henry Exp $
+.TH IPSEC_SETUP 8 "31 May 2001"
+.\" RCSID $Id: setup.8,v 1.29 2001/05/31 21:57:33 henry Exp $
 .SH NAME
 ipsec setup \- control IPsec subsystem
 .SH SYNOPSIS
@@ -38,7 +38,8 @@
 interface(s) specified in the configuration file,
 and (if the configuration file so specifies)
 setting up manually-keyed connections and/or
-asking Pluto to negotiate tunnels to other security gateways
+asking Pluto to negotiate automatically-keyed connections
+to other security gateways
 .TP
 .B stop
 shut down Klips and Pluto,
@@ -49,12 +50,27 @@
 .B stop
 followed by
 .B start
+.TP
+.B status
+report the status of the subsystem;
+normally just reports
+.B started
+or
+.B stopped
+and exits with status 0,
+but will go into more detail (and exit with status 1)
+if something strange is found.
 .PP
 The
 .B stop
 operation tries to clean up properly even if assorted accidents
 have occurred,
 e.g. Pluto having died without removing its lock file.
+If
+.B stop
+discovers that the subsystem is (supposedly) not running,
+it will complain,
+but will do its cleanup anyway before exiting with status 1.
 .PP
 Although a number of configuration-file parameters influence
 .IR setup 's
@@ -75,7 +91,11 @@
 .SH SEE ALSO
 ipsec.conf(5), ipsec(8), ipsec_manual(8), ipsec_auto(8), route(8)
 .SH DIAGNOSTICS
-All output from the commands this script invokes goes both to standard
+All output from the commands
+.B start
+and
+.B stop
+invoke goes both to standard
 output and to
 .IR syslogd (8)
 via
@@ -84,9 +104,13 @@
 .IR syslogd (8).
 .SH HISTORY
 Written for the FreeS/WAN project
-<http://www.xs4all.nl/~freeswan/>
+<http://www.freeswan.org>
 by Henry Spencer.
 .SH BUGS
 Old versions of
 .IR logger (1)
 injected spurious extra newlines onto standard output.
+.PP
+Startup failure is not consistently reported in the exit status.
+.PP
+The normal status report probably should include Pluto's process ID.
diff -bruN freeswan-1.9.orig/utils/showdefaults freeswan-1.9/utils/showdefaults
--- freeswan-1.9.orig/utils/showdefaults	Wed Nov 29 16:27:07 2000
+++ freeswan-1.9/utils/showdefaults	Mon Jun  4 11:29:24 2001
@@ -12,10 +12,15 @@
 # or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 # for more details.
 #
-# RCSID $Id: showdefaults,v 1.3 2000/11/29 21:27:07 henry Exp $
+# RCSID $Id: showdefaults,v 1.4 2001/06/01 15:49:14 henry Exp $
 
 info=/var/run/ipsec.info
-me=ipsec_showdefaults
+me="ipsec showdefaults"
+
+case "$1" in
+--help)		echo "Usage: ipsec showdefaults" ; exit 0	;;
+--version)	echo "$me $IPSEC_VERSION" ; exit 0	;;
+esac
 
 # Pick up the info.
 if test -s $info
diff -bruN freeswan-1.9.orig/utils/showdefaults.8 freeswan-1.9/utils/showdefaults.8
--- freeswan-1.9.orig/utils/showdefaults.8	Mon Jan 24 00:36:41 2000
+++ freeswan-1.9/utils/showdefaults.8	Mon Jun  4 11:29:24 2001
@@ -1,5 +1,5 @@
 .TH IPSEC_SHOWDEFAULTS 8 "23 Jan 2000"
-.\" RCSID $Id: showdefaults.8,v 1.2 2000/01/24 05:36:41 henry Exp $
+.\" RCSID $Id: showdefaults.8,v 1.3 2001/05/31 21:57:33 henry Exp $
 .SH NAME
 ipsec showdefaults \- show %defaultroute defaults
 .SH SYNOPSIS
@@ -30,5 +30,5 @@
 /var/run/ipsec.info
 .SH HISTORY
 Written for the Linux FreeS/WAN project
-<http://www.xs4all.nl/~freeswan/>
+<http://www.freeswan.org>
 by Henry Spencer.
diff -bruN freeswan-1.9.orig/utils/showhostkey freeswan-1.9/utils/showhostkey
--- freeswan-1.9.orig/utils/showhostkey	Sun Mar 11 23:03:31 2001
+++ freeswan-1.9/utils/showhostkey	Mon Jun  4 11:29:24 2001
@@ -12,19 +12,22 @@
 # or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 # for more details.
 #
-# RCSID $Id: showhostkey,v 1.1.2.1 2001/03/12 04:03:31 henry Exp $
+# RCSID $Id: showhostkey,v 1.8 2001/06/01 15:49:14 henry Exp $
 
 me="ipsec showhostkey"
-usage="Usage: $me [--file secrets] [--left] [--right]"
+usage="Usage: $me [--file secrets] [--left] [--right] [--txt gateway]"
 
 file=/etc/ipsec.secrets
 fmt="dns"
+gw=
 for dummy
 do
 	case "$1" in
 	--file)	file="$2" ; shift	;;
 	--left)	fmt="left"		;;
 	--right)	fmt="right"	;;
+	--txt)	fmt="txt" ; gw="$2" ; shift	;;
+	--version)	echo "$me $IPSEC_VERSION" ; exit 0	;;
 	--help)	echo "$usage" ; exit 0	;;
 	--)	shift ; break		;;
 	-*)	echo "$me: unknown option \`$1'" >&2 ; exit 2	;;
@@ -32,6 +35,11 @@
 	esac
 	shift
 done
+if test " $fmt" = " txt" -a " $gw" = " "
+then
+	echo "$me: --txt gateway value cannot be empty" >&2
+	exit 2
+fi
 
 if test ! -f $file
 then
@@ -54,6 +62,7 @@
 		host = "'"$host"'"
 		file = "'"$file"'"
 		fmt = "'"$fmt"'"
+		gw = "'"$gw"'"
 		comment = ""
 		status = 0
 	}
@@ -75,7 +84,14 @@
 		sub(/^[ \t]+#IN[ \t]+KEY[ \t]+/, (host ".\tIN\tKEY\t"), out)
 		nfound++
 	}
-	inkey && fmt != "dns" && $0 ~ /^[ \t]+#pubkey=/ {
+	inkey && fmt == "txt" && $0 ~ /^[ \t]+#IN[ \t]+KEY[ \t]+/ {
+		out = $0
+		gsub(/[ \t]+/, " ", out)
+		sub(/^ #IN KEY [^ ]+ [^ ]+ [^ ]+ /, "", out)
+		out = "\tIN\tTXT\t\"X-IPsec-Server(10)=" gw " " out "\""
+		nfound++
+	}
+	inkey && (fmt == "left" || fmt == "right") && $0 ~ /^[ \t]+#pubkey=/ {
 		out = $0
 		sub(/^[ \t]+#pubkey=/, ("\t" fmt "rsasigkey="), out)
 		nfound++
diff -bruN freeswan-1.9.orig/utils/showhostkey.8 freeswan-1.9/utils/showhostkey.8
--- freeswan-1.9.orig/utils/showhostkey.8	Wed Mar 14 17:54:50 2001
+++ freeswan-1.9/utils/showhostkey.8	Mon Jun  4 11:29:24 2001
@@ -1,5 +1,5 @@
-.TH IPSEC_SHOWHOSTKEY 8 "8 March 2001"
-.\" RCSID $Id: showhostkey.8,v 1.2.2.2 2001/03/14 22:54:50 henry Exp $
+.TH IPSEC_SHOWHOSTKEY 8 "22 May 2001"
+.\" RCSID $Id: showhostkey.8,v 1.6 2001/05/31 21:59:17 henry Exp $
 .SH NAME
 ipsec showhostkey \- show host's authentication key
 .SH SYNOPSIS
@@ -10,6 +10,9 @@
 ] [
 .B \-\-right
 ] [
+.B \-\-txt
+gateway
+] [
 .B \-\-file
 secretfile
 ]
@@ -40,6 +43,23 @@
 .fi
 .PP
 The
+.B \-\-txt
+option causes the output to be in opportunistic-encryption DNS TXT record
+format,
+with the specified
+.I gateway
+value.
+Again, generation information is included if available.
+For example,
+.B "\-\-txt 10.11.12.13"
+might give (with the key data trimmed for clarity):
+.PP
+.nf
+  ; RSA 2048 bits   xy.example.com   Sat Apr 15 13:53:22 2000
+      IN TXT  "X-IPsec-Server(10)=10.11.12.13 AQOF8tZ2...+buFuFn/"
+.fi
+.PP
+The
 .B \-\-left
 and
 .B \-\-right
@@ -77,7 +97,7 @@
 ipsec.secrets(5), ipsec.conf(5), ipsec_rsasigkey(8)
 .SH HISTORY
 Written for the Linux FreeS/WAN project
-<http://www.xs4all.nl/~freeswan/>
+<http://www.freeswan.org>
 by Henry Spencer.
 .SH BUGS
 Arguably,
@@ -88,3 +108,15 @@
 with the
 .B \-\-oldkey
 option, to generate a suitable output line.
+.PP
+The need to specify the gateway address (etc.) for
+.B \-\-txt
+is annoying, but there is no good way to determine it automatically.
+.PP
+There should be a way to specify the priority value for TXT records;
+currently it is hardwired to
+.BR 10 .
+.PP
+Assumes there is only one RSA key in
+.IR ipsec.secrets ,
+which is common but not necessarily universal.
diff -bruN freeswan-1.9.orig/utils/updown.firewall freeswan-1.9/utils/updown.firewall
--- freeswan-1.9.orig/utils/updown.firewall	Wed Dec 31 19:00:00 1969
+++ freeswan-1.9/utils/updown.firewall	Wed May 16 10:57:20 2001
@@ -0,0 +1,166 @@
+#! /bin/sh
+# sample updown script for ipchains
+# Copyright (C) 2000  D. Hugh Redelmeier, Henry Spencer
+# sample updown script for iptables
+# Copyright (C) 2000  Luc Lanthier
+# 
+# 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: updown.firewall,v 1.1.2.9 2001/03/27 18:44:16 lanthierl Exp $
+#
+# Modifications: Add ipchains rules specific to Netwinder OfficeServer to
+# let FreeS/WAN work with the firewall. Dacheng Tang
+
+KERNVER=`uname -r | cut -d. -f 1,2`
+
+# check interface version
+case "$PLUTO_VERSION" in
+1.0)    echo "$0: Pluto interface version 1.0 is obsolete." >&2
+        ;;
+1.1)    ;;
+*)      echo "$0: unknown interface version \`$PLUTO_VERSION'" >&2
+        exit 2
+        ;;
+esac
+
+# check parameter(s)
+case "$*" in
+'')     ;;
+*)      echo "$0: parameters unexpected" >&2
+        exit 2
+        ;;
+esac
+
+# utility functions for route manipulation
+# Meddling with this stuff should never be necessary and is most unwise.
+uproute() {
+    route add -net $PLUTO_PEER_CLIENT_NET netmask $PLUTO_PEER_CLIENT_MASK \
+      dev $PLUTO_INTERFACE gw $PLUTO_NEXT_HOP
+      st=$?
+      if test $st -ne 0
+      then
+        # route has already given its own cryptic message
+        echo "$0: \`route $1 $parms' failed" >&2
+      fi
+      return $st
+}
+
+downroute() {
+    route del -net $PLUTO_PEER_CLIENT_NET netmask $PLUTO_PEER_CLIENT_MASK \
+      dev $PLUTO_INTERFACE gw $PLUTO_NEXT_HOP 
+      st=$?
+      if test $st -ne 0
+      then
+        # route has already given its own cryptic message
+        echo "$0: \`route $1 $parms' failed" >&2
+      fi
+      return $st
+
+}
+
+# the big choice
+case "$PLUTO_VERB" in
+prepare-host|prepare-client)
+        # delete possibly-existing route (preliminary to adding a route)
+        oops="`route del -net $PLUTO_PEER_CLIENT_NET \
+                                        netmask $PLUTO_PEER_CLIENT_MASK 2>&1`"
+        status="$?"
+        if test " $oops" = " " -a " $status" != " 0"
+        then
+                oops="silent error in route command, exit status $status"
+        fi
+        case "$oops" in
+        'SIOCDELRT: No such process')
+                # This is what route (currently -- not documented!) gives
+                # for "could not find such a route".
+                status=0
+                ;;
+        esac
+        exit $status
+        ;;
+route-host|route-client)
+        # connection to this host or client being routed
+        uproute
+        ;;
+unroute-host|unroute-client)
+        # connection to this host or client being unrouted
+        downroute
+        ;;
+up-host)
+        # connection to this host coming up
+        ;;
+down-host)
+        # connection to this host going down
+        ;;
+up-client)
+  if [ "$KERNVER" = "2.2" ];
+  then
+	# add an input rule to let KLIPS decapsulated packets pass ipsec0
+	ipchains -A input -i $PLUTO_INTERFACE -j ACCEPT -p all \
+		-d $PLUTO_MY_CLIENT_NET/$PLUTO_MY_CLIENT_MASK
+        # connection to client subnet, through forwarding firewall, coming up
+        ipchains -I forward -j ACCEPT -b \
+                -s $PLUTO_MY_CLIENT_NET/$PLUTO_MY_CLIENT_MASK \
+                -d $PLUTO_PEER_CLIENT_NET/$PLUTO_PEER_CLIENT_MASK
+  elif [ "$KERNVER" = "2.4" ];
+  then
+    # add an input rule to let KLIPS decapsulated packets pass ipsec0
+    iptables -A INPUT -i $PLUTO_INTERFACE -j ACCEPT \
+        -d $PLUTO_MY_CLIENT_NET/$PLUTO_MY_CLIENT_MASK
+        # connection to client subnet, through forwarding firewall, coming up
+    iptables -I FORWARD -j ACCEPT \
+        -s $PLUTO_MY_CLIENT_NET/$PLUTO_MY_CLIENT_MASK \
+        -d $PLUTO_PEER_CLIENT_NET/$PLUTO_PEER_CLIENT_MASK
+    iptables -I FORWARD -j ACCEPT \
+        -s $PLUTO_PEER_CLIENT_NET/$PLUTO_PEER_CLIENT_MASK \
+        -d $PLUTO_MY_CLIENT_NET/$PLUTO_MY_CLIENT_MASK
+    if ( iptables -t nat -L -n &> /dev/null ) ; then
+      iptables -t nat -I POSTROUTING -j ACCEPT \
+        -s $PLUTO_MY_CLIENT_NET/$PLUTO_MY_CLIENT_MASK \
+        -d $PLUTO_PEER_CLIENT_NET/$PLUTO_PEER_CLIENT_MASK
+    fi
+  fi
+  ;;
+down-client)
+  if [ "$KERNVER" = "2.2" ];
+  then
+	# delete the input rule for the KLIPS decapsulated packets 
+	ipchains -D input -i $PLUTO_INTERFACE -j ACCEPT -p all \
+		-d $PLUTO_MY_CLIENT_NET/$PLUTO_MY_CLIENT_MASK
+        # connection to client subnet, through forwarding firewall, going down
+        ipchains -D forward -j ACCEPT -b \
+                -s $PLUTO_MY_CLIENT_NET/$PLUTO_MY_CLIENT_MASK \
+                -d $PLUTO_PEER_CLIENT_NET/$PLUTO_PEER_CLIENT_MASK
+  elif [ "$KERNVER" = "2.4" ];
+  then
+    # delete the input rule for the KLIPS decapsulated packets
+    iptables -D INPUT -i $PLUTO_INTERFACE -j ACCEPT \
+        -d $PLUTO_MY_CLIENT_NET/$PLUTO_MY_CLIENT_MASK
+        # connection to client subnet, through forwarding firewall, going down
+    iptables -D FORWARD -j ACCEPT \
+        -s $PLUTO_MY_CLIENT_NET/$PLUTO_MY_CLIENT_MASK \
+        -d $PLUTO_PEER_CLIENT_NET/$PLUTO_PEER_CLIENT_MASK
+    iptables -D FORWARD -j ACCEPT \
+        -s $PLUTO_PEER_CLIENT_NET/$PLUTO_PEER_CLIENT_MASK \
+        -d $PLUTO_MY_CLIENT_NET/$PLUTO_MY_CLIENT_MASK
+    if ( iptables -t nat -L -n &> /dev/null ) ; then
+      iptables -t nat -D POSTROUTING -j ACCEPT \
+        -s $PLUTO_MY_CLIENT_NET/$PLUTO_MY_CLIENT_MASK \
+        -d $PLUTO_PEER_CLIENT_NET/$PLUTO_PEER_CLIENT_MASK
+    fi
+  fi
+  # force a zero error code even the ipchains command(s) failed
+  echo "ok"
+  ;;
+*)      echo "$0: unknown verb \`$PLUTO_VERB' or parameter \`$1'" >&2
+        exit 1
+        ;;
+esac
diff -bruN freeswan-1.9.orig/version.c freeswan-1.9/version.c
--- freeswan-1.9.orig/version.c	Mon Feb 26 18:56:08 2001
+++ freeswan-1.9/version.c	Thu Jun  7 14:53:27 2001
@@ -1,2 +1,2 @@
-/* silly pointless RCSID $Id: version.c,v 1.17.2.1 2001/02/26 23:56:08 henry Exp $ */
-static const char freeswan_version[] = "1.9";
+/* silly pointless RCSID $Id: version.c,v 1.19 2001/05/30 13:02:20 henry Exp $ */
+static const char freeswan_version[] = "FreeSWAN-1.9-pkix2";
diff -bruN freeswan-1.9.orig/zlib/Makefile freeswan-1.9/zlib/Makefile
--- freeswan-1.9.orig/zlib/Makefile	Mon Jan 29 17:22:00 2001
+++ freeswan-1.9/zlib/Makefile	Wed May 16 10:57:20 2001
@@ -12,7 +12,7 @@
 # or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 # for more details.
 #
-# RCSID $Id: Makefile,v 1.2 2001/01/29 22:22:00 rgb Exp $
+# RCSID $Id: Makefile,v 1.3 2001/04/21 23:05:24 rgb Exp $
 #
 
 ifndef TOPDIR
@@ -44,19 +44,22 @@
 .S.o:
 	$(CC) -D__ASSEMBLY__ -DNO_UNDERLINE -traditional -c $< -o $*.o
 
-ifdef CONFIG_IPSEC_IPCOMP_ASM_FIXED
-ifdef CONFIG_M586
-  objs-y += match586.o
-  override CFLAGS += -DASMV
-endif
-ifdef CONFIG_M586TSC
-  objs-y += match586.o
-  override CFLAGS += -DASMV
-endif
-ifdef CONFIG_M686
-  objs-y += match686.o
-  override fCFLAGS += -DASMV
-endif
+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))
@@ -74,6 +77,9 @@
 
 #
 # $Log: Makefile,v $
+# 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.
 #
