diff -ruN 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 -ruN 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 -ruN 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 -ruN 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 -ruN 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	Wed May 16 10:57:20 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 -ruN freeswan-1.9.orig/doc/Makefile freeswan-1.9/doc/Makefile
--- freeswan-1.9.orig/doc/Makefile	Mon Jan 29 16:10:46 2001
+++ freeswan-1.9/doc/Makefile	Wed May 16 10:57:20 2001
@@ -66,7 +66,7 @@
 	$(SCRIPTDIR)/mkhtmlman $(HMANDIR) `find .. -type f -name '*.[1-8]'`
 
 manp.old:	$(SCRIPTDIR)/man_xref
-	$(SCRIPTDIR)/man2html.script /usr/local/man $(HMANDIR)
+	$(SCRIPTDIR)/man2html.script $(PREFIX)/usr/man $(HMANDIR)
 
 all: $(howto) $(manpages) index.html
 
diff -ruN 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	Wed May 16 10:57:20 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 -ruN 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	Wed May 16 10:57:20 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 -ruN 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	Wed May 16 10:57:20 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 -ruN 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	Wed May 16 10:57:20 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 -ruN 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	Wed May 16 10:57:20 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 -ruN 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	Wed May 16 10:57:20 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 -ruN 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	Wed May 16 10:57:20 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 -ruN 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	Wed May 16 10:57:20 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 -ruN 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	Wed May 16 10:57:20 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 -ruN 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	Wed May 16 10:57:20 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 -ruN 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	Wed May 16 10:57:20 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 -ruN 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	Wed May 16 10:57:20 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 -ruN 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	Wed May 16 10:57:20 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 -ruN 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	Wed May 16 10:57:20 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 -ruN 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	Wed May 16 10:57:20 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 -ruN 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	Wed May 16 10:57:20 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 -ruN 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	Wed May 16 10:57:20 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 -ruN 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	Wed May 16 10:57:20 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 -ruN 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	Wed May 16 10:57:20 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 -ruN 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	Wed May 16 10:57:20 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 -ruN 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	Wed May 16 10:57:20 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 -ruN 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	Wed May 16 10:57:20 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 -ruN 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	Wed May 16 10:57:20 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 -ruN 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	Wed May 16 10:57:20 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 -ruN 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	Wed May 16 10:57:20 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 -ruN 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	Wed May 16 10:57:20 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 -ruN 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	Wed May 16 10:57:20 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 -ruN 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	Wed May 16 10:57:20 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 -ruN 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	Wed May 16 10:57:20 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 -ruN 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	Wed May 16 10:57:20 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 -ruN 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	Wed May 16 10:57:20 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 -ruN 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	Wed May 16 10:57:20 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 -ruN 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	Wed May 16 10:57:20 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 -ruN 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	Wed May 16 10:57:20 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 -ruN 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	Wed May 16 10:57:20 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 -ruN 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	Wed May 16 10:57:20 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 -ruN 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	Wed May 16 10:57:20 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 -ruN 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	Wed May 16 10:57:20 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 -ruN 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	Wed May 16 10:57:20 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 -ruN 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	Wed May 16 10:57:20 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 -ruN 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	Wed May 16 10:57:20 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 -ruN 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	Wed May 16 10:57:20 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 -ruN 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	Wed May 16 10:57:20 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 -ruN 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	Wed May 16 10:57:20 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 -ruN 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	Wed May 16 10:57:20 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 -ruN 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	Wed May 16 10:57:20 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 -ruN 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	Wed May 16 10:57:20 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 -ruN 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	Wed May 16 10:57:20 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 -ruN 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	Wed May 16 10:57:20 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 -ruN 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	Wed May 16 10:57:20 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 -ruN 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	Wed May 16 10:57:20 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 -ruN 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	Wed May 16 10:57:20 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 -ruN 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	Wed May 16 10:57:20 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 -ruN 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	Wed May 16 10:57:20 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 -ruN 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 -ruN 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	Wed May 16 10:57:20 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 -ruN 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	Wed May 16 10:57:20 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 -ruN 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	Wed May 16 10:57:20 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;
-        n->used=skb->used;
+#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 -ruN 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	Wed May 16 10:57:20 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.67 2001/05/04 16:34:52 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);
@@ -497,7 +509,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 +556,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 +673,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 +703,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 +717,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);
@@ -710,7 +729,7 @@
 
 #if 0
 #ifdef CONFIG_IPSEC_IPCOMP
-  inet_add_protocol(&comp_protocol);
+	inet_add_protocol(&comp_protocol);
 #endif /* CONFIG_IPSEC_IPCOMP */
 #endif
 
@@ -733,53 +752,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");
+	if (inet_del_protocol(&comp_protocol) < 0)
+		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 +844,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 +858,18 @@
 
 /*
  * $Log: ipsec_init.c,v $
- * Revision 1.63.2.1  2001/02/27 00:50:59  henry
- * message improvements
+ * 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 -ruN 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	Wed May 16 10:57:20 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 -ruN 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	Wed May 16 10:57:20 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.44 2001/05/03 19:41:01 rgb Exp $
  */
 
 #include <linux/config.h>
@@ -90,7 +90,7 @@
 int
 ipsec_cleareroutes(void)
 {
-	int error;
+	int error = 0;
 
 	spin_lock_bh(&eroute_lock);
 
@@ -105,15 +105,17 @@
 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);
+		printk("klips_debug:ipsec_breakroute: "
+		       "attempting to delete eroute for %s->%s\n",
+		       buf1,
+		       buf2);
 	}
 #endif /* CONFIG_IPSEC_DEBUG */
 
@@ -141,7 +143,7 @@
 ipsec_makeroute(struct sockaddr_encap *eaddr, struct sockaddr_encap *emask, struct sa_id said)
 {
 	struct eroute *retrt;
-	int error;
+	int error = 0;
 	char sa[SATOA_BUF];
 	size_t sa_len;
 #ifdef CONFIG_IPSEC_DEBUG
@@ -151,14 +153,18 @@
 		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);
+		printk("klips_debug:ipsec_makeroute: "
+		       "attempting to insert eroute for %s->%s, SA: %s\n",
+		       buf1,
+		       buf2,
+		       sa_len ? sa : " (error)");
 	}
 #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));
@@ -177,12 +183,15 @@
 	
 	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);
+		printk("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;
 	}
 	KLIPS_PRINT(debug_eroute,
-		    "klips_debug:ipsec_makeroute: succeeded, I think...\n");
+		    "klips_debug:ipsec_makeroute: "
+		    "succeeded, I think...\n");
 	return 0;
 }
 
@@ -196,11 +205,21 @@
 	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);
+		printk("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 +236,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;
 	}
@@ -239,7 +260,9 @@
 	sa_len = satoa(ro->er_said, 0, sa, SATOA_BUF);
 	w->len += sprintf(w->buffer + w->len,
 			  "%-18s -> %-18s => %s\n",
-			  buf1, buf2, sa);
+			  buf1,
+			  buf2,
+			  sa_len ? sa : " (error)");
 	
 	w->pos = w->begin + w->len;
 	if(w->pos < w->offset) {
@@ -258,7 +281,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 +295,16 @@
 	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);
+		printk("klips_debug:ipsec_rj_walker_delete: "
+		       "deleting: %s -> %s\n",
+		       buf1,
+		       buf2);
 	}
 #endif /* CONFIG_IPSEC_DEBUG */
 
@@ -291,8 +316,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 +327,17 @@
 
 /*
  * $Log: ipsec_radij.c,v $
+ * 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 -ruN 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	Wed May 16 10:57:20 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.83 2001/05/04 16:45:47 rgb Exp $";
 
 #include <linux/config.h>
 #include <linux/version.h>
@@ -252,6 +252,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 +275,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 +303,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 +312,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 +347,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 +383,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 +426,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 +478,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 +493,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.
-		 */
-		spin_lock(&tdb_lock);
+		  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 +533,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 +562,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 +573,6 @@
 				    else
 					stats->rx_dropped++;
 				}
-
-				spin_unlock(&tdb_lock);
 				goto rcvleave;
 			}
 #ifdef NET_21
@@ -575,9 +587,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 +605,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 +622,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);
-			}
+			ipaddr.s_addr = ipp->saddr;
+			addrtoa(ipaddr, 0, ipaddr_txt, sizeof(ipaddr_txt));
+			KLIPS_PRINT(debug_rcv,
+				    "klips_debug:ipsec_rcv: "
+				    "SA:%s, src=%s of pkt agrees with expected SA source address policy.\n",
+				    sa_len ? sa : " (error)",
+				    ipaddr_txt);
 			if(tdbnext) {
 				if(tdbnext != tdbp) {
 					spin_unlock(&tdb_lock);
 					KLIPS_PRINT(debug_rcv,
 						    "klips_debug:ipsec_rcv: "
 						    "unexpected SA:%s: does not agree with tdb->inext policy, dropped\n",
-						    sa);
+						    sa_len ? sa : " (error)");
 					if(stats) {
 						stats->rx_dropped++;
 					}
@@ -640,22 +651,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 +674,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 +689,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 +700,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 +714,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 +723,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 +741,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 +751,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 +770,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 +780,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 +798,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 +807,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 +834,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 +876,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 +885,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 +902,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 +974,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 +998,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 +1010,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;
 		}
 		
@@ -1019,11 +1035,11 @@
 				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;
@@ -1032,15 +1048,15 @@
 			switch(tdbp->tdb_encalg) {
 			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);
+					       "got packet with esplen = %d from %s -- should be on 8 octet boundary, packet dropped\n",
+					       ilen,
+					       ipaddr_txt);
 					if(stats) {
 						stats->rx_errors++;
 					}
-					tdbp->tdb_encsize_errs += 1;
-					spin_unlock(&tdb_lock);
 					goto rcvleave;
 				}
 				des_ede3_cbc_encrypt(idat, idat, ilen,
@@ -1123,23 +1139,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 +1169,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 +1206,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 +1224,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 +1233,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 +1245,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 +1254,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 +1309,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 +1317,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++;
 			}
@@ -1355,15 +1378,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 +1394,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 +1404,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 +1432,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 +1456,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 +1494,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 +1509,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 +1520,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 +1582,36 @@
 
 /*
  * $Log: ipsec_rcv.c,v $
+ * 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.
diff -ruN 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	Wed May 16 10:57:20 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 -ruN 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	Wed May 16 10:57:20 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.148 2001/05/05 03:31:41 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"
@@ -112,8 +112,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 +122,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 +153,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 +195,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 +246,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 +270,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 +292,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]);
@@ -464,6 +474,9 @@
 	struct rtable *rt = NULL;
 #endif /* NET_21 */
 	struct sa_id outgoing_said;
+#ifdef NETDEV_23
+	int pass = 0;
+#endif /* NETDEV_23 */
 
 	/*
 	 *	Return if there is nothing to do.  (Does this ever happen?) XXX
@@ -506,10 +519,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: "
+				    "klips_error:ipsec_tunnel_start_xmit: "
 				    "skb_cow failed to allocate buffer, dropping.\n" );
+			stats->tx_dropped++;
 			goto cleanup;
 		}
 	}
@@ -572,8 +592,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;
 	}
@@ -636,18 +655,14 @@
 		if(iph->protocol == IPPROTO_UDP) {
 			struct udphdr *udph = (struct udphdr*)((caddr_t)iph + (iph->ihl << 2));
 			if(ntohs(udph->dest) == 500) {
+#ifdef NETDEV_23
+				pass = 1;
+#endif /* NETDEV_23 */
 				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
 			}
 		}
 	}
@@ -660,6 +675,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,97 +684,187 @@
 		pyldsz = ntohs(iph->tot_len) - iphlen;
 		max_headroom = max_tailroom = 0;
 		
-		if (er == NULL)	{
-			if(sysctl_ipsec_no_eroute_pass) {
-				KLIPS_PRINT(debug_tunnel & DB_TN_XMIT,
-					    "klips_debug:ipsec_tunnel_start_xmit: "
-					    "no eroute!: calling dev_queue_xmit\n");
-#if 1
-				goto bypass;
-#else
-				DEV_QUEUE_XMIT(skb, physdev, SOPRI_NORMAL);
-				/* IP_SEND(skb, physdev); */
-				skb = NULL;
-#endif
-			} else {
-				if(sysctl_ipsec_opportunistic && !er) {
-					struct tdb tdb;
-					struct sockaddr_in src, dst;
-#ifdef CONFIG_IPSEC_DEBUG
-					char bufsrc[ADDRTOA_BUF], bufdst[ADDRTOA_BUF];
-#endif /* CONFIG_IPSEC_DEBUG */
-					
-					tdb.tdb_said.proto = iph->protocol;
-					src.sin_family = AF_INET;
-					dst.sin_family = AF_INET;
-					src.sin_addr.s_addr = iph->saddr;
-					dst.sin_addr.s_addr = iph->daddr;
-					src.sin_port = 
-						(iph->protocol == IPPROTO_UDP
-						 ? ((struct udphdr*) (((caddr_t)iph) + (iph->ihl << 2)))->source
-						 : (iph->protocol == IPPROTO_TCP
-						    ? ((struct tcphdr*)((caddr_t)iph + (iph->ihl << 2)))->source
-						    : 0));
-					dst.sin_port = 
-						(iph->protocol == IPPROTO_UDP
-						 ? ((struct udphdr*) (((caddr_t)iph) + (iph->ihl << 2)))->dest
-						 : (iph->protocol == IPPROTO_TCP
-						    ? ((struct tcphdr*)((caddr_t)iph + (iph->ihl << 2)))->dest
-						    : 0));
-					for(i = 0;
-					    i < sizeof(struct sockaddr_in)
-						    - offsetof(struct sockaddr_in, sin_zero);
-					    i++) {
-						src.sin_zero[i] = 0;
-						dst.sin_zero[i] = 0;
-					}
-					
-					tdb.tdb_addr_s = (struct sockaddr*)(&src);
-					tdb.tdb_addr_d = (struct sockaddr*)(&dst);
-					KLIPS_PRINT(debug_tunnel & DB_TN_XMIT,
-						    "klips_debug:ipsec_tunnel_start_xmit: "
-						    "SADB_ACQUIRE sent with src=%s:%d, dst=%s:%d, proto=%d.\n",
-						    addrtoa(((struct sockaddr_in*)(tdb.tdb_addr_s))->sin_addr, 0, bufsrc, sizeof(bufsrc)) <= ADDRTOA_BUF ? bufsrc : "BAD_ADDR",
-						    ((struct sockaddr_in*)(tdb.tdb_addr_s))->sin_port,
-						    addrtoa(((struct sockaddr_in*)(tdb.tdb_addr_d))->sin_addr, 0, bufdst, sizeof(bufdst)) <= ADDRTOA_BUF ? bufdst : "BAD_ADDR",
-						    ((struct sockaddr_in*)(tdb.tdb_addr_d))->sin_port,
-						    tdb.tdb_said.proto);
-					pfkey_acquire(&tdb);
-				} else {
-					KLIPS_PRINT(debug_tunnel & DB_TN_XMIT,
-						    "klips_debug:ipsec_tunnel_start_xmit: "
-						    "no eroute!: dropping.\n");
-					stats->tx_dropped++;
-				}
-			}
+		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: "
+				    "magic SA of DROP or no eroute: dropping.\n");
+			stats->tx_dropped++;
 			goto cleanup;
 		}
 		
-		/*
-		  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)) {
+		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: "
+				    "magic 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 NETDEV_23
+			pass = 1;
+#endif /* NETDEV_23 */
 			KLIPS_PRINT(debug_tunnel & DB_TN_XMIT,
 				    "klips_debug:ipsec_tunnel_start_xmit: "
-				    "passthrough eroute, packet sent.\n");
-#if 1
+				    "magic SA of PASS: calling dev_queue_xmit\n");
 			goto bypass;
-#else
-			DEV_QUEUE_XMIT(skb, physdev, SOPRI_NORMAL);
-			/* IP_SEND(skb, physdev); */
-			skb = NULL;
+		}
+
+		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: "
+				    "magic 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;
+			int error = 0;
+			
+			/* Signal all listening KMds with a PF_KEY ACQUIRE */
+			tdb.tdb_said.proto = iph->protocol;
+			src.sin_family = AF_INET;
+			dst.sin_family = AF_INET;
+			src.sin_addr.s_addr = iph->saddr;
+			dst.sin_addr.s_addr = iph->daddr;
+			src.sin_port = 
+				(iph->protocol == IPPROTO_UDP
+				 ? ((struct udphdr*) (((caddr_t)iph) + (iph->ihl << 2)))->source
+				 : (iph->protocol == IPPROTO_TCP
+				    ? ((struct tcphdr*)((caddr_t)iph + (iph->ihl << 2)))->source
+				    : 0));
+			dst.sin_port = 
+				(iph->protocol == IPPROTO_UDP
+				 ? ((struct udphdr*) (((caddr_t)iph) + (iph->ihl << 2)))->dest
+				 : (iph->protocol == IPPROTO_TCP
+				    ? ((struct tcphdr*)((caddr_t)iph + (iph->ihl << 2)))->dest
+				    : 0));
+			for(i = 0;
+			    i < sizeof(struct sockaddr_in)
+				    - offsetof(struct sockaddr_in, sin_zero);
+			    i++) {
+				src.sin_zero[i] = 0;
+				dst.sin_zero[i] = 0;
+			}
+			
+			tdb.tdb_addr_s = (struct sockaddr*)(&src);
+			tdb.tdb_addr_d = (struct sockaddr*)(&dst);
+			KLIPS_PRINT(debug_tunnel & DB_TN_XMIT,
+				    "klips_debug:ipsec_tunnel_start_xmit: "
+				    "SADB_ACQUIRE sent with src=%s:%d, dst=%s:%d, proto=%d.\n",
+				    addrtoa(((struct sockaddr_in*)(tdb.tdb_addr_s))->sin_addr, 0, bufsrc, sizeof(bufsrc)) <= ADDRTOA_BUF ? bufsrc : "BAD_ADDR",
+				    ((struct sockaddr_in*)(tdb.tdb_addr_s))->sin_port,
+				    addrtoa(((struct sockaddr_in*)(tdb.tdb_addr_d))->sin_addr, 0, bufdst, sizeof(bufdst)) <= ADDRTOA_BUF ? bufdst : "BAD_ADDR",
+				    ((struct sockaddr_in*)(tdb.tdb_addr_d))->sin_port,
+				    tdb.tdb_said.proto);
+			pfkey_acquire(&tdb);
+
+			/* 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;
+			
+#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: "
+					    "calling breakeroute and makeroute for %s->%s HOLD eroute.\n",
+					    buf1, buf2);
+			}
+#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 ((error = ipsec_makeroute(&(hold_eroute.er_eaddr),
+						     &(hold_eroute.er_emask),
+						     hold_said))) {
+				KLIPS_PRINT(debug_pfkey,
+					    "klips_debug:ipsec_tunnel_start_xmit: "
+					    "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.
-		 */
-		spin_lock(&tdb_lock);
+		  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 +873,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 +882,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 +897,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 +908,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 +921,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 +936,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 +946,15 @@
 			}
 			if(tdbp->tdb_lifetime_bytes_s &&
 			   (tdbp->tdb_lifetime_bytes_c > tdbp->tdb_lifetime_bytes_s)) {
-				pfkey_expire(tdbp, 0);
+				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 +963,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 +974,15 @@
 			if(tdbp->tdb_lifetime_addtime_s &&
 			   ((jiffies / HZ) - tdbp->tdb_lifetime_addtime_c >
 			    tdbp->tdb_lifetime_addtime_s)) {
-				pfkey_expire(tdbp, 0);
+				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 +992,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 +1003,15 @@
 				if(tdbp->tdb_lifetime_usetime_s &&
 				   ((jiffies / HZ) - tdbp->tdb_lifetime_usetime_c >
 				    tdbp->tdb_lifetime_usetime_s)) {
-					pfkey_expire(tdbp, 0);
+					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 +1020,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 +1030,23 @@
 			}
 			if(tdbp->tdb_lifetime_packets_s &&
 			   (tdbp->tdb_lifetime_packets_c > tdbp->tdb_lifetime_packets_s)) {
-				pfkey_expire(tdbp, 0);
+				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:
@@ -1019,8 +1132,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,8 +1142,8 @@
 		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) {
@@ -1065,7 +1177,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 +1190,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 +1202,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 +1256,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 +1303,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
@@ -1259,9 +1373,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 +1384,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 +1400,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;
@@ -1540,10 +1653,14 @@
 				/* XXX use of skb->dst below is a questionable
 				   substitute for &rt->u.dst which is only
 				   available later-on */
-				ip_select_ident(iph, skb->dst);
-#else
+#ifdef IP_SELECT_IDENT_NEW
+				ip_select_ident(iph, skb->dst, NULL);
+#else /* IP_SELECT_IDENT_NEW */
+                                ip_select_ident(iph, skb->dst);
+#endif /* IP_SELECT_IDENT_NEW */
+#else /* IP_SELECT_IDENT */
 				iph->id       = htons(ip_id_count++);   /* Race condition here? */
-#endif
+#endif /* IP_SELECT_IDENT */
 
 				newdst = (__u32)iph->daddr;
 				newsrc = (__u32)iph->saddr;
@@ -1559,7 +1676,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 +1727,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 +1738,7 @@
 			tdbp->tdb_lifetime_usetime_l = jiffies / HZ;
 			tdbp->tdb_lifetime_packets_c += 1;
 
+			tdbprev = tdbp;
 			tdbp = tdbp->tdb_onext;
 			
 		}
@@ -1640,7 +1759,8 @@
 			outgoing_said.dst.s_addr &&
 			er &&
 			(debug_tunnel & DB_TN_XMIT),
-			"klips_debug:ipsec_tunnel_start_xmit: We are recursing here.\n");
+			"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 +1784,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;
@@ -1687,7 +1807,7 @@
 	skb->dev = physdev;
 	/*skb_orphan(skb);*/
 #ifdef NETDEV_23
-	if(sysctl_ipsec_no_eroute_pass) {
+	if(pass) {
 		/* zero the saddr used in ip_route_output */
 		route_saddr=0;
 	}else{
@@ -1719,9 +1839,9 @@
 	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",
+		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++;
 		goto cleanup;
@@ -1746,7 +1866,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,9 +1875,9 @@
 			goto cleanup;
 		}
 	}
-#else
+#else /* NETDEV_23 */
 	ip_send(skb);
-#endif
+#endif /* NETDEV_23 */
 #else /* NET_21 */
 	skb->arp = 1;
 	/* ISDN/ASYNC PPP from Matjaz Godec. */
@@ -1772,9 +1893,9 @@
  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
+#endif /* defined(HAS_NETIF_QUEUE) || defined (HAVE_NETIF_QUEUE) */
 	if(saved_header)
 		kfree(saved_header);
 	if(skb) {
@@ -1820,9 +1941,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",
@@ -1840,9 +1964,13 @@
 #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,
@@ -1882,8 +2010,7 @@
 	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,
@@ -1934,8 +2061,7 @@
 	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;
 	}
@@ -1958,8 +2084,7 @@
 	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);
 		return;
 	}
@@ -1981,8 +2106,7 @@
 	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;
 	}
@@ -2168,7 +2292,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);
@@ -2267,7 +2391,8 @@
 	{
 		case NETDEV_DOWN:
 			KLIPS_PRINT(debug_tunnel & DB_TN_INIT,
-				    "ipsec_device_event: NETDEV_DOWN...\n");
+				    "klips_debug:ipsec_device_event: "
+				    "NETDEV_DOWN...\n");
 			/* find the attached physical device and detach it. */
 			for(i = 0; i < IPSEC_NUM_IF; i++) {
 				sprintf(name, "ipsec%d", i);
@@ -2284,7 +2409,8 @@
 						}
 					} 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);
 					}
 				}
@@ -2293,7 +2419,8 @@
 			break;
 		case NETDEV_UP:
 			KLIPS_PRINT(debug_tunnel & DB_TN_INIT,
-				    "ipsec_device_event: NETDEV_UP...\n");
+				    "klips_debug:ipsec_device_event: "
+				    "NETDEV_UP...\n");
 			/* Only handle ethernet ports */
 			if(dev->type!=ARPHRD_ETHER && dev->type!=ARPHRD_LOOPBACK)
 				return NOTIFY_DONE;
@@ -2302,7 +2429,8 @@
 #ifdef NET_21
 		case NETDEV_UNREGISTER:
 			KLIPS_PRINT(debug_tunnel & DB_TN_INIT,
-				    "ipsec_device_event: NETDEV_UNREGISTER...\n");
+				    "klips_debug:ipsec_device_event: "
+				    "NETDEV_UNREGISTER...\n");
 
 			break;
 #endif /* NET_21 */
@@ -2320,8 +2448,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 +2642,44 @@
 
 /*
  * $Log: ipsec_tunnel.c,v $
- * Revision 1.137.2.1  2001/02/27 00:51:00  henry
- * message improvements
+ * 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
diff -ruN 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	Wed May 16 10:57:20 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.50 2001/05/03 19:43:18 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);
 
@@ -101,25 +101,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 +138,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 +156,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 +172,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 +219,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 +228,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,7 +311,7 @@
 {
 	int alg;
 	struct xformsw *xsp;
-	int len;
+	int error = 0;
         int i;
 #if defined(CONFIG_IPSEC_ENC_3DES)
         int error;
@@ -295,23 +322,28 @@
 
 	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 +395,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 +422,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 +455,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 +489,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 +516,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 +547,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],
@@ -570,8 +604,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);
 				}
@@ -600,8 +634,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 +651,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 +660,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);
@@ -653,8 +690,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 +706,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 +736,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],
@@ -726,8 +764,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 +779,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 +807,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],
@@ -795,18 +834,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 +860,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 +873,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 +947,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 +1018,19 @@
 
 /*
  * $Log: ipsec_xform.c,v $
+ * 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.
  *
diff -ruN 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	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_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 -ruN 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	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_parser.c,v 1.68.2.1 2001/02/27 00:51:01 henry Exp $
+ * RCSID $Id: pfkey_v2_parser.c,v 1.80 2001/05/03 19:43:59 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.80 2001/05/03 19:43:59 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,
@@ -171,7 +175,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 +206,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 +333,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 +359,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 +369,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 +381,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 +390,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 +421,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 +430,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 +439,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 +448,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 +457,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 +476,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 +506,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 +557,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 +659,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 +673,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 +688,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 +703,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 +714,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 +730,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 +744,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 +767,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,11 +794,9 @@
 			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");
+			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");
+			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;
 			debug_xform   &= pfkey_x_debug->sadb_x_debug_xform;
@@ -773,7 +813,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 +829,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 +841,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 +877,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 +903,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 +933,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],
@@ -896,29 +945,31 @@
 				    ((__u32*)octx)[3] );
 #  endif
 			
-				/* zero key buffer -- paranoid */
-			memset(akp, 0, DIVUP(tdbp->tdb_key_bits_a, BITS_PER_OCTET));
+			/* zero key buffer -- paranoid */
+			memset(akp, 0, aks);
+			kfree(akp);
 		}
 		break;
 # endif /* CONFIG_IPSEC_AUTH_HMAC_MD5 */
 # ifdef CONFIG_IPSEC_AUTH_HMAC_SHA1
 		case AH_SHA: {
-			
 			unsigned char *akp;
+			unsigned int aks;
 			SHA1_CTX *ictx;
 			SHA1_CTX *octx;
 			
 			if(tdbp->tdb_key_bits_a != (AHSHA196_KLEN * 8)) {
 				KLIPS_PRINT(debug_pfkey,
-					    "klips_debug:pfkey_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,13 +980,15 @@
 			
 			/* 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 +1010,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],
@@ -968,8 +1021,9 @@
 				    ((__u32*)octx)[2],
 				    ((__u32*)octx)[3] );
 #  endif			
-				/* zero key buffer -- paranoid */
-			memset(akp, 0, DIVUP(tdbp->tdb_key_bits_a, BITS_PER_OCTET));
+			/* zero key buffer -- paranoid */
+			memset(akp, 0, aks);
+			kfree(akp);
 		}
 		break;
 # endif /* CONFIG_IPSEC_AUTH_HMAC_SHA1 */
@@ -985,6 +1039,7 @@
 #ifdef CONFIG_IPSEC_ESP
 	case IPPROTO_ESP: {
 		unsigned char *akp, *ekp;
+		unsigned int aks, eks;
 		
 		switch(tdbp->tdb_encalg) {
 # ifdef CONFIG_IPSEC_ENC_3DES
@@ -1017,46 +1072,51 @@
 		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 */
 				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)));
+					    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
@@ -1080,15 +1140,17 @@
 
 			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 */
 			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)),
@@ -1098,13 +1160,15 @@
 			
 			/* 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 +1190,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 +1202,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 +1214,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,13 +1234,15 @@
 			
 			/* 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 +1264,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 +1275,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 +1316,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 +1341,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 +1354,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 +1367,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 +1398,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 +1413,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 +1435,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 +1444,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 +1465,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 +1512,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 +1534,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 +1547,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 +1558,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 +1569,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,12 +1580,13 @@
 		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);
 	}
 
 	spin_unlock_bh(&tdb_lock);
-
+	
 	if(!(pfkey_safe_build(error = pfkey_msg_hdr_build(&extensions_reply[0],
 							  SADB_UPDATE,
 							  satype,
@@ -1587,36 +1678,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 +1733,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 +1755,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 +1776,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 +1877,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 +1930,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 +1949,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 +1959,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 +1968,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 +2005,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 +2046,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 +2062,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 +2071,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 +2198,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 +2206,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 +2236,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 +2248,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 +2260,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 +2295,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 +2309,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 +2345,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 +2355,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 +2394,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 +2424,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 +2478,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 +2503,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 +2529,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 +2597,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 +2605,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 +2640,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 +2684,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,34 +2704,36 @@
 							     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)),
-				 extensions_reply)
-	     && pfkey_safe_build(error = pfkey_sa_build(&extensions_reply[SADB_X_EXT_SA2],
-							SADB_X_EXT_SA2,
-							extr->tdb2->tdb_said.spi,
-							extr->tdb2->tdb_replaywin,
-							extr->tdb2->tdb_state,
-							extr->tdb2->tdb_authalg,
-							extr->tdb2->tdb_encalg,
-							extr->tdb2->tdb_flags),
-				 extensions_reply)
-	     && pfkey_safe_build(error = pfkey_address_build(&extensions_reply[SADB_X_EXT_ADDRESS_DST2],
-							     SADB_X_EXT_ADDRESS_DST2,
-							     0, /*extr->tdb->tdb_said.proto,*/
-							     0,
-							     extr->tdb2->tdb_addr_d),
-				 extensions_reply)
+	     && (extr->tdb2
+		 ? (pfkey_safe_build(error = pfkey_x_satype_build(&extensions_reply[SADB_X_EXT_SATYPE2],
+								  ((struct sadb_x_satype*)extensions[SADB_X_EXT_SATYPE2])->sadb_x_satype_satype
+								  /* proto2satype(extr->tdb2->tdb_said.proto) */),
+								  extensions_reply)
+				     && pfkey_safe_build(error = pfkey_sa_build(&extensions_reply[SADB_X_EXT_SA2],
+										SADB_X_EXT_SA2,
+										extr->tdb2->tdb_said.spi,
+										extr->tdb2->tdb_replaywin,
+										extr->tdb2->tdb_state,
+										extr->tdb2->tdb_authalg,
+										extr->tdb2->tdb_encalg,
+										extr->tdb2->tdb_flags),
+							 extensions_reply)
+				     && pfkey_safe_build(error = pfkey_address_build(&extensions_reply[SADB_X_EXT_ADDRESS_DST2],
+										     SADB_X_EXT_ADDRESS_DST2,
+										     0, /*extr->tdb->tdb_said.proto,*/
+										     0,
+										     extr->tdb2->tdb_addr_d),
+							 extensions_reply) ) : 1 )
 		     )) {
 		KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_grpsa_parse: "
 			    "failed to build the x_grpsa reply message extensions\n");
-		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 +2741,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;
 }
 
@@ -2686,7 +2849,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 +2904,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 +2918,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 +3024,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 +3065,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 +3079,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 +3125,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 +3193,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 +3210,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:
@@ -3063,7 +3255,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 +3269,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 +3339,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 +3356,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 +3441,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 +3501,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 +3525,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 +3540,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 +3565,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 +3588,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 +3603,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 +3622,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 +3635,69 @@
 	}
 #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.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().
diff -ruN 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	Wed May 16 10:57:20 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 -ruN 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	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: 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 -ruN 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 May 17 14:34:12 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.17 2000/11/30 05:02:51 henry Exp $ */
+static const char freeswan_version[] = "FreeSWAN-1.9-pkix1";
diff -ruN 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	Wed May 16 10:57:20 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 -ruN 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	Wed May 16 10:57:20 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 -ruN 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 May 17 14:34: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.17 2000/11/30 05:02:51 henry Exp $ */
+static const char freeswan_version[] = "FreeSWAN-1.9-pkix1";
diff -ruN 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 -ruN 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 -ruN 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 -ruN 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 -ruN 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 -ruN 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 -ruN 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 -ruN 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	Wed May 16 10:57:20 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.10 2001/02/26 23:23: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 }
 };
 
diff -ruN 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 -ruN 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 -ruN 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"
@@ -25,10 +25,26 @@
 	{ "ah",		2,	SA_AH	},
 	{ "esp",	3,	SA_ESP	},
 	{ "tun",	3,	SA_IPIP },
-	{ "comp",	4,	SA_COMP },
+	{ "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 -ruN 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 -ruN 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	Wed May 16 10:57:20 2001
@@ -1,7 +1,63 @@
 Changes to Pluto
 ================
 
+Changes since 1.9 release by D. Hugh Redelmeier <hugh@mimosa.com>
+
+[In a state of flux, to put it mildly.]
+
+- 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.
+
+- support for TRAP eroute when a potential connection is --routed.
+  Mostly useful for opportunistic connections.
+
+  + a default route is directed at the ipsecN interface (so
+    that KLIPS can catch the packets).  Note that the
+    source address is not taken into account!
+
+  + a matching magic eroute is installed to handle the packets
+    in the absence of a negotiated tunnel.  The default is
+    a trap eroute, but the --pass and --drop can change this
+    (--pass, and --drop are obvious; together they mean reject).
+    Note that the source address is taken into account.
+
+  + the logic of routing and erouting has been redesigned.
+
+  Missing logic: when negotiation fails, a magic eroute should be
+  installed for a controlled period of time.  The kind should be
+  selected by policy: trap, pass, hold, drop, or reject.
+
+- 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 -ruN 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	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.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
 
@@ -104,11 +128,11 @@
 	 pluto.8 ipsec.secrets.5
 
 DISTGCRYPT = \
-	gcryptfix.c gcryptfix.h \
-	dsa.c dsa.h \
-	elgamal.c elgamal.h \
-	primegen.c \
-	smallprime.c
+        gcryptfix.c gcryptfix.h \
+        g10_dsa.c g10_dsa.h \
+        elgamal.c elgamal.h \
+        primegen.c \
+        smallprime.c
 
 DISTSRC = \
 	connections.c connections.h \
@@ -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 -ruN freeswan-1.9.orig/pluto/TODO freeswan-1.9/pluto/TODO
--- freeswan-1.9.orig/pluto/TODO	Sun Dec 17 12:37:03 2000
+++ freeswan-1.9/pluto/TODO	Wed May 16 10:57:20 2001
@@ -75,7 +75,7 @@
 
 - we need better policy control.  Our present flags need to be
   modulated (forbid, allow, offer, require)
-  
+
 - HS will specify how --copyright and --version should behave
 
 - HS will initiate project-wide terminology replacing ISAKMP SA, IPSEC
diff -ruN 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 May 16 11:41:27 2001
@@ -42,6 +42,11 @@
 #include "dnskey.h"	/* needs preshared.h */
 #include "whack.h"
 
+#ifdef OPENSSL
+#include "openssl.h"
+#include "xmap.h"
+#endif
+
 static struct connection *connections = NULL;
 
 /* host_pair: a nexus of information about a pair of hosts.
@@ -296,6 +301,20 @@
     }
     unorient_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);
     cur_connection = old_cur_connection;
@@ -462,12 +481,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 +605,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 +625,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 +651,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;
 
@@ -595,6 +678,35 @@
 	    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;
 	connections = c;
@@ -618,9 +730,10 @@
 
 	possibly_some_oppo = TRUE;	/* could be more careful about this */
 
-	/* log all about this connection */
-	log("added connection description \"%s\"", c->name);
-	DBG(DBG_CONTROL,
+	/* 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];
 	    char rhs[SUBNETTOT_BUF + ADDRTOT_BUF + IDTOA_BUF + ADDRTOT_BUF];
 
@@ -650,7 +763,16 @@
 		, (unsigned long) c->sa_rekey_fuzz
 		, (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);
+	}
     }
 }
 
@@ -1205,7 +1327,13 @@
 	    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
 	my_RSA_pri = get_RSA_private_key(c);
 	if (my_RSA_pri == NULL)
 	    return NULL;	/* cannot determine my RSA private key! */
@@ -1216,6 +1344,14 @@
 		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);
     }
@@ -1235,6 +1371,28 @@
 	    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;
+
+                  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
+
 	    if (!same_id(&c->this.id, &d->this.id))
 		continue;
 
@@ -1273,8 +1431,39 @@
 			 * so we must be sure that any connection we
 			 * select will use the same public key.
 			 */
-			const struct RSA_public_key *hnk = exact
-			    ? get_his_RSA_public_key(d) : get_RSA_public_key(peer_id);
+			const struct RSA_public_key *hnk;
+#ifdef OPENSSL
+		      if (!use_openssl(st->st_connection)) {
+#endif
+			hnk = exact ? get_his_RSA_public_key(d) 
+			  : get_RSA_public_key(peer_id);
+#ifdef OPENSSL
+		      } else {
+		        hnk = exact ? get_his_RSA_public_key(d) 
+		          : fs_RSA(X509_get_pubkey((X509 *)d->other));
+		      }
+#endif
+			passert(exact || d->gw_info == NULL);
+
+			if (!same_RSA_public_key(his_RSA_pub, hnk))
+			    continue;	/* different public key */
+		    }
+		    break;
+#ifdef OPENSSL
+		case OAKLEY_RSA_ENC:
+		case OAKLEY_RSA_ENC_REV:
+		    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.
+			 */
+		        const struct RSA_public_key *hnk = exact
+		          ? get_his_RSA_public_key(d) 
+		          : fs_RSA(X509_get_pubkey((X509 *)d->other));
 
 			passert(exact || d->gw_info == NULL);
 
@@ -1282,6 +1471,7 @@
 			    continue;	/* different public key */
 		    }
 		    break;
+#endif
 		default:
 		    passert(FALSE);
 		}
diff -ruN 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 May 16 10:57:20 2001
@@ -14,6 +14,10 @@
  * RCSID $Id: connections.h,v 1.43 2001/01/28 21:03:02 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)
@@ -78,6 +82,13 @@
  * the old one.  It is deleted when no longer in use.
  */
 
+#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 +103,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;
diff -ruN 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 May 16 10:57:20 2001
@@ -283,13 +283,38 @@
 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",
diff -ruN 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 May 16 10:57:20 2001
@@ -460,17 +460,45 @@
 #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
+ * (eg PFS) required of an SA.  POLICY_PSK and POLICY_RSASIG/OPENSSL are for
  * ISAKMP SAs; the rest are about IPsec SAs
  */
 
 extern const char *const sa_policy_bit_names[];
 
 #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)
@@ -479,7 +507,11 @@
 #define POLICY_PFS           LELEM(6)
 
 #define POLICY_ISAKMP_SHIFT	0	/* log2(POLICY_PSK) */
+#ifndef OPENSSL
 #define POLICY_ISAKMP_MASK	(POLICY_PSK | POLICY_RSASIG)
+#else
+#define POLICY_ISAKMP_MASK	(POLICY_PSK | POLICY_OPENSSL)
+#endif
 #define POLICY_IPSEC_SHIFT	2	/* log2(POLICY_ENCRYPT) */
 
 /* Oakley transform attributes
@@ -547,6 +579,12 @@
 #define SA_REPLACEMENT_RETRIES_DEFAULT	    3	/*  (IPSEC & IKE) */
 
 #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 */
 
diff -ruN 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 -ruN 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 -ruN 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 -ruN 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	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: 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! */
@@ -37,8 +37,8 @@
  * Needed in connections.h and state.h; here to simplify dependencies.
  */
 typedef unsigned long so_serial_t;
-#define SOS_NOBODY  0	/* null serial number */
-
+#define SOS_NOBODY	0	/* null serial number */
+#define SOS_FIRST	1	/* first normal serial number */
 
 /* memory allocation */
 
@@ -59,6 +59,22 @@
 #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;
+
+#if 0 /* *Please* don't define this - you *really* don't want single DES */
+  des_key_schedule des_ks;
+#endif
+
+#ifdef NOTYET
+  /* Other ciphers, eg CAST, RC5, etc... */
+#endif
+
+} keysched;
+#endif
 
 /* chunk is a simple pointer-and-size abstraction */
 
@@ -83,6 +99,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 +124,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 -ruN 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	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: demux.c,v 1.95 2001/01/24 23:09:33 dhr Exp $
+ * RCSID $Id: demux.c,v 1.103 2001/05/05 02:51:37 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.
  */
@@ -190,7 +194,7 @@
 
 /* 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.
@@ -241,11 +245,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 +275,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 +303,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 +329,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
@@ -749,7 +787,7 @@
 		}
 
 	    }
-#endif /* defined(IP_RECVERR) && defined(MSG_ERRQUEUE) */ 
+#endif /* defined(IP_RECVERR) && defined(MSG_ERRQUEUE) */
 	    return;
 	}
 	else if (from_ugh != NULL)
@@ -1241,6 +1279,8 @@
 	    {
 		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 +1293,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);
@@ -1396,25 +1697,25 @@
 	{
 	    loglog(RC_LOG_SERIOUS, "ignoring informational payload, type %s"
 		, enum_show(&ipsec_notification_names, p->payload.notification.isan_type));
-	    DBG_cond_dump(DBG_PARSING, "info:", p->pbs.cur, pbs_left(&p->pbs));
+	    DBG_cond_dump(DBG_RAW, "info:", p->pbs.cur, pbs_left(&p->pbs));
 	}
 
 	for (p = md.chain[ISAKMP_NEXT_D]; p != NULL; p = p->next)
 	{
 	    loglog(RC_LOG_SERIOUS, "ignoring Delete SA payload");
-	    DBG_cond_dump(DBG_PARSING, "del:", p->pbs.cur, pbs_left(&p->pbs));
+	    DBG_cond_dump(DBG_RAW, "del:", p->pbs.cur, pbs_left(&p->pbs));
 	}
 
 	for (p = md.chain[ISAKMP_NEXT_VID]; p != NULL; p = p->next)
 	{
 	    loglog(RC_LOG_SERIOUS, "ignoring Vendor ID payload");
-	    DBG_cond_dump(DBG_PARSING, "VID:", p->pbs.cur, pbs_left(&p->pbs));
+	    DBG_cond_dump(DBG_RAW, "VID:", p->pbs.cur, pbs_left(&p->pbs));
 	}
 
 	for (p = md.chain[ISAKMP_NEXT_CERT]; p != NULL; p = p->next)
 	{
 	    loglog(RC_LOG_SERIOUS, "ignoring Certificate payload");
-	    DBG_cond_dump(DBG_PARSING, "CERT:", p->pbs.cur, pbs_left(&p->pbs));
+	    DBG_cond_dump(DBG_RAW, "CERT:", p->pbs.cur, pbs_left(&p->pbs));
 	}
     }
 
@@ -1598,13 +1899,13 @@
 
 		if (result == STF_UNPEND_QUICK && md.st->st_pending_quick)
 		{
-		    struct connection *c = md.st->st_connection;
+                   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;
+                   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;
 		}
 
 		if (IS_ISAKMP_SA_ESTABLISHED(md.st->st_state)
@@ -1635,9 +1936,9 @@
 		md.st = NULL;
 		break;
 
-	    case STF_DROP_DOOMED_EXCHANGE:
+	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");
+		  " handling DH shared secret with leading zero byte");
 		delete_event(md.st);
 		delete_state(md.st);
 		md.st = NULL;
@@ -1666,3 +1967,306 @@
     }
     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) {
+#if 0
+    /* 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;
+#endif
+#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) {
+#if 0
+    /* 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;
+#endif
+#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) {
+#if 0
+  case OAKLEY_DES_CBC:
+    blocklen = DES_CBC_BLOCK_SIZE;
+    break;
+#endif
+#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) {
+#if 0
+  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;
+#endif
+#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) {
+#if 0
+  case OAKLEY_DES_CBC:
+    blocklen = DES_CBC_BLOCK_SIZE;
+    break;
+#endif
+#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) {
+#if 0
+  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;
+#endif
+#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 -ruN 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	Wed May 16 10:57:20 2001
@@ -77,3 +77,15 @@
 } 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 -ruN 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 -ruN 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 -ruN 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 -ruN 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 -ruN 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 -ruN 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 May 16 10:57:20 2001
@@ -11,31 +11,43 @@
  * 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;
@@ -56,11 +68,70 @@
     {
 	if (*src == '@')
 	{
-	    id->kind = ID_FQDN;
-	    id->name.ptr = src+1;	/* discard @ */
+#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,6 +143,25 @@
     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)
 {
@@ -86,8 +176,17 @@
 	return snprintf(dst, dstlen, "@%.*s", (int)id->name.len, id->name.ptr);
     case ID_USER_FQDN:
 	return snprintf(dst, dstlen, "%.*s", (int)id->name.len, id->name.ptr);
+#ifdef OPENSSL
+    case ID_KEY_ID:
+        return snprintf(dst, dstlen, "@#%.*s", (int)id->key_id.len,
+          id->key_id.ptr);
+    case ID_DER_ASN1_DN:
+        return snprintf(dst, dstlen, "@~%.*s", (int)id->der_asn1_dn.len,
+          id->der_asn1_dn.ptr);
+#endif
     default:
 	return snprintf(dst, dstlen, "unknown id kind %d", id->kind);
+	break;
     }
 }
 
@@ -112,8 +211,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 +251,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 +287,18 @@
 
     case ID_FQDN:
     case ID_USER_FQDN:
+#ifdef OPENSSL
+    case ID_KEY_ID:
 	/* assumption: case should be ignored */
 	return a->name.len == b->name.len
 	    && strncasecmp(a->name.ptr, b->name.ptr, a->name.len) == 0;
-
+    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);
     }
@@ -201,7 +330,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 -ruN 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	Wed May 16 10:57:20 2001
@@ -11,12 +11,16 @@
  * 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;
 };
@@ -24,6 +28,7 @@
 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) */
@@ -32,7 +37,11 @@
 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 -ruN 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	Thu May 17 11:09:08 2001
@@ -12,7 +12,7 @@
  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  * for more details.
  *
- * RCSID $Id: ipsec_doi.c,v 1.120 2001/01/28 21:03:04 dhr Exp $
+ * RCSID $Id: ipsec_doi.c,v 1.131 2001/05/08 05:37:21 dhr Exp $
  */
 
 #include <stdio.h>
@@ -49,18 +49,117 @@
 #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; }
 
+stf_status send_delete(struct state *p2st, ipsec_spi_t *spi, bool ESP);
+static bool encrypt_message(pb_stream *pbs, struct state *st);
+
+/* 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);
+    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_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];
+      MP_INT mp_g;
+
+      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);
+      *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 */
+          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);
+      }
+#endif
+
+      DBG(DBG_CRYPT,
+      DBG_dump("Local DH secret:\n", tmp, LOCALSECRETSIZE);
+      DBG_dump_chunk("Public DH value sent:\n", *g);
+      );
+    }
+    /* 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
+
 /* 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 bool
 build_and_ship_KE(struct state *st, chunk_t *g
-    , const struct oakley_group_desc *group, pb_stream *outs, u_int8_t np)
+, const struct oakley_group_desc *group, pb_stream *outs, u_int8_t np)
 {
     if (!st->st_sec_in_use)
     {
@@ -89,36 +188,13 @@
 #endif
 
 	DBG(DBG_CRYPT,
-	    DBG_dump("Local DH secret:\n", tmp, LOCALSECRETSIZE);
-	    DBG_dump_chunk("Public DH value sent:\n", *g));
+	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");
 }
 
-/* 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);
-    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);
-}
-
 /* accept_ke
  *
  * Check and accept DH public value (Gi or Gr) from peer's message.
@@ -131,7 +207,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 +232,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 +265,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
@@ -203,64 +299,181 @@
  * XXX Not modified to support ip_address and related (IPv4+IPv6) functions.
  */
 #if 0 /* not currently used */
-//static void
-//send_notification(int sock,
-//    u_int16_t type,
-//    u_char *spi,
-//    u_char spilen,
-//    u_char protoid,
-//    u_char *icookie,
-//    u_char *rcookie,
-//    msgid_t /*network order*/ msgid,
-//    struct sockaddr sa)
-//{
-//    u_char buffer[sizeof(struct isakmp_hdr) +
-//		 sizeof(struct isakmp_notification)];
-//    struct isakmp_hdr *isa = (struct isakmp_hdr *) buffer;
-//    struct isakmp_notification *isan = (struct isakmp_notification *)
-//				       (buffer + sizeof(struct isakmp_hdr));
-//
-//    memset(buffer, '\0', sizeof(struct isakmp_hdr) +
-//	  sizeof(struct isakmp_notification));
-//
-//    if (icookie != (u_char *) NULL)
-//	memcpy(isa->isa_icookie, icookie, COOKIE_SIZE);
-//
-//    if (rcookie != (u_char *) NULL)
-//	memcpy(isa->isa_rcookie, rcookie, COOKIE_SIZE);
-//
-//    /* Standard header */
-//    isa->isa_np = ISAKMP_NEXT_N;
-//    isa->isa_version = ISAKMP_MAJOR_VERSION << ISA_MAJ_SHIFT | ISAKMP_MINOR_VERSION;
-//    isa->isa_xchg = ISAKMP_XCHG_INFO;
-//    isa->isa_msgid = msgid;
-//    isa->isa_length = htonl(sizeof(struct isakmp_hdr) +
-//			    sizeof(struct isakmp_notification) +
-//			    spilen);
-//
-//    /* Notification header */
-//    isan->isan_type = htons(type);
-//    isan->isan_doi = htonl(ISAKMP_DOI_IPSEC);
-//    isan->isan_length = htons(sizeof(struct isakmp_notification) + spilen);
-//    isan->isan_spisize = spilen;
-//    memcpy((u_char *)isan + sizeof(struct isakmp_notification), spi, spilen);
-//    isan->isan_protoid = protoid;
-//
-//    DBG(DBG_CONTROL, DBG_log("sending INFO type %s to %s",
-//	enum_show(&notification_names, type),
-//	show_sa(&sa)));
-//
-//    if (sendto(sock, buffer, ntohl(isa->isa_length), 0, &sa,
-//	       sizeof(sa)) != ntohl(isa->isa_length))
-//	log_errno((e, "sendto() failed in send_notification() to %s",
-//	    show_sa(&sa)));
-//    else
-//    {
-//	DBG(DBG_CONTROL, DBG_log("transmitted %d bytes", ntohl(isa->isa_length)));
-//    }
-//}
+static void
+send_notification(int sock,
+    u_int16_t type,
+    u_char *spi,
+    u_char spilen,
+    u_char protoid,
+    u_char *icookie,
+    u_char *rcookie,
+    msgid_t /*network order*/ msgid,
+    struct sockaddr sa)
+{
+    u_char buffer[sizeof(struct isakmp_hdr) +
+		 sizeof(struct isakmp_notification)];
+    struct isakmp_hdr *isa = (struct isakmp_hdr *) buffer;
+    struct isakmp_notification *isan = (struct isakmp_notification *)
+				       (buffer + sizeof(struct isakmp_hdr));
+
+    memset(buffer, '\0', sizeof(struct isakmp_hdr) +
+	  sizeof(struct isakmp_notification));
+
+    if (icookie != (u_char *) NULL)
+	memcpy(isa->isa_icookie, icookie, COOKIE_SIZE);
+
+    if (rcookie != (u_char *) NULL)
+	memcpy(isa->isa_rcookie, rcookie, COOKIE_SIZE);
+
+    /* Standard header */
+    isa->isa_np = ISAKMP_NEXT_N;
+    isa->isa_version = ISAKMP_MAJOR_VERSION << ISA_MAJ_SHIFT | ISAKMP_MINOR_VERSION;
+    isa->isa_xchg = ISAKMP_XCHG_INFO;
+    isa->isa_msgid = msgid;
+    isa->isa_length = htonl(sizeof(struct isakmp_hdr) +
+			    sizeof(struct isakmp_notification) +
+			    spilen);
+
+    /* Notification header */
+    isan->isan_type = htons(type);
+    isan->isan_doi = htonl(ISAKMP_DOI_IPSEC);
+    isan->isan_length = htons(sizeof(struct isakmp_notification) + spilen);
+    isan->isan_spisize = spilen;
+    memcpy((u_char *)isan + sizeof(struct isakmp_notification), spi, spilen);
+    isan->isan_protoid = protoid;
+
+    DBG(DBG_CONTROL, DBG_log("sending INFO type %s to %s",
+	enum_show(&notification_names, type),
+	show_sa(&sa)));
+
+    if (sendto(sock, buffer, ntohl(isa->isa_length), 0, &sa,
+	       sizeof(sa)) != ntohl(isa->isa_length))
+	log_errno((e, "sendto() failed in send_notification() to %s",
+	    show_sa(&sa)));
+    else
+    {
+	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 +493,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,
+       bool pending_quick,
+       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,6 +505,10 @@
 
     struct state *st;
 
+    DBG(DBG_PARSING,
+    DBG_log("in main_outI1");
+    );
+
     /* set up new state */
     cur_state = st = new_state();
     st->st_connection = c;
@@ -300,7 +516,7 @@
     extra_debugging(c);
 #endif
     st->st_pending_quick = pending_quick;
-    st->st_policy = policy;
+    st->st_policy = policy; 
     st->st_whack_sock = whack_sock;
     st->st_try = try;
     st->st_state = STATE_MAIN_I1;
@@ -318,7 +534,7 @@
     {
 	struct isakmp_hdr hdr;
 
-	memset(&hdr, '\0', sizeof(hdr));	/* default to 0 */
+	memset(&hdr, '\0', sizeof(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;
@@ -345,7 +561,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 +576,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 +600,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) */
@@ -385,7 +626,7 @@
     event_schedule(EVENT_RETRANSMIT, EVENT_RETRANSMIT_DELAY_0, st);
 
     whack_log(RC_NEW_STATE + STATE_MAIN_I1
-	, "%s: initiate", enum_name(&state_names, st->st_state));
+       , "%s: initiate", enum_name(&state_names, st->st_state));
     cur_state = NULL;
     return STF_NO_REPLY;
 }
@@ -414,11 +655,11 @@
     }
     else if (pending_quick)
     {
-	/* ??? we assume that peer_nexthop_sin isn't important:
-	 * we already have it from when we negotiated the ISAKMP SA!
-	 * It isn't clear what to do with the error return.
-	 */
-	(void) quick_outI1(whack_sock, st, c, policy, try);
+       /* ??? we assume that peer_nexthop_sin isn't important:
+        * we already have it from when we negotiated the ISAKMP SA!
+        * It isn't clear what to do with the error return.
+        */
+       (void) quick_outI1(whack_sock, st, c, policy, try);
     }
     else if (whack_sock != NULL_FD)
     {
@@ -443,8 +684,7 @@
 
     if (IS_PHASE1(st->st_state))
     {
-	(void) main_outI1(whack_sock, st->st_connection, st->st_pending_quick
-	    , policy, try);
+        (void) main_outI1(whack_sock, st->st_connection, st->st_pending_quick, policy, try);
     }
     else
     {
@@ -522,6 +762,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 +833,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 +1036,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 +1244,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 +1344,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);
 
@@ -1163,12 +1472,12 @@
 }
 
 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 */
@@ -1294,6 +1603,11 @@
     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 main_outI1");
+    );
+
     return STF_NO_REPLY;
 }
 
@@ -1308,6 +1622,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 +1651,7 @@
 	return FALSE;
     }
 
+
     /* XXX Check for valid ID types? */
     peer.kind = id->isaid_idtype;
 
@@ -1361,9 +1685,9 @@
     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));
-	    return FALSE;
+	  loglog(RC_LOG_SERIOUS, "Phase 1 ID Payload of type %s contains a NULL"
+	    ,enum_show(&ident_names, peer.kind));
+	  return FALSE;
 	}
 
 	/* ??? ought to do some more sanity check, but what? */
@@ -1371,6 +1695,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 +1776,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,6 +1786,7 @@
 		enum_show(&ident_names, id->isaid_idtype),
 		buf);
 	});
+#endif
 
     /* now that we've decoded the ID payload, let's see if we
      * need to switch connections.
@@ -1419,10 +1815,29 @@
 		/* 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;
@@ -1432,6 +1847,7 @@
  * This is designed for packets that identify clients, not peers.
  */
 static bool
+
 decode_net_id(
     struct isakmp_ipsec_id *id,
     pb_stream *id_pbs,
@@ -1795,6 +2211,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 */
@@ -1872,12 +2292,17 @@
     }
 
     /* SA body in and out */
-    RETURN_STF_FAILURE(parse_isakmp_sa_body(&sa_pd->pbs, &sa_pd->payload.sa, &r_sa_pbs
-	    , FALSE, st));
+    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()");
+    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;
 }
@@ -1895,50 +2320,270 @@
 stf_status
 main_inR1_outI2(struct msg_digest *md)
 {
-    struct state *const st = md->st;
-
-    /* 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));
-    }
+  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));
+  }
+
+  /* 
+   * 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;
+      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;
+      r_hdr.isa_np = ISAKMP_NEXT_KE;
+      if (!out_struct(&r_hdr, &isakmp_hdr_desc, &md->reply, &md->rbody))
+        return STF_INTERNAL_ERROR;
     }
 
     /* KE out */
-    if (!build_and_ship_KE(st, &st->st_gi, st->st_oakley.group
-    , &md->rbody, ISAKMP_NEXT_NONCE))
-	return STF_INTERNAL_ERROR;
-
+    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));
+	}
 
-    /* finish message */
-    close_message(&md->rbody);
+        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
 
-    /* Reinsert the state, using the responder cookie we just received */
-    unhash_state(st);
-    memcpy(st->st_rcookie, md->hdr.isa_rcookie, COOKIE_SIZE);
-    insert_state(st);	/* needs cookies, connection, and msgid (0) */
+  /* finish message */
+  close_message(&md->rbody);
 
-    st->st_state = STATE_MAIN_I2;
+  /* Reinsert the state, using the responder cookie we just received */
+  unhash_state(st);
+  memcpy(st->st_rcookie, md->hdr.isa_rcookie, COOKIE_SIZE);
+  insert_state(st);	/* needs cookies, connection, and msgid (0) */
 
-    return STF_REPLY;
+  st->st_state = STATE_MAIN_I2;
+
+  DBG(DBG_PARSING,
+  DBG_log("finished main_inR1_outI2");
+  );
+
+  return STF_REPLY;
 }
 
 /* STATE_MAIN_R1:
@@ -1957,6 +2602,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 +2635,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_DROP_DOOMED_EXCHANGE;
 #endif
+
     if (!generate_skeyids_iv(st))
 	return STF_FAIL + AUTHENTICATION_FAILED;
     update_iv(st);
@@ -1995,64 +2645,470 @@
     /* 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);
+    /** build output packet HDR;KE;<IDir_b>_PubKey_i;<Nr_b>PubKey_i*********/
+
+    /* 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;
+
+    {
+      /* <IDir_b>PubKey_i out */
+      chunk_t ch;
+      
+      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));
+      }
+
+
+      /* 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);
+    }
+    
+    /* 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;
+
+    /* finish message */
+    close_message(&md->rbody);
+
+    /* next message will be encrypted, but not this one.
+     * We could defer this calculation.
+     */
+    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_REPLACE_DOOMED_EXCHANGE;
+        if (st->st_shared.ptr[0] == 0)
+            return STF_DROP_DOOMED_EXCHANGE;
 #endif
     if (!generate_skeyids_iv(st))
 	return STF_FAIL + AUTHENTICATION_FAILED;
+    update_iv(st);
 
-    /*************** build output packet HDR*;IDii;HASH/SIG_I ***************/
-    /* ??? NOTE: this is almost the same as main_inI3_outR3's code */
+    /* Advance state */
+    st->st_state = STATE_MAIN_R2;
 
-    /* HDR* out done */
+    DBG(DBG_PARSING,
+    DBG_log("finished main_inI2_outR2_pk");
+    );
 
-    /* IDii out */
-    {
-	struct isakmp_ipsec_id id_hd;
-	chunk_t id_b;
-	pb_stream id_pbs;
+    return STF_REPLY;
+}
+#endif /* OPENSSL */
+
+#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_inI2_outR2_rpk(struct msg_digest *md)
+{
+    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_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));
+
+    if (!decode_peer_id(md, FALSE))
+      return STF_FAIL + INVALID_ID_INFORMATION;
+
+    /**************** build output packet ****************/
+
+    /* HDR out done */
+
+    /* 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;
+
+    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;
+    }
+    memset(st->st_ne_r_iv, 0, MAX_DIGEST_LEN);
+
+    DBG(DBG_PARSING,
+    DBG_dump_chunk("Generated Ke_r:", st->st_ne_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;
+
+    /* <IDr1_b>Ke_r[<cert>Ke_r] out */
+    {
+      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 (!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.
+     */
+    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;
+#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 ***************/
+
+    /* 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 */
 
-	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;
+		|| !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 or SIG_I out */
-    {
+  /* 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);
 
@@ -2067,8 +3123,8 @@
 	{
 	    /* 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);
+	    size_t sig_len = RSA_sign_hash(st->st_connection, 
+			sig_val, hash_val, hash_len);
 
 	    if (sig_len == 0)
 	    {
@@ -2080,7 +3136,10 @@
 	    , &md->rbody, sig_val, sig_len, "SIG_I"))
 		return STF_INTERNAL_ERROR;
 	}
-    }
+  }
+#ifdef OPENSSL
+}
+#endif /* OPENSSL */
 
     /* encrypt message, except for fixed part of header */
 
@@ -2091,8 +3150,162 @@
     /* 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
@@ -2101,11 +3314,16 @@
  */
 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 */
@@ -2192,6 +3410,10 @@
     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 */
@@ -2213,8 +3435,348 @@
 
     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;
+    }
+
+    /**************** done input ****************/
+
+    /* Advance state */
+    st->st_state = STATE_MAIN_I4;
+    c->newest_isakmp_sa = st->st_serialno;
+
+    update_iv(st);    /* finalize our Phase 1 IV */
+
+    DBG(DBG_PARSING,
+    DBG_log("finished main_inR3_ds");
+    );
+
+    return STF_UNPEND_QUICK;
+}
+#endif
+
+#ifdef OPENSSL
+/* Handle HDR*;HASH_R from responder.
+ */
+stf_status
+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 */
+
+    DBG(DBG_PARSING,
+    DBG_log("in main_inR3_pk");
+    );
+
+    /* 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 ****************/
+
+    /* Advance state */
+    st->st_state = STATE_MAIN_I4;
+    c->newest_isakmp_sa = st->st_serialno;
+
+    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 ] -->
@@ -2375,22 +3937,22 @@
 
 			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))
-			{
+                            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]
+                               , rgwb[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));
+                            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 client says gateway is %s"
+                              , fgwb, cb, rgwb);
 			    return STF_FAIL + INVALID_ID_INFORMATION;
 			}
 
@@ -2399,7 +3961,7 @@
 			    loglog(RC_OPPOFAILURE, "peer and client disagree about public key");
 			    return STF_FAIL + INVALID_ID_INFORMATION;
 			}
-			gw->last_worked_time = now();
+                        gw->last_worked_time = now();
 		    }
 
 		    /* Instantiate inbound Opportunism, carrying over his ID
@@ -2494,8 +4056,8 @@
 
 	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;
+        if (st->st_shared.ptr[0] == 0)
+            return STF_DROP_DOOMED_EXCHANGE;
 #endif
     }
 
@@ -2574,8 +4136,8 @@
     {
 	compute_dh_shared(st, st->st_gr, st->st_pfs_group);
 #ifdef DODGE_DH_MISSING_ZERO_BUG
-	if (st->st_shared.ptr[0] == 0)
-	    return STF_REPLACE_DOOMED_EXCHANGE;
+        if (st->st_shared.ptr[0] == 0)
+            return STF_DROP_DOOMED_EXCHANGE;
 #endif
     }
 
@@ -2660,8 +4222,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;
+    st->st_connection->newest_isakmp_sa = 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;
+    st->st_connection->newest_isakmp_sa = 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 -ruN 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	Wed May 16 10:57:20 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);
+    ,bool pending_quick, 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 -ruN 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	Wed May 16 10:57:20 2001
@@ -49,6 +49,7 @@
 #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? */
 
@@ -1569,6 +1570,8 @@
     {
 	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)
diff -ruN 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 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: kernel.h,v 1.18 2001/01/23 23:09:30 dhr Exp $
+ * RCSID $Id: kernel.h,v 1.19 2001/05/08 05:37:23 dhr Exp $
  */
 
 extern bool no_klips;	/* don't actually use KLIPS */
diff -ruN 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 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: kernel_comm.c,v 1.53 2001/01/23 23:09:30 dhr Exp $
+ * RCSID $Id: kernel_comm.c,v 1.57 2001/05/08 05:37:23 dhr Exp $
  */
 
 #include <stdio.h>
@@ -46,7 +46,7 @@
 
 /* helper variables and function to decode strings from whack message */
 
-static char
+static char 
     *next_str,
     *str_roof;
 
@@ -97,21 +97,21 @@
     /* sanity check message */
     {
 	int ughno = RC_BADWHACKMESSAGE;
-	char ugh[200];	/* sufficient for our messages (we hope) */
+	char ugh[200];  /* sufficient for our messages (we hope) */
 
 	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."
+           snprintf(ugh, sizeof(ugh)
+               , "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"
+               , "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,13 +122,12 @@
 	|| !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");
+	    snprintf(ugh, sizeof(ugh), "message from whack contains bad string");
 	}
 	else
 	{
 	    msg.keyval.ptr = next_str;	/* grab chunk */
-	    ughno = 0;	/* ran through the gauntlet -- success */
+	    ughno = 0;  /* ran through the gauntlet -- success */
 	}
 
 	if (ughno != 0)
@@ -149,8 +148,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 +160,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,10 +243,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))
-		    whack_log(RC_ROUTE, "could not route");
+                if (!orient(c, TRUE))
+                   whack_log(RC_ORIENT, "could not orient connection");
+                else if (!route_connection(c, TRUE))
+		   whack_log(RC_ROUTE, "could not route");
 		UNSET_CUR_CONNECTION();
 	    }
 	}
diff -ruN 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 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: 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>
diff -ruN 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 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: 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 (;;)
     {
@@ -417,6 +451,10 @@
 #ifdef LEAK_DETECTIVE
     report_leaks();
 #endif /* LEAK_DETECTIVE */
+#ifdef OPENSSL
+    X509V3_EXT_cleanup();
+    ERR_free_strings();
+#endif
     close_log();
     exit(status);
 }
diff -ruN 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 */
-MD5_CTX *context;                                       /* context */
+#ifndef OPENSSL
+MD5_CTX *context;                                 /* context */
+#else
+PLUTO_MD5_CTX *context;
+#endif /* OPENSSL */
 {
   unsigned char bits[8];
   unsigned int index, padLen;
diff -ruN 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 -ruN 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 -ruN 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 -ruN 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 -ruN 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 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: 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"
@@ -639,7 +641,7 @@
 	/* put at least one * out */
 	for (;;)
 	{
-	    if (pre <= space)
+	  if (pre <= space)
 		break;
 	    *--pre = '*';
 	    if (p == NULL)
@@ -663,16 +665,16 @@
  */
 
 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 */
+    char ugh[100];     /* arbitrary limit on diagnostic length */
     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);
+      snprintf(ugh, sizeof(ugh), "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;
@@ -687,8 +689,8 @@
 	    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 */
@@ -723,13 +725,13 @@
 			: 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);
+                       snprintf(ugh, sizeof(ugh),
+                           "%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);
+                       snprintf(ugh, sizeof(ugh),
+                           "%s of %s is larger than can fit",
+                           fp->name, sd->name);
 		    } else {
 			roof = ins->cur + len;
 		    }
@@ -741,18 +743,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);
+                       snprintf(ugh, sizeof(ugh),
+                           "bitset %s of %s has unknown member(s): %s",
+                           fp->name, sd->name, bitnamesof(fp->desc, 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));
+			snprintf(ugh, sizeof(ugh), "bitset %s of %s has unknown member(s): %s"
+			    , fp->name, sd->name, bitnamesof(fp->desc, n));
 		    }
 		    break;
 		default:
@@ -791,8 +792,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,18 +819,18 @@
     {
 	if (bytes == NULL)
 	{
-	    DBG(DBG_PARSING,
-		DBG_log("skipping %u raw bytes of %s (%s)",
-		    (unsigned) len, ins->name, name);
-		DBG_dump(name, ins->cur, len));
+	    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_dump(name, bytes, len));
+	    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;
 	return TRUE;
@@ -851,20 +852,20 @@
  */
 
 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 */
+    char ugh[100];     /* arbitrary limit on diagnostic length */
     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);
+	snprintf(ugh, sizeof(ugh), "not enough room left in output packet to place %s"
+	    , sd->name);
     } else {
 	bool immediate = FALSE;
 	pb_stream obj;
@@ -881,8 +882,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 +935,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);
+			snprintf(ugh, sizeof(ugh), "%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));
+			snprintf(ugh, sizeof(ugh), "bitset %s of %s has unknown member(s): %s"
+			    , fp->name, sd->name, bitnamesof(fp->desc, n));
 		    }
 		    break;
 		default:
@@ -1002,8 +1001,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 +1012,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,16 +1029,16 @@
 {
     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_dump(name, bytes, len));
+	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;
 	return TRUE;
@@ -1056,8 +1055,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 +1077,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 -ruN 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	Thu May 17 11:52:35 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>
@@ -203,10 +203,17 @@
     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;
+    struct id 
+       *my_id = &c->this.id,
+       rw_id,
+       *his_id = &c->that.id;
+
+    if (c->that.id.kind != ID_IPV4_ADDR || c->that.id.kind != ID_IPV6_ADDR) {
+      DBG(DBG_PARSING,
+      DBG_log("ID payload used is invalid: %s", enum_show(&ident_names, c->that.id.kind));
+      DBG_log("Make sure it's ID_IPV4_ADDR or ID_IPV6_ADDR when using PSK.");
+      );
+    }
 
     if (c->rw_state == rwcs_instance
     && (c->that.id.kind == ID_IPV4_ADDR || c->that.id.kind == ID_IPV6_ADDR)
@@ -545,7 +552,7 @@
     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 */
+    char ugh_space[100];       /* perhaps enough space */
 
     if (*tok == '"' || *tok == '\'')
     {
@@ -573,10 +580,10 @@
 	    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;
+                snprintf(ugh_space, sizeof(ugh_space)
+                    , "PSK data malformed (%s): ", ugh);
+                ugh = ugh_space;
+                ugh_extra = tok;
 	    }
 	    else
 	    {
@@ -613,8 +620,8 @@
 		}
 		else if (!tokeqword(p->name))
 		{
-		    ugh = p->name;
-		    ugh_extra = " keyword not found where expected in RSA key";
+                   ugh = p->name;
+                   ugh_extra = " keyword not found where expected in RSA key";
 		}
 		else if (!(shift()
 		&& (!tokeq(":") || shift())))	/* ignore optional ":" */
@@ -624,10 +631,10 @@
 		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;
+                    snprintf(ugh_space, sizeof(ugh_space)
+                        , "RSA data malformed (%s): ", ugh);
+                    ugh = ugh_space;
+                    ugh_extra = tok;
 		}
 		else
 		{
@@ -667,14 +674,14 @@
     }
     else
     {
-	ugh = "unrecognized key format: ";
-	ugh_extra = tok;
+       ugh = "unrecognized key format: ";
+       ugh_extra = 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 +782,13 @@
 
 		    if (tokeq("%any"))
 		    {
-			memset(&id, 0, sizeof(id));
+                        memset(&id, 0, sizeof(id));
 			id.kind = ID_IPV4_ADDR;
 			ugh = anyaddr(AF_INET, &id.ip_addr);
 		    }
 		    else if (tokeq("%any6"))
 		    {
-			memset(&id, 0, sizeof(id));
+                        memset(&id, 0, sizeof(id));
 			id.kind = ID_IPV6_ADDR;
 			ugh = anyaddr(AF_INET6, &id.ip_addr);
 		    }
@@ -797,7 +804,7 @@
 		    }
 		    else
 		    {
-			struct id *i = clone_id(&id);
+                        struct id *i = clone_id(&id);
 
 			i->next = s->ids;
 			s->ids = i;
diff -ruN 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 -ruN 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 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: 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 */
diff -ruN 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 May 17 11:31:23 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[] = {
@@ -366,8 +909,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;
 }
 
@@ -376,18 +919,17 @@
  */
 bool
 out_sa(
-    pb_stream *outs,
-    struct db_sa *sadb,
-    struct state *st,
-    bool oakley_mode,
-    u_int8_t np)
+	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 +979,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 +1090,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))
@@ -635,8 +1197,7 @@
     {
 	/* "clamp" too large value to max representable value */
 	val -= 1;	/* portable way to get to maximum value */
-	DBG(DBG_PARSING, DBG_log("   too large duration clamped to: %lu"
-	    , (unsigned long)val));
+	DBG(DBG_PARSING, DBG_log("   too large duration clamped to: %lu", (unsigned long)val));
     }
     else
     {
@@ -648,6 +1209,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 +1412,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 +1505,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,40 +1520,44 @@
 	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) */
+	char ugh[100];  /* mailbox for diagnostics (arbitrary limit) */
 
-	ugh[0] = '\0';	/* empty mailbox */
+	ugh[0] = '\0';  /* empty mailbox */
 
 	/* initialize only optional field in ta */
-	ta.life_seconds = OAKLEY_ISAKMP_SA_LIFETIME_DEFAULT;	/* When this SA expires (seconds) */
+	/* When this SA expires (seconds) */
+	ta.life_seconds = OAKLEY_ISAKMP_SA_LIFETIME_DEFAULT;
 
 	if (no_trans_left == 0)
 	{
-	    loglog(RC_LOG_SERIOUS, "number of Transform Payloads disagrees with Oakley Proposal Payload");
-	    return BAD_PROPOSAL_SYNTAX;
+	  loglog(RC_LOG_SERIOUS, 
+	    "number of Transform Payloads disagrees with Oakley Proposal Payload");
+	  return BAD_PROPOSAL_SYNTAX;
 	}
 
-	if (!in_struct(&trans, &isakmp_isakmp_transform_desc, &proposal_pbs, &trans_pbs))
-	    return BAD_PROPOSAL_SYNTAX;
+	if (!in_struct(&trans, &isakmp_isakmp_transform_desc, 
+	  &proposal_pbs, &trans_pbs))
+	  return BAD_PROPOSAL_SYNTAX;
 
 	if (trans.isat_transnum <= last_transnum)
 	{
-	    /* picky, picky, picky */
-	    loglog(RC_LOG_SERIOUS, "Transform Numbers are not monotonically increasing"
-		" in Oakley Proposal");
-	    return BAD_PROPOSAL_SYNTAX;
+	  /* picky, picky, picky */
+	  loglog(RC_LOG_SERIOUS, 
+	    "Transform Numbers are not monotonically increasing"
+	    " in Oakley Proposal");
+	  return BAD_PROPOSAL_SYNTAX;
 	}
 	last_transnum = trans.isat_transnum;
 
 	if (trans.isat_transid != KEY_IKE)
 	{
-	    loglog(RC_LOG_SERIOUS, "expected KEY_IKE but found %s in Oakley Transform"
-		, enum_show(&isakmp_transformid_names, trans.isat_transid));
+	    loglog(RC_LOG_SERIOUS, 
+	      "expected KEY_IKE but found %s in Oakley Transform",
+	      enum_show(&isakmp_transformid_names, trans.isat_transid));
 	    return INVALID_TRANSFORM_ID;
 	}
 
@@ -820,7 +1565,6 @@
 	attr_len = pbs_left(&trans_pbs);
 
 	/* process all the attributes that make up the transform */
-
 	while (pbs_left(&trans_pbs) != 0)
 	{
 	    struct isakmp_attribute a;
@@ -828,16 +1572,18 @@
 	    enum_names *vdesc;
 	    u_int32_t val;	/* room for larger values */
 
-	    if (!in_struct(&a, &isakmp_oakley_attribute_desc, &trans_pbs, &attr_pbs))
-		return BAD_PROPOSAL_SYNTAX;
+	    if (!in_struct(&a, &isakmp_oakley_attribute_desc, 
+	      &trans_pbs, &attr_pbs))
+	      return BAD_PROPOSAL_SYNTAX;
 
 	    passert((a.isaat_af_type & ISAKMP_ATTR_RTYPE_MASK) < 32);
 
 	    if (seen_attrs & LELEM(a.isaat_af_type & ISAKMP_ATTR_RTYPE_MASK))
 	    {
-		loglog(RC_LOG_SERIOUS, "repeated %s attribute in Oakley Transform %u"
-		    , enum_show(&oakley_attr_names, a.isaat_af_type)
-		    , trans.isat_transnum);
+	      loglog(RC_LOG_SERIOUS, 
+	        "repeated %s attribute in Oakley Transform %u",
+	          enum_show(&oakley_attr_names, a.isaat_af_type),
+		    trans.isat_transnum);
 		return BAD_PROPOSAL_SYNTAX;
 	    }
 
@@ -854,10 +1600,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,12 +1611,25 @@
 		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 {
+			  snprintf(ugh, sizeof(ugh), "%s is not accepted",
+			    enum_show(&oakley_enc_names, val));
+			}
+			break;
 		    case OAKLEY_3DES_CBC:
-			ta.encrypt = val;
-			ta.encrypter = &oakley_encrypter[val];
+			if ((c->block_cypher == ALL_BLOCK_CYPHER) ||
+			  (c->block_cypher == DES3_BLOCK_CYPHER)) {
+			  ta.encrypt = val;
+			  ta.encrypter = &oakley_encrypter[val];
+			} else {
+			  snprintf(ugh, sizeof(ugh), "%s is not accepted",
+			    enum_show(&oakley_enc_names, val));
+			}
 			break;
 		    default:
 			snprintf(ugh, sizeof(ugh), "%s is not supported"
@@ -887,8 +1646,8 @@
 			ta.hasher = &oakley_hasher[val];
 			break;
 		    default:
-			snprintf(ugh, sizeof(ugh), "%s is not supported",
-			    enum_show(&oakley_hash_names, val));
+			snprintf(ugh, sizeof(ugh), "%s is not supported"
+			    , enum_show(&oakley_hash_names, val));
 		    }
 		    break;
 
@@ -896,27 +1655,65 @@
 		    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)
+                        /* Accept if policy specifies PSK or is default */
+                        if (((st->st_policy & POLICY_PSK)
+                        || (st->st_policy & POLICY_ISAKMP_MASK) == 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;
+                            /* 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;
 			}
 			else
 			{
-			    snprintf(ugh, sizeof(ugh)
-				, "policy does not allow OAKLEY_PRESHARED_KEY authentication");
+                          snprintf(ugh, sizeof(ugh), 
+                            "policy does not allow OAKLEY_PRESHARED_KEY authentication");
 			}
-			break;
+		        break;
 
-		    case OAKLEY_RSA_SIG:
-			/* Accept if policy specifies RSASIG or is default */
-			if ((st->st_policy & POLICY_RSASIG)
-			|| (st->st_policy & POLICY_ISAKMP_MASK) == LEMPTY)
+#ifdef OPENSSL
+                  case OAKLEY_DSS_SIG:
+                    if ((st->st_connection->key == NULL) ||
+                        (((EVP_PKEY *)(st->st_connection->key))->type != EVP_PKEY_DSA))
+                      snprintf(ugh, sizeof(ugh), "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))
+                      snprintf(ugh, sizeof(ugh), "OAKLEY_RSA_ENC requested, but no cert available to encrypt with");
+                    ta.auth = val;
+                    break;
+                  case OAKLEY_ELGAMAL_ENC:
+                    if (!have_elgamal_keypair(st))
+                      snprintf(ugh, sizeof(ugh), "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))
+                      snprintf(ugh, sizeof(ugh), "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))
+                      snprintf(ugh, sizeof(ugh), "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 */
+#ifndef OPENSSL
+                       if ((st->st_policy & POLICY_RSASIG)
+#else
+                       if ((st->st_policy & POLICY_OPENSSL)
+#endif
+                       || (st->st_policy & POLICY_ISAKMP_MASK) == LEMPTY)
 			{
 			    /* We'd like to check that we can find a public
 			     * key for him and a private key for us that is
@@ -930,15 +1727,23 @@
 			}
 			else
 			{
-			    snprintf(ugh, sizeof(ugh)
-				, "policy does not allow OAKLEY_RSA_SIG authentication");
+                          snprintf(ugh, sizeof(ugh)
+                              , "policy does not allow OAKLEY_RSA_SIG authentication");
 			}
-			break;
+#ifdef OPENSSL
+		    } else { /* use_openssl */
+		      if ((st->st_connection->key == NULL) ||
+		        (((EVP_PKEY *)(st->st_connection->key))->type != EVP_PKEY_RSA))
+		        snprintf(ugh, sizeof(ugh), "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"
-			    , enum_show(&oakley_auth_names, val));
+			snprintf(ugh, sizeof(ugh), 
+			  "Pluto does not support %s authentication", 
+			  enum_show(&oakley_auth_names, val));
 			break;
 		    }
 		    break;
@@ -947,7 +1752,8 @@
 		    ta.group = lookup_group(val);
 		    if (ta.group == NULL)
 		    {
-			snprintf(ugh, sizeof(ugh), "only OAKLEY_GROUP_MODP1024 and OAKLEY_GROUP_MODP1536 supported");
+			snprintf(ugh, sizeof(ugh), 
+		          "only OAKLEY_GROUP_MODP1024 and OAKLEY_GROUP_MODP1536 supported");
 			break;
 		    }
 		    break;
@@ -969,8 +1775,8 @@
 		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");
+			snprintf(ugh, sizeof(ugh), 
+		          "OAKLEY_LIFE_DURATION attribute not preceded by OAKLEY_LIFE_TYPE attribute");
 			break;
 		    }
 		    seen_attrs &= ~(LELEM(OAKLEY_LIFE_DURATION) | LELEM(OAKLEY_LIFE_TYPE));
@@ -979,7 +1785,7 @@
 		    {
 			case OAKLEY_LIFE_SECONDS:
 			    if (val > OAKLEY_ISAKMP_SA_LIFETIME_MAXIMUM)
-				snprintf(ugh, sizeof(ugh),
+				snprintf(ugh, sizeof(ugh), 
 				    "peer requested %lu seconds"
 				    " which exceeds our limit %d seconds"
 				    , (long) val
@@ -1016,7 +1822,7 @@
 		default:
 		    snprintf(ugh, sizeof(ugh), "unsupported OAKLEY attribute");
 		    break;
-	    }
+	    }   /* switch (a.isaat_af_type) */
 
 	    if (ugh[0] != '\0')
 	    {
@@ -1024,7 +1830,7 @@
 		    , ugh, enum_show(&oakley_attr_names, a.isaat_af_type));
 		break;
 	    }
-	}
+	} /* while (pbs_left(&trans_pbs) != 0) */
 
 	if (ugh[0] == '\0')
 	{
@@ -1049,8 +1855,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)
 	    {
@@ -1084,15 +1891,16 @@
 
 		/* 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_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);
 		close_output_pbs(&r_proposal_pbs);
 		close_output_pbs(r_sa_pbs);
-	    }
+	    }     /* if (r_sa_pbs != NULL) */
 
 	    /* ??? If selection, we used to save the proposal in state.
 	     * We never used it.  From proposal_pbs.start,
@@ -1102,7 +1910,15 @@
 	    /* 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
+	} /* if (ugh == '\0') */
 
 	/* on to next transform */
 	no_trans_left--;
@@ -1111,20 +1927,90 @@
 	{
 	    if (no_trans_left != 0)
 	    {
-		loglog(RC_LOG_SERIOUS, "number of Transform Payloads disagrees with Oakley Proposal Payload");
+		loglog(RC_LOG_SERIOUS, 
+	          "number of Transform Payloads disagrees with Oakley Proposal Payload");
 		return BAD_PROPOSAL_SYNTAX;
 	    }
 	    break;
 	}
+
 	if (trans.isat_np != ISAKMP_NEXT_T)
 	{
 	    loglog(RC_LOG_SERIOUS, "unexpected %s payload in Oakley Proposal"
 		, 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).
@@ -1164,18 +2050,19 @@
 };
 
 static bool
-parse_ipsec_transform(struct isakmp_transform *trans
-, struct ipsec_trans_attrs *attrs
-, pb_stream *prop_pbs
-, pb_stream *trans_pbs
-, struct_desc *trans_desc
-, int previous_transnum	/* or -1 if none */
-, bool selection
-, bool is_last
-, bool is_ipcomp
-, struct state *st)	/* current state object */
+parse_ipsec_transform(
+    struct isakmp_transform *trans,
+    struct ipsec_trans_attrs *attrs,
+    pb_stream *prop_pbs,
+    pb_stream *trans_pbs,
+    struct_desc *trans_desc,
+    int previous_transnum,	/* or -1 if none */
+    bool selection,
+    bool is_last,
+    bool is_ipcomp,
+    struct state *st)	/* current state object */
 {
-    lset_t
+    lset_t 
 	seen_attrs = 0,
 	seen_durations = 0;
     u_int16_t life_type;
@@ -1249,10 +2136,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 +2440,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));
+                memset(&next_spi, '\0', sizeof(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 +2646,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 +2684,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 +2697,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 +2739,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 +2831,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 +2859,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 -ruN 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 -ruN 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	Wed May 16 10:57:20 2001
@@ -348,6 +348,16 @@
     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);
 }
 
diff -ruN 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 May 16 10:57:20 2001
@@ -146,6 +146,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 */
 
diff -ruN 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 May 17 14:34:39 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.17 2000/11/30 05:02:51 henry Exp $ */
+static const char freeswan_version[] = "FreeSWAN-1.9-pkix1";
diff -ruN 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 May 16 10:57:20 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.76 2001/05/08 05:37:24 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
@@ -488,6 +544,7 @@
     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 */
 
@@ -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)))
diff -ruN 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 May 16 10:57:20 2001
@@ -16,6 +16,11 @@
 
 #include <freeswan.h>
 
+#ifdef OPENSSL
+#include "openssl_defs.h"
+#endif
+#include <freeswan.h>
+
 /*
  * Since the message remains on one host, native representation is used.
  * Think of this as horizontal microcode: all selected operations are
@@ -83,6 +88,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 +123,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 -ruN 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 -ruN 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 -ruN 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 -ruN 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 -ruN 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 -ruN 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 -ruN 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 -ruN 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 -ruN 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 -ruN 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 -ruN 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 -ruN 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 -ruN 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	Wed May 16 10:57:20 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 $@
 
@@ -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 ; \
-	then chkconfig --add ipsec ; \
-	else $(MAKE) setup4 ; \
+	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 -ruN 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	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: _confread,v 1.33.2.4 2001/03/15 00:05:54 henry Exp $
+# RCSID $Id: _confread,v 1.36 2001/05/07 12:43:38 henry Exp $
 #
 # Extract configuration info from /etc/ipsec.conf, repackage as assignments
 # to shell variables or tab-delimited fields.  Success or failure is reported
@@ -115,10 +115,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 +127,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 +160,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 +322,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 -ruN 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)
-	parms="-net $PLUTO_PEER_CLIENT_NET netmask $PLUTO_PEER_CLIENT_MASK"
-	oops="`route del $parms 2>&1`"
+	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 -ruN 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	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: 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:
@@ -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)
@@ -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")
-			fail("unknown authby value \"" s["authby"] "\"")
+		}
+
+
+		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 -ruN freeswan-1.9.orig/utils/four2perm.1 freeswan-1.9/utils/four2perm.1
--- freeswan-1.9.orig/utils/four2perm.1	Wed Dec 31 19:00:00 1969
+++ freeswan-1.9/utils/four2perm.1	Wed May 16 10:57:20 2001
@@ -0,0 +1,20 @@
+.TH FOUR2PERM 1 "August 1999"
+.\" RCSID $Id: four2perm.1,v 1.1 1999/09/04 20:51:01 sandy Exp $
+.SH NAME
+four2perm - generate permuted index from four-field lines
+.SH SYNOPSIS
+.B four2perm
+.SH DESCRIPTION
+.I four2perm
+expects input lines with four tab-separated fields, such as that
+created from HTML files by html2four(1). Given that, it does most
+of the work of generating a permuted index, gets things close
+enough that a simple pipeline through sort(1) and awk(1) can
+finish the job.
+.SH SEE ALSO
+.hy 0
+html2four(1)
+.SH HISTORY
+Written for the Linux FreeS/WAN project
+<http://www.xs4all.nl/~freeswan/>
+by Sandy Harris.
diff -ruN freeswan-1.9.orig/utils/four2perm.c freeswan-1.9/utils/four2perm.c
--- freeswan-1.9.orig/utils/four2perm.c	Wed Dec 31 19:00:00 1969
+++ freeswan-1.9/utils/four2perm.c	Wed May 16 10:57:20 2001
@@ -0,0 +1,144 @@
+#include <ctype.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+
+#define MAX_LINE  512
+
+void die( char * ) ;
+
+char buffer[MAX_LINE+1] ;
+char *prog_name ;
+
+void die( char *message )
+{
+	fflush(stdout) ;
+	fprintf(stderr, "%s: %s\n", prog_name, message) ;
+	exit(1) ;
+}
+
+int main(int argc, char* argv[])
+{
+	int errors ;
+	prog_name = *argv ;
+	if( argc != 1 )
+		die("pure filter, takes no arguments") ;
+	errors = 0 ;
+	while( fgets(buffer, MAX_LINE, stdin))
+		errors += do_line(buffer) ;
+	exit(errors ? 1 : 0 ) ;
+}
+
+int do_line(char *data)
+{
+	char *p, *q, *r, *end, *before, *after ;
+	// expecting two tab-separated fields
+	// point r to 2nd, null terminate 1st
+	for( r = data ; *r && *r != '\t' ; r++ )
+		;
+	if( *r != '\t' )
+		return(1) ;
+	end = r++ ;
+	*end = '\0' ;
+	for( q = r ; *q ; q++ )
+		if( *q == '\n' )
+			*q = '\0' ;
+	if( !strlen(r) )
+		return(1) ;
+	// within 1st, parse as space-separated
+	// p will point to current word, q past its end
+	// before & after point to rest of text
+	// spaces converted to nulls & back as req'd
+	before = "" ;
+	for( p = data ; p < end ; p = q + 1 )	{
+		if( p > data )	{
+			before = data ;
+			p[-1] = '\0' ;
+		}
+		// find end of word
+		for( q = p ; *q && *q != ' ' ; q++ )
+			;
+		if( q == end )
+			after = "" ;
+		else if( q < end )	{
+			after = q + 1 ;
+			*q = '\0' ;
+		}
+		else	assert(0) ;
+		print_line(before, p, after, r) ;
+		if( q < end )
+			*q = ' ' ;
+		if( p > data )
+			p[-1] = ' ' ;
+	}
+	return(0) ;
+}
+
+/*
+ * print formatted line for permuted index
+ * two tab-separated fields
+ *    1st is sort key
+ *    2nd is printable line
+ * pipe it through something like
+ *   sort -F | awk -F '\t' '{print $2}'
+ * to get final output
+ */
+
+print_line( char *before, char *word, char *after, char *tag)
+{
+	int i , x, y, z ;
+/*
+	printf("%s\t%s\t%s\t%s\n", before, word, after, tag) ;
+*/
+	if( list_word(word) )
+		return ;
+	x = strlen(before) ;
+	y = strlen(word) ;
+	z = strlen(after) ;
+	// put in sortable field
+	// strip out with awk after sorting
+	printf("%s %s\t", word, after) ;
+	// shorten before string to fit field
+	for( ; x > 30 ; x-- )
+		before++ ;
+	printf("%30s", before) ;
+	// print keyword, html tagged
+	printf("  %s%s</a>  ", tag, word) ;
+	// padding, outside tag
+	for( ; y < 18 ; y++ )
+		putchar(' ') ;
+	if( z )
+		printf("%s", after) ;
+	printf("\n") ;
+}
+
+/* avoid indexing on common English words */
+
+char *list[] = {
+		"the", "of", "a", "an", "to", "and",  "or", "if", "for", "at",
+		"am", "is", "are", "was", "were", "have", "has", "had", "be", "been",
+		"on", "some", "with", "any", "into", "as", "by", "in", "out",
+		"that", "then", "this", "that", "than", "these", "those",
+		"he", "his", "him", "she", "her", "hers", "it", "its",
+		"&", "", "+", "-", "=", "--", "<", ">", "<=", ">=",
+		"!", "?", "#", "$", "%", "/", "\\", "\"", "\'",
+		NULL
+		} ;
+/*
+ * interrogative words like "how" and "where" deliberately left out of
+ * above list because users might want to search for "how to..." etc.
+ * 
+ * return 1 if word in list, else 0
+ * case-insensitive comparison
+ */
+
+list_word( char *p )
+{
+	char **z ;
+	for( z = list ; *z != NULL ; z++ )
+		if( ! strcasecmp( p, *z ) )
+			return 1 ;
+	return 0 ;
+}
+
diff -ruN 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 -ruN 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 -ruN 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 -ruN 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 -ruN 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	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: manual,v 1.76 2000/12/03 22:16:24 henry Exp $
+# RCSID $Id: manual,v 1.77 2001/02/26 18:24:11 henry Exp $
 
 me='ipsec manual'
 usage="Usage:
@@ -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 -ruN 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 -ruN 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 -ruN 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	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: rsasigkey.c,v 1.14.2.2 2001/02/22 22:11:30 henry Exp $
+ * RCSID $Id: rsasigkey.c,v 1.15 2001/02/23 16:40:31 henry Exp $
  */
 
 #include <stdio.h>
diff -ruN 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	Wed May 16 10:57:20 2001
@@ -1,4 +1,4 @@
-# RCSID $Id: secrets.proto,v 1.12.2.1 2001/03/12 04:03:48 henry Exp $
+# RCSID $Id: secrets.proto,v 1.13 2001/03/28 01:05:09 henry Exp $
 # This file holds shared secrets or RSA private keys for inter-Pluto
 # authentication.  See ipsec_pluto(8) manpage, and HTML documentation.
 
diff -ruN 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	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: setup,v 1.90.2.3 2001/03/14 23:52:41 henry Exp $
+# RCSID $Id: setup,v 1.94 2001/05/08 00:48:38 henry Exp $
 #
 # ipsec         init.d script for starting and stopping
 #               the IPsec security subsystem (KLIPS and Pluto).
@@ -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
-		unset MODPATH MODULECONF	# no user overrides!
-		depmod -a >/dev/null 2>&1 && modprobe ipsec
+		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" --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
@@ -508,6 +543,9 @@
 	fore)	plutogo 2>&1 | logit	;;
 	esac
 	echo "...FreeS/WAN IPsec started" | logonly
+
+	echo "Starting background tunnels..." | logit
+	$0 --startbacktunnels
 	;;
 
   stop|--stop)
@@ -531,8 +569,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
@@ -578,6 +629,26 @@
   --help)
 	echo "Usage: $me {--start|--stop|--restart}"
 	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 
+	) &
 	;;
 
   *)
diff -ruN 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	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: showhostkey,v 1.1.2.1 2001/03/12 04:03:31 henry Exp $
+# RCSID $Id: showhostkey,v 1.2 2001/03/28 01:12:44 henry Exp $
 
 me="ipsec showhostkey"
 usage="Usage: $me [--file secrets] [--left] [--right]"
diff -ruN 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 -ruN 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 May 17 14:34:51 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.17 2000/11/30 05:02:51 henry Exp $ */
+static const char freeswan_version[] = "FreeSWAN-1.9-pkix1";
diff -ruN 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.
 #
