Migrate from perforce repository.
diff --git a/src/Makefile.am b/src/Makefile.am
new file mode 100644
index 0000000..6d0d780
--- /dev/null
+++ b/src/Makefile.am
@@ -0,0 +1,3 @@
+SUBDIRS = @INCLUDE_GLIBC@ libipsec setkey racoon
+
+DIST_SUBDIRS = include-glibc libipsec setkey racoon
diff --git a/src/Makefile.in b/src/Makefile.in
new file mode 100644
index 0000000..6ba76a0
--- /dev/null
+++ b/src/Makefile.in
@@ -0,0 +1,501 @@
+# Makefile.in generated by automake 1.10.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008  Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+subdir = src
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/acracoon.m4 \
+	$(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+	$(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+SOURCES =
+DIST_SOURCES =
+RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \
+	html-recursive info-recursive install-data-recursive \
+	install-dvi-recursive install-exec-recursive \
+	install-html-recursive install-info-recursive \
+	install-pdf-recursive install-ps-recursive install-recursive \
+	installcheck-recursive installdirs-recursive pdf-recursive \
+	ps-recursive uninstall-recursive
+RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive	\
+  distclean-recursive maintainer-clean-recursive
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CONFIGURE_AMFLAGS = @CONFIGURE_AMFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CRYPTOBJS = @CRYPTOBJS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DSYMUTIL = @DSYMUTIL@
+ECHO = @ECHO@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+EXTRA_CRYPTO = @EXTRA_CRYPTO@
+F77 = @F77@
+FFLAGS = @FFLAGS@
+FRAG_OBJS = @FRAG_OBJS@
+GLIBC_BUGS = @GLIBC_BUGS@
+GREP = @GREP@
+HYBRID_OBJS = @HYBRID_OBJS@
+INCLUDE_GLIBC = @INCLUDE_GLIBC@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_OPTS = @INSTALL_OPTS@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+KERNEL_INCLUDE = @KERNEL_INCLUDE@
+KRB5_CONFIG = @KRB5_CONFIG@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+NATT_OBJS = @NATT_OBJS@
+NMEDIT = @NMEDIT@
+OBJEXT = @OBJEXT@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+RANLIB = @RANLIB@
+RPM = @RPM@
+SECCTX_OBJS = @SECCTX_OBJS@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+YACC = @YACC@
+YFLAGS = @YFLAGS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_F77 = @ac_ct_F77@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+include_racoondir = @include_racoondir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+SUBDIRS = @INCLUDE_GLIBC@ libipsec setkey racoon
+DIST_SUBDIRS = include-glibc libipsec setkey racoon
+all: all-recursive
+
+.SUFFIXES:
+$(srcdir)/Makefile.in:  $(srcdir)/Makefile.am  $(am__configure_deps)
+	@for dep in $?; do \
+	  case '$(am__configure_deps)' in \
+	    *$$dep*) \
+	      cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
+		&& exit 0; \
+	      exit 1;; \
+	  esac; \
+	done; \
+	echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign  src/Makefile'; \
+	cd $(top_srcdir) && \
+	  $(AUTOMAKE) --foreign  src/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+	@case '$?' in \
+	  *config.status*) \
+	    cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+	  *) \
+	    echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+	    cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+	esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure:  $(am__configure_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4):  $(am__aclocal_m4_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+mostlyclean-libtool:
+	-rm -f *.lo
+
+clean-libtool:
+	-rm -rf .libs _libs
+
+# This directory's subdirectories are mostly independent; you can cd
+# into them and run `make' without going through this Makefile.
+# To change the values of `make' variables: instead of editing Makefiles,
+# (1) if the variable is set in `config.status', edit `config.status'
+#     (which will cause the Makefiles to be regenerated when you run `make');
+# (2) otherwise, pass the desired values on the `make' command line.
+$(RECURSIVE_TARGETS):
+	@failcom='exit 1'; \
+	for f in x $$MAKEFLAGS; do \
+	  case $$f in \
+	    *=* | --[!k]*);; \
+	    *k*) failcom='fail=yes';; \
+	  esac; \
+	done; \
+	dot_seen=no; \
+	target=`echo $@ | sed s/-recursive//`; \
+	list='$(SUBDIRS)'; for subdir in $$list; do \
+	  echo "Making $$target in $$subdir"; \
+	  if test "$$subdir" = "."; then \
+	    dot_seen=yes; \
+	    local_target="$$target-am"; \
+	  else \
+	    local_target="$$target"; \
+	  fi; \
+	  (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+	  || eval $$failcom; \
+	done; \
+	if test "$$dot_seen" = "no"; then \
+	  $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
+	fi; test -z "$$fail"
+
+$(RECURSIVE_CLEAN_TARGETS):
+	@failcom='exit 1'; \
+	for f in x $$MAKEFLAGS; do \
+	  case $$f in \
+	    *=* | --[!k]*);; \
+	    *k*) failcom='fail=yes';; \
+	  esac; \
+	done; \
+	dot_seen=no; \
+	case "$@" in \
+	  distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \
+	  *) list='$(SUBDIRS)' ;; \
+	esac; \
+	rev=''; for subdir in $$list; do \
+	  if test "$$subdir" = "."; then :; else \
+	    rev="$$subdir $$rev"; \
+	  fi; \
+	done; \
+	rev="$$rev ."; \
+	target=`echo $@ | sed s/-recursive//`; \
+	for subdir in $$rev; do \
+	  echo "Making $$target in $$subdir"; \
+	  if test "$$subdir" = "."; then \
+	    local_target="$$target-am"; \
+	  else \
+	    local_target="$$target"; \
+	  fi; \
+	  (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+	  || eval $$failcom; \
+	done && test -z "$$fail"
+tags-recursive:
+	list='$(SUBDIRS)'; for subdir in $$list; do \
+	  test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \
+	done
+ctags-recursive:
+	list='$(SUBDIRS)'; for subdir in $$list; do \
+	  test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \
+	done
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+	list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '{ files[$$0] = 1; nonemtpy = 1; } \
+	      END { if (nonempty) { for (i in files) print i; }; }'`; \
+	mkid -fID $$unique
+tags: TAGS
+
+TAGS: tags-recursive $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+		$(TAGS_FILES) $(LISP)
+	tags=; \
+	here=`pwd`; \
+	if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \
+	  include_option=--etags-include; \
+	  empty_fix=.; \
+	else \
+	  include_option=--include; \
+	  empty_fix=; \
+	fi; \
+	list='$(SUBDIRS)'; for subdir in $$list; do \
+	  if test "$$subdir" = .; then :; else \
+	    test ! -f $$subdir/TAGS || \
+	      tags="$$tags $$include_option=$$here/$$subdir/TAGS"; \
+	  fi; \
+	done; \
+	list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+	      END { if (nonempty) { for (i in files) print i; }; }'`; \
+	if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
+	  test -n "$$unique" || unique=$$empty_fix; \
+	  $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+	    $$tags $$unique; \
+	fi
+ctags: CTAGS
+CTAGS: ctags-recursive $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+		$(TAGS_FILES) $(LISP)
+	tags=; \
+	list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+	      END { if (nonempty) { for (i in files) print i; }; }'`; \
+	test -z "$(CTAGS_ARGS)$$tags$$unique" \
+	  || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+	     $$tags $$unique
+
+GTAGS:
+	here=`$(am__cd) $(top_builddir) && pwd` \
+	  && cd $(top_srcdir) \
+	  && gtags -i $(GTAGS_ARGS) $$here
+
+distclean-tags:
+	-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+	@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+	topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+	list='$(DISTFILES)'; \
+	  dist_files=`for file in $$list; do echo $$file; done | \
+	  sed -e "s|^$$srcdirstrip/||;t" \
+	      -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+	case $$dist_files in \
+	  */*) $(MKDIR_P) `echo "$$dist_files" | \
+			   sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+			   sort -u` ;; \
+	esac; \
+	for file in $$dist_files; do \
+	  if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+	  if test -d $$d/$$file; then \
+	    dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+	    if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+	      cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+	    fi; \
+	    cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
+	  else \
+	    test -f $(distdir)/$$file \
+	    || cp -p $$d/$$file $(distdir)/$$file \
+	    || exit 1; \
+	  fi; \
+	done
+	list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
+	  if test "$$subdir" = .; then :; else \
+	    test -d "$(distdir)/$$subdir" \
+	    || $(MKDIR_P) "$(distdir)/$$subdir" \
+	    || exit 1; \
+	    distdir=`$(am__cd) $(distdir) && pwd`; \
+	    top_distdir=`$(am__cd) $(top_distdir) && pwd`; \
+	    (cd $$subdir && \
+	      $(MAKE) $(AM_MAKEFLAGS) \
+	        top_distdir="$$top_distdir" \
+	        distdir="$$distdir/$$subdir" \
+		am__remove_distdir=: \
+		am__skip_length_check=: \
+	        distdir) \
+	      || exit 1; \
+	  fi; \
+	done
+check-am: all-am
+check: check-recursive
+all-am: Makefile
+installdirs: installdirs-recursive
+installdirs-am:
+install: install-recursive
+install-exec: install-exec-recursive
+install-data: install-data-recursive
+uninstall: uninstall-recursive
+
+install-am: all-am
+	@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-recursive
+install-strip:
+	$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+	  install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+	  `test -z '$(STRIP)' || \
+	    echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+	-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+	@echo "This command is intended for maintainers to use"
+	@echo "it deletes files that may require special tools to rebuild."
+clean: clean-recursive
+
+clean-am: clean-generic clean-libtool mostlyclean-am
+
+distclean: distclean-recursive
+	-rm -f Makefile
+distclean-am: clean-am distclean-generic distclean-tags
+
+dvi: dvi-recursive
+
+dvi-am:
+
+html: html-recursive
+
+info: info-recursive
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-recursive
+
+install-exec-am:
+
+install-html: install-html-recursive
+
+install-info: install-info-recursive
+
+install-man:
+
+install-pdf: install-pdf-recursive
+
+install-ps: install-ps-recursive
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-recursive
+	-rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-recursive
+
+mostlyclean-am: mostlyclean-generic mostlyclean-libtool
+
+pdf: pdf-recursive
+
+pdf-am:
+
+ps: ps-recursive
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) install-am \
+	install-strip
+
+.PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \
+	all all-am check check-am clean clean-generic clean-libtool \
+	ctags ctags-recursive distclean distclean-generic \
+	distclean-libtool distclean-tags distdir dvi dvi-am html \
+	html-am info info-am install install-am install-data \
+	install-data-am install-dvi install-dvi-am install-exec \
+	install-exec-am install-html install-html-am install-info \
+	install-info-am install-man install-pdf install-pdf-am \
+	install-ps install-ps-am install-strip installcheck \
+	installcheck-am installdirs installdirs-am maintainer-clean \
+	maintainer-clean-generic mostlyclean mostlyclean-generic \
+	mostlyclean-libtool pdf pdf-am ps ps-am tags tags-recursive \
+	uninstall uninstall-am
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/src/include-glibc/Makefile.am b/src/include-glibc/Makefile.am
new file mode 100644
index 0000000..9f2faa0
--- /dev/null
+++ b/src/include-glibc/Makefile.am
@@ -0,0 +1,14 @@
+
+.includes: ${top_builddir}/config.status
+	ln -sf $(KERNEL_INCLUDE)/linux
+	touch .includes
+
+all: .includes
+
+EXTRA_DIST = \
+  glibc-bugs.h \
+  net/pfkeyv2.h \
+  netinet/ipsec.h \
+  sys/queue.h
+
+DISTCLEANFILES = .includes linux
diff --git a/src/include-glibc/Makefile.in b/src/include-glibc/Makefile.in
new file mode 100644
index 0000000..842728e
--- /dev/null
+++ b/src/include-glibc/Makefile.in
@@ -0,0 +1,356 @@
+# Makefile.in generated by automake 1.10.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008  Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+subdir = src/include-glibc
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/acracoon.m4 \
+	$(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+	$(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+SOURCES =
+DIST_SOURCES =
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CONFIGURE_AMFLAGS = @CONFIGURE_AMFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CRYPTOBJS = @CRYPTOBJS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DSYMUTIL = @DSYMUTIL@
+ECHO = @ECHO@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+EXTRA_CRYPTO = @EXTRA_CRYPTO@
+F77 = @F77@
+FFLAGS = @FFLAGS@
+FRAG_OBJS = @FRAG_OBJS@
+GLIBC_BUGS = @GLIBC_BUGS@
+GREP = @GREP@
+HYBRID_OBJS = @HYBRID_OBJS@
+INCLUDE_GLIBC = @INCLUDE_GLIBC@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_OPTS = @INSTALL_OPTS@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+KERNEL_INCLUDE = @KERNEL_INCLUDE@
+KRB5_CONFIG = @KRB5_CONFIG@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+NATT_OBJS = @NATT_OBJS@
+NMEDIT = @NMEDIT@
+OBJEXT = @OBJEXT@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+RANLIB = @RANLIB@
+RPM = @RPM@
+SECCTX_OBJS = @SECCTX_OBJS@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+YACC = @YACC@
+YFLAGS = @YFLAGS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_F77 = @ac_ct_F77@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+include_racoondir = @include_racoondir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+EXTRA_DIST = \
+  glibc-bugs.h \
+  net/pfkeyv2.h \
+  netinet/ipsec.h \
+  sys/queue.h
+
+DISTCLEANFILES = .includes linux
+all: all-am
+
+.SUFFIXES:
+$(srcdir)/Makefile.in:  $(srcdir)/Makefile.am  $(am__configure_deps)
+	@for dep in $?; do \
+	  case '$(am__configure_deps)' in \
+	    *$$dep*) \
+	      cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
+		&& exit 0; \
+	      exit 1;; \
+	  esac; \
+	done; \
+	echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign  src/include-glibc/Makefile'; \
+	cd $(top_srcdir) && \
+	  $(AUTOMAKE) --foreign  src/include-glibc/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+	@case '$?' in \
+	  *config.status*) \
+	    cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+	  *) \
+	    echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+	    cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+	esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure:  $(am__configure_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4):  $(am__aclocal_m4_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+mostlyclean-libtool:
+	-rm -f *.lo
+
+clean-libtool:
+	-rm -rf .libs _libs
+tags: TAGS
+TAGS:
+
+ctags: CTAGS
+CTAGS:
+
+
+distdir: $(DISTFILES)
+	@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+	topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+	list='$(DISTFILES)'; \
+	  dist_files=`for file in $$list; do echo $$file; done | \
+	  sed -e "s|^$$srcdirstrip/||;t" \
+	      -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+	case $$dist_files in \
+	  */*) $(MKDIR_P) `echo "$$dist_files" | \
+			   sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+			   sort -u` ;; \
+	esac; \
+	for file in $$dist_files; do \
+	  if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+	  if test -d $$d/$$file; then \
+	    dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+	    if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+	      cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+	    fi; \
+	    cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
+	  else \
+	    test -f $(distdir)/$$file \
+	    || cp -p $$d/$$file $(distdir)/$$file \
+	    || exit 1; \
+	  fi; \
+	done
+check-am: all-am
+check: check-am
+all-am: Makefile
+installdirs:
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+	@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+	$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+	  install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+	  `test -z '$(STRIP)' || \
+	    echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+	-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+	-test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES)
+
+maintainer-clean-generic:
+	@echo "This command is intended for maintainers to use"
+	@echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libtool mostlyclean-am
+
+distclean: distclean-am
+	-rm -f Makefile
+distclean-am: clean-am distclean-generic
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-info: install-info-am
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-ps: install-ps-am
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+	-rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-generic mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: install-am install-strip
+
+.PHONY: all all-am check check-am clean clean-generic clean-libtool \
+	distclean distclean-generic distclean-libtool distdir dvi \
+	dvi-am html html-am info info-am install install-am \
+	install-data install-data-am install-dvi install-dvi-am \
+	install-exec install-exec-am install-html install-html-am \
+	install-info install-info-am install-man install-pdf \
+	install-pdf-am install-ps install-ps-am install-strip \
+	installcheck installcheck-am installdirs maintainer-clean \
+	maintainer-clean-generic mostlyclean mostlyclean-generic \
+	mostlyclean-libtool pdf pdf-am ps ps-am uninstall uninstall-am
+
+
+.includes: ${top_builddir}/config.status
+	ln -sf $(KERNEL_INCLUDE)/linux
+	touch .includes
+
+all: .includes
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/src/include-glibc/glibc-bugs.h b/src/include-glibc/glibc-bugs.h
new file mode 100644
index 0000000..605c7a2
--- /dev/null
+++ b/src/include-glibc/glibc-bugs.h
@@ -0,0 +1,18 @@
+/*	$NetBSD: glibc-bugs.h,v 1.4 2006/09/09 16:22:08 manu Exp $	*/
+
+#ifndef __GLIBC_BUGS_H__
+#define __GLIBC_BUGS_H__ 1
+
+#define _XOPEN_SOURCE 500
+
+#ifdef ANDROID_CHANGES
+#define yywrap() 1
+#define YY_SKIP_YYWRAP
+#else
+#define _BSD_SOURCE
+#endif
+
+#include <features.h>
+#include <sys/types.h>
+
+#endif
diff --git a/src/include-glibc/glob.h b/src/include-glibc/glob.h
new file mode 100644
index 0000000..889d69d
--- /dev/null
+++ b/src/include-glibc/glob.h
@@ -0,0 +1,17 @@
+# define GLOB_TILDE  (1 << 12)/* Expand ~user and ~ to home directories. */
+
+typedef struct
+  {
+    int gl_pathc;		/* Count of paths matched by the pattern.  */
+    char **gl_pathv;		/* List of matched pathnames.  */
+    int gl_offs;		/* Slots to reserve in `gl_pathv'.  */
+    int gl_flags;		/* Set to FLAGS, maybe | GLOB_MAGCHAR.  */
+
+    /* If the GLOB_ALTDIRFUNC flag is set, the following functions
+       are used instead of the normal file access functions.  */
+    void (*gl_closedir) (void *);
+    void *(*gl_readdir) (void *);
+    void *(*gl_opendir) (__const char *);
+    int (*gl_lstat) (__const char *__restrict, void *__restrict);
+    int (*gl_stat) (__const char *__restrict, void *__restrict);
+  } glob_t;
diff --git a/src/include-glibc/linux/ipsec.h b/src/include-glibc/linux/ipsec.h
new file mode 100644
index 0000000..d3c5276
--- /dev/null
+++ b/src/include-glibc/linux/ipsec.h
@@ -0,0 +1,46 @@
+#ifndef _LINUX_IPSEC_H
+#define _LINUX_IPSEC_H
+
+/* The definitions, required to talk to KAME racoon IKE. */
+
+#include <linux/pfkeyv2.h>
+
+#define IPSEC_PORT_ANY		0
+#define IPSEC_ULPROTO_ANY	255
+#define IPSEC_PROTO_ANY		255
+
+enum {
+	IPSEC_MODE_ANY		= 0,	/* We do not support this for SA */
+	IPSEC_MODE_TRANSPORT	= 1,
+	IPSEC_MODE_TUNNEL	= 2
+};
+
+enum {
+	IPSEC_DIR_ANY		= 0,
+	IPSEC_DIR_INBOUND	= 1,
+	IPSEC_DIR_OUTBOUND	= 2,
+	IPSEC_DIR_FWD		= 3,	/* It is our own */
+	IPSEC_DIR_MAX		= 4,
+	IPSEC_DIR_INVALID	= 5
+};
+
+enum {
+	IPSEC_POLICY_DISCARD	= 0,
+	IPSEC_POLICY_NONE	= 1,
+	IPSEC_POLICY_IPSEC	= 2,
+	IPSEC_POLICY_ENTRUST	= 3,
+	IPSEC_POLICY_BYPASS	= 4
+};
+
+enum {
+	IPSEC_LEVEL_DEFAULT	= 0,
+	IPSEC_LEVEL_USE		= 1,
+	IPSEC_LEVEL_REQUIRE	= 2,
+	IPSEC_LEVEL_UNIQUE	= 3
+};
+
+#define IPSEC_MANUAL_REQID_MAX	0x3fff
+
+#define IPSEC_REPLAYWSIZE  32
+
+#endif	/* _LINUX_IPSEC_H */
diff --git a/src/include-glibc/net/pfkeyv2.h b/src/include-glibc/net/pfkeyv2.h
new file mode 100644
index 0000000..e8eb4f8
--- /dev/null
+++ b/src/include-glibc/net/pfkeyv2.h
@@ -0,0 +1,71 @@
+/*	$NetBSD: pfkeyv2.h,v 1.4 2006/09/09 16:22:08 manu Exp $	*/
+
+#ifndef __NET_PFKEYV2_H_
+#define __NET_PFKEYV2_H_ 1
+
+#include <stdint.h>
+#include <linux/pfkeyv2.h>
+
+/* Private allocations for authentication algorithms */
+#define SADB_AALG_SHA2_256		SADB_X_AALG_SHA2_256HMAC
+#define SADB_X_AALG_SHA2_256		SADB_X_AALG_SHA2_256HMAC
+#define SADB_AALG_SHA2_384		SADB_X_AALG_SHA2_384HMAC
+#define SADB_X_AALG_SHA2_384		SADB_X_AALG_SHA2_384HMAC
+#define SADB_AALG_SHA2_512		SADB_X_AALG_SHA2_512HMAC
+#define SADB_X_AALG_SHA2_512		SADB_X_AALG_SHA2_512HMAC
+#define SADB_AALG_RIPEMD160HMAC		SADB_X_AALG_RIPEMD160HMAC
+#define SADB_X_AALG_MD5              249
+#define SADB_X_AALG_SHA              250
+
+/* private allocations - based on RFC2407/IANA assignment */
+#define SADB_X_EALG_CAST128CBC	5	/* SADB_X_EALG_CASTCBC? == 6 */
+#define SADB_X_EALG_RIJNDAELCBC		SADB_X_EALG_AESCBC
+#define SADB_X_EALG_AES			SADB_X_EALG_AESCBC
+
+
+#define SADB_X_CALG_NONE	0
+#define SADB_X_CALG_OUI		1
+#define SADB_X_CALG_DEFLATE	2
+#define SADB_X_CALG_LZS		3
+#define SADB_X_CALG_MAX		4
+
+
+#define SADB_X_EXT_NONE		0x0000	/* i.e. new format. */
+#define SADB_X_EXT_OLD		0x0001	/* old format. */
+
+#define SADB_X_EXT_IV4B		0x0010	/* IV length of 4 bytes in use */
+#define SADB_X_EXT_DERIV	0x0020	/* DES derived */
+#define SADB_X_EXT_CYCSEQ	0x0040	/* allowing to cyclic sequence. */
+
+	/* three of followings are exclusive flags each them */
+#define SADB_X_EXT_PSEQ		0x0000	/* sequencial padding for ESP */
+#define SADB_X_EXT_PRAND	0x0100	/* random padding for ESP */
+#define SADB_X_EXT_PZERO	0x0200	/* zero padding for ESP */
+#define SADB_X_EXT_PMASK	0x0300	/* mask for padding flag */
+
+#define SADB_X_EXT_RAWCPI	0x0080	/* use well known CPI (IPComp) */
+
+
+#define PFKEY_SOFT_LIFETIME_RATE	80
+
+#define SADB_X_LIFETIME_ALLOCATIONS	0
+#define SADB_X_LIFETIME_BYTES		1
+#define SADB_X_LIFETIME_ADDTIME		2
+#define SADB_X_LIFETIME_USETIME		3
+
+
+#define PFKEY_ALIGN8(a) (1 + (((a) - 1) | (8 - 1)))
+#define	PFKEY_EXTLEN(msg) \
+	PFKEY_UNUNIT64(((struct sadb_ext *)(msg))->sadb_ext_len)
+#define PFKEY_ADDR_PREFIX(ext) \
+	(((struct sadb_address *)(ext))->sadb_address_prefixlen)
+#define PFKEY_ADDR_PROTO(ext) \
+	(((struct sadb_address *)(ext))->sadb_address_proto)
+#define PFKEY_ADDR_SADDR(ext) \
+	((struct sockaddr *)((caddr_t)(ext) + sizeof(struct sadb_address)))
+
+/* in 64bits */
+#define	PFKEY_UNUNIT64(a)	((a) << 3)
+#define	PFKEY_UNIT64(a)		((a) >> 3)
+
+#endif
diff --git a/src/include-glibc/netinet/ipsec.h b/src/include-glibc/netinet/ipsec.h
new file mode 100644
index 0000000..cbaf612
--- /dev/null
+++ b/src/include-glibc/netinet/ipsec.h
@@ -0,0 +1,4 @@
+/*	$NetBSD: ipsec.h,v 1.4 2006/09/09 16:22:09 manu Exp $	*/
+
+#include <net/pfkeyv2.h>
+#include <linux/ipsec.h>
diff --git a/src/include-glibc/sys/queue.h b/src/include-glibc/sys/queue.h
new file mode 100644
index 0000000..4a5ec75
--- /dev/null
+++ b/src/include-glibc/sys/queue.h
@@ -0,0 +1,454 @@
+/*	$NetBSD: queue.h,v 1.4 2006/09/09 16:22:09 manu Exp $	*/
+
+/*
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)queue.h	8.5 (Berkeley) 8/20/94
+ * $FreeBSD: src/sys/sys/queue.h,v 1.58 2004/04/07 04:19:49 imp Exp $
+ *
+ * 04/24/2004    Backport to v1.45 functionality for ipsec-tools
+ *               Heiko Hund <heiko@ist.eigentlich.net>
+ */
+
+#ifndef _SYS_QUEUE_H_
+#define _SYS_QUEUE_H_
+
+//#include <sys/cdefs.h>
+
+/*
+ * This file defines four types of data structures: singly-linked lists,
+ * singly-linked tail queues, lists and tail queues.
+ *
+ * A singly-linked list is headed by a single forward pointer. The elements
+ * are singly linked for minimum space and pointer manipulation overhead at
+ * the expense of O(n) removal for arbitrary elements. New elements can be
+ * added to the list after an existing element or at the head of the list.
+ * Elements being removed from the head of the list should use the explicit
+ * macro for this purpose for optimum efficiency. A singly-linked list may
+ * only be traversed in the forward direction.  Singly-linked lists are ideal
+ * for applications with large datasets and few or no removals or for
+ * implementing a LIFO queue.
+ *
+ * A singly-linked tail queue is headed by a pair of pointers, one to the
+ * head of the list and the other to the tail of the list. The elements are
+ * singly linked for minimum space and pointer manipulation overhead at the
+ * expense of O(n) removal for arbitrary elements. New elements can be added
+ * to the list after an existing element, at the head of the list, or at the
+ * end of the list. Elements being removed from the head of the tail queue
+ * should use the explicit macro for this purpose for optimum efficiency.
+ * A singly-linked tail queue may only be traversed in the forward direction.
+ * Singly-linked tail queues are ideal for applications with large datasets
+ * and few or no removals or for implementing a FIFO queue.
+ *
+ * A list is headed by a single forward pointer (or an array of forward
+ * pointers for a hash table header). The elements are doubly linked
+ * so that an arbitrary element can be removed without a need to
+ * traverse the list. New elements can be added to the list before
+ * or after an existing element or at the head of the list. A list
+ * may only be traversed in the forward direction.
+ *
+ * A tail queue is headed by a pair of pointers, one to the head of the
+ * list and the other to the tail of the list. The elements are doubly
+ * linked so that an arbitrary element can be removed without a need to
+ * traverse the list. New elements can be added to the list before or
+ * after an existing element, at the head of the list, or at the end of
+ * the list. A tail queue may be traversed in either direction.
+ *
+ * For details on the use of these macros, see the queue(3) manual page.
+ *
+ *
+ *			SLIST	LIST	STAILQ	TAILQ
+ * _HEAD		+	+	+	+
+ * _HEAD_INITIALIZER	+	+	+	+
+ * _ENTRY		+	+	+	+
+ * _INIT		+	+	+	+
+ * _EMPTY		+	+	+	+
+ * _FIRST		+	+	+	+
+ * _NEXT		+	+	+	+
+ * _PREV		-	-	-	+
+ * _LAST		-	-	+	+
+ * _FOREACH		+	+	+	+
+ * _FOREACH_REVERSE	-	-	-	+
+ * _INSERT_HEAD		+	+	+	+
+ * _INSERT_BEFORE	-	+	-	+
+ * _INSERT_AFTER	+	+	+	+
+ * _INSERT_TAIL		-	-	+	+
+ * _REMOVE_HEAD		+	-	+	-
+ * _REMOVE		+	+	+	+
+ *
+ */
+
+/*
+ * Singly-linked List declarations.
+ */
+#define	SLIST_HEAD(name, type)						\
+struct name {								\
+	struct type *slh_first;	/* first element */			\
+}
+
+#define	SLIST_HEAD_INITIALIZER(head)					\
+	{ NULL }
+ 
+#define	SLIST_ENTRY(type)						\
+struct {								\
+	struct type *sle_next;	/* next element */			\
+}
+ 
+/*
+ * Singly-linked List functions.
+ */
+#define	SLIST_EMPTY(head)	((head)->slh_first == NULL)
+
+#define	SLIST_FIRST(head)	((head)->slh_first)
+
+#define	SLIST_FOREACH(var, head, field)					\
+	for ((var) = SLIST_FIRST((head));				\
+	    (var);							\
+	    (var) = SLIST_NEXT((var), field))
+
+#define	SLIST_INIT(head) do {						\
+	SLIST_FIRST((head)) = NULL;					\
+} while (0)
+
+#define	SLIST_INSERT_AFTER(slistelm, elm, field) do {			\
+	SLIST_NEXT((elm), field) = SLIST_NEXT((slistelm), field);	\
+	SLIST_NEXT((slistelm), field) = (elm);				\
+} while (0)
+
+#define	SLIST_INSERT_HEAD(head, elm, field) do {			\
+	SLIST_NEXT((elm), field) = SLIST_FIRST((head));			\
+	SLIST_FIRST((head)) = (elm);					\
+} while (0)
+
+#define	SLIST_NEXT(elm, field)	((elm)->field.sle_next)
+
+#define	SLIST_REMOVE(head, elm, type, field) do {			\
+	if (SLIST_FIRST((head)) == (elm)) {				\
+		SLIST_REMOVE_HEAD((head), field);			\
+	}								\
+	else {								\
+		struct type *curelm = SLIST_FIRST((head));		\
+		while (SLIST_NEXT(curelm, field) != (elm))		\
+			curelm = SLIST_NEXT(curelm, field);		\
+		SLIST_NEXT(curelm, field) =				\
+		    SLIST_NEXT(SLIST_NEXT(curelm, field), field);	\
+	}								\
+} while (0)
+
+#define	SLIST_REMOVE_HEAD(head, field) do {				\
+	SLIST_FIRST((head)) = SLIST_NEXT(SLIST_FIRST((head)), field);	\
+} while (0)
+
+/*
+ * Singly-linked Tail queue declarations.
+ */
+#define	STAILQ_HEAD(name, type)						\
+struct name {								\
+	struct type *stqh_first;/* first element */			\
+	struct type **stqh_last;/* addr of last next element */		\
+}
+
+#define	STAILQ_HEAD_INITIALIZER(head)					\
+	{ NULL, &(head).stqh_first }
+
+#define	STAILQ_ENTRY(type)						\
+struct {								\
+	struct type *stqe_next;	/* next element */			\
+}
+
+/*
+ * Singly-linked Tail queue functions.
+ */
+#define	STAILQ_EMPTY(head)	((head)->stqh_first == NULL)
+
+#define	STAILQ_FIRST(head)	((head)->stqh_first)
+
+#define	STAILQ_FOREACH(var, head, field)				\
+	for((var) = STAILQ_FIRST((head));				\
+	   (var);							\
+	   (var) = STAILQ_NEXT((var), field))
+
+#define	STAILQ_INIT(head) do {						\
+	STAILQ_FIRST((head)) = NULL;					\
+	(head)->stqh_last = &STAILQ_FIRST((head));			\
+} while (0)
+
+#define	STAILQ_INSERT_AFTER(head, tqelm, elm, field) do {		\
+	if ((STAILQ_NEXT((elm), field) = STAILQ_NEXT((tqelm), field)) == NULL)\
+		(head)->stqh_last = &STAILQ_NEXT((elm), field);		\
+	STAILQ_NEXT((tqelm), field) = (elm);				\
+} while (0)
+
+#define	STAILQ_INSERT_HEAD(head, elm, field) do {			\
+	if ((STAILQ_NEXT((elm), field) = STAILQ_FIRST((head))) == NULL)	\
+		(head)->stqh_last = &STAILQ_NEXT((elm), field);		\
+	STAILQ_FIRST((head)) = (elm);					\
+} while (0)
+
+#define	STAILQ_INSERT_TAIL(head, elm, field) do {			\
+	STAILQ_NEXT((elm), field) = NULL;				\
+	*(head)->stqh_last = (elm);					\
+	(head)->stqh_last = &STAILQ_NEXT((elm), field);			\
+} while (0)
+
+#define	STAILQ_LAST(head, type, field)					\
+	(STAILQ_EMPTY(head) ?						\
+		NULL :							\
+	        ((struct type *)					\
+		((char *)((head)->stqh_last) - __offsetof(struct type, field))))
+
+#define	STAILQ_NEXT(elm, field)	((elm)->field.stqe_next)
+
+#define	STAILQ_REMOVE(head, elm, type, field) do {			\
+	if (STAILQ_FIRST((head)) == (elm)) {				\
+		STAILQ_REMOVE_HEAD(head, field);			\
+	}								\
+	else {								\
+		struct type *curelm = STAILQ_FIRST((head));		\
+		while (STAILQ_NEXT(curelm, field) != (elm))		\
+			curelm = STAILQ_NEXT(curelm, field);		\
+		if ((STAILQ_NEXT(curelm, field) =			\
+		     STAILQ_NEXT(STAILQ_NEXT(curelm, field), field)) == NULL)\
+			(head)->stqh_last = &STAILQ_NEXT((curelm), field);\
+	}								\
+} while (0)
+
+#define	STAILQ_REMOVE_HEAD(head, field) do {				\
+	if ((STAILQ_FIRST((head)) =					\
+	     STAILQ_NEXT(STAILQ_FIRST((head)), field)) == NULL)		\
+		(head)->stqh_last = &STAILQ_FIRST((head));		\
+} while (0)
+
+#define	STAILQ_REMOVE_HEAD_UNTIL(head, elm, field) do {			\
+	if ((STAILQ_FIRST((head)) = STAILQ_NEXT((elm), field)) == NULL)	\
+		(head)->stqh_last = &STAILQ_FIRST((head));		\
+} while (0)
+
+/*
+ * List declarations.
+ */
+#define	LIST_HEAD(name, type)						\
+struct name {								\
+	struct type *lh_first;	/* first element */			\
+}
+
+#define	LIST_HEAD_INITIALIZER(head)					\
+	{ NULL }
+
+#define	LIST_ENTRY(type)						\
+struct {								\
+	struct type *le_next;	/* next element */			\
+	struct type **le_prev;	/* address of previous next element */	\
+}
+
+/*
+ * List functions.
+ */
+
+#define	LIST_EMPTY(head)	((head)->lh_first == NULL)
+
+#define	LIST_FIRST(head)	((head)->lh_first)
+
+#define	LIST_FOREACH(var, head, field)					\
+	for ((var) = LIST_FIRST((head));				\
+	    (var);							\
+	    (var) = LIST_NEXT((var), field))
+
+#define	LIST_INIT(head) do {						\
+	LIST_FIRST((head)) = NULL;					\
+} while (0)
+
+#define	LIST_INSERT_AFTER(listelm, elm, field) do {			\
+	if ((LIST_NEXT((elm), field) = LIST_NEXT((listelm), field)) != NULL)\
+		LIST_NEXT((listelm), field)->field.le_prev =		\
+		    &LIST_NEXT((elm), field);				\
+	LIST_NEXT((listelm), field) = (elm);				\
+	(elm)->field.le_prev = &LIST_NEXT((listelm), field);		\
+} while (0)
+
+#define	LIST_INSERT_BEFORE(listelm, elm, field) do {			\
+	(elm)->field.le_prev = (listelm)->field.le_prev;		\
+	LIST_NEXT((elm), field) = (listelm);				\
+	*(listelm)->field.le_prev = (elm);				\
+	(listelm)->field.le_prev = &LIST_NEXT((elm), field);		\
+} while (0)
+
+#define	LIST_INSERT_HEAD(head, elm, field) do {				\
+	if ((LIST_NEXT((elm), field) = LIST_FIRST((head))) != NULL)	\
+		LIST_FIRST((head))->field.le_prev = &LIST_NEXT((elm), field);\
+	LIST_FIRST((head)) = (elm);					\
+	(elm)->field.le_prev = &LIST_FIRST((head));			\
+} while (0)
+
+#define	LIST_NEXT(elm, field)	((elm)->field.le_next)
+
+#define	LIST_REMOVE(elm, field) do {					\
+	if (LIST_NEXT((elm), field) != NULL)				\
+		LIST_NEXT((elm), field)->field.le_prev = 		\
+		    (elm)->field.le_prev;				\
+	*(elm)->field.le_prev = LIST_NEXT((elm), field);		\
+} while (0)
+
+/*
+ * Tail queue declarations.
+ */
+#define	TAILQ_HEAD(name, type)						\
+struct name {								\
+	struct type *tqh_first;	/* first element */			\
+	struct type **tqh_last;	/* addr of last next element */		\
+}
+
+#define	TAILQ_HEAD_INITIALIZER(head)					\
+	{ NULL, &(head).tqh_first }
+
+#define	TAILQ_ENTRY(type)						\
+struct {								\
+	struct type *tqe_next;	/* next element */			\
+	struct type **tqe_prev;	/* address of previous next element */	\
+}
+
+/*
+ * Tail queue functions.
+ */
+#define	TAILQ_EMPTY(head)	((head)->tqh_first == NULL)
+
+#define	TAILQ_FIRST(head)	((head)->tqh_first)
+
+#define	TAILQ_FOREACH(var, head, field)					\
+	for ((var) = TAILQ_FIRST((head));				\
+	    (var);							\
+	    (var) = TAILQ_NEXT((var), field))
+
+#define	TAILQ_FOREACH_REVERSE(var, head, headname, field)		\
+	for ((var) = TAILQ_LAST((head), headname);			\
+	    (var);							\
+	    (var) = TAILQ_PREV((var), headname, field))
+
+#define	TAILQ_INIT(head) do {						\
+	TAILQ_FIRST((head)) = NULL;					\
+	(head)->tqh_last = &TAILQ_FIRST((head));			\
+} while (0)
+
+#define	TAILQ_INSERT_AFTER(head, listelm, elm, field) do {		\
+	if ((TAILQ_NEXT((elm), field) = TAILQ_NEXT((listelm), field)) != NULL)\
+		TAILQ_NEXT((elm), field)->field.tqe_prev = 		\
+		    &TAILQ_NEXT((elm), field);				\
+	else								\
+		(head)->tqh_last = &TAILQ_NEXT((elm), field);		\
+	TAILQ_NEXT((listelm), field) = (elm);				\
+	(elm)->field.tqe_prev = &TAILQ_NEXT((listelm), field);		\
+} while (0)
+
+#define	TAILQ_INSERT_BEFORE(listelm, elm, field) do {			\
+	(elm)->field.tqe_prev = (listelm)->field.tqe_prev;		\
+	TAILQ_NEXT((elm), field) = (listelm);				\
+	*(listelm)->field.tqe_prev = (elm);				\
+	(listelm)->field.tqe_prev = &TAILQ_NEXT((elm), field);		\
+} while (0)
+
+#define	TAILQ_INSERT_HEAD(head, elm, field) do {			\
+	if ((TAILQ_NEXT((elm), field) = TAILQ_FIRST((head))) != NULL)	\
+		TAILQ_FIRST((head))->field.tqe_prev =			\
+		    &TAILQ_NEXT((elm), field);				\
+	else								\
+		(head)->tqh_last = &TAILQ_NEXT((elm), field);		\
+	TAILQ_FIRST((head)) = (elm);					\
+	(elm)->field.tqe_prev = &TAILQ_FIRST((head));			\
+} while (0)
+
+#define	TAILQ_INSERT_TAIL(head, elm, field) do {			\
+	TAILQ_NEXT((elm), field) = NULL;				\
+	(elm)->field.tqe_prev = (head)->tqh_last;			\
+	*(head)->tqh_last = (elm);					\
+	(head)->tqh_last = &TAILQ_NEXT((elm), field);			\
+} while (0)
+
+#define	TAILQ_LAST(head, headname)					\
+	(*(((struct headname *)((head)->tqh_last))->tqh_last))
+
+#define	TAILQ_NEXT(elm, field) ((elm)->field.tqe_next)
+
+#define	TAILQ_PREV(elm, headname, field)				\
+	(*(((struct headname *)((elm)->field.tqe_prev))->tqh_last))
+
+#define	TAILQ_REMOVE(head, elm, field) do {				\
+	if ((TAILQ_NEXT((elm), field)) != NULL)				\
+		TAILQ_NEXT((elm), field)->field.tqe_prev = 		\
+		    (elm)->field.tqe_prev;				\
+	else								\
+		(head)->tqh_last = (elm)->field.tqe_prev;		\
+	*(elm)->field.tqe_prev = TAILQ_NEXT((elm), field);		\
+} while (0)
+
+
+#ifdef _KERNEL
+
+/*
+ * XXX insque() and remque() are an old way of handling certain queues.
+ * They bogusly assumes that all queue heads look alike.
+ */
+
+struct quehead {
+	struct quehead *qh_link;
+	struct quehead *qh_rlink;
+};
+
+#ifdef	__GNUC__
+
+static __inline void
+insque(void *a, void *b)
+{
+	struct quehead *element = (struct quehead *)a,
+		 *head = (struct quehead *)b;
+
+	element->qh_link = head->qh_link;
+	element->qh_rlink = head;
+	head->qh_link = element;
+	element->qh_link->qh_rlink = element;
+}
+
+static __inline void
+remque(void *a)
+{
+	struct quehead *element = (struct quehead *)a;
+
+	element->qh_link->qh_rlink = element->qh_rlink;
+	element->qh_rlink->qh_link = element->qh_link;
+	element->qh_rlink = 0;
+}
+
+#else /* !__GNUC__ */
+
+void	insque __P((void *a, void *b));
+void	remque __P((void *a));
+
+#endif /* __GNUC__ */
+
+#endif /* _KERNEL */
+
+#endif /* !_SYS_QUEUE_H_ */
diff --git a/src/libipsec/Android.mk b/src/libipsec/Android.mk
new file mode 100755
index 0000000..ad1d7e4
--- /dev/null
+++ b/src/libipsec/Android.mk
@@ -0,0 +1,29 @@
+LOCAL_PATH:= $(call my-dir)
+
+L_CFLAGS += -O3 -DANDROID_CHANGES -DHAVE_CONFIG_H
+
+lib_SRC_FILES := ipsec_dump_policy.c ipsec_get_policylen.c ipsec_strerror.c \
+	key_debug.c pfkey.c pfkey_dump.c policy_parse.c policy_token.c
+
+common_C_INCLUDES += $(LOCAL_PATH)/../..
+
+common_SHARED_LIBRARIES = libc libcutils
+
+L_CFLAGS += -include $(LOCAL_PATH)/../../src/include-glibc/glibc-bugs.h \
+  -I$(LOCAL_PATH)/../../src/include-glibc -I$(LOCAL_PATH)/../../src/libipsec \
+  -Iexternal/openssl/include -I bionic/libc/private \
+  -DSYSCONFDIR=\"/etc\" -DADMINPORTDIR=\"/var/racoon\" -g -O2
+
+
+# For libracoon
+# =====================================================
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := $(lib_SRC_FILES)
+LOCAL_C_INCLUDES += $(common_C_INCLUDES)
+LOCAL_SHARED_LIBRARIES += $(common_SHARED_LIBRARIES)
+LOCAL_CFLAGS += $(L_CFLAGS)
+LOCAL_MODULE:= libipsec
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/src/libipsec/Makefile.am b/src/libipsec/Makefile.am
new file mode 100644
index 0000000..6a4e3b3
--- /dev/null
+++ b/src/libipsec/Makefile.am
@@ -0,0 +1,39 @@
+
+#bin_PROGRAMS = test-policy test-policy-priority
+lib_LTLIBRARIES = libipsec.la
+
+libipsecdir = $(includedir)/libipsec
+libipsec_HEADERS = libpfkey.h
+
+man3_MANS = ipsec_set_policy.3 ipsec_strerror.3
+
+AM_CFLAGS = @GLIBC_BUGS@
+AM_YFLAGS = -d -p __libipsec
+AM_LFLAGS = -P__libipsec -olex.yy.c
+
+BUILT_SOURCES = policy_parse.h
+
+libipsec_la_SOURCES = \
+  ipsec_dump_policy.c \
+  ipsec_get_policylen.c \
+  ipsec_strerror.c \
+  key_debug.c \
+  pfkey.c \
+  pfkey_dump.c \
+  policy_parse.y \
+  policy_token.l
+
+# version is current:revision:age.
+# See: http://www.gnu.org/manual/libtool-1.4.2/html_chapter/libtool_6.html#SEC32
+libipsec_la_LDFLAGS = -version-info 0:1:0
+libipsec_la_LIBADD = $(LEXLIB)
+
+noinst_HEADERS = ipsec_strerror.h
+
+#test_policy_SOURCES = test-policy.c
+#test_policy_LDFLAGS = libipsec.la
+
+#test_policy_priority_SOURCES = test-policy-priority.c
+#test_policy_priority_LDFLAGS = libipsec.la
+
+EXTRA_DIST = ${man3_MANS} test-policy.c
diff --git a/src/libipsec/Makefile.in b/src/libipsec/Makefile.in
new file mode 100644
index 0000000..748877a
--- /dev/null
+++ b/src/libipsec/Makefile.in
@@ -0,0 +1,627 @@
+# Makefile.in generated by automake 1.10.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008  Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+subdir = src/libipsec
+DIST_COMMON = $(libipsec_HEADERS) $(noinst_HEADERS) \
+	$(srcdir)/Makefile.am $(srcdir)/Makefile.in policy_parse.c \
+	policy_parse.h policy_token.c
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/acracoon.m4 \
+	$(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+	$(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+    $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+    *) f=$$p;; \
+  esac;
+am__strip_dir = `echo $$p | sed -e 's|^.*/||'`;
+am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(man3dir)" \
+	"$(DESTDIR)$(libipsecdir)"
+libLTLIBRARIES_INSTALL = $(INSTALL)
+LTLIBRARIES = $(lib_LTLIBRARIES)
+am__DEPENDENCIES_1 =
+libipsec_la_DEPENDENCIES = $(am__DEPENDENCIES_1)
+am_libipsec_la_OBJECTS = ipsec_dump_policy.lo ipsec_get_policylen.lo \
+	ipsec_strerror.lo key_debug.lo pfkey.lo pfkey_dump.lo \
+	policy_parse.lo policy_token.lo
+libipsec_la_OBJECTS = $(am_libipsec_la_OBJECTS)
+libipsec_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
+	$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+	$(libipsec_la_LDFLAGS) $(LDFLAGS) -o $@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+	$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+	--mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+	$(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+	--mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+	$(LDFLAGS) -o $@
+LEXCOMPILE = $(LEX) $(LFLAGS) $(AM_LFLAGS)
+LTLEXCOMPILE = $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+	--mode=compile $(LEX) $(LFLAGS) $(AM_LFLAGS)
+YLWRAP = $(top_srcdir)/ylwrap
+YACCCOMPILE = $(YACC) $(YFLAGS) $(AM_YFLAGS)
+LTYACCCOMPILE = $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+	--mode=compile $(YACC) $(YFLAGS) $(AM_YFLAGS)
+SOURCES = $(libipsec_la_SOURCES)
+DIST_SOURCES = $(libipsec_la_SOURCES)
+man3dir = $(mandir)/man3
+NROFF = nroff
+MANS = $(man3_MANS)
+libipsecHEADERS_INSTALL = $(INSTALL_HEADER)
+HEADERS = $(libipsec_HEADERS) $(noinst_HEADERS)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CONFIGURE_AMFLAGS = @CONFIGURE_AMFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CRYPTOBJS = @CRYPTOBJS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DSYMUTIL = @DSYMUTIL@
+ECHO = @ECHO@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+EXTRA_CRYPTO = @EXTRA_CRYPTO@
+F77 = @F77@
+FFLAGS = @FFLAGS@
+FRAG_OBJS = @FRAG_OBJS@
+GLIBC_BUGS = @GLIBC_BUGS@
+GREP = @GREP@
+HYBRID_OBJS = @HYBRID_OBJS@
+INCLUDE_GLIBC = @INCLUDE_GLIBC@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_OPTS = @INSTALL_OPTS@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+KERNEL_INCLUDE = @KERNEL_INCLUDE@
+KRB5_CONFIG = @KRB5_CONFIG@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+NATT_OBJS = @NATT_OBJS@
+NMEDIT = @NMEDIT@
+OBJEXT = @OBJEXT@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+RANLIB = @RANLIB@
+RPM = @RPM@
+SECCTX_OBJS = @SECCTX_OBJS@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+YACC = @YACC@
+YFLAGS = @YFLAGS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_F77 = @ac_ct_F77@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+include_racoondir = @include_racoondir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+
+#bin_PROGRAMS = test-policy test-policy-priority
+lib_LTLIBRARIES = libipsec.la
+libipsecdir = $(includedir)/libipsec
+libipsec_HEADERS = libpfkey.h
+man3_MANS = ipsec_set_policy.3 ipsec_strerror.3
+AM_CFLAGS = @GLIBC_BUGS@
+AM_YFLAGS = -d -p __libipsec
+AM_LFLAGS = -P__libipsec -olex.yy.c
+BUILT_SOURCES = policy_parse.h
+libipsec_la_SOURCES = \
+  ipsec_dump_policy.c \
+  ipsec_get_policylen.c \
+  ipsec_strerror.c \
+  key_debug.c \
+  pfkey.c \
+  pfkey_dump.c \
+  policy_parse.y \
+  policy_token.l
+
+
+# version is current:revision:age.
+# See: http://www.gnu.org/manual/libtool-1.4.2/html_chapter/libtool_6.html#SEC32
+libipsec_la_LDFLAGS = -version-info 0:1:0
+libipsec_la_LIBADD = $(LEXLIB)
+noinst_HEADERS = ipsec_strerror.h
+
+#test_policy_SOURCES = test-policy.c
+#test_policy_LDFLAGS = libipsec.la
+
+#test_policy_priority_SOURCES = test-policy-priority.c
+#test_policy_priority_LDFLAGS = libipsec.la
+EXTRA_DIST = ${man3_MANS} test-policy.c
+all: $(BUILT_SOURCES)
+	$(MAKE) $(AM_MAKEFLAGS) all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .l .lo .o .obj .y
+$(srcdir)/Makefile.in:  $(srcdir)/Makefile.am  $(am__configure_deps)
+	@for dep in $?; do \
+	  case '$(am__configure_deps)' in \
+	    *$$dep*) \
+	      cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
+		&& exit 0; \
+	      exit 1;; \
+	  esac; \
+	done; \
+	echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign  src/libipsec/Makefile'; \
+	cd $(top_srcdir) && \
+	  $(AUTOMAKE) --foreign  src/libipsec/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+	@case '$?' in \
+	  *config.status*) \
+	    cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+	  *) \
+	    echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+	    cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+	esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure:  $(am__configure_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4):  $(am__aclocal_m4_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+install-libLTLIBRARIES: $(lib_LTLIBRARIES)
+	@$(NORMAL_INSTALL)
+	test -z "$(libdir)" || $(MKDIR_P) "$(DESTDIR)$(libdir)"
+	@list='$(lib_LTLIBRARIES)'; for p in $$list; do \
+	  if test -f $$p; then \
+	    f=$(am__strip_dir) \
+	    echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(libLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) '$$p' '$(DESTDIR)$(libdir)/$$f'"; \
+	    $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(libLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) "$$p" "$(DESTDIR)$(libdir)/$$f"; \
+	  else :; fi; \
+	done
+
+uninstall-libLTLIBRARIES:
+	@$(NORMAL_UNINSTALL)
+	@list='$(lib_LTLIBRARIES)'; for p in $$list; do \
+	  p=$(am__strip_dir) \
+	  echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$p'"; \
+	  $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$p"; \
+	done
+
+clean-libLTLIBRARIES:
+	-test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES)
+	@list='$(lib_LTLIBRARIES)'; for p in $$list; do \
+	  dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+	  test "$$dir" != "$$p" || dir=.; \
+	  echo "rm -f \"$${dir}/so_locations\""; \
+	  rm -f "$${dir}/so_locations"; \
+	done
+policy_parse.h: policy_parse.c
+	@if test ! -f $@; then \
+	  rm -f policy_parse.c; \
+	  $(MAKE) $(AM_MAKEFLAGS) policy_parse.c; \
+	else :; fi
+libipsec.la: $(libipsec_la_OBJECTS) $(libipsec_la_DEPENDENCIES) 
+	$(libipsec_la_LINK) -rpath $(libdir) $(libipsec_la_OBJECTS) $(libipsec_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+	-rm -f *.$(OBJEXT)
+
+distclean-compile:
+	-rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ipsec_dump_policy.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ipsec_get_policylen.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ipsec_strerror.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/key_debug.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pfkey.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pfkey_dump.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/policy_parse.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/policy_token.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@	$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@	mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@	$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@	mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@	$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@	mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LTCOMPILE) -c -o $@ $<
+
+.l.c:
+	$(am__skiplex) $(SHELL) $(YLWRAP) $< $(LEX_OUTPUT_ROOT).c $@ -- $(LEXCOMPILE)
+
+.y.c:
+	$(am__skipyacc) $(SHELL) $(YLWRAP) $< y.tab.c $@ y.tab.h $*.h y.output $*.output -- $(YACCCOMPILE)
+
+mostlyclean-libtool:
+	-rm -f *.lo
+
+clean-libtool:
+	-rm -rf .libs _libs
+install-man3: $(man3_MANS) $(man_MANS)
+	@$(NORMAL_INSTALL)
+	test -z "$(man3dir)" || $(MKDIR_P) "$(DESTDIR)$(man3dir)"
+	@list='$(man3_MANS) $(dist_man3_MANS) $(nodist_man3_MANS)'; \
+	l2='$(man_MANS) $(dist_man_MANS) $(nodist_man_MANS)'; \
+	for i in $$l2; do \
+	  case "$$i" in \
+	    *.3*) list="$$list $$i" ;; \
+	  esac; \
+	done; \
+	for i in $$list; do \
+	  if test -f $(srcdir)/$$i; then file=$(srcdir)/$$i; \
+	  else file=$$i; fi; \
+	  ext=`echo $$i | sed -e 's/^.*\\.//'`; \
+	  case "$$ext" in \
+	    3*) ;; \
+	    *) ext='3' ;; \
+	  esac; \
+	  inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \
+	  inst=`echo $$inst | sed -e 's/^.*\///'`; \
+	  inst=`echo $$inst | sed '$(transform)'`.$$ext; \
+	  echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man3dir)/$$inst'"; \
+	  $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man3dir)/$$inst"; \
+	done
+uninstall-man3:
+	@$(NORMAL_UNINSTALL)
+	@list='$(man3_MANS) $(dist_man3_MANS) $(nodist_man3_MANS)'; \
+	l2='$(man_MANS) $(dist_man_MANS) $(nodist_man_MANS)'; \
+	for i in $$l2; do \
+	  case "$$i" in \
+	    *.3*) list="$$list $$i" ;; \
+	  esac; \
+	done; \
+	for i in $$list; do \
+	  ext=`echo $$i | sed -e 's/^.*\\.//'`; \
+	  case "$$ext" in \
+	    3*) ;; \
+	    *) ext='3' ;; \
+	  esac; \
+	  inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \
+	  inst=`echo $$inst | sed -e 's/^.*\///'`; \
+	  inst=`echo $$inst | sed '$(transform)'`.$$ext; \
+	  echo " rm -f '$(DESTDIR)$(man3dir)/$$inst'"; \
+	  rm -f "$(DESTDIR)$(man3dir)/$$inst"; \
+	done
+install-libipsecHEADERS: $(libipsec_HEADERS)
+	@$(NORMAL_INSTALL)
+	test -z "$(libipsecdir)" || $(MKDIR_P) "$(DESTDIR)$(libipsecdir)"
+	@list='$(libipsec_HEADERS)'; for p in $$list; do \
+	  if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+	  f=$(am__strip_dir) \
+	  echo " $(libipsecHEADERS_INSTALL) '$$d$$p' '$(DESTDIR)$(libipsecdir)/$$f'"; \
+	  $(libipsecHEADERS_INSTALL) "$$d$$p" "$(DESTDIR)$(libipsecdir)/$$f"; \
+	done
+
+uninstall-libipsecHEADERS:
+	@$(NORMAL_UNINSTALL)
+	@list='$(libipsec_HEADERS)'; for p in $$list; do \
+	  f=$(am__strip_dir) \
+	  echo " rm -f '$(DESTDIR)$(libipsecdir)/$$f'"; \
+	  rm -f "$(DESTDIR)$(libipsecdir)/$$f"; \
+	done
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+	list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '{ files[$$0] = 1; nonemtpy = 1; } \
+	      END { if (nonempty) { for (i in files) print i; }; }'`; \
+	mkid -fID $$unique
+tags: TAGS
+
+TAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+		$(TAGS_FILES) $(LISP)
+	tags=; \
+	here=`pwd`; \
+	list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+	      END { if (nonempty) { for (i in files) print i; }; }'`; \
+	if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
+	  test -n "$$unique" || unique=$$empty_fix; \
+	  $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+	    $$tags $$unique; \
+	fi
+ctags: CTAGS
+CTAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+		$(TAGS_FILES) $(LISP)
+	tags=; \
+	list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+	      END { if (nonempty) { for (i in files) print i; }; }'`; \
+	test -z "$(CTAGS_ARGS)$$tags$$unique" \
+	  || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+	     $$tags $$unique
+
+GTAGS:
+	here=`$(am__cd) $(top_builddir) && pwd` \
+	  && cd $(top_srcdir) \
+	  && gtags -i $(GTAGS_ARGS) $$here
+
+distclean-tags:
+	-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+	@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+	topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+	list='$(DISTFILES)'; \
+	  dist_files=`for file in $$list; do echo $$file; done | \
+	  sed -e "s|^$$srcdirstrip/||;t" \
+	      -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+	case $$dist_files in \
+	  */*) $(MKDIR_P) `echo "$$dist_files" | \
+			   sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+			   sort -u` ;; \
+	esac; \
+	for file in $$dist_files; do \
+	  if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+	  if test -d $$d/$$file; then \
+	    dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+	    if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+	      cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+	    fi; \
+	    cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
+	  else \
+	    test -f $(distdir)/$$file \
+	    || cp -p $$d/$$file $(distdir)/$$file \
+	    || exit 1; \
+	  fi; \
+	done
+check-am: all-am
+check: $(BUILT_SOURCES)
+	$(MAKE) $(AM_MAKEFLAGS) check-am
+all-am: Makefile $(LTLIBRARIES) $(MANS) $(HEADERS)
+installdirs:
+	for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(man3dir)" "$(DESTDIR)$(libipsecdir)"; do \
+	  test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+	done
+install: $(BUILT_SOURCES)
+	$(MAKE) $(AM_MAKEFLAGS) install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+	@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+	$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+	  install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+	  `test -z '$(STRIP)' || \
+	    echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+	-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+	@echo "This command is intended for maintainers to use"
+	@echo "it deletes files that may require special tools to rebuild."
+	-rm -f policy_parse.c
+	-rm -f policy_parse.h
+	-rm -f policy_token.c
+	-test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES)
+clean: clean-am
+
+clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \
+	mostlyclean-am
+
+distclean: distclean-am
+	-rm -rf ./$(DEPDIR)
+	-rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+	distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+info: info-am
+
+info-am:
+
+install-data-am: install-libipsecHEADERS install-man
+
+install-dvi: install-dvi-am
+
+install-exec-am: install-libLTLIBRARIES
+
+install-html: install-html-am
+
+install-info: install-info-am
+
+install-man: install-man3
+
+install-pdf: install-pdf-am
+
+install-ps: install-ps-am
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+	-rm -rf ./$(DEPDIR)
+	-rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+	mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-libLTLIBRARIES uninstall-libipsecHEADERS \
+	uninstall-man
+
+uninstall-man: uninstall-man3
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+	clean-libLTLIBRARIES clean-libtool ctags distclean \
+	distclean-compile distclean-generic distclean-libtool \
+	distclean-tags distdir dvi dvi-am html html-am info info-am \
+	install install-am install-data install-data-am install-dvi \
+	install-dvi-am install-exec install-exec-am install-html \
+	install-html-am install-info install-info-am \
+	install-libLTLIBRARIES install-libipsecHEADERS install-man \
+	install-man3 install-pdf install-pdf-am install-ps \
+	install-ps-am install-strip installcheck installcheck-am \
+	installdirs maintainer-clean maintainer-clean-generic \
+	mostlyclean mostlyclean-compile mostlyclean-generic \
+	mostlyclean-libtool pdf pdf-am ps ps-am tags uninstall \
+	uninstall-am uninstall-libLTLIBRARIES \
+	uninstall-libipsecHEADERS uninstall-man uninstall-man3
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/src/libipsec/ipsec_dump_policy.c b/src/libipsec/ipsec_dump_policy.c
new file mode 100644
index 0000000..bdadb47
--- /dev/null
+++ b/src/libipsec/ipsec_dump_policy.c
@@ -0,0 +1,416 @@
+/*	$NetBSD: ipsec_dump_policy.c,v 1.7.6.1 2007/08/01 11:52:17 vanhu Exp $	*/
+
+/* Id: ipsec_dump_policy.c,v 1.10 2005/06/29 09:12:37 manubsd Exp */
+
+/*
+ * Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+
+#include <netinet/in.h>
+#include PATH_IPSEC_H
+
+#include <arpa/inet.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <netdb.h>
+
+#include "ipsec_strerror.h"
+#include "libpfkey.h"
+
+static const char *ipsp_dir_strs[] = {
+	"any", "in", "out", "fwd"
+};
+
+static const char *ipsp_policy_strs[] = {
+	"discard", "none", "ipsec", "entrust", "bypass",
+};
+
+static char *ipsec_dump_ipsecrequest __P((char *, size_t,
+	struct sadb_x_ipsecrequest *, size_t, int));
+static char *ipsec_dump_policy1 __P((void *, const char *, int));
+static int set_addresses __P((char *, size_t, struct sockaddr *,
+	struct sockaddr *, int));
+static char *set_address __P((char *, size_t, struct sockaddr *, int));
+
+/*
+ * policy is sadb_x_policy buffer.
+ * Must call free() later.
+ * When delimiter == NULL, alternatively ' '(space) is applied.
+ */
+char *
+ipsec_dump_policy(policy, delimiter)
+	ipsec_policy_t policy;
+	__ipsec_const char *delimiter;
+{
+	return ipsec_dump_policy1(policy, delimiter, 0);
+}
+
+char *
+ipsec_dump_policy_withports(policy, delimiter)
+	void *policy;
+	const char *delimiter;
+{
+	return ipsec_dump_policy1(policy, delimiter, 1);
+}
+
+static char *
+ipsec_dump_policy1(policy, delimiter, withports)
+	void *policy;
+	const char *delimiter;
+	int withports;
+{
+	struct sadb_x_policy *xpl = policy;
+	struct sadb_x_ipsecrequest *xisr;
+	size_t off, buflen;
+	char *buf;
+	char isrbuf[1024];
+	char *newbuf;
+
+#ifdef HAVE_PFKEY_POLICY_PRIORITY
+	int32_t priority_offset;
+	char *priority_str;
+	char operator;
+#endif
+
+	/* sanity check */
+	if (policy == NULL)
+		return NULL;
+	if (xpl->sadb_x_policy_exttype != SADB_X_EXT_POLICY) {
+		__ipsec_errcode = EIPSEC_INVAL_EXTTYPE;
+		return NULL;
+	}
+
+	/* set delimiter */
+	if (delimiter == NULL)
+		delimiter = " ";
+
+#ifdef HAVE_PFKEY_POLICY_PRIORITY
+	if (xpl->sadb_x_policy_priority == 0)
+	{
+		priority_offset = 0;
+		priority_str = "";
+	}
+	/* find which constant the priority is closest to */
+	else if (xpl->sadb_x_policy_priority < 
+	         (u_int32_t) (PRIORITY_DEFAULT / 4) * 3)
+	{
+		priority_offset = xpl->sadb_x_policy_priority - PRIORITY_HIGH;
+		priority_str = "prio high";
+	}
+	else if (xpl->sadb_x_policy_priority >= 
+	         (u_int32_t) (PRIORITY_DEFAULT / 4) * 3 &&
+	         xpl->sadb_x_policy_priority < 
+	         (u_int32_t) (PRIORITY_DEFAULT / 4) * 5)
+	{
+		priority_offset = xpl->sadb_x_policy_priority - PRIORITY_DEFAULT;
+		priority_str = "prio def";
+	}
+	else
+	{
+		priority_offset = xpl->sadb_x_policy_priority - PRIORITY_LOW;
+		priority_str = "prio low";
+	}
+
+	/* fix sign to match the way it is input */
+	priority_offset *= -1;
+	if (priority_offset < 0)
+	{
+		operator = '-';
+		priority_offset *= -1;
+	}
+	else
+	{
+		operator = '+';
+	}
+#endif
+	
+	switch (xpl->sadb_x_policy_dir) {
+	case IPSEC_DIR_ANY:
+	case IPSEC_DIR_INBOUND:
+	case IPSEC_DIR_OUTBOUND:
+#ifdef HAVE_POLICY_FWD
+	case IPSEC_DIR_FWD:
+#endif
+		break;
+	default:
+		__ipsec_errcode = EIPSEC_INVAL_DIR;
+		return NULL;
+	}
+
+	switch (xpl->sadb_x_policy_type) {
+	case IPSEC_POLICY_DISCARD:
+	case IPSEC_POLICY_NONE:
+	case IPSEC_POLICY_IPSEC:
+	case IPSEC_POLICY_BYPASS:
+	case IPSEC_POLICY_ENTRUST:
+		break;
+	default:
+		__ipsec_errcode = EIPSEC_INVAL_POLICY;
+		return NULL;
+	}
+
+	buflen = strlen(ipsp_dir_strs[xpl->sadb_x_policy_dir])
+		+ 1	/* space */
+#ifdef HAVE_PFKEY_POLICY_PRIORITY
+		+ strlen(priority_str)
+		+ ((priority_offset != 0) ? 13 : 0) /* [space operator space int] */
+		+ ((strlen(priority_str) != 0) ? 1 : 0) /* space */
+#endif
+		+ strlen(ipsp_policy_strs[xpl->sadb_x_policy_type])
+		+ 1;	/* NUL */
+
+	if ((buf = malloc(buflen)) == NULL) {
+		__ipsec_errcode = EIPSEC_NO_BUFS;
+		return NULL;
+	}
+#ifdef HAVE_PFKEY_POLICY_PRIORITY
+	if (priority_offset != 0)
+	{
+		snprintf(buf, buflen, "%s %s %c %u %s", 
+	    	ipsp_dir_strs[xpl->sadb_x_policy_dir], priority_str, operator, 
+			priority_offset, ipsp_policy_strs[xpl->sadb_x_policy_type]);
+	}
+	else if (strlen (priority_str) != 0)
+	{
+		snprintf(buf, buflen, "%s %s %s", 
+	    	ipsp_dir_strs[xpl->sadb_x_policy_dir], priority_str, 
+			ipsp_policy_strs[xpl->sadb_x_policy_type]);
+	}
+	else
+	{
+		snprintf(buf, buflen, "%s %s", 
+	    	ipsp_dir_strs[xpl->sadb_x_policy_dir],
+			ipsp_policy_strs[xpl->sadb_x_policy_type]);
+	}
+#else
+	snprintf(buf, buflen, "%s %s", ipsp_dir_strs[xpl->sadb_x_policy_dir],
+	    ipsp_policy_strs[xpl->sadb_x_policy_type]);
+#endif
+
+	if (xpl->sadb_x_policy_type != IPSEC_POLICY_IPSEC) {
+		__ipsec_errcode = EIPSEC_NO_ERROR;
+		return buf;
+	}
+
+	/* count length of buffer for use */
+	off = sizeof(*xpl);
+	while (off < PFKEY_EXTLEN(xpl)) {
+		xisr = (void *)((caddr_t)(void *)xpl + off);
+		off += xisr->sadb_x_ipsecrequest_len;
+	}
+
+	/* validity check */
+	if (off != PFKEY_EXTLEN(xpl)) {
+		__ipsec_errcode = EIPSEC_INVAL_SADBMSG;
+		free(buf);
+		return NULL;
+	}
+
+	off = sizeof(*xpl);
+	while (off < PFKEY_EXTLEN(xpl)) {
+		int offset;
+		xisr = (void *)((caddr_t)(void *)xpl + off);
+
+		if (ipsec_dump_ipsecrequest(isrbuf, sizeof(isrbuf), xisr,
+		    PFKEY_EXTLEN(xpl) - off, withports) == NULL) {
+			free(buf);
+			return NULL;
+		}
+
+		offset = strlen(buf);
+		buflen = offset + strlen(delimiter) + strlen(isrbuf) + 1;
+		newbuf = (char *)realloc(buf, buflen);
+		if (newbuf == NULL) {
+			__ipsec_errcode = EIPSEC_NO_BUFS;
+			free(buf);
+			return NULL;
+		}
+		buf = newbuf;
+		snprintf(buf+offset, buflen-offset, "%s%s", delimiter, isrbuf);
+
+		off += xisr->sadb_x_ipsecrequest_len;
+	}
+
+	__ipsec_errcode = EIPSEC_NO_ERROR;
+	return buf;
+}
+
+static char *
+ipsec_dump_ipsecrequest(buf, len, xisr, bound, withports)
+	char *buf;
+	size_t len;
+	struct sadb_x_ipsecrequest *xisr;
+	size_t bound;	/* boundary */
+	int withports;
+{
+	const char *proto, *mode, *level;
+	char abuf[NI_MAXHOST * 2 + 2];
+
+	if (xisr->sadb_x_ipsecrequest_len > bound) {
+		__ipsec_errcode = EIPSEC_INVAL_PROTO;
+		return NULL;
+	}
+
+	switch (xisr->sadb_x_ipsecrequest_proto) {
+	case IPPROTO_ESP:
+		proto = "esp";
+		break;
+	case IPPROTO_AH:
+		proto = "ah";
+		break;
+	case IPPROTO_IPCOMP:
+		proto = "ipcomp";
+		break;
+	default:
+		__ipsec_errcode = EIPSEC_INVAL_PROTO;
+		return NULL;
+	}
+
+	switch (xisr->sadb_x_ipsecrequest_mode) {
+	case IPSEC_MODE_ANY:
+		mode = "any";
+		break;
+	case IPSEC_MODE_TRANSPORT:
+		mode = "transport";
+		break;
+	case IPSEC_MODE_TUNNEL:
+		mode = "tunnel";
+		break;
+	default:
+		__ipsec_errcode = EIPSEC_INVAL_MODE;
+		return NULL;
+	}
+
+	abuf[0] = '\0';
+	if (xisr->sadb_x_ipsecrequest_len > sizeof(*xisr)) {
+		struct sockaddr *sa1, *sa2;
+		caddr_t p;
+
+		p = (void *)(xisr + 1);
+		sa1 = (void *)p;
+		sa2 = (void *)(p + sysdep_sa_len(sa1));
+		if (sizeof(*xisr) + sysdep_sa_len(sa1) + sysdep_sa_len(sa2) !=
+		    xisr->sadb_x_ipsecrequest_len) {
+			__ipsec_errcode = EIPSEC_INVAL_ADDRESS;
+			return NULL;
+		}
+		if (set_addresses(abuf, sizeof(abuf), 
+		    sa1, sa2, withports) != 0) {
+			__ipsec_errcode = EIPSEC_INVAL_ADDRESS;
+			return NULL;
+		}
+	}
+
+	switch (xisr->sadb_x_ipsecrequest_level) {
+	case IPSEC_LEVEL_DEFAULT:
+		level = "default";
+		break;
+	case IPSEC_LEVEL_USE:
+		level = "use";
+		break;
+	case IPSEC_LEVEL_REQUIRE:
+		level = "require";
+		break;
+	case IPSEC_LEVEL_UNIQUE:
+		level = "unique";
+		break;
+	default:
+		__ipsec_errcode = EIPSEC_INVAL_LEVEL;
+		return NULL;
+	}
+
+	if (xisr->sadb_x_ipsecrequest_reqid == 0)
+		snprintf(buf, len, "%s/%s/%s/%s", proto, mode, abuf, level);
+	else {
+		int ch;
+
+		if (xisr->sadb_x_ipsecrequest_reqid > IPSEC_MANUAL_REQID_MAX)
+			ch = '#';
+		else
+			ch = ':';
+		snprintf(buf, len, "%s/%s/%s/%s%c%u", proto, mode, abuf, level,
+		    ch, xisr->sadb_x_ipsecrequest_reqid);
+	}
+
+	return buf;
+}
+
+static int
+set_addresses(buf, len, sa1, sa2, withports)
+	char *buf;
+	size_t len;
+	struct sockaddr *sa1;
+	struct sockaddr *sa2;
+	int withports;
+{
+	char tmp1[NI_MAXHOST], tmp2[NI_MAXHOST];
+
+	if (set_address(tmp1, sizeof(tmp1), sa1, withports) == NULL ||
+	    set_address(tmp2, sizeof(tmp2), sa2, withports) == NULL)
+		return -1;
+	if (strlen(tmp1) + 1 + strlen(tmp2) + 1 > len)
+		return -1;
+	snprintf(buf, len, "%s-%s", tmp1, tmp2);
+	return 0;
+}
+
+static char *
+set_address(buf, len, sa, withports)
+	char *buf;
+	size_t len;
+	struct sockaddr *sa;
+	int withports;
+{
+	const int niflags = NI_NUMERICHOST | NI_NUMERICSERV;
+	char host[NI_MAXHOST];
+	char serv[NI_MAXSERV];
+
+	if (len < 1)
+		return NULL;
+	buf[0] = '\0';
+	if (getnameinfo(sa, (socklen_t)sysdep_sa_len(sa), host, sizeof(host), 
+	    serv, sizeof(serv), niflags) != 0)
+		return NULL;
+
+	if (withports)
+		snprintf(buf, len, "%s[%s]", host, serv);
+	else
+		snprintf(buf, len, "%s", host);
+
+	return buf;
+}
diff --git a/src/libipsec/ipsec_dump_policy.d b/src/libipsec/ipsec_dump_policy.d
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/libipsec/ipsec_dump_policy.d
diff --git a/src/libipsec/ipsec_get_policylen.c b/src/libipsec/ipsec_get_policylen.c
new file mode 100644
index 0000000..2f4f6e9
--- /dev/null
+++ b/src/libipsec/ipsec_get_policylen.c
@@ -0,0 +1,54 @@
+/*	$NetBSD: ipsec_get_policylen.c,v 1.6.6.1 2007/08/01 11:52:17 vanhu Exp $	*/
+
+/*	$KAME: ipsec_get_policylen.c,v 1.5 2000/05/07 05:25:03 itojun Exp $	*/
+
+/*
+ * Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+
+#include PATH_IPSEC_H
+
+#include <net/pfkeyv2.h>
+
+#include "libpfkey.h"
+#include "ipsec_strerror.h"
+
+int
+ipsec_get_policylen(policy)
+	ipsec_policy_t policy;
+{
+	return policy ? PFKEY_EXTLEN(policy) : -1;
+}
diff --git a/src/libipsec/ipsec_set_policy.3 b/src/libipsec/ipsec_set_policy.3
new file mode 100644
index 0000000..643b582
--- /dev/null
+++ b/src/libipsec/ipsec_set_policy.3
@@ -0,0 +1,328 @@
+.\"	$NetBSD: ipsec_set_policy.3,v 1.13 2006/09/09 16:22:09 manu Exp $
+.\"
+.\"	$KAME: ipsec_set_policy.3,v 1.16 2003/01/06 21:59:03 sumikawa Exp $
+.\"
+.\" Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project.
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\" 3. Neither the name of the project nor the names of its contributors
+.\"    may be used to endorse or promote products derived from this software
+.\"    without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.Dd May 5, 1998
+.Dt IPSEC_SET_POLICY 3
+.Os
+.Sh NAME
+.Nm ipsec_set_policy ,
+.Nm ipsec_get_policylen ,
+.Nm ipsec_dump_policy
+.Nd manipulate IPsec policy specification structure from human-readable policy string
+.\"
+.Sh LIBRARY
+.Lb libipsec
+.Sh SYNOPSIS
+.In netinet6/ipsec.h
+.Ft "char *"
+.Fn ipsec_set_policy "char *policy" "int len"
+.Ft int
+.Fn ipsec_get_policylen "char *buf"
+.Ft "char *"
+.Fn ipsec_dump_policy "char *buf" "char *delim"
+.Sh DESCRIPTION
+.Fn ipsec_set_policy
+generates an IPsec policy specification structure, namely
+.Li struct sadb_x_policy
+and/or
+.Li struct sadb_x_ipsecrequest
+from a human-readable policy specification.
+The policy specification must be given as a C string
+.Fa policy
+and its length
+.Fa len .
+.Fn ipsec_set_policy
+will return a buffer with the corresponding IPsec policy specification structure.
+The buffer is dynamically allocated, and must be
+.Xr free 3 Ap d
+by the caller.
+.Pp
+You can get the length of the generated buffer with
+.Fn ipsec_get_policylen
+(i.e. for calling
+.Xr setsockopt 2 ) .
+.Pp
+.Fn ipsec_dump_policy
+converts an IPsec policy structure into human-readable form.
+Therefore,
+.Fn ipsec_dump_policy
+can be regarded as the inverse function to
+.Fn ipsec_set_policy .
+.Fa buf
+points to an IPsec policy structure,
+.Li struct sadb_x_policy .
+.Fa delim
+is a delimiter string, which is usually a blank character.
+If you set
+.Fa delim
+to
+.Dv NULL ,
+a single whitespace is assumed.
+.Fn ipsec_dump_policy
+returns a pointer to a dynamically allocated string.
+It is the caller's responsibility to
+.Xr free 3
+it.
+.Pp
+.Fa policy
+is formatted as either of the following:
+.Bl -tag  -width "discard"
+.It Ar direction [priority specification] Li discard
+.Ar direction
+must be
+.Li in ,
+.Li out ,
+or
+.Li fwd .
+.Ar direction
+specifies in which direction the policy needs to be applied.
+The non-standard direction
+.Li fwd
+is substituted with
+.Li in
+on platforms which do not support forward policies.
+.Pp
+.Ar priority specification
+is used to control the placement of the policy within the SPD.
+The policy position is determined by
+a signed integer where higher priorities indicate the policy is placed
+closer to the beginning of the list and lower priorities indicate the
+policy is placed closer to the end of the list.
+Policies with equal
+priorities are added at the end of the group of such policies.
+.Pp
+Priority can only
+be specified when libipsec has been compiled against kernel headers that
+support policy priorities (Linux \*[Gt]= 2.6.6).
+It takes one of the following formats:
+.Bl -tag  -width "discard"
+.It Xo
+.Ar {priority,prio} offset
+.Xc
+.Ar offset
+is an integer in the range -2147483647..214783648.
+.It Xo
+.Ar {priority,prio} base {+,-} offset
+.Xc
+.Ar base
+is either
+.Li low (-1073741824) ,
+.Li def (0) ,
+or
+.Li high (1073741824) .
+.Pp
+.Ar offset
+is an unsigned integer.
+It can be up to 1073741824 for
+positive offsets, and up to 1073741823 for negative offsets.
+.El
+.Pp
+The interpretation of policy priority in these functions and the
+kernel DOES differ.
+The relationship between the two can be described as
+p(kernel) = 0x80000000 - p(func)
+.Pp
+With
+.Li discard
+policy, packets will be dropped if they match the policy.
+.It Ar direction [priority specification] Li entrust
+.Li entrust
+means to consult the SPD defined by
+.Xr setkey 8 .
+.It Ar direction [priority specification] Li bypass
+.Li bypass
+means to bypass the IPsec processing.
+.Pq the packet will be transmitted in clear .
+This is for privileged sockets.
+.It Xo
+.Ar direction
+.Bq Ar priority specification
+.Li ipsec
+.Ar request ...
+.Xc
+.Li ipsec
+means that the matching packets are subject to IPsec processing.
+.Li ipsec
+can be followed by one or more
+.Ar request
+strings, which are formatted as below:
+.Bl -tag  -width "discard"
+.It Xo
+.Ar protocol
+.Li /
+.Ar mode
+.Li /
+.Ar src
+.Li -
+.Ar dst
+.Op Ar /level
+.Xc
+.Ar protocol
+is either
+.Li ah ,
+.Li esp ,
+or
+.Li ipcomp .
+.Pp
+.Ar mode
+is either
+.Li transport
+or
+.Li tunnel .
+.Pp
+.Ar src
+and
+.Ar dst
+specifies the IPsec endpoint.
+.Ar src
+always means the
+.Dq sending node
+and
+.Ar dst
+always means the
+.Dq receiving node .
+Therefore, when
+.Ar direction
+is
+.Li in ,
+.Ar dst
+is this node
+and
+.Ar src
+is the other node
+.Pq peer .
+If
+.Ar mode
+is
+.Li transport ,
+Both
+.Ar src
+and
+.Ar dst
+can be omitted.
+.Pp
+.Ar level
+must be set to one of the following:
+.Li default , use , require ,
+or
+.Li unique .
+.Li default
+means that the kernel should consult the system default policy
+defined by
+.Xr sysctl 8 ,
+such as
+.Li net.inet.ipsec.esp_trans_deflev .
+See
+.Xr ipsec 4
+regarding the system default.
+.Li use
+means that a relevant SA can be used when available,
+since the kernel may perform IPsec operation against packets when possible.
+In this case, packets can be transmitted in clear
+.Pq when SA is not available ,
+or encrypted
+.Pq when SA is available .
+.Li require
+means that a relevant SA is required,
+since the kernel must perform IPsec operation against packets.
+.Li unique
+is the same as
+.Li require ,
+but adds the restriction that the SA for outbound traffic is used
+only for this policy.
+You may need the identifier in order to relate the policy and the SA
+when you define the SA by manual keying.
+You can put the decimal number as the identifier after
+.Li unique
+like
+.Li unique : number .
+.Li number
+must be between 1 and 32767 .
+If the
+.Ar request
+string is kept unambiguous,
+.Ar level
+and slash prior to
+.Ar level
+can be omitted.
+However, it is encouraged to specify them explicitly
+to avoid unintended behavior.
+If
+.Ar level
+is omitted, it will be interpreted as
+.Li default .
+.El
+.Pp
+Note that there are slight differences to the specification of
+.Xr setkey 8 .
+In the specification of
+.Xr setkey 8 ,
+both
+.Li entrust
+and
+.Li bypass
+are not used.
+Refer to
+.Xr setkey 8
+for details.
+.Pp
+Here are several examples
+.Pq long lines are wrapped for readability :
+.Bd -literal -offset indent
+in discard
+out ipsec esp/transport//require
+in ipsec ah/transport//require
+out ipsec esp/tunnel/10.1.1.2-10.1.1.1/use
+in ipsec ipcomp/transport//use
+        esp/transport//use
+.Ed
+.El
+.Sh RETURN VALUES
+.Fn ipsec_set_policy
+returns a pointer to the allocated buffer with the policy specification
+if successful; otherwise a
+.Dv NULL
+pointer is returned.
+.Fn ipsec_get_policylen
+returns a positive value
+.Pq meaning the buffer size
+on success, and a negative value on errors.
+.Fn ipsec_dump_policy
+returns a pointer to a dynamically allocated region on success,
+and
+.Dv NULL
+on errors.
+.Sh SEE ALSO
+.Xr ipsec_strerror 3 ,
+.Xr ipsec 4 ,
+.Xr setkey 8
+.Sh HISTORY
+The functions first appeared in the WIDE/KAME IPv6 protocol stack kit.
diff --git a/src/libipsec/ipsec_strerror.3 b/src/libipsec/ipsec_strerror.3
new file mode 100644
index 0000000..c2e86cd
--- /dev/null
+++ b/src/libipsec/ipsec_strerror.3
@@ -0,0 +1,88 @@
+.\"	$NetBSD: ipsec_strerror.3,v 1.10 2006/09/09 16:22:09 manu Exp $
+.\"
+.\"	$KAME: ipsec_strerror.3,v 1.9 2001/08/17 07:21:36 itojun Exp $
+.\"
+.\" Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project.
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\" 3. Neither the name of the project nor the names of its contributors
+.\"    may be used to endorse or promote products derived from this software
+.\"    without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.Dd May 6, 1998
+.Dt IPSEC_STRERROR 3
+.Os
+.\"
+.Sh NAME
+.Nm ipsec_strerror
+.Nd error messages for the IPsec policy manipulation library
+.\"
+.Sh LIBRARY
+.Lb libipsec
+.Sh SYNOPSIS
+.In netinet6/ipsec.h
+.Ft "const char *"
+.Fn ipsec_strerror void
+.\"
+.Sh DESCRIPTION
+.Pa netinet6/ipsec.h
+declares
+.Pp
+.Dl extern int ipsec_errcode ;
+.Pp
+which is used to pass an error code from the IPsec policy manipulation
+library to a program.
+.Fn ipsec_strerror
+can be used to obtain the error message string for the error code.
+.Pp
+The array pointed to is not to be modified by the calling program.
+Since
+.Fn ipsec_strerror
+uses
+.Xr strerror 3
+as underlying function, calling
+.Xr strerror 3
+after
+.Fn ipsec_strerror
+will make the return value from
+.Fn ipsec_strerror
+invalid or overwritten.
+.\"
+.Sh RETURN VALUES
+.Fn ipsec_strerror
+always returns a pointer to a C string.
+The C string must not be overwritten by the calling program.
+.\"
+.Sh SEE ALSO
+.Xr ipsec_set_policy 3
+.\"
+.Sh HISTORY
+.Fn ipsec_strerror
+first appeared in the WIDE/KAME IPv6 protocol stack kit.
+.\"
+.Sh BUGS
+.Fn ipsec_strerror
+will return its result which may be overwritten by subsequent calls.
+.Pp
+.Va ipsec_errcode
+is not thread safe.
diff --git a/src/libipsec/ipsec_strerror.c b/src/libipsec/ipsec_strerror.c
new file mode 100644
index 0000000..ad1ab2a
--- /dev/null
+++ b/src/libipsec/ipsec_strerror.c
@@ -0,0 +1,96 @@
+/*	$NetBSD: ipsec_strerror.c,v 1.4.6.1 2007/08/01 11:52:17 vanhu Exp $	*/
+
+/*	$KAME: ipsec_strerror.c,v 1.7 2000/07/30 00:45:12 itojun Exp $	*/
+
+/*
+ * Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/types.h>
+#include <sys/param.h>
+
+#include <string.h>
+#include PATH_IPSEC_H
+
+#include "ipsec_strerror.h"
+
+int __ipsec_errcode;
+
+static const char *ipsec_errlist[] = {
+"Success",					/*EIPSEC_NO_ERROR*/
+"Not supported",				/*EIPSEC_NOT_SUPPORTED*/
+"Invalid argument",				/*EIPSEC_INVAL_ARGUMENT*/
+"Invalid sadb message",				/*EIPSEC_INVAL_SADBMSG*/
+"Invalid version",				/*EIPSEC_INVAL_VERSION*/
+"Invalid security policy",			/*EIPSEC_INVAL_POLICY*/
+"Invalid address specification",		/*EIPSEC_INVAL_ADDRESS*/
+"Invalid ipsec protocol",			/*EIPSEC_INVAL_PROTO*/
+"Invalid ipsec mode",				/*EIPSEC_INVAL_MODE*/
+"Invalid ipsec level",				/*EIPSEC_INVAL_LEVEL*/
+"Invalid SA type",				/*EIPSEC_INVAL_SATYPE*/
+"Invalid message type",				/*EIPSEC_INVAL_MSGTYPE*/
+"Invalid extension type",			/*EIPSEC_INVAL_EXTTYPE*/
+"Invalid algorithm type",			/*EIPSEC_INVAL_ALGS*/
+"Invalid key length",				/*EIPSEC_INVAL_KEYLEN*/
+"Invalid address family",			/*EIPSEC_INVAL_FAMILY*/
+"Invalid prefix length",			/*EIPSEC_INVAL_PREFIXLEN*/
+"Invalid direciton",				/*EIPSEC_INVAL_DIR*/
+"SPI range violation",				/*EIPSEC_INVAL_SPI*/
+"No protocol specified",			/*EIPSEC_NO_PROTO*/
+"No algorithm specified",			/*EIPSEC_NO_ALGS*/
+"No buffers available",				/*EIPSEC_NO_BUFS*/
+"Must get supported algorithms list first",	/*EIPSEC_DO_GET_SUPP_LIST*/
+"Protocol mismatch",				/*EIPSEC_PROTO_MISMATCH*/
+"Family mismatch",				/*EIPSEC_FAMILY_MISMATCH*/
+"Too few arguments",				/*EIPSEC_FEW_ARGUMENTS*/
+NULL,						/*EIPSEC_SYSTEM_ERROR*/
+"Priority offset not in valid range [-2147483647, 2147483648]",	/*EIPSEC_INVAL_PRIORITY_OFFSET*/
+"Priority offset from base not in valid range [0, 1073741823] for negative offsets and [0, 1073741824] for positive offsets", /* EIPSEC_INVAL_PRIORITY_OFFSET */
+"Policy priority not compiled in",	/*EIPSEC_PRIORITY_NOT_COMPILED*/
+"Unknown error",				/*EIPSEC_MAX*/
+};
+
+const char *ipsec_strerror(void)
+{
+	if (__ipsec_errcode < 0 || __ipsec_errcode > EIPSEC_MAX)
+		__ipsec_errcode = EIPSEC_MAX;
+
+	return ipsec_errlist[__ipsec_errcode];
+}
+
+void __ipsec_set_strerror(const char *str)
+{
+	__ipsec_errcode = EIPSEC_SYSTEM_ERROR;
+	ipsec_errlist[EIPSEC_SYSTEM_ERROR] = str;
+
+	return;
+}
diff --git a/src/libipsec/ipsec_strerror.h b/src/libipsec/ipsec_strerror.h
new file mode 100644
index 0000000..2b4264f
--- /dev/null
+++ b/src/libipsec/ipsec_strerror.h
@@ -0,0 +1,73 @@
+/*	$NetBSD: ipsec_strerror.h,v 1.4 2006/09/09 16:22:09 manu Exp $	*/
+
+/* Id: ipsec_strerror.h,v 1.4 2004/06/07 09:18:46 ludvigm Exp */
+
+/*
+ * Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _IPSEC_STRERROR_H
+#define _IPSEC_STRERROR_H
+
+extern int __ipsec_errcode;
+extern void __ipsec_set_strerror __P((const char *));
+
+#define EIPSEC_NO_ERROR		0	/*success*/
+#define EIPSEC_NOT_SUPPORTED	1	/*not supported*/
+#define EIPSEC_INVAL_ARGUMENT	2	/*invalid argument*/
+#define EIPSEC_INVAL_SADBMSG	3	/*invalid sadb message*/
+#define EIPSEC_INVAL_VERSION	4	/*invalid version*/
+#define EIPSEC_INVAL_POLICY	5	/*invalid security policy*/
+#define EIPSEC_INVAL_ADDRESS	6	/*invalid address specification*/
+#define EIPSEC_INVAL_PROTO	7	/*invalid ipsec protocol*/
+#define EIPSEC_INVAL_MODE	8	/*Invalid ipsec mode*/
+#define EIPSEC_INVAL_LEVEL	9	/*invalid ipsec level*/
+#define EIPSEC_INVAL_SATYPE	10	/*invalid SA type*/
+#define EIPSEC_INVAL_MSGTYPE	11	/*invalid message type*/
+#define EIPSEC_INVAL_EXTTYPE	12	/*invalid extension type*/
+#define EIPSEC_INVAL_ALGS	13	/*Invalid algorithm type*/
+#define EIPSEC_INVAL_KEYLEN	14	/*invalid key length*/
+#define EIPSEC_INVAL_FAMILY	15	/*invalid address family*/
+#define EIPSEC_INVAL_PREFIXLEN	16	/*SPI range violation*/
+#define EIPSEC_INVAL_DIR	17	/*Invalid direciton*/
+#define EIPSEC_INVAL_SPI	18	/*invalid prefixlen*/
+#define EIPSEC_NO_PROTO		19	/*no protocol specified*/
+#define EIPSEC_NO_ALGS		20	/*No algorithm specified*/
+#define EIPSEC_NO_BUFS		21	/*no buffers available*/
+#define EIPSEC_DO_GET_SUPP_LIST	22	/*must get supported algorithm first*/
+#define EIPSEC_PROTO_MISMATCH	23	/*protocol mismatch*/
+#define EIPSEC_FAMILY_MISMATCH	24	/*family mismatch*/
+#define EIPSEC_FEW_ARGUMENTS	25	/*Too few arguments*/
+#define EIPSEC_SYSTEM_ERROR	26	/*system error*/
+#define EIPSEC_INVAL_PRIORITY_OFFSET	27	/*priority offset out of range*/
+#define EIPSEC_INVAL_PRIORITY_BASE_OFFSET	28	/* priority base offset too
+                                                   large */
+#define EIPSEC_PRIORITY_NOT_COMPILED	29	/*no priority support in libipsec*/
+#define EIPSEC_MAX		30	/*unknown error*/
+
+#endif /* _IPSEC_STRERROR_H */
diff --git a/src/libipsec/key_debug.c b/src/libipsec/key_debug.c
new file mode 100644
index 0000000..60f1602
--- /dev/null
+++ b/src/libipsec/key_debug.c
@@ -0,0 +1,848 @@
+/*	$NetBSD: key_debug.c,v 1.7.6.1 2007/08/01 11:52:18 vanhu Exp $	*/
+
+/*	$KAME: key_debug.c,v 1.29 2001/08/16 14:25:41 itojun Exp $	*/
+
+/*
+ * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#ifdef _KERNEL
+#if defined(__FreeBSD__) && __FreeBSD__ >= 3
+#include "opt_inet.h"
+#include "opt_inet6.h"
+#include "opt_ipsec.h"
+#endif
+#ifdef __NetBSD__
+#include "opt_inet.h"
+#endif
+#endif
+
+#if HAVE_STDINT_H
+#include <stdint.h>
+#endif
+
+#include <sys/types.h>
+#include <sys/param.h>
+#ifdef _KERNEL
+#include <sys/systm.h>
+#include <sys/mbuf.h>
+#include <sys/queue.h>
+#endif
+#include <sys/socket.h>
+
+#include <netinet/in.h>
+#include PATH_IPSEC_H
+
+#ifndef _KERNEL
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#endif /* !_KERNEL */
+
+#include "config.h"
+#include "libpfkey.h"
+
+static void kdebug_sadb_prop __P((struct sadb_ext *));
+static void kdebug_sadb_identity __P((struct sadb_ext *));
+static void kdebug_sadb_supported __P((struct sadb_ext *));
+static void kdebug_sadb_lifetime __P((struct sadb_ext *));
+static void kdebug_sadb_sa __P((struct sadb_ext *));
+static void kdebug_sadb_address __P((struct sadb_ext *));
+static void kdebug_sadb_key __P((struct sadb_ext *));
+static void kdebug_sadb_x_sa2 __P((struct sadb_ext *));
+static void kdebug_sadb_x_policy __P((struct sadb_ext *ext));
+static void kdebug_sockaddr __P((struct sockaddr *addr));
+
+#ifdef SADB_X_EXT_NAT_T_TYPE
+static void kdebug_sadb_x_nat_t_type __P((struct sadb_ext *ext));
+static void kdebug_sadb_x_nat_t_port __P((struct sadb_ext *ext));
+#endif
+
+#ifdef SADB_X_EXT_PACKET
+static void kdebug_sadb_x_packet __P((struct sadb_ext *));
+#endif
+
+#ifdef _KERNEL
+static void kdebug_secreplay __P((struct secreplay *));
+#endif
+
+#ifndef _KERNEL
+#define panic(param)	{ printf(param); exit(1); }
+#endif
+
+#include "libpfkey.h"
+/* NOTE: host byte order */
+
+/* %%%: about struct sadb_msg */
+void
+kdebug_sadb(base)
+	struct sadb_msg *base;
+{
+	struct sadb_ext *ext;
+	int tlen, extlen;
+
+	/* sanity check */
+	if (base == NULL)
+		panic("kdebug_sadb: NULL pointer was passed.\n");
+
+	printf("sadb_msg{ version=%u type=%u errno=%u satype=%u\n",
+	    base->sadb_msg_version, base->sadb_msg_type,
+	    base->sadb_msg_errno, base->sadb_msg_satype);
+	printf("  len=%u reserved=%u seq=%u pid=%u\n",
+	    base->sadb_msg_len, base->sadb_msg_reserved,
+	    base->sadb_msg_seq, base->sadb_msg_pid);
+
+	tlen = PFKEY_UNUNIT64(base->sadb_msg_len) - sizeof(struct sadb_msg);
+	ext = (void *)((caddr_t)(void *)base + sizeof(struct sadb_msg));
+
+	while (tlen > 0) {
+		printf("sadb_ext{ len=%u type=%u }\n",
+		    ext->sadb_ext_len, ext->sadb_ext_type);
+
+		if (ext->sadb_ext_len == 0) {
+			printf("kdebug_sadb: invalid ext_len=0 was passed.\n");
+			return;
+		}
+		if (ext->sadb_ext_len > tlen) {
+			printf("kdebug_sadb: ext_len exceeds end of buffer.\n");
+			return;
+		}
+
+		switch (ext->sadb_ext_type) {
+		case SADB_EXT_SA:
+			kdebug_sadb_sa(ext);
+			break;
+		case SADB_EXT_LIFETIME_CURRENT:
+		case SADB_EXT_LIFETIME_HARD:
+		case SADB_EXT_LIFETIME_SOFT:
+			kdebug_sadb_lifetime(ext);
+			break;
+		case SADB_EXT_ADDRESS_SRC:
+		case SADB_EXT_ADDRESS_DST:
+		case SADB_EXT_ADDRESS_PROXY:
+			kdebug_sadb_address(ext);
+			break;
+		case SADB_EXT_KEY_AUTH:
+		case SADB_EXT_KEY_ENCRYPT:
+			kdebug_sadb_key(ext);
+			break;
+		case SADB_EXT_IDENTITY_SRC:
+		case SADB_EXT_IDENTITY_DST:
+			kdebug_sadb_identity(ext);
+			break;
+		case SADB_EXT_SENSITIVITY:
+			break;
+		case SADB_EXT_PROPOSAL:
+			kdebug_sadb_prop(ext);
+			break;
+		case SADB_EXT_SUPPORTED_AUTH:
+		case SADB_EXT_SUPPORTED_ENCRYPT:
+			kdebug_sadb_supported(ext);
+			break;
+		case SADB_EXT_SPIRANGE:
+		case SADB_X_EXT_KMPRIVATE:
+			break;
+		case SADB_X_EXT_POLICY:
+			kdebug_sadb_x_policy(ext);
+			break;
+		case SADB_X_EXT_SA2:
+			kdebug_sadb_x_sa2(ext);
+			break;
+#ifdef SADB_X_EXT_NAT_T_TYPE
+		case SADB_X_EXT_NAT_T_TYPE:
+			kdebug_sadb_x_nat_t_type(ext);
+			break;
+		case SADB_X_EXT_NAT_T_SPORT:
+		case SADB_X_EXT_NAT_T_DPORT:
+			kdebug_sadb_x_nat_t_port(ext);
+			break;
+		case SADB_X_EXT_NAT_T_OA:
+			kdebug_sadb_address(ext);
+			break;
+#endif
+#ifdef SADB_X_EXT_PACKET
+		case SADB_X_EXT_PACKET:
+			kdebug_sadb_x_packet(ext);
+			break;
+#endif
+		default:
+			printf("kdebug_sadb: invalid ext_type %u was passed.\n",
+			    ext->sadb_ext_type);
+			return;
+		}
+
+		extlen = PFKEY_UNUNIT64(ext->sadb_ext_len);
+		tlen -= extlen;
+		ext = (void *)((caddr_t)(void *)ext + extlen);
+	}
+
+	return;
+}
+
+static void
+kdebug_sadb_prop(ext)
+	struct sadb_ext *ext;
+{
+	struct sadb_prop *prop = (void *)ext;
+	struct sadb_comb *comb;
+	int len;
+
+	/* sanity check */
+	if (ext == NULL)
+		panic("kdebug_sadb_prop: NULL pointer was passed.\n");
+
+	len = (PFKEY_UNUNIT64(prop->sadb_prop_len) - sizeof(*prop))
+		/ sizeof(*comb);
+	comb = (void *)(prop + 1);
+	printf("sadb_prop{ replay=%u\n", prop->sadb_prop_replay);
+
+	while (len--) {
+		printf("sadb_comb{ auth=%u encrypt=%u "
+			"flags=0x%04x reserved=0x%08x\n",
+			comb->sadb_comb_auth, comb->sadb_comb_encrypt,
+			comb->sadb_comb_flags, comb->sadb_comb_reserved);
+
+		printf("  auth_minbits=%u auth_maxbits=%u "
+			"encrypt_minbits=%u encrypt_maxbits=%u\n",
+			comb->sadb_comb_auth_minbits,
+			comb->sadb_comb_auth_maxbits,
+			comb->sadb_comb_encrypt_minbits,
+			comb->sadb_comb_encrypt_maxbits);
+
+		printf("  soft_alloc=%u hard_alloc=%u "
+			"soft_bytes=%lu hard_bytes=%lu\n",
+			comb->sadb_comb_soft_allocations,
+			comb->sadb_comb_hard_allocations,
+			(unsigned long)comb->sadb_comb_soft_bytes,
+			(unsigned long)comb->sadb_comb_hard_bytes);
+
+		printf("  soft_alloc=%lu hard_alloc=%lu "
+			"soft_bytes=%lu hard_bytes=%lu }\n",
+			(unsigned long)comb->sadb_comb_soft_addtime,
+			(unsigned long)comb->sadb_comb_hard_addtime,
+			(unsigned long)comb->sadb_comb_soft_usetime,
+			(unsigned long)comb->sadb_comb_hard_usetime);
+		comb++;
+	}
+	printf("}\n");
+
+	return;
+}
+
+static void
+kdebug_sadb_identity(ext)
+	struct sadb_ext *ext;
+{
+	struct sadb_ident *id = (void *)ext;
+	int len;
+
+	/* sanity check */
+	if (ext == NULL)
+		panic("kdebug_sadb_identity: NULL pointer was passed.\n");
+
+	len = PFKEY_UNUNIT64(id->sadb_ident_len) - sizeof(*id);
+	printf("sadb_ident_%s{",
+	    id->sadb_ident_exttype == SADB_EXT_IDENTITY_SRC ? "src" : "dst");
+	switch (id->sadb_ident_type) {
+	default:
+		printf(" type=%d id=%lu",
+			id->sadb_ident_type, (u_long)id->sadb_ident_id);
+		if (len) {
+#ifdef _KERNEL
+			ipsec_hexdump((caddr_t)(id + 1), len); /*XXX cast ?*/
+#else
+			char *p, *ep;
+			printf("\n  str=\"");
+			p = (void *)(id + 1);
+			ep = p + len;
+			for (/*nothing*/; *p && p < ep; p++) {
+				if (isprint((int)*p))
+					printf("%c", *p & 0xff);
+				else
+					printf("\\%03o", *p & 0xff);
+			}
+#endif
+			printf("\"");
+		}
+		break;
+	}
+
+	printf(" }\n");
+
+	return;
+}
+
+static void
+kdebug_sadb_supported(ext)
+	struct sadb_ext *ext;
+{
+	struct sadb_supported *sup = (void *)ext;
+	struct sadb_alg *alg;
+	int len;
+
+	/* sanity check */
+	if (ext == NULL)
+		panic("kdebug_sadb_supported: NULL pointer was passed.\n");
+
+	len = (PFKEY_UNUNIT64(sup->sadb_supported_len) - sizeof(*sup))
+		/ sizeof(*alg);
+	alg = (void *)(sup + 1);
+	printf("sadb_sup{\n");
+	while (len--) {
+		printf("  { id=%d ivlen=%d min=%d max=%d }\n",
+			alg->sadb_alg_id, alg->sadb_alg_ivlen,
+			alg->sadb_alg_minbits, alg->sadb_alg_maxbits);
+		alg++;
+	}
+	printf("}\n");
+
+	return;
+}
+
+static void
+kdebug_sadb_lifetime(ext)
+	struct sadb_ext *ext;
+{
+	struct sadb_lifetime *lft = (void *)ext;
+
+	/* sanity check */
+	if (ext == NULL)
+		printf("kdebug_sadb_lifetime: NULL pointer was passed.\n");
+
+	printf("sadb_lifetime{ alloc=%u, bytes=%u\n",
+		lft->sadb_lifetime_allocations,
+		(u_int32_t)lft->sadb_lifetime_bytes);
+	printf("  addtime=%u, usetime=%u }\n",
+		(u_int32_t)lft->sadb_lifetime_addtime,
+		(u_int32_t)lft->sadb_lifetime_usetime);
+
+	return;
+}
+
+static void
+kdebug_sadb_sa(ext)
+	struct sadb_ext *ext;
+{
+	struct sadb_sa *sa = (void *)ext;
+
+	/* sanity check */
+	if (ext == NULL)
+		panic("kdebug_sadb_sa: NULL pointer was passed.\n");
+
+	printf("sadb_sa{ spi=%u replay=%u state=%u\n",
+	    (u_int32_t)ntohl(sa->sadb_sa_spi), sa->sadb_sa_replay,
+	    sa->sadb_sa_state);
+	printf("  auth=%u encrypt=%u flags=0x%08x }\n",
+	    sa->sadb_sa_auth, sa->sadb_sa_encrypt, sa->sadb_sa_flags);
+
+	return;
+}
+
+static void
+kdebug_sadb_address(ext)
+	struct sadb_ext *ext;
+{
+	struct sadb_address *addr = (void *)ext;
+
+	/* sanity check */
+	if (ext == NULL)
+		panic("kdebug_sadb_address: NULL pointer was passed.\n");
+
+	printf("sadb_address{ proto=%u prefixlen=%u reserved=0x%02x%02x }\n",
+	    addr->sadb_address_proto, addr->sadb_address_prefixlen,
+	    ((u_char *)(void *)&addr->sadb_address_reserved)[0],
+	    ((u_char *)(void *)&addr->sadb_address_reserved)[1]);
+
+	kdebug_sockaddr((void *)((caddr_t)(void *)ext + sizeof(*addr)));
+
+	return;
+}
+
+static void
+kdebug_sadb_key(ext)
+	struct sadb_ext *ext;
+{
+	struct sadb_key *key = (void *)ext;
+
+	/* sanity check */
+	if (ext == NULL)
+		panic("kdebug_sadb_key: NULL pointer was passed.\n");
+
+	printf("sadb_key{ bits=%u reserved=%u\n",
+	    key->sadb_key_bits, key->sadb_key_reserved);
+	printf("  key=");
+
+	/* sanity check 2 */
+	if (((uint32_t)key->sadb_key_bits >> 3) >
+		(PFKEY_UNUNIT64(key->sadb_key_len) - sizeof(struct sadb_key))) {
+		printf("kdebug_sadb_key: key length mismatch, bit:%d len:%ld.\n",
+			(uint32_t)key->sadb_key_bits >> 3,
+			(long)PFKEY_UNUNIT64(key->sadb_key_len) - sizeof(struct sadb_key));
+	}
+
+	ipsec_hexdump(key + sizeof(struct sadb_key),
+	              (int)((uint32_t)key->sadb_key_bits >> 3));
+	printf(" }\n");
+	return;
+}
+
+static void
+kdebug_sadb_x_sa2(ext)
+	struct sadb_ext *ext;
+{
+	struct sadb_x_sa2 *sa2 = (void *)ext;
+
+	/* sanity check */
+	if (ext == NULL)
+		panic("kdebug_sadb_x_sa2: NULL pointer was passed.\n");
+
+	printf("sadb_x_sa2{ mode=%u reqid=%u\n",
+	    sa2->sadb_x_sa2_mode, sa2->sadb_x_sa2_reqid);
+	printf("  reserved1=%u reserved2=%u sequence=%u }\n",
+	    sa2->sadb_x_sa2_reserved1, sa2->sadb_x_sa2_reserved2,
+	    sa2->sadb_x_sa2_sequence);
+
+	return;
+}
+
+void
+kdebug_sadb_x_policy(ext)
+	struct sadb_ext *ext;
+{
+	struct sadb_x_policy *xpl = (void *)ext;
+	struct sockaddr *addr;
+
+	/* sanity check */
+	if (ext == NULL)
+		panic("kdebug_sadb_x_policy: NULL pointer was passed.\n");
+
+#ifdef HAVE_PFKEY_POLICY_PRIORITY
+	printf("sadb_x_policy{ type=%u dir=%u id=%x priority=%u }\n",
+#else
+	printf("sadb_x_policy{ type=%u dir=%u id=%x }\n",
+#endif
+		xpl->sadb_x_policy_type, xpl->sadb_x_policy_dir,
+#ifdef HAVE_PFKEY_POLICY_PRIORITY
+		xpl->sadb_x_policy_id, xpl->sadb_x_policy_priority);
+#else
+		xpl->sadb_x_policy_id);
+#endif
+
+	if (xpl->sadb_x_policy_type == IPSEC_POLICY_IPSEC) {
+		int tlen;
+		struct sadb_x_ipsecrequest *xisr;
+
+		tlen = PFKEY_UNUNIT64(xpl->sadb_x_policy_len) - sizeof(*xpl);
+		xisr = (void *)(xpl + 1);
+
+		while (tlen > 0) {
+			printf(" { len=%u proto=%u mode=%u level=%u reqid=%u\n",
+				xisr->sadb_x_ipsecrequest_len,
+				xisr->sadb_x_ipsecrequest_proto,
+				xisr->sadb_x_ipsecrequest_mode,
+				xisr->sadb_x_ipsecrequest_level,
+				xisr->sadb_x_ipsecrequest_reqid);
+
+			if (xisr->sadb_x_ipsecrequest_len > sizeof(*xisr)) {
+				addr = (void *)(xisr + 1);
+				kdebug_sockaddr(addr);
+				addr = (void *)((caddr_t)(void *)addr
+							+ sysdep_sa_len(addr));
+				kdebug_sockaddr(addr);
+			}
+
+			printf(" }\n");
+
+			/* prevent infinite loop */
+			if (xisr->sadb_x_ipsecrequest_len == 0) {
+				printf("kdebug_sadb_x_policy: wrong policy struct.\n");
+				return;
+			}
+			/* prevent overflow */
+			if (xisr->sadb_x_ipsecrequest_len > tlen) {
+				printf("invalid ipsec policy length\n");
+				return;
+			}
+
+			tlen -= xisr->sadb_x_ipsecrequest_len;
+
+			xisr = (void *)((caddr_t)(void *)xisr
+			                + xisr->sadb_x_ipsecrequest_len);
+		}
+
+		if (tlen != 0)
+			panic("kdebug_sadb_x_policy: wrong policy struct.\n");
+	}
+
+	return;
+}
+
+#ifdef SADB_X_EXT_NAT_T_TYPE
+static void
+kdebug_sadb_x_nat_t_type(struct sadb_ext *ext)
+{
+	struct sadb_x_nat_t_type *ntt = (void *)ext;
+
+	/* sanity check */
+	if (ext == NULL)
+		panic("kdebug_sadb_x_nat_t_type: NULL pointer was passed.\n");
+
+	printf("sadb_x_nat_t_type{ type=%u }\n", ntt->sadb_x_nat_t_type_type);
+
+	return;
+}
+
+static void
+kdebug_sadb_x_nat_t_port(struct sadb_ext *ext)
+{
+	struct sadb_x_nat_t_port *ntp = (void *)ext;
+
+	/* sanity check */
+	if (ext == NULL)
+		panic("kdebug_sadb_x_nat_t_port: NULL pointer was passed.\n");
+
+	printf("sadb_x_nat_t_port{ port=%u }\n", ntohs(ntp->sadb_x_nat_t_port_port));
+
+	return;
+}
+#endif
+
+#ifdef SADB_X_EXT_PACKET
+static void
+kdebug_sadb_x_packet(ext)
+	struct sadb_ext *ext;
+{
+	struct sadb_x_packet *pkt = (struct sadb_x_packet *)ext;
+
+	/* sanity check */
+	if (ext == NULL)
+		panic("kdebug_sadb_x_packet: NULL pointer was passed.\n");
+
+	printf("sadb_x_packet{ copylen=%u\n", pkt->sadb_x_packet_copylen);
+	printf("  packet=");
+	ipsec_hexdump((caddr_t)pkt + sizeof(struct sadb_x_packet),
+		      pkt->sadb_x_packet_copylen);
+	printf(" }\n");
+	return;
+}
+#endif
+
+
+#ifdef _KERNEL
+/* %%%: about SPD and SAD */
+void
+kdebug_secpolicy(sp)
+	struct secpolicy *sp;
+{
+	/* sanity check */
+	if (sp == NULL)
+		panic("kdebug_secpolicy: NULL pointer was passed.\n");
+
+	printf("secpolicy{ refcnt=%u state=%u policy=%u\n",
+		sp->refcnt, sp->state, sp->policy);
+
+	kdebug_secpolicyindex(&sp->spidx);
+
+	switch (sp->policy) {
+	case IPSEC_POLICY_DISCARD:
+		printf("  type=discard }\n");
+		break;
+	case IPSEC_POLICY_NONE:
+		printf("  type=none }\n");
+		break;
+	case IPSEC_POLICY_IPSEC:
+	    {
+		struct ipsecrequest *isr;
+		for (isr = sp->req; isr != NULL; isr = isr->next) {
+
+			printf("  level=%u\n", isr->level);
+			kdebug_secasindex(&isr->saidx);
+
+			if (isr->sav != NULL)
+				kdebug_secasv(isr->sav);
+		}
+		printf("  }\n");
+	    }
+		break;
+	case IPSEC_POLICY_BYPASS:
+		printf("  type=bypass }\n");
+		break;
+	case IPSEC_POLICY_ENTRUST:
+		printf("  type=entrust }\n");
+		break;
+	default:
+		printf("kdebug_secpolicy: Invalid policy found. %d\n",
+			sp->policy);
+		break;
+	}
+
+	return;
+}
+
+void
+kdebug_secpolicyindex(spidx)
+	struct secpolicyindex *spidx;
+{
+	/* sanity check */
+	if (spidx == NULL)
+		panic("kdebug_secpolicyindex: NULL pointer was passed.\n");
+
+	printf("secpolicyindex{ dir=%u prefs=%u prefd=%u ul_proto=%u\n",
+		spidx->dir, spidx->prefs, spidx->prefd, spidx->ul_proto);
+
+	ipsec_hexdump((caddr_t)&spidx->src,
+		sysdep_sa_len((struct sockaddr *)&spidx->src));
+	printf("\n");
+	ipsec_hexdump((caddr_t)&spidx->dst,
+		sysdep_sa_len((struct sockaddr *)&spidx->dst));
+	printf("}\n");
+
+	return;
+}
+
+void
+kdebug_secasindex(saidx)
+	struct secasindex *saidx;
+{
+	/* sanity check */
+	if (saidx == NULL)
+		panic("kdebug_secpolicyindex: NULL pointer was passed.\n");
+
+	printf("secasindex{ mode=%u proto=%u\n",
+		saidx->mode, saidx->proto);
+
+	ipsec_hexdump((caddr_t)&saidx->src,
+		sysdep_sa_len((struct sockaddr *)&saidx->src));
+	printf("\n");
+	ipsec_hexdump((caddr_t)&saidx->dst,
+		sysdep_sa_len((struct sockaddr *)&saidx->dst));
+	printf("\n");
+
+	return;
+}
+
+void
+kdebug_secasv(sav)
+	struct secasvar *sav;
+{
+	/* sanity check */
+	if (sav == NULL)
+		panic("kdebug_secasv: NULL pointer was passed.\n");
+
+	printf("secas{");
+	kdebug_secasindex(&sav->sah->saidx);
+
+	printf("  refcnt=%u state=%u auth=%u enc=%u\n",
+	    sav->refcnt, sav->state, sav->alg_auth, sav->alg_enc);
+	printf("  spi=%u flags=%u\n",
+	    (u_int32_t)ntohl(sav->spi), sav->flags);
+
+	if (sav->key_auth != NULL)
+		kdebug_sadb_key((struct sadb_ext *)sav->key_auth);
+	if (sav->key_enc != NULL)
+		kdebug_sadb_key((struct sadb_ext *)sav->key_enc);
+	if (sav->iv != NULL) {
+		printf("  iv=");
+		ipsec_hexdump(sav->iv, sav->ivlen ? sav->ivlen : 8);
+		printf("\n");
+	}
+
+	if (sav->replay != NULL)
+		kdebug_secreplay(sav->replay);
+	if (sav->lft_c != NULL)
+		kdebug_sadb_lifetime((struct sadb_ext *)sav->lft_c);
+	if (sav->lft_h != NULL)
+		kdebug_sadb_lifetime((struct sadb_ext *)sav->lft_h);
+	if (sav->lft_s != NULL)
+		kdebug_sadb_lifetime((struct sadb_ext *)sav->lft_s);
+
+#if notyet
+	/* XXX: misc[123] ? */
+#endif
+
+	return;
+}
+
+static void
+kdebug_secreplay(rpl)
+	struct secreplay *rpl;
+{
+	int len, l;
+
+	/* sanity check */
+	if (rpl == NULL)
+		panic("kdebug_secreplay: NULL pointer was passed.\n");
+
+	printf(" secreplay{ count=%u wsize=%u seq=%u lastseq=%u",
+	    rpl->count, rpl->wsize, rpl->seq, rpl->lastseq);
+
+	if (rpl->bitmap == NULL) {
+		printf(" }\n");
+		return;
+	}
+
+	printf("\n   bitmap { ");
+
+	for (len = 0; len < rpl->wsize; len++) {
+		for (l = 7; l >= 0; l--)
+			printf("%u", (((rpl->bitmap)[len] >> l) & 1) ? 1 : 0);
+	}
+	printf(" }\n");
+
+	return;
+}
+
+void
+kdebug_mbufhdr(m)
+	struct mbuf *m;
+{
+	/* sanity check */
+	if (m == NULL)
+		return;
+
+	printf("mbuf(%p){ m_next:%p m_nextpkt:%p m_data:%p "
+	       "m_len:%d m_type:0x%02x m_flags:0x%02x }\n",
+		m, m->m_next, m->m_nextpkt, m->m_data,
+		m->m_len, m->m_type, m->m_flags);
+
+	if (m->m_flags & M_PKTHDR) {
+		printf("  m_pkthdr{ len:%d rcvif:%p }\n",
+		    m->m_pkthdr.len, m->m_pkthdr.rcvif);
+	}
+
+#ifdef __FreeBSD__
+	if (m->m_flags & M_EXT) {
+		printf("  m_ext{ ext_buf:%p ext_free:%p "
+		       "ext_size:%u ext_ref:%p }\n",
+			m->m_ext.ext_buf, m->m_ext.ext_free,
+			m->m_ext.ext_size, m->m_ext.ext_ref);
+	}
+#endif
+
+	return;
+}
+
+void
+kdebug_mbuf(m0)
+	struct mbuf *m0;
+{
+	struct mbuf *m = m0;
+	int i, j;
+
+	for (j = 0; m; m = m->m_next) {
+		kdebug_mbufhdr(m);
+		printf("  m_data:\n");
+		for (i = 0; i < m->m_len; i++) {
+			if (i && i % 32 == 0)
+				printf("\n");
+			if (i % 4 == 0)
+				printf(" ");
+			printf("%02x", mtod(m, u_char *)[i]);
+			j++;
+		}
+		printf("\n");
+	}
+
+	return;
+}
+#endif /* _KERNEL */
+
+static void
+kdebug_sockaddr(addr)
+	struct sockaddr *addr;
+{
+	struct sockaddr_in *sin4;
+#ifdef INET6
+	struct sockaddr_in6 *sin6;
+#endif
+
+	/* sanity check */
+	if (addr == NULL)
+		panic("kdebug_sockaddr: NULL pointer was passed.\n");
+
+	/* NOTE: We deal with port number as host byte order. */
+	printf("sockaddr{ len=%u family=%u", sysdep_sa_len(addr), addr->sa_family);
+
+	switch (addr->sa_family) {
+	case AF_INET:
+		sin4 = (void *)addr;
+		printf(" port=%u\n", ntohs(sin4->sin_port));
+		ipsec_hexdump(&sin4->sin_addr, sizeof(sin4->sin_addr));
+		break;
+#ifdef INET6
+	case AF_INET6:
+		sin6 = (void *)addr;
+		printf(" port=%u\n", ntohs(sin6->sin6_port));
+		printf("  flowinfo=0x%08x, scope_id=0x%08x\n",
+		    sin6->sin6_flowinfo, sin6->sin6_scope_id);
+		ipsec_hexdump(&sin6->sin6_addr, sizeof(sin6->sin6_addr));
+		break;
+#endif
+	}
+
+	printf("  }\n");
+
+	return;
+}
+
+void
+ipsec_bindump(buf, len)
+	caddr_t buf;
+	int len;
+{
+	int i;
+
+	for (i = 0; i < len; i++)
+		printf("%c", (unsigned char)buf[i]);
+
+	return;
+}
+
+
+void
+ipsec_hexdump(buf, len)
+	const void *buf;
+	int len;
+{
+	int i;
+
+	for (i = 0; i < len; i++) {
+		if (i != 0 && i % 32 == 0) printf("\n");
+		if (i % 4 == 0) printf(" ");
+		printf("%02x", ((const unsigned char *)buf)[i]);
+	}
+#if 0
+	if (i % 32 != 0) printf("\n");
+#endif
+
+	return;
+}
diff --git a/src/libipsec/libpfkey.h b/src/libipsec/libpfkey.h
new file mode 100644
index 0000000..e7e369f
--- /dev/null
+++ b/src/libipsec/libpfkey.h
@@ -0,0 +1,220 @@
+/*	$NetBSD: libpfkey.h,v 1.12.4.1 2007/08/01 11:52:18 vanhu Exp $	*/
+
+/* Id: libpfkey.h,v 1.13 2005/12/04 20:26:43 manubsd Exp */
+
+/*
+ * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _LIBPFKEY_H
+#define _LIBPFKEY_H
+
+#ifndef KAME_LIBPFKEY_H
+#define KAME_LIBPFKEY_H
+
+#define PRIORITY_LOW        0xC0000000
+#define PRIORITY_DEFAULT    0x80000000
+#define PRIORITY_HIGH       0x40000000
+
+#define PRIORITY_OFFSET_POSITIVE_MAX	0x3fffffff
+#define PRIORITY_OFFSET_NEGATIVE_MAX	0x40000000
+
+struct sadb_msg;
+extern void pfkey_sadump __P((struct sadb_msg *));
+extern void pfkey_sadump_withports __P((struct sadb_msg *));
+extern void pfkey_spdump __P((struct sadb_msg *));
+extern void pfkey_spdump_withports __P((struct sadb_msg *));
+
+struct sockaddr;
+struct sadb_alg;
+
+/* Accomodate different prototypes in <netinet6/ipsec.h> */
+#include <sys/types.h>
+#include PATH_IPSEC_H
+
+#ifndef HAVE_IPSEC_POLICY_T
+typedef caddr_t ipsec_policy_t;
+#define __ipsec_const
+#else
+#define __ipsec_const const
+#endif
+
+struct pfkey_send_sa_args {
+	int 		so;			/* socket */
+	u_int		type;			
+	u_int 		satype;
+	u_int		mode;
+	struct sockaddr *src;			/* IP src address for SA */
+	struct sockaddr *dst;			/* IP dst address for SA */
+	u_int32_t 	spi;			/* SA's spi */
+	u_int32_t 	reqid;
+	u_int		wsize;
+	caddr_t		keymat;
+	u_int		e_type, e_keylen;	/* Encryption alg and keylen */
+	u_int		a_type, a_keylen;	/* Authentication alg and key */
+	u_int		flags;
+	u_int32_t	l_alloc;
+	u_int32_t	l_bytes;
+	u_int32_t	l_addtime;
+	u_int32_t	l_usetime;
+	u_int32_t	seq;
+	u_int8_t	l_natt_type;
+	u_int16_t	l_natt_sport, l_natt_dport;
+	struct sockaddr *l_natt_oa;
+	u_int16_t	l_natt_frag;
+	u_int8_t ctxdoi, ctxalg;	/* Security context DOI and algorithm */
+	caddr_t ctxstr;			/* Security context string */
+	u_int16_t ctxstrlen;		/* length of security context string */
+};
+
+/* The options built into libipsec */
+extern int libipsec_opt;
+#define LIBIPSEC_OPT_NATT		0x01
+#define LIBIPSEC_OPT_FRAG		0x02
+#define LIBIPSEC_OPT_SEC_CTX		0x04
+
+/* IPsec Library Routines */
+
+int ipsec_check_keylen __P((u_int, u_int, u_int));
+int ipsec_check_keylen2 __P((u_int, u_int, u_int));
+int ipsec_get_keylen __P((u_int, u_int, struct sadb_alg *));
+char *ipsec_dump_policy_withports __P((void *, const char *));
+void ipsec_hexdump __P((const void *, int));
+const char *ipsec_strerror __P((void));
+void kdebug_sadb __P((struct sadb_msg *));
+ipsec_policy_t ipsec_set_policy __P((__ipsec_const char *, int));
+int  ipsec_get_policylen __P((ipsec_policy_t));
+char *ipsec_dump_policy __P((ipsec_policy_t, __ipsec_const char *));
+
+/* PFKey Routines */
+
+u_int pfkey_set_softrate __P((u_int, u_int));
+u_int pfkey_get_softrate __P((u_int));
+int pfkey_send_getspi __P((int, u_int, u_int, struct sockaddr *,
+	struct sockaddr *, u_int32_t, u_int32_t, u_int32_t, u_int32_t));
+int pfkey_send_update2 __P((struct pfkey_send_sa_args *));
+int pfkey_send_add2 __P((struct pfkey_send_sa_args *)); 
+int pfkey_send_delete __P((int, u_int, u_int,
+	struct sockaddr *, struct sockaddr *, u_int32_t));
+int pfkey_send_delete_all __P((int, u_int, u_int,
+	struct sockaddr *, struct sockaddr *));
+int pfkey_send_get __P((int, u_int, u_int,
+	struct sockaddr *, struct sockaddr *, u_int32_t));
+int pfkey_send_register __P((int, u_int));
+int pfkey_recv_register __P((int));
+int pfkey_set_supported __P((struct sadb_msg *, int));
+int pfkey_send_flush __P((int, u_int));
+int pfkey_send_dump __P((int, u_int));
+int pfkey_send_promisc_toggle __P((int, int));
+int pfkey_send_spdadd __P((int, struct sockaddr *, u_int,
+	struct sockaddr *, u_int, u_int, caddr_t, int, u_int32_t));
+int pfkey_send_spdadd2 __P((int, struct sockaddr *, u_int,
+	struct sockaddr *, u_int, u_int, u_int64_t, u_int64_t,
+	caddr_t, int, u_int32_t));
+int pfkey_send_spdupdate __P((int, struct sockaddr *, u_int,
+	struct sockaddr *, u_int, u_int, caddr_t, int, u_int32_t));
+int pfkey_send_spdupdate2 __P((int, struct sockaddr *, u_int,
+	struct sockaddr *, u_int, u_int, u_int64_t, u_int64_t,
+	caddr_t, int, u_int32_t));
+int pfkey_send_spddelete __P((int, struct sockaddr *, u_int,
+	struct sockaddr *, u_int, u_int, caddr_t, int, u_int32_t));
+int pfkey_send_spddelete2 __P((int, u_int32_t));
+int pfkey_send_spdget __P((int, u_int32_t));
+int pfkey_send_spdsetidx __P((int, struct sockaddr *, u_int,
+	struct sockaddr *, u_int, u_int, caddr_t, int, u_int32_t));
+int pfkey_send_spdflush __P((int));
+int pfkey_send_spddump __P((int));
+#ifdef SADB_X_MIGRATE
+int pfkey_send_migrate __P((int, struct sockaddr *, u_int,
+	struct sockaddr *, u_int, u_int, caddr_t, int, u_int32_t));
+#endif
+
+int pfkey_open __P((void));
+void pfkey_close __P((int));
+struct sadb_msg *pfkey_recv __P((int));
+int pfkey_send __P((int, struct sadb_msg *, int));
+int pfkey_align __P((struct sadb_msg *, caddr_t *));
+int pfkey_check __P((caddr_t *));
+
+/* 
+ * Deprecated, available for backward compatibility with third party 
+ * libipsec users. Please use pfkey_send_update2 and pfkey_send_add2 instead
+ */
+int pfkey_send_update __P((int, u_int, u_int, struct sockaddr *,
+	struct sockaddr *, u_int32_t, u_int32_t, u_int,
+	caddr_t, u_int, u_int, u_int, u_int, u_int, u_int32_t, u_int64_t,
+	u_int64_t, u_int64_t, u_int32_t));
+int pfkey_send_update_nat __P((int, u_int, u_int, struct sockaddr *,
+	struct sockaddr *, u_int32_t, u_int32_t, u_int,
+	caddr_t, u_int, u_int, u_int, u_int, u_int, u_int32_t, u_int64_t,
+	u_int64_t, u_int64_t, u_int32_t,
+	u_int8_t, u_int16_t, u_int16_t, struct sockaddr *, u_int16_t));
+int pfkey_send_add __P((int, u_int, u_int, struct sockaddr *,
+	struct sockaddr *, u_int32_t, u_int32_t, u_int,
+	caddr_t, u_int, u_int, u_int, u_int, u_int, u_int32_t, u_int64_t,
+	u_int64_t, u_int64_t, u_int32_t));
+int pfkey_send_add_nat __P((int, u_int, u_int, struct sockaddr *,
+	struct sockaddr *, u_int32_t, u_int32_t, u_int,
+	caddr_t, u_int, u_int, u_int, u_int, u_int, u_int32_t, u_int64_t,
+	u_int64_t, u_int64_t, u_int32_t,
+	u_int8_t, u_int16_t, u_int16_t, struct sockaddr *, u_int16_t));
+
+#ifndef __SYSDEP_SA_LEN__
+#define __SYSDEP_SA_LEN__
+#include <netinet/in.h>
+
+#ifndef IPPROTO_IPV4
+#define IPPROTO_IPV4 IPPROTO_IPIP
+#endif
+
+#ifndef IPPROTO_IPCOMP
+#define IPPROTO_IPCOMP IPPROTO_COMP
+#endif
+
+static __inline u_int8_t
+sysdep_sa_len (const struct sockaddr *sa)
+{
+#ifdef __linux__
+  switch (sa->sa_family)
+    {
+    case AF_INET:
+      return sizeof (struct sockaddr_in);
+    case AF_INET6:
+      return sizeof (struct sockaddr_in6);
+    }
+  // log_print ("sysdep_sa_len: unknown sa family %d", sa->sa_family);
+  return sizeof (struct sockaddr_in);
+#else
+  return sa->sa_len;
+#endif
+}
+#endif
+
+#endif /* KAME_LIBPFKEY_H */
+
+#endif /* _LIBPFKEY_H */
diff --git a/src/libipsec/pfkey.c b/src/libipsec/pfkey.c
new file mode 100644
index 0000000..fae0415
--- /dev/null
+++ b/src/libipsec/pfkey.c
@@ -0,0 +1,2663 @@
+/*	$NetBSD: pfkey.c,v 1.13.4.2 2007/10/15 16:05:22 vanhu Exp $	*/
+
+/*	$KAME: pfkey.c,v 1.47 2003/10/02 19:52:12 itojun Exp $	*/
+
+/*
+ * Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <net/pfkeyv2.h>
+#include <netinet/in.h>
+#include PATH_IPSEC_H
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <stdio.h>
+
+#include "ipsec_strerror.h"
+#include "libpfkey.h"
+
+#define CALLOC(size, cast) (cast)calloc(1, (size))
+
+static int findsupportedmap __P((int));
+static int setsupportedmap __P((struct sadb_supported *));
+static struct sadb_alg *findsupportedalg __P((u_int, u_int));
+static int pfkey_send_x1 __P((struct pfkey_send_sa_args *));
+static int pfkey_send_x2 __P((int, u_int, u_int, u_int,
+	struct sockaddr *, struct sockaddr *, u_int32_t));
+static int pfkey_send_x3 __P((int, u_int, u_int));
+static int pfkey_send_x4 __P((int, u_int, struct sockaddr *, u_int,
+	struct sockaddr *, u_int, u_int, u_int64_t, u_int64_t,
+	char *, int, u_int32_t));
+static int pfkey_send_x5 __P((int, u_int, u_int32_t));
+
+static caddr_t pfkey_setsadbmsg __P((caddr_t, caddr_t, u_int, u_int,
+	u_int, u_int32_t, pid_t));
+static caddr_t pfkey_setsadbsa __P((caddr_t, caddr_t, u_int32_t, u_int,
+	u_int, u_int, u_int32_t));
+static caddr_t pfkey_setsadbaddr __P((caddr_t, caddr_t, u_int,
+	struct sockaddr *, u_int, u_int));
+static caddr_t pfkey_setsadbkey __P((caddr_t, caddr_t, u_int, caddr_t, u_int));
+static caddr_t pfkey_setsadblifetime __P((caddr_t, caddr_t, u_int, u_int32_t,
+	u_int32_t, u_int32_t, u_int32_t));
+static caddr_t pfkey_setsadbxsa2 __P((caddr_t, caddr_t, u_int32_t, u_int32_t));
+
+#ifdef SADB_X_EXT_NAT_T_TYPE
+static caddr_t pfkey_set_natt_type __P((caddr_t, caddr_t, u_int, u_int8_t));
+static caddr_t pfkey_set_natt_port __P((caddr_t, caddr_t, u_int, u_int16_t));
+#endif
+#ifdef SADB_X_EXT_NAT_T_FRAG
+static caddr_t pfkey_set_natt_frag __P((caddr_t, caddr_t, u_int, u_int16_t));
+#endif
+
+#ifdef SADB_X_EXT_SEC_CTX
+static caddr_t pfkey_setsecctx __P((caddr_t, caddr_t, u_int, u_int8_t, u_int8_t,
+				    caddr_t, u_int16_t));
+#endif
+
+int libipsec_opt = 0
+#ifdef SADB_X_EXT_NAT_T_TYPE
+	| LIBIPSEC_OPT_NATT
+#endif
+#ifdef SADB_X_EXT_NAT_T_FRAG
+	| LIBIPSEC_OPT_FRAG
+#endif
+#ifdef SADB_X_EXT_NAT_T_SEC_CTX
+	| LIBIPSEC_OPT_SEC_CTX
+#endif
+	;
+
+/*
+ * make and search supported algorithm structure.
+ */
+static struct sadb_supported *ipsec_supported[] = { NULL, NULL, NULL, 
+#ifdef SADB_X_SATYPE_TCPSIGNATURE
+    NULL,
+#endif
+};
+
+static int supported_map[] = {
+	SADB_SATYPE_AH,
+	SADB_SATYPE_ESP,
+	SADB_X_SATYPE_IPCOMP,
+#ifdef SADB_X_SATYPE_TCPSIGNATURE
+	SADB_X_SATYPE_TCPSIGNATURE,
+#endif
+};
+
+static int
+findsupportedmap(satype)
+	int satype;
+{
+	int i;
+
+	for (i = 0; i < sizeof(supported_map)/sizeof(supported_map[0]); i++)
+		if (supported_map[i] == satype)
+			return i;
+	return -1;
+}
+
+static struct sadb_alg *
+findsupportedalg(satype, alg_id)
+	u_int satype, alg_id;
+{
+	int algno;
+	int tlen;
+	caddr_t p;
+
+	/* validity check */
+	algno = findsupportedmap((int)satype);
+	if (algno == -1) {
+		__ipsec_errcode = EIPSEC_INVAL_ARGUMENT;
+		return NULL;
+	}
+	if (ipsec_supported[algno] == NULL) {
+		__ipsec_errcode = EIPSEC_DO_GET_SUPP_LIST;
+		return NULL;
+	}
+
+	tlen = ipsec_supported[algno]->sadb_supported_len
+		- sizeof(struct sadb_supported);
+	p = (void *)(ipsec_supported[algno] + 1);
+	while (tlen > 0) {
+		if (tlen < sizeof(struct sadb_alg)) {
+			/* invalid format */
+			break;
+		}
+		if (((struct sadb_alg *)(void *)p)->sadb_alg_id == alg_id)
+			return (void *)p;
+
+		tlen -= sizeof(struct sadb_alg);
+		p += sizeof(struct sadb_alg);
+	}
+
+	__ipsec_errcode = EIPSEC_NOT_SUPPORTED;
+	return NULL;
+}
+
+static int
+setsupportedmap(sup)
+	struct sadb_supported *sup;
+{
+	struct sadb_supported **ipsup;
+
+	switch (sup->sadb_supported_exttype) {
+	case SADB_EXT_SUPPORTED_AUTH:
+		ipsup = &ipsec_supported[findsupportedmap(SADB_SATYPE_AH)];
+		break;
+	case SADB_EXT_SUPPORTED_ENCRYPT:
+		ipsup = &ipsec_supported[findsupportedmap(SADB_SATYPE_ESP)];
+		break;
+	default:
+		__ipsec_errcode = EIPSEC_INVAL_SATYPE;
+		return -1;
+	}
+
+	if (*ipsup)
+		free(*ipsup);
+
+	*ipsup = malloc((size_t)sup->sadb_supported_len);
+	if (!*ipsup) {
+		__ipsec_set_strerror(strerror(errno));
+		return -1;
+	}
+	memcpy(*ipsup, sup, (size_t)sup->sadb_supported_len);
+
+	return 0;
+}
+
+/*
+ * check key length against algorithm specified.
+ * This function is called with SADB_EXT_SUPPORTED_{AUTH,ENCRYPT} as the
+ * augument, and only calls to ipsec_check_keylen2();
+ * keylen is the unit of bit.
+ * OUT:
+ *	-1: invalid.
+ *	 0: valid.
+ */
+int
+ipsec_check_keylen(supported, alg_id, keylen)
+	u_int supported;
+	u_int alg_id;
+	u_int keylen;
+{
+	u_int satype;
+
+	/* validity check */
+	switch (supported) {
+	case SADB_EXT_SUPPORTED_AUTH:
+		satype = SADB_SATYPE_AH;
+		break;
+	case SADB_EXT_SUPPORTED_ENCRYPT:
+		satype = SADB_SATYPE_ESP;
+		break;
+	default:
+		__ipsec_errcode = EIPSEC_INVAL_ARGUMENT;
+		return -1;
+	}
+
+	return ipsec_check_keylen2(satype, alg_id, keylen);
+}
+
+/*
+ * check key length against algorithm specified.
+ * satype is one of satype defined at pfkeyv2.h.
+ * keylen is the unit of bit.
+ * OUT:
+ *	-1: invalid.
+ *	 0: valid.
+ */
+int
+ipsec_check_keylen2(satype, alg_id, keylen)
+	u_int satype;
+	u_int alg_id;
+	u_int keylen;
+{
+	struct sadb_alg *alg;
+
+	alg = findsupportedalg(satype, alg_id);
+	if (!alg)
+		return -1;
+
+	if (keylen < alg->sadb_alg_minbits || keylen > alg->sadb_alg_maxbits) {
+		fprintf(stderr, "%d %d %d\n", keylen, alg->sadb_alg_minbits,
+			alg->sadb_alg_maxbits);
+		__ipsec_errcode = EIPSEC_INVAL_KEYLEN;
+		return -1;
+	}
+
+	__ipsec_errcode = EIPSEC_NO_ERROR;
+	return 0;
+}
+
+/*
+ * get max/min key length against algorithm specified.
+ * satype is one of satype defined at pfkeyv2.h.
+ * keylen is the unit of bit.
+ * OUT:
+ *	-1: invalid.
+ *	 0: valid.
+ */
+int
+ipsec_get_keylen(supported, alg_id, alg0)
+	u_int supported, alg_id;
+	struct sadb_alg *alg0;
+{
+	struct sadb_alg *alg;
+	u_int satype;
+
+	/* validity check */
+	if (!alg0) {
+		__ipsec_errcode = EIPSEC_INVAL_ARGUMENT;
+		return -1;
+	}
+
+	switch (supported) {
+	case SADB_EXT_SUPPORTED_AUTH:
+		satype = SADB_SATYPE_AH;
+		break;
+	case SADB_EXT_SUPPORTED_ENCRYPT:
+		satype = SADB_SATYPE_ESP;
+		break;
+	default:
+		__ipsec_errcode = EIPSEC_INVAL_ARGUMENT;
+		return -1;
+	}
+
+	alg = findsupportedalg(satype, alg_id);
+	if (!alg)
+		return -1;
+
+	memcpy(alg0, alg, sizeof(*alg0));
+
+	__ipsec_errcode = EIPSEC_NO_ERROR;
+	return 0;
+}
+
+/*
+ * set the rate for SOFT lifetime against HARD one.
+ * If rate is more than 100 or equal to zero, then set to 100.
+ */
+static u_int soft_lifetime_allocations_rate = PFKEY_SOFT_LIFETIME_RATE;
+static u_int soft_lifetime_bytes_rate = PFKEY_SOFT_LIFETIME_RATE;
+static u_int soft_lifetime_addtime_rate = PFKEY_SOFT_LIFETIME_RATE;
+static u_int soft_lifetime_usetime_rate = PFKEY_SOFT_LIFETIME_RATE;
+
+u_int
+pfkey_set_softrate(type, rate)
+	u_int type, rate;
+{
+	__ipsec_errcode = EIPSEC_NO_ERROR;
+
+	if (rate > 100 || rate == 0)
+		rate = 100;
+
+	switch (type) {
+	case SADB_X_LIFETIME_ALLOCATIONS:
+		soft_lifetime_allocations_rate = rate;
+		return 0;
+	case SADB_X_LIFETIME_BYTES:
+		soft_lifetime_bytes_rate = rate;
+		return 0;
+	case SADB_X_LIFETIME_ADDTIME:
+		soft_lifetime_addtime_rate = rate;
+		return 0;
+	case SADB_X_LIFETIME_USETIME:
+		soft_lifetime_usetime_rate = rate;
+		return 0;
+	}
+
+	__ipsec_errcode = EIPSEC_INVAL_ARGUMENT;
+	return 1;
+}
+
+/*
+ * get current rate for SOFT lifetime against HARD one.
+ * ATTENTION: ~0 is returned if invalid type was passed.
+ */
+u_int
+pfkey_get_softrate(type)
+	u_int type;
+{
+	switch (type) {
+	case SADB_X_LIFETIME_ALLOCATIONS:
+		return soft_lifetime_allocations_rate;
+	case SADB_X_LIFETIME_BYTES:
+		return soft_lifetime_bytes_rate;
+	case SADB_X_LIFETIME_ADDTIME:
+		return soft_lifetime_addtime_rate;
+	case SADB_X_LIFETIME_USETIME:
+		return soft_lifetime_usetime_rate;
+	}
+
+	return (u_int)~0;
+}
+
+/*
+ * sending SADB_GETSPI message to the kernel.
+ * OUT:
+ *	positive: success and return length sent.
+ *	-1	: error occured, and set errno.
+ */
+int
+pfkey_send_getspi(so, satype, mode, src, dst, min, max, reqid, seq)
+	int so;
+	u_int satype, mode;
+	struct sockaddr *src, *dst;
+	u_int32_t min, max, reqid, seq;
+{
+	struct sadb_msg *newmsg;
+	caddr_t ep;
+	int len;
+	int need_spirange = 0;
+	caddr_t p;
+	int plen;
+
+	/* validity check */
+	if (src == NULL || dst == NULL) {
+		__ipsec_errcode = EIPSEC_INVAL_ARGUMENT;
+		return -1;
+	}
+	if (src->sa_family != dst->sa_family) {
+		__ipsec_errcode = EIPSEC_FAMILY_MISMATCH;
+		return -1;
+	}
+	if (min > max || (min > 0 && min <= 255)) {
+		__ipsec_errcode = EIPSEC_INVAL_SPI;
+		return -1;
+	}
+	switch (src->sa_family) {
+	case AF_INET:
+		plen = sizeof(struct in_addr) << 3;
+		break;
+	case AF_INET6:
+		plen = sizeof(struct in6_addr) << 3;
+		break;
+	default:
+		__ipsec_errcode = EIPSEC_INVAL_FAMILY;
+		return -1;
+	}
+
+	/* create new sadb_msg to send. */
+	len = sizeof(struct sadb_msg)
+		+ sizeof(struct sadb_x_sa2)
+		+ sizeof(struct sadb_address)
+		+ PFKEY_ALIGN8(sysdep_sa_len(src))
+		+ sizeof(struct sadb_address)
+		+ PFKEY_ALIGN8(sysdep_sa_len(dst));
+
+	if (min > 255 && max < (u_int)~0) {
+		need_spirange++;
+		len += sizeof(struct sadb_spirange);
+	}
+
+	if ((newmsg = CALLOC((size_t)len, struct sadb_msg *)) == NULL) {
+		__ipsec_set_strerror(strerror(errno));
+		return -1;
+	}
+	ep = ((caddr_t)(void *)newmsg) + len;
+
+	p = pfkey_setsadbmsg((void *)newmsg, ep, SADB_GETSPI,
+	    (u_int)len, satype, seq, getpid());
+	if (!p) {
+		free(newmsg);
+		return -1;
+	}
+
+	p = pfkey_setsadbxsa2(p, ep, mode, reqid);
+	if (!p) {
+		free(newmsg);
+		return -1;
+	}
+
+	/* set sadb_address for source */
+	p = pfkey_setsadbaddr(p, ep, SADB_EXT_ADDRESS_SRC, src, (u_int)plen,
+	    IPSEC_ULPROTO_ANY);
+	if (!p) {
+		free(newmsg);
+		return -1;
+	}
+
+	/* set sadb_address for destination */
+	p = pfkey_setsadbaddr(p, ep, SADB_EXT_ADDRESS_DST, dst, (u_int)plen,
+	    IPSEC_ULPROTO_ANY);
+	if (!p) {
+		free(newmsg);
+		return -1;
+	}
+
+	/* proccessing spi range */
+	if (need_spirange) {
+		struct sadb_spirange spirange;
+
+		if (p + sizeof(spirange) > ep) {
+			free(newmsg);
+			return -1;
+		}
+
+		memset(&spirange, 0, sizeof(spirange));
+		spirange.sadb_spirange_len = PFKEY_UNIT64(sizeof(spirange));
+		spirange.sadb_spirange_exttype = SADB_EXT_SPIRANGE;
+		spirange.sadb_spirange_min = min;
+		spirange.sadb_spirange_max = max;
+
+		memcpy(p, &spirange, sizeof(spirange));
+
+		p += sizeof(spirange);
+	}
+	if (p != ep) {
+		free(newmsg);
+		return -1;
+	}
+
+	/* send message */
+	len = pfkey_send(so, newmsg, len);
+	free(newmsg);
+
+	if (len < 0)
+		return -1;
+
+	__ipsec_errcode = EIPSEC_NO_ERROR;
+	return len;
+}
+
+/*
+ * sending SADB_UPDATE message to the kernel.
+ * The length of key material is a_keylen + e_keylen.
+ * OUT:
+ *	positive: success and return length sent.
+ *	-1	: error occured, and set errno.
+ */
+int
+pfkey_send_update2(sa_parms)
+	struct pfkey_send_sa_args *sa_parms;
+{
+	int len;
+
+	
+	sa_parms->type = SADB_UPDATE;
+	if ((len = pfkey_send_x1(sa_parms)) < 0)
+		return -1;
+
+	return len;
+}
+
+/*
+ * sending SADB_ADD message to the kernel.
+ * The length of key material is a_keylen + e_keylen.
+ * OUT:
+ *	positive: success and return length sent.
+ *	-1	: error occured, and set errno.
+ */
+int
+pfkey_send_add2(sa_parms)
+	struct pfkey_send_sa_args *sa_parms;
+{
+	int len;
+	
+	sa_parms->type = SADB_ADD;
+	if ((len = pfkey_send_x1(sa_parms)) < 0)
+		return -1;
+
+	return len;
+}
+
+/*
+ * sending SADB_DELETE message to the kernel.
+ * OUT:
+ *	positive: success and return length sent.
+ *	-1	: error occured, and set errno.
+ */
+int
+pfkey_send_delete(so, satype, mode, src, dst, spi)
+	int so;
+	u_int satype, mode;
+	struct sockaddr *src, *dst;
+	u_int32_t spi;
+{
+	int len;
+	if ((len = pfkey_send_x2(so, SADB_DELETE, satype, mode, src, dst, spi)) < 0)
+		return -1;
+
+	return len;
+}
+
+/*
+ * sending SADB_DELETE without spi to the kernel.  This is
+ * the "delete all" request (an extension also present in
+ * Solaris).
+ *
+ * OUT:
+ *	positive: success and return length sent
+ *	-1	: error occured, and set errno
+ */
+/*ARGSUSED*/
+int
+pfkey_send_delete_all(so, satype, mode, src, dst)
+	int so;
+	u_int satype, mode;
+	struct sockaddr *src, *dst;
+{
+	struct sadb_msg *newmsg;
+	int len;
+	caddr_t p;
+	int plen;
+	caddr_t ep;
+
+	/* validity check */
+	if (src == NULL || dst == NULL) {
+		__ipsec_errcode = EIPSEC_INVAL_ARGUMENT;
+		return -1;
+	}
+	if (src->sa_family != dst->sa_family) {
+		__ipsec_errcode = EIPSEC_FAMILY_MISMATCH;
+		return -1;
+	}
+	switch (src->sa_family) {
+	case AF_INET:
+		plen = sizeof(struct in_addr) << 3;
+		break;
+	case AF_INET6:
+		plen = sizeof(struct in6_addr) << 3;
+		break;
+	default:
+		__ipsec_errcode = EIPSEC_INVAL_FAMILY;
+		return -1;
+	}
+
+	/* create new sadb_msg to reply. */
+	len = sizeof(struct sadb_msg)
+		+ sizeof(struct sadb_address)
+		+ PFKEY_ALIGN8(sysdep_sa_len(src))
+		+ sizeof(struct sadb_address)
+		+ PFKEY_ALIGN8(sysdep_sa_len(dst));
+
+	if ((newmsg = CALLOC((size_t)len, struct sadb_msg *)) == NULL) {
+		__ipsec_set_strerror(strerror(errno));
+		return -1;
+	}
+	ep = ((caddr_t)(void *)newmsg) + len;
+
+	p = pfkey_setsadbmsg((void *)newmsg, ep, SADB_DELETE, (u_int)len, 
+	    satype, 0, getpid());
+	if (!p) {
+		free(newmsg);
+		return -1;
+	}
+	p = pfkey_setsadbaddr(p, ep, SADB_EXT_ADDRESS_SRC, src, (u_int)plen,
+	    IPSEC_ULPROTO_ANY);
+	if (!p) {
+		free(newmsg);
+		return -1;
+	}
+	p = pfkey_setsadbaddr(p, ep, SADB_EXT_ADDRESS_DST, dst, (u_int)plen,
+	    IPSEC_ULPROTO_ANY);
+	if (!p || p != ep) {
+		free(newmsg);
+		return -1;
+	}
+
+	/* send message */
+	len = pfkey_send(so, newmsg, len);
+	free(newmsg);
+
+	if (len < 0)
+		return -1;
+
+	__ipsec_errcode = EIPSEC_NO_ERROR;
+	return len;
+}
+
+/*
+ * sending SADB_GET message to the kernel.
+ * OUT:
+ *	positive: success and return length sent.
+ *	-1	: error occured, and set errno.
+ */
+int
+pfkey_send_get(so, satype, mode, src, dst, spi)
+	int so;
+	u_int satype, mode;
+	struct sockaddr *src, *dst;
+	u_int32_t spi;
+{
+	int len;
+	if ((len = pfkey_send_x2(so, SADB_GET, satype, mode, src, dst, spi)) < 0)
+		return -1;
+
+	return len;
+}
+
+/*
+ * sending SADB_REGISTER message to the kernel.
+ * OUT:
+ *	positive: success and return length sent.
+ *	-1	: error occured, and set errno.
+ */
+int
+pfkey_send_register(so, satype)
+	int so;
+	u_int satype;
+{
+	int len, algno;
+
+	if (satype == PF_UNSPEC) {
+		for (algno = 0;
+		     algno < sizeof(supported_map)/sizeof(supported_map[0]);
+		     algno++) {
+			if (ipsec_supported[algno]) {
+				free(ipsec_supported[algno]);
+				ipsec_supported[algno] = NULL;
+			}
+		}
+	} else {
+		algno = findsupportedmap((int)satype);
+		if (algno == -1) {
+			__ipsec_errcode = EIPSEC_INVAL_ARGUMENT;
+			return -1;
+		}
+
+		if (ipsec_supported[algno]) {
+			free(ipsec_supported[algno]);
+			ipsec_supported[algno] = NULL;
+		}
+	}
+
+	if ((len = pfkey_send_x3(so, SADB_REGISTER, satype)) < 0)
+		return -1;
+
+	return len;
+}
+
+/*
+ * receiving SADB_REGISTER message from the kernel, and copy buffer for
+ * sadb_supported returned into ipsec_supported.
+ * OUT:
+ *	 0: success and return length sent.
+ *	-1: error occured, and set errno.
+ */
+int
+pfkey_recv_register(so)
+	int so;
+{
+	pid_t pid = getpid();
+	struct sadb_msg *newmsg;
+	int error = -1;
+
+	/* receive message */
+	for (;;) {
+		if ((newmsg = pfkey_recv(so)) == NULL)
+			return -1;
+		if (newmsg->sadb_msg_type == SADB_REGISTER &&
+		    newmsg->sadb_msg_pid == pid)
+			break;
+		free(newmsg);
+	}
+
+	/* check and fix */
+	newmsg->sadb_msg_len = PFKEY_UNUNIT64(newmsg->sadb_msg_len);
+
+	error = pfkey_set_supported(newmsg, newmsg->sadb_msg_len);
+	free(newmsg);
+
+	if (error == 0)
+		__ipsec_errcode = EIPSEC_NO_ERROR;
+
+	return error;
+}
+
+/*
+ * receiving SADB_REGISTER message from the kernel, and copy buffer for
+ * sadb_supported returned into ipsec_supported.
+ * NOTE: sadb_msg_len must be host order.
+ * IN:
+ *	tlen: msg length, it's to makeing sure.
+ * OUT:
+ *	 0: success and return length sent.
+ *	-1: error occured, and set errno.
+ */
+int
+pfkey_set_supported(msg, tlen)
+	struct sadb_msg *msg;
+	int tlen;
+{
+	struct sadb_supported *sup;
+	caddr_t p;
+	caddr_t ep;
+
+	/* validity */
+	if (msg->sadb_msg_len != tlen) {
+		__ipsec_errcode = EIPSEC_INVAL_ARGUMENT;
+		return -1;
+	}
+
+	p = (void *)msg;
+	ep = p + tlen;
+
+	p += sizeof(struct sadb_msg);
+
+	while (p < ep) {
+		sup = (void *)p;
+		if (ep < p + sizeof(*sup) ||
+		    PFKEY_EXTLEN(sup) < sizeof(*sup) ||
+		    ep < p + sup->sadb_supported_len) {
+			/* invalid format */
+			break;
+		}
+
+		switch (sup->sadb_supported_exttype) {
+		case SADB_EXT_SUPPORTED_AUTH:
+		case SADB_EXT_SUPPORTED_ENCRYPT:
+			break;
+		default:
+			__ipsec_errcode = EIPSEC_INVAL_SATYPE;
+			return -1;
+		}
+
+		/* fixed length */
+		sup->sadb_supported_len = PFKEY_EXTLEN(sup);
+
+		/* set supported map */
+		if (setsupportedmap(sup) != 0)
+			return -1;
+
+		p += sup->sadb_supported_len;
+	}
+
+	if (p != ep) {
+		__ipsec_errcode = EIPSEC_INVAL_SATYPE;
+		return -1;
+	}
+
+	__ipsec_errcode = EIPSEC_NO_ERROR;
+
+	return 0;
+}
+
+/*
+ * sending SADB_FLUSH message to the kernel.
+ * OUT:
+ *	positive: success and return length sent.
+ *	-1	: error occured, and set errno.
+ */
+int
+pfkey_send_flush(so, satype)
+	int so;
+	u_int satype;
+{
+	int len;
+
+	if ((len = pfkey_send_x3(so, SADB_FLUSH, satype)) < 0)
+		return -1;
+
+	return len;
+}
+
+/*
+ * sending SADB_DUMP message to the kernel.
+ * OUT:
+ *	positive: success and return length sent.
+ *	-1	: error occured, and set errno.
+ */
+int
+pfkey_send_dump(so, satype)
+	int so;
+	u_int satype;
+{
+	int len;
+
+	if ((len = pfkey_send_x3(so, SADB_DUMP, satype)) < 0)
+		return -1;
+
+	return len;
+}
+
+/*
+ * sending SADB_X_PROMISC message to the kernel.
+ * NOTE that this function handles promisc mode toggle only.
+ * IN:
+ *	flag:	set promisc off if zero, set promisc on if non-zero.
+ * OUT:
+ *	positive: success and return length sent.
+ *	-1	: error occured, and set errno.
+ *	0     : error occured, and set errno.
+ *	others: a pointer to new allocated buffer in which supported
+ *	        algorithms is.
+ */
+int
+pfkey_send_promisc_toggle(so, flag)
+	int so;
+	int flag;
+{
+	int len;
+
+	if ((len = pfkey_send_x3(so, SADB_X_PROMISC, 
+	    (u_int)(flag ? 1 : 0))) < 0)
+		return -1;
+
+	return len;
+}
+
+/*
+ * sending SADB_X_SPDADD message to the kernel.
+ * OUT:
+ *	positive: success and return length sent.
+ *	-1	: error occured, and set errno.
+ */
+int
+pfkey_send_spdadd(so, src, prefs, dst, prefd, proto, policy, policylen, seq)
+	int so;
+	struct sockaddr *src, *dst;
+	u_int prefs, prefd, proto;
+	caddr_t policy;
+	int policylen;
+	u_int32_t seq;
+{
+	int len;
+
+	if ((len = pfkey_send_x4(so, SADB_X_SPDADD,
+				src, prefs, dst, prefd, proto,
+				(u_int64_t)0, (u_int64_t)0,
+				policy, policylen, seq)) < 0)
+		return -1;
+
+	return len;
+}
+
+/*
+ * sending SADB_X_SPDADD message to the kernel.
+ * OUT:
+ *	positive: success and return length sent.
+ *	-1	: error occured, and set errno.
+ */
+int
+pfkey_send_spdadd2(so, src, prefs, dst, prefd, proto, ltime, vtime,
+		policy, policylen, seq)
+	int so;
+	struct sockaddr *src, *dst;
+	u_int prefs, prefd, proto;
+	u_int64_t ltime, vtime;
+	caddr_t policy;
+	int policylen;
+	u_int32_t seq;
+{
+	int len;
+
+	if ((len = pfkey_send_x4(so, SADB_X_SPDADD,
+				src, prefs, dst, prefd, proto,
+				ltime, vtime,
+				policy, policylen, seq)) < 0)
+		return -1;
+
+	return len;
+}
+
+/*
+ * sending SADB_X_SPDUPDATE message to the kernel.
+ * OUT:
+ *	positive: success and return length sent.
+ *	-1	: error occured, and set errno.
+ */
+int
+pfkey_send_spdupdate(so, src, prefs, dst, prefd, proto, policy, policylen, seq)
+	int so;
+	struct sockaddr *src, *dst;
+	u_int prefs, prefd, proto;
+	caddr_t policy;
+	int policylen;
+	u_int32_t seq;
+{
+	int len;
+
+	if ((len = pfkey_send_x4(so, SADB_X_SPDUPDATE,
+				src, prefs, dst, prefd, proto,
+				(u_int64_t)0, (u_int64_t)0,
+				policy, policylen, seq)) < 0)
+		return -1;
+
+	return len;
+}
+
+/*
+ * sending SADB_X_SPDUPDATE message to the kernel.
+ * OUT:
+ *	positive: success and return length sent.
+ *	-1	: error occured, and set errno.
+ */
+int
+pfkey_send_spdupdate2(so, src, prefs, dst, prefd, proto, ltime, vtime,
+		policy, policylen, seq)
+	int so;
+	struct sockaddr *src, *dst;
+	u_int prefs, prefd, proto;
+	u_int64_t ltime, vtime;
+	caddr_t policy;
+	int policylen;
+	u_int32_t seq;
+{
+	int len;
+
+	if ((len = pfkey_send_x4(so, SADB_X_SPDUPDATE,
+				src, prefs, dst, prefd, proto,
+				ltime, vtime,
+				policy, policylen, seq)) < 0)
+		return -1;
+
+	return len;
+}
+
+/*
+ * sending SADB_X_SPDDELETE message to the kernel.
+ * OUT:
+ *	positive: success and return length sent.
+ *	-1	: error occured, and set errno.
+ */
+int
+pfkey_send_spddelete(so, src, prefs, dst, prefd, proto, policy, policylen, seq)
+	int so;
+	struct sockaddr *src, *dst;
+	u_int prefs, prefd, proto;
+	caddr_t policy;
+	int policylen;
+	u_int32_t seq;
+{
+	int len;
+
+	if (policylen != sizeof(struct sadb_x_policy)) {
+		__ipsec_errcode = EIPSEC_INVAL_ARGUMENT;
+		return -1;
+	}
+
+	if ((len = pfkey_send_x4(so, SADB_X_SPDDELETE,
+				src, prefs, dst, prefd, proto,
+				(u_int64_t)0, (u_int64_t)0,
+				policy, policylen, seq)) < 0)
+		return -1;
+
+	return len;
+}
+
+/*
+ * sending SADB_X_SPDDELETE message to the kernel.
+ * OUT:
+ *	positive: success and return length sent.
+ *	-1	: error occured, and set errno.
+ */
+int
+pfkey_send_spddelete2(so, spid)
+	int so;
+	u_int32_t spid;
+{
+	int len;
+
+	if ((len = pfkey_send_x5(so, SADB_X_SPDDELETE2, spid)) < 0)
+		return -1;
+
+	return len;
+}
+
+/*
+ * sending SADB_X_SPDGET message to the kernel.
+ * OUT:
+ *	positive: success and return length sent.
+ *	-1	: error occured, and set errno.
+ */
+int
+pfkey_send_spdget(so, spid)
+	int so;
+	u_int32_t spid;
+{
+	int len;
+
+	if ((len = pfkey_send_x5(so, SADB_X_SPDGET, spid)) < 0)
+		return -1;
+
+	return len;
+}
+
+/*
+ * sending SADB_X_SPDSETIDX message to the kernel.
+ * OUT:
+ *	positive: success and return length sent.
+ *	-1	: error occured, and set errno.
+ */
+int
+pfkey_send_spdsetidx(so, src, prefs, dst, prefd, proto, policy, policylen, seq)
+	int so;
+	struct sockaddr *src, *dst;
+	u_int prefs, prefd, proto;
+	caddr_t policy;
+	int policylen;
+	u_int32_t seq;
+{
+	int len;
+
+	if (policylen != sizeof(struct sadb_x_policy)) {
+		__ipsec_errcode = EIPSEC_INVAL_ARGUMENT;
+		return -1;
+	}
+
+	if ((len = pfkey_send_x4(so, SADB_X_SPDSETIDX,
+				src, prefs, dst, prefd, proto,
+				(u_int64_t)0, (u_int64_t)0,
+				policy, policylen, seq)) < 0)
+		return -1;
+
+	return len;
+}
+
+/*
+ * sending SADB_SPDFLUSH message to the kernel.
+ * OUT:
+ *	positive: success and return length sent.
+ *	-1	: error occured, and set errno.
+ */
+int
+pfkey_send_spdflush(so)
+	int so;
+{
+	int len;
+
+	if ((len = pfkey_send_x3(so, SADB_X_SPDFLUSH, SADB_SATYPE_UNSPEC)) < 0)
+		return -1;
+
+	return len;
+}
+
+/*
+ * sending SADB_SPDDUMP message to the kernel.
+ * OUT:
+ *	positive: success and return length sent.
+ *	-1	: error occured, and set errno.
+ */
+int
+pfkey_send_spddump(so)
+	int so;
+{
+	int len;
+
+	if ((len = pfkey_send_x3(so, SADB_X_SPDDUMP, SADB_SATYPE_UNSPEC)) < 0)
+		return -1;
+
+	return len;
+}
+
+
+#ifdef SADB_X_MIGRATE
+/*
+ * sending SADB_X_MIGRATE message to the kernel.
+ * OUT:
+ *	positive: success and return length sent.
+ *	-1	: error occured, and set errno.
+ */
+int
+pfkey_send_migrate(so, src, prefs, dst, prefd, proto, policy, policylen, seq)
+	int so;
+	struct sockaddr *src, *dst;
+	u_int prefs, prefd, proto;
+	caddr_t policy;
+	int policylen;
+	u_int32_t seq;
+{
+	struct sadb_msg *newmsg;
+	int len;
+	caddr_t p;
+	int plen;
+	caddr_t ep;
+
+	/* validity check */
+	if (src == NULL || dst == NULL) {
+		__ipsec_errcode = EIPSEC_INVAL_ARGUMENT;
+		return -1;
+	}
+	if (src->sa_family != dst->sa_family) {
+		__ipsec_errcode = EIPSEC_FAMILY_MISMATCH;
+		return -1;
+	}
+
+	switch (src->sa_family) {
+	case AF_INET:
+		plen = sizeof(struct in_addr) << 3;
+		break;
+	case AF_INET6:
+		plen = sizeof(struct in6_addr) << 3;
+		break;
+	default:
+		__ipsec_errcode = EIPSEC_INVAL_FAMILY;
+		return -1;
+	}
+	if (prefs > plen || prefd > plen) {
+		__ipsec_errcode = EIPSEC_INVAL_PREFIXLEN;
+		return -1;
+	}
+
+	/* create new sadb_msg to reply. */
+	len = sizeof(struct sadb_msg)
+		+ sizeof(struct sadb_address)
+		+ PFKEY_ALIGN8(sysdep_sa_len(src))
+		+ sizeof(struct sadb_address)
+		+ PFKEY_ALIGN8(sysdep_sa_len(dst))
+		+ policylen;
+
+	if ((newmsg = CALLOC(len, struct sadb_msg *)) == NULL) {
+		__ipsec_set_strerror(strerror(errno));
+		return -1;
+	}
+	ep = ((caddr_t)newmsg) + len;
+
+	p = pfkey_setsadbmsg((caddr_t)newmsg, ep, SADB_X_MIGRATE, (u_int)len,
+	    SADB_SATYPE_UNSPEC, seq, getpid());
+	if (!p) {
+		free(newmsg);
+		return -1;
+	}
+	p = pfkey_setsadbaddr(p, ep, SADB_EXT_ADDRESS_SRC, src, prefs, proto);
+	if (!p) {
+		free(newmsg);
+		return -1;
+	}
+	p = pfkey_setsadbaddr(p, ep, SADB_EXT_ADDRESS_DST, dst, prefd, proto);
+	if (!p || p + policylen != ep) {
+		free(newmsg);
+		return -1;
+	}
+	memcpy(p, policy, policylen);
+
+	/* send message */
+	len = pfkey_send(so, newmsg, len);
+	free(newmsg);
+
+	if (len < 0)
+		return -1;
+
+	__ipsec_errcode = EIPSEC_NO_ERROR;
+	return len;
+}
+#endif
+
+
+/* sending SADB_ADD or SADB_UPDATE message to the kernel */
+static int
+pfkey_send_x1(sa_parms)
+	struct pfkey_send_sa_args *sa_parms;
+{
+	struct sadb_msg *newmsg;
+	int len;
+	caddr_t p;
+	int plen;
+	caddr_t ep;
+
+	/* validity check */
+	if (sa_parms->src == NULL || sa_parms->dst == NULL) {
+		__ipsec_errcode = EIPSEC_INVAL_ARGUMENT;
+		return -1;
+	}
+	if (sa_parms->src->sa_family != sa_parms->dst->sa_family) {
+		__ipsec_errcode = EIPSEC_FAMILY_MISMATCH;
+		return -1;
+	}
+	switch (sa_parms->src->sa_family) {
+	case AF_INET:
+		plen = sizeof(struct in_addr) << 3;
+		break;
+	case AF_INET6:
+		plen = sizeof(struct in6_addr) << 3;
+		break;
+	default:
+		__ipsec_errcode = EIPSEC_INVAL_FAMILY;
+		return -1;
+	}
+
+	switch (sa_parms->satype) {
+	case SADB_SATYPE_ESP:
+		if (sa_parms->e_type == SADB_EALG_NONE) {
+			__ipsec_errcode = EIPSEC_NO_ALGS;
+			return -1;
+		}
+		break;
+	case SADB_SATYPE_AH:
+		if (sa_parms->e_type != SADB_EALG_NONE) {
+			__ipsec_errcode = EIPSEC_INVAL_ALGS;
+			return -1;
+		}
+		if (sa_parms->a_type == SADB_AALG_NONE) {
+			__ipsec_errcode = EIPSEC_NO_ALGS;
+			return -1;
+		}
+		break;
+	case SADB_X_SATYPE_IPCOMP:
+		if (sa_parms->e_type == SADB_X_CALG_NONE) {
+			__ipsec_errcode = EIPSEC_INVAL_ALGS;
+			return -1;
+		}
+		if (sa_parms->a_type != SADB_AALG_NONE) {
+			__ipsec_errcode = EIPSEC_NO_ALGS;
+			return -1;
+		}
+		break;
+#ifdef SADB_X_AALG_TCP_MD5
+	case SADB_X_SATYPE_TCPSIGNATURE:
+		if (sa_parms->e_type != SADB_EALG_NONE) {
+			__ipsec_errcode = EIPSEC_INVAL_ALGS;
+			return -1;
+		}
+		if (sa_parms->a_type != SADB_X_AALG_TCP_MD5) {
+			__ipsec_errcode = EIPSEC_INVAL_ALGS;
+			return -1;
+		}
+		break;
+#endif
+	default:
+		__ipsec_errcode = EIPSEC_INVAL_SATYPE;
+		return -1;
+	}
+
+	/* create new sadb_msg to reply. */
+	len = sizeof(struct sadb_msg)
+		+ sizeof(struct sadb_sa)
+		+ sizeof(struct sadb_x_sa2)
+		+ sizeof(struct sadb_address)
+		+ PFKEY_ALIGN8(sysdep_sa_len(sa_parms->src))
+		+ sizeof(struct sadb_address)
+		+ PFKEY_ALIGN8(sysdep_sa_len(sa_parms->dst))
+		+ sizeof(struct sadb_lifetime)
+		+ sizeof(struct sadb_lifetime);
+
+	if (sa_parms->e_type != SADB_EALG_NONE && 
+	    sa_parms->satype != SADB_X_SATYPE_IPCOMP)
+		len += (sizeof(struct sadb_key) + 
+			PFKEY_ALIGN8(sa_parms->e_keylen));
+	if (sa_parms->a_type != SADB_AALG_NONE)
+		len += (sizeof(struct sadb_key) + 
+			PFKEY_ALIGN8(sa_parms->a_keylen));
+
+#ifdef SADB_X_EXT_SEC_CTX
+	if (sa_parms->ctxstr != NULL)
+		len += (sizeof(struct sadb_x_sec_ctx)
+		    + PFKEY_ALIGN8(sa_parms->ctxstrlen));
+#endif
+
+#ifdef SADB_X_EXT_NAT_T_TYPE
+	/* add nat-t packets */
+	if (sa_parms->l_natt_type) {
+		switch(sa_parms->satype) {
+		case SADB_SATYPE_ESP:
+		case SADB_X_SATYPE_IPCOMP:
+			break;
+		default:
+			__ipsec_errcode = EIPSEC_NO_ALGS;
+			return -1;
+		}
+
+		len += sizeof(struct sadb_x_nat_t_type);
+		len += sizeof(struct sadb_x_nat_t_port);
+		len += sizeof(struct sadb_x_nat_t_port);
+		if (sa_parms->l_natt_oa)
+			len += sizeof(struct sadb_address) +
+			  PFKEY_ALIGN8(sysdep_sa_len(sa_parms->l_natt_oa));
+#ifdef SADB_X_EXT_NAT_T_FRAG
+		if (sa_parms->l_natt_frag)
+			len += sizeof(struct sadb_x_nat_t_frag);
+#endif
+	}
+#endif
+
+	if ((newmsg = CALLOC((size_t)len, struct sadb_msg *)) == NULL) {
+		__ipsec_set_strerror(strerror(errno));
+		return -1;
+	}
+	ep = ((caddr_t)(void *)newmsg) + len;
+
+	p = pfkey_setsadbmsg((void *)newmsg, ep, sa_parms->type, (u_int)len,
+	                     sa_parms->satype, sa_parms->seq, getpid());
+	if (!p) {
+		free(newmsg);
+		return -1;
+	}
+	p = pfkey_setsadbsa(p, ep, sa_parms->spi, sa_parms->wsize, 
+			    sa_parms->a_type, sa_parms->e_type, 
+			    sa_parms->flags);
+	if (!p) {
+		free(newmsg);
+		return -1;
+	}
+	p = pfkey_setsadbxsa2(p, ep, sa_parms->mode, sa_parms->reqid);
+	if (!p) {
+		free(newmsg);
+		return -1;
+	}
+	p = pfkey_setsadbaddr(p, ep, SADB_EXT_ADDRESS_SRC, sa_parms->src, 
+			      (u_int)plen, IPSEC_ULPROTO_ANY);
+	if (!p) {
+		free(newmsg);
+		return -1;
+	}
+	p = pfkey_setsadbaddr(p, ep, SADB_EXT_ADDRESS_DST, sa_parms->dst, 
+			      (u_int)plen, IPSEC_ULPROTO_ANY);
+	if (!p) {
+		free(newmsg);
+		return -1;
+	}
+
+	if (sa_parms->e_type != SADB_EALG_NONE && 
+	    sa_parms->satype != SADB_X_SATYPE_IPCOMP) {
+		p = pfkey_setsadbkey(p, ep, SADB_EXT_KEY_ENCRYPT,
+		                   sa_parms->keymat, sa_parms->e_keylen);
+		if (!p) {
+			free(newmsg);
+			return -1;
+		}
+	}
+	if (sa_parms->a_type != SADB_AALG_NONE) {
+		p = pfkey_setsadbkey(p, ep, SADB_EXT_KEY_AUTH,
+				     sa_parms->keymat + sa_parms->e_keylen, 
+				     sa_parms->a_keylen);
+		if (!p) {
+			free(newmsg);
+			return -1;
+		}
+	}
+
+	/* set sadb_lifetime for destination */
+	p = pfkey_setsadblifetime(p, ep, SADB_EXT_LIFETIME_HARD,
+			sa_parms->l_alloc, sa_parms->l_bytes, 
+			sa_parms->l_addtime, sa_parms->l_usetime);
+	if (!p) {
+		free(newmsg);
+		return -1;
+	}
+	p = pfkey_setsadblifetime(p, ep, SADB_EXT_LIFETIME_SOFT,
+				  sa_parms->l_alloc, sa_parms->l_bytes, 
+				  sa_parms->l_addtime, sa_parms->l_usetime);
+	if (!p) {
+		free(newmsg);
+		return -1;
+	}
+#ifdef SADB_X_EXT_SEC_CTX
+	if (sa_parms->ctxstr != NULL) {
+		p = pfkey_setsecctx(p, ep, SADB_X_EXT_SEC_CTX, sa_parms->ctxdoi,
+				    sa_parms->ctxalg, sa_parms->ctxstr, 
+				    sa_parms->ctxstrlen);
+		if (!p) {
+			free(newmsg);
+			return -1;
+		}
+	}
+#endif
+
+#ifdef SADB_X_EXT_NAT_T_TYPE
+	/* Add nat-t messages */
+	if (sa_parms->l_natt_type) {
+		p = pfkey_set_natt_type(p, ep, SADB_X_EXT_NAT_T_TYPE, 
+					sa_parms->l_natt_type);
+		if (!p) {
+			free(newmsg);
+			return -1;
+		}
+
+		p = pfkey_set_natt_port(p, ep, SADB_X_EXT_NAT_T_SPORT,
+					sa_parms->l_natt_sport);
+		if (!p) {
+			free(newmsg);
+			return -1;
+		}
+
+		p = pfkey_set_natt_port(p, ep, SADB_X_EXT_NAT_T_DPORT,
+					sa_parms->l_natt_dport);
+		if (!p) {
+			free(newmsg);
+			return -1;
+		}
+
+		if (sa_parms->l_natt_oa) {
+			p = pfkey_setsadbaddr(p, ep, SADB_X_EXT_NAT_T_OA,
+					      sa_parms->l_natt_oa,
+					      (u_int)PFKEY_ALIGN8(sysdep_sa_len(sa_parms->l_natt_oa)),
+					      IPSEC_ULPROTO_ANY);
+			if (!p) {
+				free(newmsg);
+				return -1;
+			}
+		}
+
+#ifdef SADB_X_EXT_NAT_T_FRAG
+		if (sa_parms->l_natt_frag) {
+			p = pfkey_set_natt_frag(p, ep, SADB_X_EXT_NAT_T_FRAG,
+					sa_parms->l_natt_frag);
+			if (!p) {
+				free(newmsg);
+				return -1;
+			}
+		}
+#endif
+	}
+#endif
+
+	if (p != ep) {
+		free(newmsg);
+		return -1;
+	}
+
+	/* send message */
+	len = pfkey_send(sa_parms->so, newmsg, len);
+	free(newmsg);
+
+	if (len < 0)
+		return -1;
+
+	__ipsec_errcode = EIPSEC_NO_ERROR;
+	return len;
+}
+
+/* sending SADB_DELETE or SADB_GET message to the kernel */
+/*ARGSUSED*/
+static int
+pfkey_send_x2(so, type, satype, mode, src, dst, spi)
+	int so;
+	u_int type, satype, mode;
+	struct sockaddr *src, *dst;
+	u_int32_t spi;
+{
+	struct sadb_msg *newmsg;
+	int len;
+	caddr_t p;
+	int plen;
+	caddr_t ep;
+
+	/* validity check */
+	if (src == NULL || dst == NULL) {
+		__ipsec_errcode = EIPSEC_INVAL_ARGUMENT;
+		return -1;
+	}
+	if (src->sa_family != dst->sa_family) {
+		__ipsec_errcode = EIPSEC_FAMILY_MISMATCH;
+		return -1;
+	}
+	switch (src->sa_family) {
+	case AF_INET:
+		plen = sizeof(struct in_addr) << 3;
+		break;
+	case AF_INET6:
+		plen = sizeof(struct in6_addr) << 3;
+		break;
+	default:
+		__ipsec_errcode = EIPSEC_INVAL_FAMILY;
+		return -1;
+	}
+
+	/* create new sadb_msg to reply. */
+	len = sizeof(struct sadb_msg)
+		+ sizeof(struct sadb_sa)
+		+ sizeof(struct sadb_address)
+		+ PFKEY_ALIGN8(sysdep_sa_len(src))
+		+ sizeof(struct sadb_address)
+		+ PFKEY_ALIGN8(sysdep_sa_len(dst));
+
+	if ((newmsg = CALLOC((size_t)len, struct sadb_msg *)) == NULL) {
+		__ipsec_set_strerror(strerror(errno));
+		return -1;
+	}
+	ep = ((caddr_t)(void *)newmsg) + len;
+
+	p = pfkey_setsadbmsg((void *)newmsg, ep, type, (u_int)len, satype, 0,
+	    getpid());
+	if (!p) {
+		free(newmsg);
+		return -1;
+	}
+	p = pfkey_setsadbsa(p, ep, spi, 0, 0, 0, 0);
+	if (!p) {
+		free(newmsg);
+		return -1;
+	}
+	p = pfkey_setsadbaddr(p, ep, SADB_EXT_ADDRESS_SRC, src, (u_int)plen,
+	    IPSEC_ULPROTO_ANY);
+	if (!p) {
+		free(newmsg);
+		return -1;
+	}
+	p = pfkey_setsadbaddr(p, ep, SADB_EXT_ADDRESS_DST, dst, (u_int)plen,
+	    IPSEC_ULPROTO_ANY);
+	if (!p || p != ep) {
+		free(newmsg);
+		return -1;
+	}
+
+	/* send message */
+	len = pfkey_send(so, newmsg, len);
+	free(newmsg);
+
+	if (len < 0)
+		return -1;
+
+	__ipsec_errcode = EIPSEC_NO_ERROR;
+	return len;
+}
+
+/*
+ * sending SADB_REGISTER, SADB_FLUSH, SADB_DUMP or SADB_X_PROMISC message
+ * to the kernel
+ */
+static int
+pfkey_send_x3(so, type, satype)
+	int so;
+	u_int type, satype;
+{
+	struct sadb_msg *newmsg;
+	int len;
+	caddr_t p;
+	caddr_t ep;
+
+	/* validity check */
+	switch (type) {
+	case SADB_X_PROMISC:
+		if (satype != 0 && satype != 1) {
+			__ipsec_errcode = EIPSEC_INVAL_SATYPE;
+			return -1;
+		}
+		break;
+	default:
+		switch (satype) {
+		case SADB_SATYPE_UNSPEC:
+		case SADB_SATYPE_AH:
+		case SADB_SATYPE_ESP:
+		case SADB_X_SATYPE_IPCOMP:
+#ifdef SADB_X_SATYPE_TCPSIGNATURE
+		case SADB_X_SATYPE_TCPSIGNATURE:
+#endif
+			break;
+		default:
+			__ipsec_errcode = EIPSEC_INVAL_SATYPE;
+			return -1;
+		}
+	}
+
+	/* create new sadb_msg to send. */
+	len = sizeof(struct sadb_msg);
+
+	if ((newmsg = CALLOC((size_t)len, struct sadb_msg *)) == NULL) {
+		__ipsec_set_strerror(strerror(errno));
+		return -1;
+	}
+	ep = ((caddr_t)(void *)newmsg) + len;
+
+	p = pfkey_setsadbmsg((void *)newmsg, ep, type, (u_int)len, satype, 0,
+	    getpid());
+	if (!p || p != ep) {
+		free(newmsg);
+		return -1;
+	}
+
+	/* send message */
+	len = pfkey_send(so, newmsg, len);
+	free(newmsg);
+
+	if (len < 0)
+		return -1;
+
+	__ipsec_errcode = EIPSEC_NO_ERROR;
+	return len;
+}
+
+/* sending SADB_X_SPDADD message to the kernel */
+static int
+pfkey_send_x4(so, type, src, prefs, dst, prefd, proto,
+		ltime, vtime, policy, policylen, seq)
+	int so;
+	struct sockaddr *src, *dst;
+	u_int type, prefs, prefd, proto;
+	u_int64_t ltime, vtime;
+	char *policy;
+	int policylen;
+	u_int32_t seq;
+{
+	struct sadb_msg *newmsg;
+	int len;
+	caddr_t p;
+	int plen;
+	caddr_t ep;
+
+	/* validity check */
+	if (src == NULL || dst == NULL) {
+		__ipsec_errcode = EIPSEC_INVAL_ARGUMENT;
+		return -1;
+	}
+	if (src->sa_family != dst->sa_family) {
+		__ipsec_errcode = EIPSEC_FAMILY_MISMATCH;
+		return -1;
+	}
+
+	switch (src->sa_family) {
+	case AF_INET:
+		plen = sizeof(struct in_addr) << 3;
+		break;
+	case AF_INET6:
+		plen = sizeof(struct in6_addr) << 3;
+		break;
+	default:
+		__ipsec_errcode = EIPSEC_INVAL_FAMILY;
+		return -1;
+	}
+	if (prefs > plen || prefd > plen) {
+		__ipsec_errcode = EIPSEC_INVAL_PREFIXLEN;
+		return -1;
+	}
+
+	/* create new sadb_msg to reply. */
+	len = sizeof(struct sadb_msg)
+		+ sizeof(struct sadb_address)
+		+ PFKEY_ALIGN8(sysdep_sa_len(src))
+		+ sizeof(struct sadb_address)
+		+ PFKEY_ALIGN8(sysdep_sa_len(src))
+		+ sizeof(struct sadb_lifetime)
+		+ policylen;
+
+	if ((newmsg = CALLOC((size_t)len, struct sadb_msg *)) == NULL) {
+		__ipsec_set_strerror(strerror(errno));
+		return -1;
+	}
+	ep = ((caddr_t)(void *)newmsg) + len;
+
+	p = pfkey_setsadbmsg((void *)newmsg, ep, type, (u_int)len,
+	    SADB_SATYPE_UNSPEC, seq, getpid());
+	if (!p) {
+		free(newmsg);
+		return -1;
+	}
+	p = pfkey_setsadbaddr(p, ep, SADB_EXT_ADDRESS_SRC, src, prefs, proto);
+	if (!p) {
+		free(newmsg);
+		return -1;
+	}
+	p = pfkey_setsadbaddr(p, ep, SADB_EXT_ADDRESS_DST, dst, prefd, proto);
+	if (!p) {
+		free(newmsg);
+		return -1;
+	}
+	p = pfkey_setsadblifetime(p, ep, SADB_EXT_LIFETIME_HARD,
+			0, 0, (u_int)ltime, (u_int)vtime);
+	if (!p || p + policylen != ep) {
+		free(newmsg);
+		return -1;
+	}
+	memcpy(p, policy, (size_t)policylen);
+
+	/* send message */
+	len = pfkey_send(so, newmsg, len);
+	free(newmsg);
+
+	if (len < 0)
+		return -1;
+
+	__ipsec_errcode = EIPSEC_NO_ERROR;
+	return len;
+}
+
+/* sending SADB_X_SPDGET or SADB_X_SPDDELETE message to the kernel */
+static int
+pfkey_send_x5(so, type, spid)
+	int so;
+	u_int type;
+	u_int32_t spid;
+{
+	struct sadb_msg *newmsg;
+	struct sadb_x_policy xpl;
+	int len;
+	caddr_t p;
+	caddr_t ep;
+
+	/* create new sadb_msg to reply. */
+	len = sizeof(struct sadb_msg)
+		+ sizeof(xpl);
+
+	if ((newmsg = CALLOC((size_t)len, struct sadb_msg *)) == NULL) {
+		__ipsec_set_strerror(strerror(errno));
+		return -1;
+	}
+	ep = ((caddr_t)(void *)newmsg) + len;
+
+	p = pfkey_setsadbmsg((void *)newmsg, ep, type, (u_int)len,
+	    SADB_SATYPE_UNSPEC, 0, getpid());
+	if (!p) {
+		free(newmsg);
+		return -1;
+	}
+
+	if (p + sizeof(xpl) != ep) {
+		free(newmsg);
+		return -1;
+	}
+	memset(&xpl, 0, sizeof(xpl));
+	xpl.sadb_x_policy_len = PFKEY_UNIT64(sizeof(xpl));
+	xpl.sadb_x_policy_exttype = SADB_X_EXT_POLICY;
+	xpl.sadb_x_policy_id = spid;
+	memcpy(p, &xpl, sizeof(xpl));
+
+	/* send message */
+	len = pfkey_send(so, newmsg, len);
+	free(newmsg);
+
+	if (len < 0)
+		return -1;
+
+	__ipsec_errcode = EIPSEC_NO_ERROR;
+	return len;
+}
+
+/*
+ * open a socket.
+ * OUT:
+ *	-1: fail.
+ *	others : success and return value of socket.
+ */
+int
+pfkey_open()
+{
+	int so;
+	int bufsiz = 128 * 1024;	/*is 128K enough?*/
+
+	if ((so = socket(PF_KEY, SOCK_RAW, PF_KEY_V2)) < 0) {
+		__ipsec_set_strerror(strerror(errno));
+		return -1;
+	}
+
+	/*
+	 * This is a temporary workaround for KAME PR 154.
+	 * Don't really care even if it fails.
+	 */
+	(void)setsockopt(so, SOL_SOCKET, SO_SNDBUF, &bufsiz, sizeof(bufsiz));
+	(void)setsockopt(so, SOL_SOCKET, SO_RCVBUF, &bufsiz, sizeof(bufsiz));
+	bufsiz = 256 * 1024;
+	(void)setsockopt(so, SOL_SOCKET, SO_RCVBUF, &bufsiz, sizeof(bufsiz));
+	bufsiz = 512 * 1024;
+	(void)setsockopt(so, SOL_SOCKET, SO_RCVBUF, &bufsiz, sizeof(bufsiz));
+	bufsiz = 1024 * 1024;
+	(void)setsockopt(so, SOL_SOCKET, SO_RCVBUF, &bufsiz, sizeof(bufsiz));
+	__ipsec_errcode = EIPSEC_NO_ERROR;
+	return so;
+}
+
+/*
+ * close a socket.
+ * OUT:
+ *	 0: success.
+ *	-1: fail.
+ */
+void
+pfkey_close(so)
+	int so;
+{
+	(void)close(so);
+
+	__ipsec_errcode = EIPSEC_NO_ERROR;
+	return;
+}
+
+/*
+ * receive sadb_msg data, and return pointer to new buffer allocated.
+ * Must free this buffer later.
+ * OUT:
+ *	NULL	: error occured.
+ *	others	: a pointer to sadb_msg structure.
+ *
+ * XXX should be rewritten to pass length explicitly
+ */
+struct sadb_msg *
+pfkey_recv(so)
+	int so;
+{
+	struct sadb_msg buf, *newmsg;
+	int len, reallen;
+
+	while ((len = recv(so, (void *)&buf, sizeof(buf), MSG_PEEK)) < 0) {
+		if (errno == EINTR)
+			continue;
+		__ipsec_set_strerror(strerror(errno));
+		return NULL;
+	}
+
+	if (len < sizeof(buf)) {
+		recv(so, (void *)&buf, sizeof(buf), 0);
+		__ipsec_errcode = EIPSEC_MAX;
+		return NULL;
+	}
+
+	/* read real message */
+	reallen = PFKEY_UNUNIT64(buf.sadb_msg_len);
+	if ((newmsg = CALLOC((size_t)reallen, struct sadb_msg *)) == 0) {
+		__ipsec_set_strerror(strerror(errno));
+		return NULL;
+	}
+
+	while ((len = recv(so, (void *)newmsg, (socklen_t)reallen, 0)) < 0) {
+		if (errno == EINTR)
+			continue;
+		__ipsec_set_strerror(strerror(errno));
+		free(newmsg);
+		return NULL;
+	}
+
+	if (len != reallen) {
+		__ipsec_errcode = EIPSEC_SYSTEM_ERROR;
+		free(newmsg);
+		return NULL;
+	}
+
+	/* don't trust what the kernel says, validate! */
+	if (PFKEY_UNUNIT64(newmsg->sadb_msg_len) != len) {
+		__ipsec_errcode = EIPSEC_SYSTEM_ERROR;
+		free(newmsg);
+		return NULL;
+	}
+
+	__ipsec_errcode = EIPSEC_NO_ERROR;
+	return newmsg;
+}
+
+/*
+ * send message to a socket.
+ * OUT:
+ *	 others: success and return length sent.
+ *	-1     : fail.
+ */
+int
+pfkey_send(so, msg, len)
+	int so;
+	struct sadb_msg *msg;
+	int len;
+{
+	if ((len = send(so, (void *)msg, (socklen_t)len, 0)) < 0) {
+		__ipsec_set_strerror(strerror(errno));
+		return -1;
+	}
+
+	__ipsec_errcode = EIPSEC_NO_ERROR;
+	return len;
+}
+
+/*
+ * %%% Utilities
+ * NOTE: These functions are derived from netkey/key.c in KAME.
+ */
+/*
+ * set the pointer to each header in this message buffer.
+ * IN:	msg: pointer to message buffer.
+ *	mhp: pointer to the buffer initialized like below:
+ *		caddr_t mhp[SADB_EXT_MAX + 1];
+ * OUT:	-1: invalid.
+ *	 0: valid.
+ *
+ * XXX should be rewritten to obtain length explicitly
+ */
+int
+pfkey_align(msg, mhp)
+	struct sadb_msg *msg;
+	caddr_t *mhp;
+{
+	struct sadb_ext *ext;
+	int i;
+	caddr_t p;
+	caddr_t ep;	/* XXX should be passed from upper layer */
+
+	/* validity check */
+	if (msg == NULL || mhp == NULL) {
+		__ipsec_errcode = EIPSEC_INVAL_ARGUMENT;
+		return -1;
+	}
+
+	/* initialize */
+	for (i = 0; i < SADB_EXT_MAX + 1; i++)
+		mhp[i] = NULL;
+
+	mhp[0] = (void *)msg;
+
+	/* initialize */
+	p = (void *) msg;
+	ep = p + PFKEY_UNUNIT64(msg->sadb_msg_len);
+
+	/* skip base header */
+	p += sizeof(struct sadb_msg);
+
+	while (p < ep) {
+		ext = (void *)p;
+		if (ep < p + sizeof(*ext) || PFKEY_EXTLEN(ext) < sizeof(*ext) ||
+		    ep < p + PFKEY_EXTLEN(ext)) {
+			/* invalid format */
+			break;
+		}
+
+		/* duplicate check */
+		/* XXX Are there duplication either KEY_AUTH or KEY_ENCRYPT ?*/
+		if (mhp[ext->sadb_ext_type] != NULL) {
+			__ipsec_errcode = EIPSEC_INVAL_EXTTYPE;
+			return -1;
+		}
+
+		/* set pointer */
+		switch (ext->sadb_ext_type) {
+		case SADB_EXT_SA:
+		case SADB_EXT_LIFETIME_CURRENT:
+		case SADB_EXT_LIFETIME_HARD:
+		case SADB_EXT_LIFETIME_SOFT:
+		case SADB_EXT_ADDRESS_SRC:
+		case SADB_EXT_ADDRESS_DST:
+		case SADB_EXT_ADDRESS_PROXY:
+		case SADB_EXT_KEY_AUTH:
+			/* XXX should to be check weak keys. */
+		case SADB_EXT_KEY_ENCRYPT:
+			/* XXX should to be check weak keys. */
+		case SADB_EXT_IDENTITY_SRC:
+		case SADB_EXT_IDENTITY_DST:
+		case SADB_EXT_SENSITIVITY:
+		case SADB_EXT_PROPOSAL:
+		case SADB_EXT_SUPPORTED_AUTH:
+		case SADB_EXT_SUPPORTED_ENCRYPT:
+		case SADB_EXT_SPIRANGE:
+		case SADB_X_EXT_POLICY:
+		case SADB_X_EXT_SA2:
+#ifdef SADB_X_EXT_NAT_T_TYPE
+		case SADB_X_EXT_NAT_T_TYPE:
+		case SADB_X_EXT_NAT_T_SPORT:
+		case SADB_X_EXT_NAT_T_DPORT:
+		case SADB_X_EXT_NAT_T_OA:
+#endif
+#ifdef SADB_X_EXT_TAG
+		case SADB_X_EXT_TAG:
+#endif
+#ifdef SADB_X_EXT_PACKET
+		case SADB_X_EXT_PACKET:
+#endif
+#ifdef SADB_X_EXT_SEC_CTX
+		case SADB_X_EXT_SEC_CTX:
+#endif
+			mhp[ext->sadb_ext_type] = (void *)ext;
+			break;
+		default:
+			__ipsec_errcode = EIPSEC_INVAL_EXTTYPE;
+			return -1;
+		}
+
+		p += PFKEY_EXTLEN(ext);
+	}
+
+	if (p != ep) {
+		__ipsec_errcode = EIPSEC_INVAL_SADBMSG;
+		return -1;
+	}
+
+	__ipsec_errcode = EIPSEC_NO_ERROR;
+	return 0;
+}
+
+/*
+ * check basic usage for sadb_msg,
+ * NOTE: This routine is derived from netkey/key.c in KAME.
+ * IN:	msg: pointer to message buffer.
+ *	mhp: pointer to the buffer initialized like below:
+ *
+ *		caddr_t mhp[SADB_EXT_MAX + 1];
+ *
+ * OUT:	-1: invalid.
+ *	 0: valid.
+ */
+int
+pfkey_check(mhp)
+	caddr_t *mhp;
+{
+	struct sadb_msg *msg;
+
+	/* validity check */
+	if (mhp == NULL || mhp[0] == NULL) {
+		__ipsec_errcode = EIPSEC_INVAL_ARGUMENT;
+		return -1;
+	}
+
+	msg = (void *)mhp[0];
+
+	/* check version */
+	if (msg->sadb_msg_version != PF_KEY_V2) {
+		__ipsec_errcode = EIPSEC_INVAL_VERSION;
+		return -1;
+	}
+
+	/* check type */
+	if (msg->sadb_msg_type > SADB_MAX) {
+		__ipsec_errcode = EIPSEC_INVAL_MSGTYPE;
+		return -1;
+	}
+
+	/* check SA type */
+	switch (msg->sadb_msg_satype) {
+	case SADB_SATYPE_UNSPEC:
+		switch (msg->sadb_msg_type) {
+		case SADB_GETSPI:
+		case SADB_UPDATE:
+		case SADB_ADD:
+		case SADB_DELETE:
+		case SADB_GET:
+		case SADB_ACQUIRE:
+		case SADB_EXPIRE:
+#ifdef SADB_X_NAT_T_NEW_MAPPING
+		case SADB_X_NAT_T_NEW_MAPPING:
+#endif
+			__ipsec_errcode = EIPSEC_INVAL_SATYPE;
+			return -1;
+		}
+		break;
+	case SADB_SATYPE_ESP:
+	case SADB_SATYPE_AH:
+	case SADB_X_SATYPE_IPCOMP:
+#ifdef SADB_X_SATYPE_TCPSIGNATURE
+	case SADB_X_SATYPE_TCPSIGNATURE:
+#endif
+		switch (msg->sadb_msg_type) {
+		case SADB_X_SPDADD:
+		case SADB_X_SPDDELETE:
+		case SADB_X_SPDGET:
+		case SADB_X_SPDDUMP:
+		case SADB_X_SPDFLUSH:
+			__ipsec_errcode = EIPSEC_INVAL_SATYPE;
+			return -1;
+		}
+#ifdef SADB_X_NAT_T_NEW_MAPPING
+		if (msg->sadb_msg_type == SADB_X_NAT_T_NEW_MAPPING &&
+		    msg->sadb_msg_satype != SADB_SATYPE_ESP) {
+			__ipsec_errcode = EIPSEC_INVAL_SATYPE;
+			return -1;
+		}
+#endif
+		break;
+	case SADB_SATYPE_RSVP:
+	case SADB_SATYPE_OSPFV2:
+	case SADB_SATYPE_RIPV2:
+	case SADB_SATYPE_MIP:
+		__ipsec_errcode = EIPSEC_NOT_SUPPORTED;
+		return -1;
+	case 1:	/* XXX: What does it do ? */
+		if (msg->sadb_msg_type == SADB_X_PROMISC)
+			break;
+		/*FALLTHROUGH*/
+	default:
+		__ipsec_errcode = EIPSEC_INVAL_SATYPE;
+		return -1;
+	}
+
+	/* check field of upper layer protocol and address family */
+	if (mhp[SADB_EXT_ADDRESS_SRC] != NULL
+	 && mhp[SADB_EXT_ADDRESS_DST] != NULL) {
+		struct sadb_address *src0, *dst0;
+
+		src0 = (void *)(mhp[SADB_EXT_ADDRESS_SRC]);
+		dst0 = (void *)(mhp[SADB_EXT_ADDRESS_DST]);
+
+		if (src0->sadb_address_proto != dst0->sadb_address_proto) {
+			__ipsec_errcode = EIPSEC_PROTO_MISMATCH;
+			return -1;
+		}
+
+		if (PFKEY_ADDR_SADDR(src0)->sa_family
+		 != PFKEY_ADDR_SADDR(dst0)->sa_family) {
+			__ipsec_errcode = EIPSEC_FAMILY_MISMATCH;
+			return -1;
+		}
+
+		switch (PFKEY_ADDR_SADDR(src0)->sa_family) {
+		case AF_INET:
+		case AF_INET6:
+			break;
+		default:
+			__ipsec_errcode = EIPSEC_INVAL_FAMILY;
+			return -1;
+		}
+
+		/*
+		 * prefixlen == 0 is valid because there must be the case
+		 * all addresses are matched.
+		 */
+	}
+
+	__ipsec_errcode = EIPSEC_NO_ERROR;
+	return 0;
+}
+
+/*
+ * set data into sadb_msg.
+ * `buf' must has been allocated sufficiently.
+ */
+static caddr_t
+pfkey_setsadbmsg(buf, lim, type, tlen, satype, seq, pid)
+	caddr_t buf;
+	caddr_t lim;
+	u_int type, satype;
+	u_int tlen;
+	u_int32_t seq;
+	pid_t pid;
+{
+	struct sadb_msg *p;
+	u_int len;
+
+	p = (void *)buf;
+	len = sizeof(struct sadb_msg);
+
+	if (buf + len > lim)
+		return NULL;
+
+	memset(p, 0, len);
+	p->sadb_msg_version = PF_KEY_V2;
+	p->sadb_msg_type = type;
+	p->sadb_msg_errno = 0;
+	p->sadb_msg_satype = satype;
+	p->sadb_msg_len = PFKEY_UNIT64(tlen);
+	p->sadb_msg_reserved = 0;
+	p->sadb_msg_seq = seq;
+	p->sadb_msg_pid = (u_int32_t)pid;
+
+	return(buf + len);
+}
+
+/*
+ * copy secasvar data into sadb_address.
+ * `buf' must has been allocated sufficiently.
+ */
+static caddr_t
+pfkey_setsadbsa(buf, lim, spi, wsize, auth, enc, flags)
+	caddr_t buf;
+	caddr_t lim;
+	u_int32_t spi, flags;
+	u_int wsize, auth, enc;
+{
+	struct sadb_sa *p;
+	u_int len;
+
+	p = (void *)buf;
+	len = sizeof(struct sadb_sa);
+
+	if (buf + len > lim)
+		return NULL;
+
+	memset(p, 0, len);
+	p->sadb_sa_len = PFKEY_UNIT64(len);
+	p->sadb_sa_exttype = SADB_EXT_SA;
+	p->sadb_sa_spi = spi;
+	p->sadb_sa_replay = wsize;
+	p->sadb_sa_state = SADB_SASTATE_LARVAL;
+	p->sadb_sa_auth = auth;
+	p->sadb_sa_encrypt = enc;
+	p->sadb_sa_flags = flags;
+
+	return(buf + len);
+}
+
+/*
+ * set data into sadb_address.
+ * `buf' must has been allocated sufficiently.
+ * prefixlen is in bits.
+ */
+static caddr_t
+pfkey_setsadbaddr(buf, lim, exttype, saddr, prefixlen, ul_proto)
+	caddr_t buf;
+	caddr_t lim;
+	u_int exttype;
+	struct sockaddr *saddr;
+	u_int prefixlen;
+	u_int ul_proto;
+{
+	struct sadb_address *p;
+	u_int len;
+
+	p = (void *)buf;
+	len = sizeof(struct sadb_address) + PFKEY_ALIGN8(sysdep_sa_len(saddr));
+
+	if (buf + len > lim)
+		return NULL;
+
+	memset(p, 0, len);
+	p->sadb_address_len = PFKEY_UNIT64(len);
+	p->sadb_address_exttype = exttype & 0xffff;
+	p->sadb_address_proto = ul_proto & 0xff;
+	p->sadb_address_prefixlen = prefixlen;
+	p->sadb_address_reserved = 0;
+
+	memcpy(p + 1, saddr, (size_t)sysdep_sa_len(saddr));
+
+	return(buf + len);
+}
+
+/*
+ * set sadb_key structure after clearing buffer with zero.
+ * OUT: the pointer of buf + len.
+ */
+static caddr_t
+pfkey_setsadbkey(buf, lim, type, key, keylen)
+	caddr_t buf;
+	caddr_t lim;
+	caddr_t key;
+	u_int type, keylen;
+{
+	struct sadb_key *p;
+	u_int len;
+
+	p = (void *)buf;
+	len = sizeof(struct sadb_key) + PFKEY_ALIGN8(keylen);
+
+	if (buf + len > lim)
+		return NULL;
+
+	memset(p, 0, len);
+	p->sadb_key_len = PFKEY_UNIT64(len);
+	p->sadb_key_exttype = type;
+	p->sadb_key_bits = keylen << 3;
+	p->sadb_key_reserved = 0;
+
+	memcpy(p + 1, key, keylen);
+
+	return buf + len;
+}
+
+/*
+ * set sadb_lifetime structure after clearing buffer with zero.
+ * OUT: the pointer of buf + len.
+ */
+static caddr_t
+pfkey_setsadblifetime(buf, lim, type, l_alloc, l_bytes, l_addtime, l_usetime)
+	caddr_t buf;
+	caddr_t lim;
+	u_int type;
+	u_int32_t l_alloc, l_bytes, l_addtime, l_usetime;
+{
+	struct sadb_lifetime *p;
+	u_int len;
+
+	p = (void *)buf;
+	len = sizeof(struct sadb_lifetime);
+
+	if (buf + len > lim)
+		return NULL;
+
+	memset(p, 0, len);
+	p->sadb_lifetime_len = PFKEY_UNIT64(len);
+	p->sadb_lifetime_exttype = type;
+
+	switch (type) {
+	case SADB_EXT_LIFETIME_SOFT:
+		p->sadb_lifetime_allocations
+			= (l_alloc * soft_lifetime_allocations_rate) /100;
+		p->sadb_lifetime_bytes
+			= (l_bytes * soft_lifetime_bytes_rate) /100;
+		p->sadb_lifetime_addtime
+			= (l_addtime * soft_lifetime_addtime_rate) /100;
+		p->sadb_lifetime_usetime
+			= (l_usetime * soft_lifetime_usetime_rate) /100;
+		break;
+	case SADB_EXT_LIFETIME_HARD:
+		p->sadb_lifetime_allocations = l_alloc;
+		p->sadb_lifetime_bytes = l_bytes;
+		p->sadb_lifetime_addtime = l_addtime;
+		p->sadb_lifetime_usetime = l_usetime;
+		break;
+	}
+
+	return buf + len;
+}
+
+/*
+ * copy secasvar data into sadb_address.
+ * `buf' must has been allocated sufficiently.
+ */
+static caddr_t
+pfkey_setsadbxsa2(buf, lim, mode0, reqid)
+	caddr_t buf;
+	caddr_t lim;
+	u_int32_t mode0;
+	u_int32_t reqid;
+{
+	struct sadb_x_sa2 *p;
+	u_int8_t mode = mode0 & 0xff;
+	u_int len;
+
+	p = (void *)buf;
+	len = sizeof(struct sadb_x_sa2);
+
+	if (buf + len > lim)
+		return NULL;
+
+	memset(p, 0, len);
+	p->sadb_x_sa2_len = PFKEY_UNIT64(len);
+	p->sadb_x_sa2_exttype = SADB_X_EXT_SA2;
+	p->sadb_x_sa2_mode = mode;
+	p->sadb_x_sa2_reqid = reqid;
+
+	return(buf + len);
+}
+
+#ifdef SADB_X_EXT_NAT_T_TYPE
+static caddr_t
+pfkey_set_natt_type(buf, lim, type, l_natt_type)
+	caddr_t buf;
+	caddr_t lim;
+	u_int type;
+	u_int8_t l_natt_type;
+{
+	struct sadb_x_nat_t_type *p;
+	u_int len;
+
+	p = (void *)buf;
+	len = sizeof(struct sadb_x_nat_t_type);
+
+	if (buf + len > lim)
+		return NULL;
+
+	memset(p, 0, len);
+	p->sadb_x_nat_t_type_len = PFKEY_UNIT64(len);
+	p->sadb_x_nat_t_type_exttype = type;
+	p->sadb_x_nat_t_type_type = l_natt_type;
+
+	return(buf + len);
+}
+
+static caddr_t
+pfkey_set_natt_port(buf, lim, type, l_natt_port)
+	caddr_t buf;
+	caddr_t lim;
+	u_int type;
+	u_int16_t l_natt_port;
+{
+	struct sadb_x_nat_t_port *p;
+	u_int len;
+
+	p = (void *)buf;
+	len = sizeof(struct sadb_x_nat_t_port);
+
+	if (buf + len > lim)
+		return NULL;
+
+	memset(p, 0, len);
+	p->sadb_x_nat_t_port_len = PFKEY_UNIT64(len);
+	p->sadb_x_nat_t_port_exttype = type;
+	p->sadb_x_nat_t_port_port = htons(l_natt_port);
+
+	return(buf + len);
+}
+#endif
+
+#ifdef SADB_X_EXT_NAT_T_FRAG
+static caddr_t
+pfkey_set_natt_frag(buf, lim, type, l_natt_frag)
+	caddr_t buf;
+	caddr_t lim;
+	u_int type;
+	u_int16_t l_natt_frag;
+{
+	struct sadb_x_nat_t_frag *p;
+	u_int len;
+
+	p = (void *)buf;
+	len = sizeof(struct sadb_x_nat_t_frag);
+
+	if (buf + len > lim)
+		return NULL;
+
+	memset(p, 0, len);
+	p->sadb_x_nat_t_frag_len = PFKEY_UNIT64(len);
+	p->sadb_x_nat_t_frag_exttype = type;
+	p->sadb_x_nat_t_frag_fraglen = l_natt_frag;
+
+	return(buf + len);
+}
+#endif
+
+#ifdef SADB_X_EXT_SEC_CTX
+static caddr_t
+pfkey_setsecctx(buf, lim, type, ctx_doi, ctx_alg, sec_ctx, sec_ctxlen)
+	caddr_t buf;
+	caddr_t lim;
+	u_int type;
+	u_int8_t ctx_doi, ctx_alg;
+	caddr_t sec_ctx;
+	u_int16_t sec_ctxlen;
+{
+	struct sadb_x_sec_ctx *p;
+	u_int len;
+
+	p = (struct sadb_x_sec_ctx *)buf;
+	len = sizeof(struct sadb_x_sec_ctx) + PFKEY_ALIGN8(sec_ctxlen);
+
+	if (buf + len > lim)
+		return NULL;
+
+	memset(p, 0, len);
+	p->sadb_x_sec_len = PFKEY_UNIT64(len);
+	p->sadb_x_sec_exttype = type;
+	p->sadb_x_ctx_len = sec_ctxlen;
+	p->sadb_x_ctx_doi = ctx_doi;
+	p->sadb_x_ctx_alg = ctx_alg;
+
+	memcpy(p + 1, sec_ctx, sec_ctxlen);
+
+	return buf + len;
+}
+#endif
+
+/* 
+ * Deprecated, available for backward compatibility with third party 
+ * libipsec users. Please use pfkey_send_update2 and pfkey_send_add2 instead 
+ */
+int
+pfkey_send_update(so, satype, mode, src, dst, spi, reqid, wsize,
+		keymat, e_type, e_keylen, a_type, a_keylen, flags,
+		l_alloc, l_bytes, l_addtime, l_usetime, seq)
+	int so;
+	u_int satype, mode, wsize;
+	struct sockaddr *src, *dst;
+	u_int32_t spi, reqid;
+	caddr_t keymat;
+	u_int e_type, e_keylen, a_type, a_keylen, flags;
+	u_int32_t l_alloc;
+	u_int64_t l_bytes, l_addtime, l_usetime;
+	u_int32_t seq;
+{
+	struct pfkey_send_sa_args psaa;
+
+	memset(&psaa, 0, sizeof(psaa));
+	psaa.so = so;
+	psaa.type = SADB_UPDATE;
+	psaa.satype = satype;
+	psaa.mode = mode;
+	psaa.wsize = wsize;
+	psaa.src = src;
+	psaa.dst = dst;
+	psaa.spi = spi;
+	psaa.reqid = reqid;
+	psaa.keymat = keymat;
+	psaa.e_type = e_type;
+	psaa.e_keylen = e_keylen;
+	psaa.a_type = a_type;
+	psaa.a_keylen = a_keylen;
+	psaa.flags = flags;
+	psaa.l_alloc = l_alloc;
+	psaa.l_bytes = l_bytes;
+	psaa.l_addtime = l_addtime;
+	psaa.l_usetime = l_usetime;
+	psaa.seq = seq;
+
+	return pfkey_send_update2(&psaa);
+}
+
+int
+pfkey_send_update_nat(so, satype, mode, src, dst, spi, reqid, wsize,
+		      keymat, e_type, e_keylen, a_type, a_keylen, flags,
+		      l_alloc, l_bytes, l_addtime, l_usetime, seq,
+		      l_natt_type, l_natt_sport, l_natt_dport, l_natt_oa,
+		      l_natt_frag)
+	int so;
+	u_int satype, mode, wsize;
+	struct sockaddr *src, *dst;
+	u_int32_t spi, reqid;
+	caddr_t keymat;
+	u_int e_type, e_keylen, a_type, a_keylen, flags;
+	u_int32_t l_alloc;
+	u_int64_t l_bytes, l_addtime, l_usetime;
+	u_int32_t seq;
+	u_int8_t l_natt_type;
+	u_int16_t l_natt_sport, l_natt_dport;
+	struct sockaddr *l_natt_oa;
+	u_int16_t l_natt_frag;
+{
+	struct pfkey_send_sa_args psaa;
+
+	memset(&psaa, 0, sizeof(psaa));
+	psaa.so = so;
+	psaa.type = SADB_UPDATE;
+	psaa.satype = satype;
+	psaa.mode = mode;
+	psaa.wsize = wsize;
+	psaa.src = src;
+	psaa.dst = dst;
+	psaa.spi = spi;
+	psaa.reqid = reqid;
+	psaa.keymat = keymat;
+	psaa.e_type = e_type;
+	psaa.e_keylen = e_keylen;
+	psaa.a_type = a_type;
+	psaa.a_keylen = a_keylen;
+	psaa.flags = flags;
+	psaa.l_alloc = l_alloc;
+	psaa.l_bytes = l_bytes;
+	psaa.l_addtime = l_addtime;
+	psaa.l_usetime = l_usetime;
+	psaa.seq = seq;
+	psaa.l_natt_type = l_natt_type;
+	psaa.l_natt_sport = l_natt_sport;
+	psaa.l_natt_dport = l_natt_dport;
+	psaa.l_natt_oa = l_natt_oa;
+	psaa.l_natt_frag = l_natt_frag;
+
+	return pfkey_send_update2(&psaa);
+}
+
+int
+pfkey_send_add(so, satype, mode, src, dst, spi, reqid, wsize,
+		keymat, e_type, e_keylen, a_type, a_keylen, flags,
+		l_alloc, l_bytes, l_addtime, l_usetime, seq)
+	int so;
+	u_int satype, mode, wsize;
+	struct sockaddr *src, *dst;
+	u_int32_t spi, reqid;
+	caddr_t keymat;
+	u_int e_type, e_keylen, a_type, a_keylen, flags;
+	u_int32_t l_alloc;
+	u_int64_t l_bytes, l_addtime, l_usetime;
+	u_int32_t seq;
+{
+	struct pfkey_send_sa_args psaa;
+
+	memset(&psaa, 0, sizeof(psaa));
+	psaa.so = so;
+	psaa.type = SADB_ADD;
+	psaa.satype = satype;
+	psaa.mode = mode;
+	psaa.wsize = wsize;
+	psaa.src = src;
+	psaa.dst = dst;
+	psaa.spi = spi;
+	psaa.reqid = reqid;
+	psaa.keymat = keymat;
+	psaa.e_type = e_type;
+	psaa.e_keylen = e_keylen;
+	psaa.a_type = a_type;
+	psaa.a_keylen = a_keylen;
+	psaa.flags = flags;
+	psaa.l_alloc = l_alloc;
+	psaa.l_bytes = l_bytes;
+	psaa.l_addtime = l_addtime;
+	psaa.l_usetime = l_usetime;
+	psaa.seq = seq;
+
+	return pfkey_send_add2(&psaa);
+}
+
+int
+pfkey_send_add_nat(so, satype, mode, src, dst, spi, reqid, wsize,
+		      keymat, e_type, e_keylen, a_type, a_keylen, flags,
+		      l_alloc, l_bytes, l_addtime, l_usetime, seq,
+		      l_natt_type, l_natt_sport, l_natt_dport, l_natt_oa,
+		      l_natt_frag)
+	int so;
+	u_int satype, mode, wsize;
+	struct sockaddr *src, *dst;
+	u_int32_t spi, reqid;
+	caddr_t keymat;
+	u_int e_type, e_keylen, a_type, a_keylen, flags;
+	u_int32_t l_alloc;
+	u_int64_t l_bytes, l_addtime, l_usetime;
+	u_int32_t seq;
+	u_int8_t l_natt_type;
+	u_int16_t l_natt_sport, l_natt_dport;
+	struct sockaddr *l_natt_oa;
+	u_int16_t l_natt_frag;
+{
+	struct pfkey_send_sa_args psaa;
+
+	memset(&psaa, 0, sizeof(psaa));
+	psaa.so = so;
+	psaa.type = SADB_ADD;
+	psaa.satype = satype;
+	psaa.mode = mode;
+	psaa.wsize = wsize;
+	psaa.src = src;
+	psaa.dst = dst;
+	psaa.spi = spi;
+	psaa.reqid = reqid;
+	psaa.keymat = keymat;
+	psaa.e_type = e_type;
+	psaa.e_keylen = e_keylen;
+	psaa.a_type = a_type;
+	psaa.a_keylen = a_keylen;
+	psaa.flags = flags;
+	psaa.l_alloc = l_alloc;
+	psaa.l_bytes = l_bytes;
+	psaa.l_addtime = l_addtime;
+	psaa.l_usetime = l_usetime;
+	psaa.seq = seq;
+	psaa.l_natt_type = l_natt_type;
+	psaa.l_natt_sport = l_natt_sport;
+	psaa.l_natt_dport = l_natt_dport;
+	psaa.l_natt_oa = l_natt_oa;
+	psaa.l_natt_frag = l_natt_frag;
+
+	return pfkey_send_add2(&psaa);
+}
diff --git a/src/libipsec/pfkey_dump.c b/src/libipsec/pfkey_dump.c
new file mode 100644
index 0000000..497c5d7
--- /dev/null
+++ b/src/libipsec/pfkey_dump.c
@@ -0,0 +1,824 @@
+/*	$NetBSD: pfkey_dump.c,v 1.15.6.1 2007/08/01 11:52:18 vanhu Exp $	*/
+
+/*	$KAME: pfkey_dump.c,v 1.45 2003/09/08 10:14:56 itojun Exp $	*/
+
+/*
+ * Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+#include PATH_IPSEC_H
+#include <net/pfkeyv2.h>
+
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <string.h>
+#include <time.h>
+#include <netdb.h>
+
+#include "ipsec_strerror.h"
+#include "libpfkey.h"
+
+/* cope with old kame headers - ugly */
+#ifndef SADB_X_AALG_MD5
+#define SADB_X_AALG_MD5		SADB_AALG_MD5	
+#endif
+#ifndef SADB_X_AALG_SHA
+#define SADB_X_AALG_SHA		SADB_AALG_SHA
+#endif
+#ifndef SADB_X_AALG_NULL
+#define SADB_X_AALG_NULL	SADB_AALG_NULL
+#endif
+
+#ifndef SADB_X_EALG_BLOWFISHCBC
+#define SADB_X_EALG_BLOWFISHCBC	SADB_EALG_BLOWFISHCBC
+#endif
+#ifndef SADB_X_EALG_CAST128CBC
+#define SADB_X_EALG_CAST128CBC	SADB_EALG_CAST128CBC
+#endif
+#ifndef SADB_X_EALG_RC5CBC
+#ifdef SADB_EALG_RC5CBC
+#define SADB_X_EALG_RC5CBC	SADB_EALG_RC5CBC
+#endif
+#endif
+#if defined(SADB_X_EALG_AES) && ! defined(SADB_X_EALG_AESCBC)
+#define SADB_X_EALG_AESCBC  SADB_X_EALG_AES
+#endif
+
+#ifdef ANDROID_CHANGES
+void endprotoent() {}
+#endif
+
+#define GETMSGSTR(str, num) \
+do { \
+	/*CONSTCOND*/ \
+	if (sizeof((str)[0]) == 0 \
+	 || num >= sizeof(str)/sizeof((str)[0])) \
+		printf("%u ", (num)); \
+	else if (strlen((str)[(num)]) == 0) \
+		printf("%u ", (num)); \
+	else \
+		printf("%s ", (str)[(num)]); \
+} while (/*CONSTCOND*/0)
+
+#define GETMSGV2S(v2s, num) \
+do { \
+	struct val2str *p;  \
+	for (p = (v2s); p && p->str; p++) { \
+		if (p->val == (num)) \
+			break; \
+	} \
+	if (p && p->str) \
+		printf("%s ", p->str); \
+	else \
+		printf("%u ", (num)); \
+} while (/*CONSTCOND*/0)
+
+static char *str_ipaddr __P((struct sockaddr *));
+static char *str_ipport __P((struct sockaddr *));
+static char *str_prefport __P((u_int, u_int, u_int, u_int));
+static void str_upperspec __P((u_int, u_int, u_int));
+static char *str_time __P((time_t));
+static void str_lifetime_byte __P((struct sadb_lifetime *, char *));
+static void pfkey_sadump1(struct sadb_msg *, int);
+static void pfkey_spdump1(struct sadb_msg *, int);
+
+struct val2str {
+	int val;
+	const char *str;
+};
+
+/*
+ * Must to be re-written about following strings.
+ */
+static char *str_satype[] = {
+	"unspec",
+	"unknown",
+	"ah",
+	"esp",
+	"unknown",
+	"rsvp",
+	"ospfv2",
+	"ripv2",
+	"mip",
+	"ipcomp",
+	"policy",
+	"tcp",
+};
+
+static char *str_mode[] = {
+	"any",
+	"transport",
+	"tunnel",
+};
+
+static char *str_state[] = {
+	"larval",
+	"mature",
+	"dying",
+	"dead",
+};
+
+static struct val2str str_alg_auth[] = {
+	{ SADB_AALG_NONE, "none", },
+	{ SADB_AALG_MD5HMAC, "hmac-md5", },
+	{ SADB_AALG_SHA1HMAC, "hmac-sha1", },
+	{ SADB_X_AALG_MD5, "md5", },
+	{ SADB_X_AALG_SHA, "sha", },
+	{ SADB_X_AALG_NULL, "null", },
+#ifdef SADB_X_AALG_TCP_MD5
+	{ SADB_X_AALG_TCP_MD5, "tcp-md5", },
+#endif
+#ifdef SADB_X_AALG_SHA2_256
+	{ SADB_X_AALG_SHA2_256, "hmac-sha256", },
+#endif
+#ifdef SADB_X_AALG_SHA2_384
+	{ SADB_X_AALG_SHA2_384, "hmac-sha384", },
+#endif
+#ifdef SADB_X_AALG_SHA2_512
+	{ SADB_X_AALG_SHA2_512, "hmac-sha512", },
+#endif
+#ifdef SADB_X_AALG_RIPEMD160HMAC
+	{ SADB_X_AALG_RIPEMD160HMAC, "hmac-ripemd160", },
+#endif
+#ifdef SADB_X_AALG_AES_XCBC_MAC
+	{ SADB_X_AALG_AES_XCBC_MAC, "aes-xcbc-mac", },
+#endif
+	{ -1, NULL, },
+};
+
+static struct val2str str_alg_enc[] = {
+	{ SADB_EALG_NONE, "none", },
+	{ SADB_EALG_DESCBC, "des-cbc", },
+	{ SADB_EALG_3DESCBC, "3des-cbc", },
+	{ SADB_EALG_NULL, "null", },
+#ifdef SADB_X_EALG_RC5CBC
+	{ SADB_X_EALG_RC5CBC, "rc5-cbc", },
+#endif
+	{ SADB_X_EALG_CAST128CBC, "cast128-cbc", },
+	{ SADB_X_EALG_BLOWFISHCBC, "blowfish-cbc", },
+#ifdef SADB_X_EALG_AESCBC
+	{ SADB_X_EALG_AESCBC, "aes-cbc", },
+#endif
+#ifdef SADB_X_EALG_TWOFISHCBC
+	{ SADB_X_EALG_TWOFISHCBC, "twofish-cbc", },
+#endif
+#ifdef SADB_X_EALG_AESCTR
+	{ SADB_X_EALG_AESCTR, "aes-ctr", },
+#endif
+#ifdef SADB_X_EALG_CAMELLIACBC
+	{ SADB_X_EALG_CAMELLIACBC, "camellia-cbc", },
+#endif
+	{ -1, NULL, },
+};
+
+static struct val2str str_alg_comp[] = {
+	{ SADB_X_CALG_NONE, "none", },
+	{ SADB_X_CALG_OUI, "oui", },
+	{ SADB_X_CALG_DEFLATE, "deflate", },
+	{ SADB_X_CALG_LZS, "lzs", },
+	{ -1, NULL, },
+};
+
+/*
+ * dump SADB_MSG formated.  For debugging, you should use kdebug_sadb().
+ */
+
+void
+pfkey_sadump(m)
+	struct sadb_msg *m;
+{
+	pfkey_sadump1(m, 0);
+}
+
+void
+pfkey_sadump_withports(m)
+	struct sadb_msg *m;
+{
+	pfkey_sadump1(m, 1);
+}
+
+void
+pfkey_sadump1(m, withports)
+	struct sadb_msg *m;
+	int withports;
+{
+	caddr_t mhp[SADB_EXT_MAX + 1];
+	struct sadb_sa *m_sa;
+	struct sadb_x_sa2 *m_sa2;
+	struct sadb_lifetime *m_lftc, *m_lfth, *m_lfts;
+	struct sadb_address *m_saddr, *m_daddr;
+#ifdef notdef
+	struct sadb_address *m_paddr;
+#endif
+	struct sadb_key *m_auth, *m_enc;
+#ifdef notdef
+	struct sadb_ident *m_sid, *m_did;
+	struct sadb_sens *m_sens;
+#endif
+#ifdef SADB_X_EXT_SEC_CTX
+	struct sadb_x_sec_ctx *m_sec_ctx;
+#endif
+#ifdef SADB_X_EXT_NAT_T_TYPE
+	struct sadb_x_nat_t_type *natt_type;
+	struct sadb_x_nat_t_port *natt_sport, *natt_dport;
+	struct sadb_address *natt_oa;
+
+	int use_natt = 0;
+#endif
+	struct sockaddr *sa;
+
+	/* check pfkey message. */
+	if (pfkey_align(m, mhp)) {
+		printf("%s\n", ipsec_strerror());
+		return;
+	}
+	if (pfkey_check(mhp)) {
+		printf("%s\n", ipsec_strerror());
+		return;
+	}
+
+	m_sa = (void *)mhp[SADB_EXT_SA];
+	m_sa2 = (void *)mhp[SADB_X_EXT_SA2];
+	m_lftc = (void *)mhp[SADB_EXT_LIFETIME_CURRENT];
+	m_lfth = (void *)mhp[SADB_EXT_LIFETIME_HARD];
+	m_lfts = (void *)mhp[SADB_EXT_LIFETIME_SOFT];
+	m_saddr = (void *)mhp[SADB_EXT_ADDRESS_SRC];
+	m_daddr = (void *)mhp[SADB_EXT_ADDRESS_DST];
+#ifdef notdef
+	m_paddr = (void *)mhp[SADB_EXT_ADDRESS_PROXY];
+#endif
+	m_auth = (void *)mhp[SADB_EXT_KEY_AUTH];
+	m_enc = (void *)mhp[SADB_EXT_KEY_ENCRYPT];
+#ifdef notdef
+	m_sid = (void *)mhp[SADB_EXT_IDENTITY_SRC];
+	m_did = (void *)mhp[SADB_EXT_IDENTITY_DST];
+	m_sens = (void *)mhp[SADB_EXT_SENSITIVITY];
+#endif
+#ifdef SADB_X_EXT_SEC_CTX
+	m_sec_ctx = (struct sadb_x_sec_ctx *)mhp[SADB_X_EXT_SEC_CTX];
+#endif
+#ifdef SADB_X_EXT_NAT_T_TYPE
+	natt_type = (void *)mhp[SADB_X_EXT_NAT_T_TYPE];
+	natt_sport = (void *)mhp[SADB_X_EXT_NAT_T_SPORT];
+	natt_dport = (void *)mhp[SADB_X_EXT_NAT_T_DPORT];
+	natt_oa = (void *)mhp[SADB_X_EXT_NAT_T_OA];
+
+	if (natt_type && natt_type->sadb_x_nat_t_type_type)
+		use_natt = 1;
+#endif
+	/* source address */
+	if (m_saddr == NULL) {
+		printf("no ADDRESS_SRC extension.\n");
+		return;
+	}
+	sa = (void *)(m_saddr + 1);
+	if (withports)
+		printf("%s[%s]", str_ipaddr(sa), str_ipport(sa));
+	else
+		printf("%s", str_ipaddr(sa));
+#ifdef SADB_X_EXT_NAT_T_TYPE
+	if (use_natt && natt_sport)
+		printf("[%u]", ntohs(natt_sport->sadb_x_nat_t_port_port));
+#endif
+	printf(" ");
+
+	/* destination address */
+	if (m_daddr == NULL) {
+		printf(" no ADDRESS_DST extension.\n");
+		return;
+	}
+	sa = (void *)(m_daddr + 1);
+	if (withports)
+		printf("%s[%s]", str_ipaddr(sa), str_ipport(sa));
+	else
+		printf("%s", str_ipaddr(sa));
+#ifdef SADB_X_EXT_NAT_T_TYPE
+	if (use_natt && natt_dport)
+		printf("[%u]", ntohs(natt_dport->sadb_x_nat_t_port_port));
+#endif
+	printf(" ");
+
+	/* SA type */
+	if (m_sa == NULL) {
+		printf("no SA extension.\n");
+		return;
+	}
+	if (m_sa2 == NULL) {
+		printf("no SA2 extension.\n");
+		return;
+	}
+	printf("\n\t");
+
+#ifdef SADB_X_EXT_NAT_T_TYPE
+	if (use_natt && m->sadb_msg_satype == SADB_SATYPE_ESP)
+		printf("esp-udp ");
+	else if (use_natt)
+		printf("natt+");
+
+	if (!use_natt || m->sadb_msg_satype != SADB_SATYPE_ESP)
+#endif
+	GETMSGSTR(str_satype, m->sadb_msg_satype);
+
+	printf("mode=");
+	GETMSGSTR(str_mode, m_sa2->sadb_x_sa2_mode);
+
+	printf("spi=%u(0x%08x) reqid=%u(0x%08x)\n",
+		(u_int32_t)ntohl(m_sa->sadb_sa_spi),
+		(u_int32_t)ntohl(m_sa->sadb_sa_spi),
+		(u_int32_t)m_sa2->sadb_x_sa2_reqid,
+		(u_int32_t)m_sa2->sadb_x_sa2_reqid);
+
+#ifdef SADB_X_EXT_NAT_T_TYPE
+	/* other NAT-T information */
+	if (use_natt && natt_oa)
+		printf("\tNAT OA=%s\n",
+		       str_ipaddr((void *)(natt_oa + 1)));
+#endif
+
+	/* encryption key */
+	if (m->sadb_msg_satype == SADB_X_SATYPE_IPCOMP) {
+		printf("\tC: ");
+		GETMSGV2S(str_alg_comp, m_sa->sadb_sa_encrypt);
+	} else if (m->sadb_msg_satype == SADB_SATYPE_ESP) {
+		if (m_enc != NULL) {
+			printf("\tE: ");
+			GETMSGV2S(str_alg_enc, m_sa->sadb_sa_encrypt);
+			ipsec_hexdump((caddr_t)(void *)m_enc + sizeof(*m_enc),
+				      m_enc->sadb_key_bits / 8);
+			printf("\n");
+		}
+	}
+
+	/* authentication key */
+	if (m_auth != NULL) {
+		printf("\tA: ");
+		GETMSGV2S(str_alg_auth, m_sa->sadb_sa_auth);
+		ipsec_hexdump((caddr_t)(void *)m_auth + sizeof(*m_auth),
+		              m_auth->sadb_key_bits / 8);
+		printf("\n");
+	}
+
+	/* replay windoe size & flags */
+	printf("\tseq=0x%08x replay=%u flags=0x%08x ",
+		m_sa2->sadb_x_sa2_sequence,
+		m_sa->sadb_sa_replay,
+		m_sa->sadb_sa_flags);
+
+	/* state */
+	printf("state=");
+	GETMSGSTR(str_state, m_sa->sadb_sa_state);
+	printf("\n");
+
+	/* lifetime */
+	if (m_lftc != NULL) {
+		time_t tmp_time = time(0);
+
+		printf("\tcreated: %s",
+			str_time((long)m_lftc->sadb_lifetime_addtime));
+		printf("\tcurrent: %s\n", str_time(tmp_time));
+		printf("\tdiff: %lu(s)",
+			(u_long)(m_lftc->sadb_lifetime_addtime == 0 ?
+			0 : (tmp_time - m_lftc->sadb_lifetime_addtime)));
+
+		printf("\thard: %lu(s)",
+			(u_long)(m_lfth == NULL ?
+			0 : m_lfth->sadb_lifetime_addtime));
+		printf("\tsoft: %lu(s)\n",
+			(u_long)(m_lfts == NULL ?
+			0 : m_lfts->sadb_lifetime_addtime));
+
+		printf("\tlast: %s",
+			str_time((long)m_lftc->sadb_lifetime_usetime));
+		printf("\thard: %lu(s)",
+			(u_long)(m_lfth == NULL ?
+			0 : m_lfth->sadb_lifetime_usetime));
+		printf("\tsoft: %lu(s)\n",
+			(u_long)(m_lfts == NULL ?
+			0 : m_lfts->sadb_lifetime_usetime));
+
+		str_lifetime_byte(m_lftc, "current");
+		str_lifetime_byte(m_lfth, "hard");
+		str_lifetime_byte(m_lfts, "soft");
+		printf("\n");
+
+		printf("\tallocated: %lu",
+			(unsigned long)m_lftc->sadb_lifetime_allocations);
+		printf("\thard: %lu",
+			(u_long)(m_lfth == NULL ?
+			0 : m_lfth->sadb_lifetime_allocations));
+		printf("\tsoft: %lu\n",
+			(u_long)(m_lfts == NULL ?
+			0 : m_lfts->sadb_lifetime_allocations));
+	}
+
+#ifdef SADB_X_EXT_SEC_CTX
+	if (m_sec_ctx != NULL) {
+		printf("\tsecurity context doi: %u\n",
+					m_sec_ctx->sadb_x_ctx_doi);
+		printf("\tsecurity context algorithm: %u\n",
+					m_sec_ctx->sadb_x_ctx_alg);
+		printf("\tsecurity context length: %u\n",
+					m_sec_ctx->sadb_x_ctx_len);
+		printf("\tsecurity context: %s\n",
+			(char *)m_sec_ctx + sizeof(struct sadb_x_sec_ctx));
+	}
+#endif
+
+	printf("\tsadb_seq=%lu pid=%lu ",
+		(u_long)m->sadb_msg_seq,
+		(u_long)m->sadb_msg_pid);
+
+	/* XXX DEBUG */
+	printf("refcnt=%u\n", m->sadb_msg_reserved);
+
+	return;
+}
+
+void
+pfkey_spdump(m)
+	struct sadb_msg *m;
+{
+	pfkey_spdump1(m, 0);
+}
+
+void
+pfkey_spdump_withports(m)
+	struct sadb_msg *m;
+{
+	pfkey_spdump1(m, 1);
+}
+
+static void
+pfkey_spdump1(m, withports)
+	struct sadb_msg *m;
+	int withports;
+{
+	char pbuf[NI_MAXSERV];
+	caddr_t mhp[SADB_EXT_MAX + 1];
+	struct sadb_address *m_saddr, *m_daddr;
+#ifdef SADB_X_EXT_TAG
+	struct sadb_x_tag *m_tag;
+#endif
+	struct sadb_x_policy *m_xpl;
+	struct sadb_lifetime *m_lftc = NULL, *m_lfth = NULL;
+#ifdef SADB_X_EXT_SEC_CTX
+	struct sadb_x_sec_ctx *m_sec_ctx;
+#endif
+	struct sockaddr *sa;
+	u_int16_t sport = 0, dport = 0;
+
+	/* check pfkey message. */
+	if (pfkey_align(m, mhp)) {
+		printf("%s\n", ipsec_strerror());
+		return;
+	}
+	if (pfkey_check(mhp)) {
+		printf("%s\n", ipsec_strerror());
+		return;
+	}
+
+	m_saddr = (void *)mhp[SADB_EXT_ADDRESS_SRC];
+	m_daddr = (void *)mhp[SADB_EXT_ADDRESS_DST];
+#ifdef SADB_X_EXT_TAG
+	m_tag = (void *)mhp[SADB_X_EXT_TAG];
+#endif
+	m_xpl = (void *)mhp[SADB_X_EXT_POLICY];
+	m_lftc = (void *)mhp[SADB_EXT_LIFETIME_CURRENT];
+	m_lfth = (void *)mhp[SADB_EXT_LIFETIME_HARD];
+
+#ifdef SADB_X_EXT_SEC_CTX
+	m_sec_ctx = (struct sadb_x_sec_ctx *)mhp[SADB_X_EXT_SEC_CTX];
+#endif
+#ifdef __linux__
+	/* *bsd indicates per-socket policies by omiting src and dst 
+	 * extensions. Linux always includes them, but we can catch it
+	 * by checkin for policy id.
+	 */
+	if (m_xpl->sadb_x_policy_id % 8 >= 3) {
+		printf("(per-socket policy) ");
+	} else
+#endif
+	if (m_saddr && m_daddr) {
+		/* source address */
+		sa = (void *)(m_saddr + 1);
+		switch (sa->sa_family) {
+		case AF_INET:
+		case AF_INET6:
+			if (getnameinfo(sa, (socklen_t)sysdep_sa_len(sa), NULL,
+			    0, pbuf, sizeof(pbuf), NI_NUMERICSERV) != 0)
+				sport = 0;	/*XXX*/
+			else
+				sport = atoi(pbuf);
+			printf("%s%s ", str_ipaddr(sa),
+				str_prefport((u_int)sa->sa_family,
+				    (u_int)m_saddr->sadb_address_prefixlen, 
+				    (u_int)sport,
+				    (u_int)m_saddr->sadb_address_proto));
+			break;
+		default:
+			printf("unknown-af ");
+			break;
+		}
+
+		/* destination address */
+		sa = (void *)(m_daddr + 1);
+		switch (sa->sa_family) {
+		case AF_INET:
+		case AF_INET6:
+			if (getnameinfo(sa, (socklen_t)sysdep_sa_len(sa), NULL,
+			    0, pbuf, sizeof(pbuf), NI_NUMERICSERV) != 0)
+				dport = 0;	/*XXX*/
+			else
+				dport = atoi(pbuf);
+			printf("%s%s ", str_ipaddr(sa),
+				str_prefport((u_int)sa->sa_family,
+				    (u_int)m_daddr->sadb_address_prefixlen, 
+				    (u_int)dport,
+				    (u_int)m_saddr->sadb_address_proto));
+			break;
+		default:
+			printf("unknown-af ");
+			break;
+		}
+
+		/* upper layer protocol */
+		if (m_saddr->sadb_address_proto !=
+		    m_daddr->sadb_address_proto) {
+			printf("upper layer protocol mismatched.\n");
+			return;
+		}
+		str_upperspec((u_int)m_saddr->sadb_address_proto, (u_int)sport,
+		    (u_int)dport);
+	}
+#ifdef SADB_X_EXT_TAG
+	else if (m_tag)
+		printf("tagged \"%s\" ", m_tag->sadb_x_tag_name);
+#endif
+	else
+		printf("(no selector, probably per-socket policy) ");
+
+	/* policy */
+    {
+	char *d_xpl;
+
+	if (m_xpl == NULL) {
+		printf("no X_POLICY extension.\n");
+		return;
+	}
+	if (withports)
+		d_xpl = ipsec_dump_policy_withports(m_xpl, "\n\t");
+	else
+		d_xpl = ipsec_dump_policy((ipsec_policy_t)m_xpl, "\n\t");
+		
+	if (!d_xpl)
+		printf("\n\tPolicy:[%s]\n", ipsec_strerror());
+	else {
+		/* dump SPD */
+		printf("\n\t%s\n", d_xpl);
+		free(d_xpl);
+	}
+    }
+
+	/* lifetime */
+	if (m_lftc) {
+		printf("\tcreated: %s  ",
+			str_time((long)m_lftc->sadb_lifetime_addtime));
+		printf("lastused: %s\n",
+			str_time((long)m_lftc->sadb_lifetime_usetime));
+	}
+	if (m_lfth) {
+		printf("\tlifetime: %lu(s) ",
+			(u_long)m_lfth->sadb_lifetime_addtime);
+		printf("validtime: %lu(s)\n",
+			(u_long)m_lfth->sadb_lifetime_usetime);
+	}
+
+#ifdef SADB_X_EXT_SEC_CTX
+	if (m_sec_ctx != NULL) {
+		printf("\tsecurity context doi: %u\n",
+					m_sec_ctx->sadb_x_ctx_doi);
+		printf("\tsecurity context algorithm: %u\n",
+					m_sec_ctx->sadb_x_ctx_alg);
+		printf("\tsecurity context length: %u\n",
+					m_sec_ctx->sadb_x_ctx_len);
+		printf("\tsecurity context: %s\n",
+			(char *)m_sec_ctx + sizeof(struct sadb_x_sec_ctx));
+	}
+#endif
+
+	printf("\tspid=%ld seq=%ld pid=%ld\n",
+		(u_long)m_xpl->sadb_x_policy_id,
+		(u_long)m->sadb_msg_seq,
+		(u_long)m->sadb_msg_pid);
+
+	/* XXX TEST */
+	printf("\trefcnt=%u\n", m->sadb_msg_reserved);
+
+	return;
+}
+
+/*
+ * set "ipaddress" to buffer.
+ */
+static char *
+str_ipaddr(sa)
+	struct sockaddr *sa;
+{
+	static char buf[NI_MAXHOST];
+	const int niflag = NI_NUMERICHOST;
+
+	if (sa == NULL)
+		return "";
+
+	if (getnameinfo(sa, (socklen_t)sysdep_sa_len(sa), buf, sizeof(buf), 
+	    NULL, 0, niflag) == 0)
+		return buf;
+	return NULL;
+}
+
+/*
+ * set "port" to buffer.
+ */
+static char *
+str_ipport(sa)
+	struct sockaddr *sa;
+{
+	static char buf[NI_MAXHOST];
+	const int niflag = NI_NUMERICSERV;
+
+	if (sa == NULL)
+		return "";
+
+	if (getnameinfo(sa, (socklen_t)sysdep_sa_len(sa), NULL, 0, 
+	    buf, sizeof(buf), niflag) == 0)
+		return buf;
+	return NULL;
+}
+
+
+/*
+ * set "/prefix[port number]" to buffer.
+ */
+static char *
+str_prefport(family, pref, port, ulp)
+	u_int family, pref, port, ulp;
+{
+	static char buf[128];
+	char prefbuf[128];
+	char portbuf[128];
+	int plen;
+
+	switch (family) {
+	case AF_INET:
+		plen = sizeof(struct in_addr) << 3;
+		break;
+	case AF_INET6:
+		plen = sizeof(struct in6_addr) << 3;
+		break;
+	default:
+		return "?";
+	}
+
+	if (pref == plen)
+		prefbuf[0] = '\0';
+	else
+		snprintf(prefbuf, sizeof(prefbuf), "/%u", pref);
+
+	if (ulp == IPPROTO_ICMPV6)
+		memset(portbuf, 0, sizeof(portbuf));
+	else {
+		if (port == IPSEC_PORT_ANY)
+			snprintf(portbuf, sizeof(portbuf), "[%s]", "any");
+		else
+			snprintf(portbuf, sizeof(portbuf), "[%u]", port);
+	}
+
+	snprintf(buf, sizeof(buf), "%s%s", prefbuf, portbuf);
+
+	return buf;
+}
+
+static void
+str_upperspec(ulp, p1, p2)
+	u_int ulp, p1, p2;
+{
+	if (ulp == IPSEC_ULPROTO_ANY)
+		printf("any");
+	else if (ulp == IPPROTO_ICMPV6) {
+		printf("icmp6");
+		if (!(p1 == IPSEC_PORT_ANY && p2 == IPSEC_PORT_ANY))
+			printf(" %u,%u", p1, p2);
+	} else {
+		struct protoent *ent;
+
+		switch (ulp) {
+		case IPPROTO_IPV4:
+			printf("ip4");
+			break;
+		default:
+			ent = getprotobynumber((int)ulp);
+			if (ent)
+				printf("%s", ent->p_name);
+			else
+				printf("%u", ulp);
+
+			endprotoent();
+			break;
+		}
+	}
+}
+
+/*
+ * set "Mon Day Time Year" to buffer
+ */
+static char *
+str_time(t)
+	time_t t;
+{
+	static char buf[128];
+
+	if (t == 0) {
+		int i = 0;
+		for (;i < 20;) buf[i++] = ' ';
+	} else {
+		char *t0;
+		t0 = ctime(&t);
+		memcpy(buf, t0 + 4, 20);
+	}
+
+	buf[20] = '\0';
+
+	return(buf);
+}
+
+static void
+str_lifetime_byte(x, str)
+	struct sadb_lifetime *x;
+	char *str;
+{
+	double y;
+	char *unit;
+	int w;
+
+	if (x == NULL) {
+		printf("\t%s: 0(bytes)", str);
+		return;
+	}
+
+#if 0
+	if ((x->sadb_lifetime_bytes) / 1024 / 1024) {
+		y = (x->sadb_lifetime_bytes) * 1.0 / 1024 / 1024;
+		unit = "M";
+		w = 1;
+	} else if ((x->sadb_lifetime_bytes) / 1024) {
+		y = (x->sadb_lifetime_bytes) * 1.0 / 1024;
+		unit = "K";
+		w = 1;
+	} else {
+		y = (x->sadb_lifetime_bytes) * 1.0;
+		unit = "";
+		w = 0;
+	}
+#else
+	y = (x->sadb_lifetime_bytes) * 1.0;
+	unit = "";
+	w = 0;
+#endif
+	printf("\t%s: %.*f(%sbytes)", str, w, y, unit);
+}
diff --git a/src/libipsec/policy_parse.c b/src/libipsec/policy_parse.c
new file mode 100644
index 0000000..d237176
--- /dev/null
+++ b/src/libipsec/policy_parse.c
@@ -0,0 +1,2212 @@
+/* A Bison parser, made by GNU Bison 2.3.  */
+
+/* Skeleton implementation for Bison's Yacc-like parsers in C
+
+   Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
+   Free Software Foundation, Inc.
+
+   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, or (at your option)
+   any later version.
+
+   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.
+
+   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., 51 Franklin Street, Fifth Floor,
+   Boston, MA 02110-1301, USA.  */
+
+/* As a special exception, you may create a larger work that contains
+   part or all of the Bison parser skeleton and distribute that work
+   under terms of your choice, so long as that work isn't itself a
+   parser generator using the skeleton or a modified version thereof
+   as a parser skeleton.  Alternatively, if you modify or redistribute
+   the parser skeleton itself, you may (at your option) remove this
+   special exception, which will cause the skeleton and the resulting
+   Bison output files to be licensed under the GNU General Public
+   License without this special exception.
+
+   This special exception was added by the Free Software Foundation in
+   version 2.2 of Bison.  */
+
+/* C LALR(1) parser skeleton written by Richard Stallman, by
+   simplifying the original so-called "semantic" parser.  */
+
+/* All symbols defined below should begin with yy or YY, to avoid
+   infringing on user name space.  This should be done even for local
+   variables, as they might otherwise be expanded by user macros.
+   There are some unavoidable exceptions within include files to
+   define necessary library symbols; they are noted "INFRINGES ON
+   USER NAME SPACE" below.  */
+
+/* Identify Bison output.  */
+#define YYBISON 1
+
+/* Bison version.  */
+#define YYBISON_VERSION "2.3"
+
+/* Skeleton name.  */
+#define YYSKELETON_NAME "yacc.c"
+
+/* Pure parsers.  */
+#define YYPURE 0
+
+/* Using locations.  */
+#define YYLSP_NEEDED 0
+
+/* Substitute the variable and function names.  */
+#define yyparse __libipsecparse
+#define yylex   __libipseclex
+#define yyerror __libipsecerror
+#define yylval  __libipseclval
+#define yychar  __libipsecchar
+#define yydebug __libipsecdebug
+#define yynerrs __libipsecnerrs
+
+
+/* Tokens.  */
+#ifndef YYTOKENTYPE
+# define YYTOKENTYPE
+   /* Put the tokens into the symbol table, so that GDB and other debuggers
+      know about them.  */
+   enum yytokentype {
+     DIR = 258,
+     PRIORITY = 259,
+     PLUS = 260,
+     PRIO_BASE = 261,
+     PRIO_OFFSET = 262,
+     ACTION = 263,
+     PROTOCOL = 264,
+     MODE = 265,
+     LEVEL = 266,
+     LEVEL_SPECIFY = 267,
+     IPADDRESS = 268,
+     PORT = 269,
+     ME = 270,
+     ANY = 271,
+     SLASH = 272,
+     HYPHEN = 273
+   };
+#endif
+/* Tokens.  */
+#define DIR 258
+#define PRIORITY 259
+#define PLUS 260
+#define PRIO_BASE 261
+#define PRIO_OFFSET 262
+#define ACTION 263
+#define PROTOCOL 264
+#define MODE 265
+#define LEVEL 266
+#define LEVEL_SPECIFY 267
+#define IPADDRESS 268
+#define PORT 269
+#define ME 270
+#define ANY 271
+#define SLASH 272
+#define HYPHEN 273
+
+
+
+
+/* Copy the first part of user declarations.  */
+#line 65 "policy_parse.y"
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+
+#include <netinet/in.h>
+#include PATH_IPSEC_H
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <netdb.h>
+
+#include <errno.h>
+
+#include "config.h"
+
+#include "ipsec_strerror.h"
+#include "libpfkey.h"
+
+#ifndef INT32_MAX
+#define INT32_MAX	(0xffffffff)
+#endif
+
+#ifndef INT32_MIN
+#define INT32_MIN	(-INT32_MAX-1)
+#endif
+
+#define ATOX(c) \
+  (isdigit(c) ? (c - '0') : (isupper(c) ? (c - 'A' + 10) : (c - 'a' + 10) ))
+
+static u_int8_t *pbuf = NULL;		/* sadb_x_policy buffer */
+static int tlen = 0;			/* total length of pbuf */
+static int offset = 0;			/* offset of pbuf */
+static int p_dir, p_type, p_protocol, p_mode, p_level, p_reqid;
+static u_int32_t p_priority = 0;
+static long p_priority_offset = 0;
+static struct sockaddr *p_src = NULL;
+static struct sockaddr *p_dst = NULL;
+
+struct _val;
+extern void yyerror __P((char *msg));
+static struct sockaddr *parse_sockaddr __P((struct _val *addrbuf,
+    struct _val *portbuf));
+static int rule_check __P((void));
+static int init_x_policy __P((void));
+static int set_x_request __P((struct sockaddr *, struct sockaddr *));
+static int set_sockaddr __P((struct sockaddr *));
+static void policy_parse_request_init __P((void));
+static void *policy_parse __P((const char *, int));
+
+extern void __policy__strbuffer__init__ __P((const char *));
+extern void __policy__strbuffer__free__ __P((void));
+extern int yyparse __P((void));
+extern int yylex __P((void));
+
+extern char *__libipsectext;	/*XXX*/
+
+
+
+/* Enabling traces.  */
+#ifndef YYDEBUG
+# define YYDEBUG 0
+#endif
+
+/* Enabling verbose error messages.  */
+#ifdef YYERROR_VERBOSE
+# undef YYERROR_VERBOSE
+# define YYERROR_VERBOSE 1
+#else
+# define YYERROR_VERBOSE 0
+#endif
+
+/* Enabling the token table.  */
+#ifndef YYTOKEN_TABLE
+# define YYTOKEN_TABLE 0
+#endif
+
+#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
+typedef union YYSTYPE
+#line 129 "policy_parse.y"
+{
+	u_int num;
+	u_int32_t num32;
+	struct _val {
+		int len;
+		char *buf;
+	} val;
+}
+/* Line 187 of yacc.c.  */
+#line 213 "policy_parse.c"
+	YYSTYPE;
+# define yystype YYSTYPE /* obsolescent; will be withdrawn */
+# define YYSTYPE_IS_DECLARED 1
+# define YYSTYPE_IS_TRIVIAL 1
+#endif
+
+
+
+/* Copy the second part of user declarations.  */
+
+
+/* Line 216 of yacc.c.  */
+#line 226 "policy_parse.c"
+
+#ifdef short
+# undef short
+#endif
+
+#ifdef YYTYPE_UINT8
+typedef YYTYPE_UINT8 yytype_uint8;
+#else
+typedef unsigned char yytype_uint8;
+#endif
+
+#ifdef YYTYPE_INT8
+typedef YYTYPE_INT8 yytype_int8;
+#elif (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+typedef signed char yytype_int8;
+#else
+typedef short int yytype_int8;
+#endif
+
+#ifdef YYTYPE_UINT16
+typedef YYTYPE_UINT16 yytype_uint16;
+#else
+typedef unsigned short int yytype_uint16;
+#endif
+
+#ifdef YYTYPE_INT16
+typedef YYTYPE_INT16 yytype_int16;
+#else
+typedef short int yytype_int16;
+#endif
+
+#ifndef YYSIZE_T
+# ifdef __SIZE_TYPE__
+#  define YYSIZE_T __SIZE_TYPE__
+# elif defined size_t
+#  define YYSIZE_T size_t
+# elif ! defined YYSIZE_T && (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+#  include <stddef.h> /* INFRINGES ON USER NAME SPACE */
+#  define YYSIZE_T size_t
+# else
+#  define YYSIZE_T unsigned int
+# endif
+#endif
+
+#define YYSIZE_MAXIMUM ((YYSIZE_T) -1)
+
+#ifndef YY_
+# if YYENABLE_NLS
+#  if ENABLE_NLS
+#   include <libintl.h> /* INFRINGES ON USER NAME SPACE */
+#   define YY_(msgid) dgettext ("bison-runtime", msgid)
+#  endif
+# endif
+# ifndef YY_
+#  define YY_(msgid) msgid
+# endif
+#endif
+
+/* Suppress unused-variable warnings by "using" E.  */
+#if ! defined lint || defined __GNUC__
+# define YYUSE(e) ((void) (e))
+#else
+# define YYUSE(e) /* empty */
+#endif
+
+/* Identity function, used to suppress warnings about constant conditions.  */
+#ifndef lint
+# define YYID(n) (n)
+#else
+#if (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+static int
+YYID (int i)
+#else
+static int
+YYID (i)
+    int i;
+#endif
+{
+  return i;
+}
+#endif
+
+#if ! defined yyoverflow || YYERROR_VERBOSE
+
+/* The parser invokes alloca or malloc; define the necessary symbols.  */
+
+# ifdef YYSTACK_USE_ALLOCA
+#  if YYSTACK_USE_ALLOCA
+#   ifdef __GNUC__
+#    define YYSTACK_ALLOC __builtin_alloca
+#   elif defined __BUILTIN_VA_ARG_INCR
+#    include <alloca.h> /* INFRINGES ON USER NAME SPACE */
+#   elif defined _AIX
+#    define YYSTACK_ALLOC __alloca
+#   elif defined _MSC_VER
+#    include <malloc.h> /* INFRINGES ON USER NAME SPACE */
+#    define alloca _alloca
+#   else
+#    define YYSTACK_ALLOC alloca
+#    if ! defined _ALLOCA_H && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+#     include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
+#     ifndef _STDLIB_H
+#      define _STDLIB_H 1
+#     endif
+#    endif
+#   endif
+#  endif
+# endif
+
+# ifdef YYSTACK_ALLOC
+   /* Pacify GCC's `empty if-body' warning.  */
+#  define YYSTACK_FREE(Ptr) do { /* empty */; } while (YYID (0))
+#  ifndef YYSTACK_ALLOC_MAXIMUM
+    /* The OS might guarantee only one guard page at the bottom of the stack,
+       and a page size can be as small as 4096 bytes.  So we cannot safely
+       invoke alloca (N) if N exceeds 4096.  Use a slightly smaller number
+       to allow for a few compiler-allocated temporary stack slots.  */
+#   define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */
+#  endif
+# else
+#  define YYSTACK_ALLOC YYMALLOC
+#  define YYSTACK_FREE YYFREE
+#  ifndef YYSTACK_ALLOC_MAXIMUM
+#   define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM
+#  endif
+#  if (defined __cplusplus && ! defined _STDLIB_H \
+       && ! ((defined YYMALLOC || defined malloc) \
+	     && (defined YYFREE || defined free)))
+#   include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
+#   ifndef _STDLIB_H
+#    define _STDLIB_H 1
+#   endif
+#  endif
+#  ifndef YYMALLOC
+#   define YYMALLOC malloc
+#   if ! defined malloc && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */
+#   endif
+#  endif
+#  ifndef YYFREE
+#   define YYFREE free
+#   if ! defined free && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+void free (void *); /* INFRINGES ON USER NAME SPACE */
+#   endif
+#  endif
+# endif
+#endif /* ! defined yyoverflow || YYERROR_VERBOSE */
+
+
+#if (! defined yyoverflow \
+     && (! defined __cplusplus \
+	 || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL)))
+
+/* A type that is properly aligned for any stack member.  */
+union yyalloc
+{
+  yytype_int16 yyss;
+  YYSTYPE yyvs;
+  };
+
+/* The size of the maximum gap between one aligned stack and the next.  */
+# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1)
+
+/* The size of an array large to enough to hold all stacks, each with
+   N elements.  */
+# define YYSTACK_BYTES(N) \
+     ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \
+      + YYSTACK_GAP_MAXIMUM)
+
+/* Copy COUNT objects from FROM to TO.  The source and destination do
+   not overlap.  */
+# ifndef YYCOPY
+#  if defined __GNUC__ && 1 < __GNUC__
+#   define YYCOPY(To, From, Count) \
+      __builtin_memcpy (To, From, (Count) * sizeof (*(From)))
+#  else
+#   define YYCOPY(To, From, Count)		\
+      do					\
+	{					\
+	  YYSIZE_T yyi;				\
+	  for (yyi = 0; yyi < (Count); yyi++)	\
+	    (To)[yyi] = (From)[yyi];		\
+	}					\
+      while (YYID (0))
+#  endif
+# endif
+
+/* Relocate STACK from its old location to the new one.  The
+   local variables YYSIZE and YYSTACKSIZE give the old and new number of
+   elements in the stack, and YYPTR gives the new location of the
+   stack.  Advance YYPTR to a properly aligned location for the next
+   stack.  */
+# define YYSTACK_RELOCATE(Stack)					\
+    do									\
+      {									\
+	YYSIZE_T yynewbytes;						\
+	YYCOPY (&yyptr->Stack, Stack, yysize);				\
+	Stack = &yyptr->Stack;						\
+	yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
+	yyptr += yynewbytes / sizeof (*yyptr);				\
+      }									\
+    while (YYID (0))
+
+#endif
+
+/* YYFINAL -- State number of the termination state.  */
+#define YYFINAL  5
+/* YYLAST -- Last index in YYTABLE.  */
+#define YYLAST   48
+
+/* YYNTOKENS -- Number of terminals.  */
+#define YYNTOKENS  19
+/* YYNNTS -- Number of nonterminals.  */
+#define YYNNTS  16
+/* YYNRULES -- Number of rules.  */
+#define YYNRULES  34
+/* YYNRULES -- Number of states.  */
+#define YYNSTATES  60
+
+/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX.  */
+#define YYUNDEFTOK  2
+#define YYMAXUTOK   273
+
+#define YYTRANSLATE(YYX)						\
+  ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
+
+/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX.  */
+static const yytype_uint8 yytranslate[] =
+{
+       0,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     1,     2,     3,     4,
+       5,     6,     7,     8,     9,    10,    11,    12,    13,    14,
+      15,    16,    17,    18
+};
+
+#if YYDEBUG
+/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in
+   YYRHS.  */
+static const yytype_uint8 yyprhs[] =
+{
+       0,     0,     3,     4,     9,    10,    17,    18,    26,    27,
+      34,    35,    44,    45,    54,    56,    57,    60,    68,    75,
+      81,    86,    93,    97,   100,   102,   104,   106,   108,   110,
+     111,   116,   117,   124,   128
+};
+
+/* YYRHS -- A `-1'-separated list of the rules' RHS.  */
+static const yytype_int8 yyrhs[] =
+{
+      20,     0,    -1,    -1,     3,     8,    21,    27,    -1,    -1,
+       3,     4,     7,     8,    22,    27,    -1,    -1,     3,     4,
+      18,     7,     8,    23,    27,    -1,    -1,     3,     4,     6,
+       8,    24,    27,    -1,    -1,     3,     4,     6,     5,     7,
+       8,    25,    27,    -1,    -1,     3,     4,     6,    18,     7,
+       8,    26,    27,    -1,     3,    -1,    -1,    27,    28,    -1,
+      29,    17,    30,    17,    32,    17,    31,    -1,    29,    17,
+      30,    17,    32,    17,    -1,    29,    17,    30,    17,    32,
+      -1,    29,    17,    30,    17,    -1,    29,    17,    30,    17,
+      17,    31,    -1,    29,    17,    30,    -1,    29,    17,    -1,
+      29,    -1,     9,    -1,    10,    -1,    11,    -1,    12,    -1,
+      -1,    13,    33,    18,    13,    -1,    -1,    13,    14,    34,
+      18,    13,    14,    -1,    15,    18,    16,    -1,    16,    18,
+      15,    -1
+};
+
+/* YYRLINE[YYN] -- source line where rule number YYN was defined.  */
+static const yytype_uint16 yyrline[] =
+{
+       0,   151,   151,   150,   166,   165,   202,   201,   224,   223,
+     235,   234,   257,   256,   278,   290,   292,   304,   305,   306,
+     307,   308,   309,   310,   314,   321,   325,   329,   333,   340,
+     340,   351,   351,   362,   368
+};
+#endif
+
+#if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE
+/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
+   First, the terminals, then, starting at YYNTOKENS, nonterminals.  */
+static const char *const yytname[] =
+{
+  "$end", "error", "$undefined", "DIR", "PRIORITY", "PLUS", "PRIO_BASE",
+  "PRIO_OFFSET", "ACTION", "PROTOCOL", "MODE", "LEVEL", "LEVEL_SPECIFY",
+  "IPADDRESS", "PORT", "ME", "ANY", "SLASH", "HYPHEN", "$accept",
+  "policy_spec", "@1", "@2", "@3", "@4", "@5", "@6", "rules", "rule",
+  "protocol", "mode", "level", "addresses", "@7", "@8", 0
+};
+#endif
+
+# ifdef YYPRINT
+/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to
+   token YYLEX-NUM.  */
+static const yytype_uint16 yytoknum[] =
+{
+       0,   256,   257,   258,   259,   260,   261,   262,   263,   264,
+     265,   266,   267,   268,   269,   270,   271,   272,   273
+};
+# endif
+
+/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives.  */
+static const yytype_uint8 yyr1[] =
+{
+       0,    19,    21,    20,    22,    20,    23,    20,    24,    20,
+      25,    20,    26,    20,    20,    27,    27,    28,    28,    28,
+      28,    28,    28,    28,    28,    29,    30,    31,    31,    33,
+      32,    34,    32,    32,    32
+};
+
+/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN.  */
+static const yytype_uint8 yyr2[] =
+{
+       0,     2,     0,     4,     0,     6,     0,     7,     0,     6,
+       0,     8,     0,     8,     1,     0,     2,     7,     6,     5,
+       4,     6,     3,     2,     1,     1,     1,     1,     1,     0,
+       4,     0,     6,     3,     3
+};
+
+/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state
+   STATE-NUM when YYTABLE doesn't specify something else to do.  Zero
+   means the default is an error.  */
+static const yytype_uint8 yydefact[] =
+{
+       0,    14,     0,     0,     2,     1,     0,     0,     0,    15,
+       0,     8,     0,     4,     0,     3,     0,    15,     0,    15,
+       6,    25,    16,    24,    10,     9,    12,     5,    15,    23,
+      15,    15,     7,    26,    22,    11,    13,    20,    29,     0,
+       0,     0,    19,    31,     0,     0,     0,    27,    28,    21,
+      18,     0,     0,    33,    34,    17,     0,    30,     0,    32
+};
+
+/* YYDEFGOTO[NTERM-NUM].  */
+static const yytype_int8 yydefgoto[] =
+{
+      -1,     2,     9,    19,    28,    17,    30,    31,    15,    22,
+      23,    34,    49,    42,    44,    51
+};
+
+/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
+   STATE-NUM.  */
+#define YYPACT_NINF -18
+static const yytype_int8 yypact[] =
+{
+       6,    -3,     4,     1,   -18,   -18,    -2,     2,     8,   -18,
+      10,   -18,    18,   -18,    19,     3,    20,   -18,    21,   -18,
+     -18,   -18,   -18,     9,   -18,     3,   -18,     3,   -18,    22,
+     -18,   -18,     3,   -18,    13,     3,     3,     5,    17,    15,
+      16,    12,    23,   -18,    24,    25,    28,   -18,   -18,   -18,
+      12,    26,    32,   -18,   -18,   -18,    33,   -18,    34,   -18
+};
+
+/* YYPGOTO[NTERM-NUM].  */
+static const yytype_int8 yypgoto[] =
+{
+     -18,   -18,   -18,   -18,   -18,   -18,   -18,   -18,   -17,   -18,
+     -18,   -18,   -15,   -18,   -18,   -18
+};
+
+/* YYTABLE[YYPACT[STATE-NUM]].  What to do in state STATE-NUM.  If
+   positive, shift that token.  If negative, reduce the rule which
+   number is the opposite.  If zero, do what YYDEFACT says.
+   If YYTABLE_NINF, syntax error.  */
+#define YYTABLE_NINF -1
+static const yytype_uint8 yytable[] =
+{
+      25,     3,    27,    10,     5,     4,    11,     6,     7,     1,
+      13,    32,    21,    35,    36,    14,    12,    16,    38,     8,
+      39,    40,    41,    47,    48,    18,    29,    20,    24,    26,
+      37,    43,    33,    45,    46,    55,     0,     0,     0,     0,
+      50,    53,    52,    54,    56,    57,    58,     0,    59
+};
+
+static const yytype_int8 yycheck[] =
+{
+      17,     4,    19,     5,     0,     8,     8,     6,     7,     3,
+       8,    28,     9,    30,    31,     7,    18,     7,    13,    18,
+      15,    16,    17,    11,    12,     7,    17,     8,     8,     8,
+      17,    14,    10,    18,    18,    50,    -1,    -1,    -1,    -1,
+      17,    16,    18,    15,    18,    13,    13,    -1,    14
+};
+
+/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
+   symbol of state STATE-NUM.  */
+static const yytype_uint8 yystos[] =
+{
+       0,     3,    20,     4,     8,     0,     6,     7,    18,    21,
+       5,     8,    18,     8,     7,    27,     7,    24,     7,    22,
+       8,     9,    28,    29,     8,    27,     8,    27,    23,    17,
+      25,    26,    27,    10,    30,    27,    27,    17,    13,    15,
+      16,    17,    32,    14,    33,    18,    18,    11,    12,    31,
+      17,    34,    18,    16,    15,    31,    18,    13,    13,    14
+};
+
+#define yyerrok		(yyerrstatus = 0)
+#define yyclearin	(yychar = YYEMPTY)
+#define YYEMPTY		(-2)
+#define YYEOF		0
+
+#define YYACCEPT	goto yyacceptlab
+#define YYABORT		goto yyabortlab
+#define YYERROR		goto yyerrorlab
+
+
+/* Like YYERROR except do call yyerror.  This remains here temporarily
+   to ease the transition to the new meaning of YYERROR, for GCC.
+   Once GCC version 2 has supplanted version 1, this can go.  */
+
+#define YYFAIL		goto yyerrlab
+
+#define YYRECOVERING()  (!!yyerrstatus)
+
+#define YYBACKUP(Token, Value)					\
+do								\
+  if (yychar == YYEMPTY && yylen == 1)				\
+    {								\
+      yychar = (Token);						\
+      yylval = (Value);						\
+      yytoken = YYTRANSLATE (yychar);				\
+      YYPOPSTACK (1);						\
+      goto yybackup;						\
+    }								\
+  else								\
+    {								\
+      yyerror (YY_("syntax error: cannot back up")); \
+      YYERROR;							\
+    }								\
+while (YYID (0))
+
+
+#define YYTERROR	1
+#define YYERRCODE	256
+
+
+/* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N].
+   If N is 0, then set CURRENT to the empty location which ends
+   the previous symbol: RHS[0] (always defined).  */
+
+#define YYRHSLOC(Rhs, K) ((Rhs)[K])
+#ifndef YYLLOC_DEFAULT
+# define YYLLOC_DEFAULT(Current, Rhs, N)				\
+    do									\
+      if (YYID (N))                                                    \
+	{								\
+	  (Current).first_line   = YYRHSLOC (Rhs, 1).first_line;	\
+	  (Current).first_column = YYRHSLOC (Rhs, 1).first_column;	\
+	  (Current).last_line    = YYRHSLOC (Rhs, N).last_line;		\
+	  (Current).last_column  = YYRHSLOC (Rhs, N).last_column;	\
+	}								\
+      else								\
+	{								\
+	  (Current).first_line   = (Current).last_line   =		\
+	    YYRHSLOC (Rhs, 0).last_line;				\
+	  (Current).first_column = (Current).last_column =		\
+	    YYRHSLOC (Rhs, 0).last_column;				\
+	}								\
+    while (YYID (0))
+#endif
+
+
+/* YY_LOCATION_PRINT -- Print the location on the stream.
+   This macro was not mandated originally: define only if we know
+   we won't break user code: when these are the locations we know.  */
+
+#ifndef YY_LOCATION_PRINT
+# if YYLTYPE_IS_TRIVIAL
+#  define YY_LOCATION_PRINT(File, Loc)			\
+     fprintf (File, "%d.%d-%d.%d",			\
+	      (Loc).first_line, (Loc).first_column,	\
+	      (Loc).last_line,  (Loc).last_column)
+# else
+#  define YY_LOCATION_PRINT(File, Loc) ((void) 0)
+# endif
+#endif
+
+
+/* YYLEX -- calling `yylex' with the right arguments.  */
+
+#ifdef YYLEX_PARAM
+# define YYLEX yylex (YYLEX_PARAM)
+#else
+# define YYLEX yylex ()
+#endif
+
+/* Enable debugging if requested.  */
+#if YYDEBUG
+
+# ifndef YYFPRINTF
+#  include <stdio.h> /* INFRINGES ON USER NAME SPACE */
+#  define YYFPRINTF fprintf
+# endif
+
+# define YYDPRINTF(Args)			\
+do {						\
+  if (yydebug)					\
+    YYFPRINTF Args;				\
+} while (YYID (0))
+
+# define YY_SYMBOL_PRINT(Title, Type, Value, Location)			  \
+do {									  \
+  if (yydebug)								  \
+    {									  \
+      YYFPRINTF (stderr, "%s ", Title);					  \
+      yy_symbol_print (stderr,						  \
+		  Type, Value); \
+      YYFPRINTF (stderr, "\n");						  \
+    }									  \
+} while (YYID (0))
+
+
+/*--------------------------------.
+| Print this symbol on YYOUTPUT.  |
+`--------------------------------*/
+
+/*ARGSUSED*/
+#if (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+static void
+yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep)
+#else
+static void
+yy_symbol_value_print (yyoutput, yytype, yyvaluep)
+    FILE *yyoutput;
+    int yytype;
+    YYSTYPE const * const yyvaluep;
+#endif
+{
+  if (!yyvaluep)
+    return;
+# ifdef YYPRINT
+  if (yytype < YYNTOKENS)
+    YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep);
+# else
+  YYUSE (yyoutput);
+# endif
+  switch (yytype)
+    {
+      default:
+	break;
+    }
+}
+
+
+/*--------------------------------.
+| Print this symbol on YYOUTPUT.  |
+`--------------------------------*/
+
+#if (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+static void
+yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep)
+#else
+static void
+yy_symbol_print (yyoutput, yytype, yyvaluep)
+    FILE *yyoutput;
+    int yytype;
+    YYSTYPE const * const yyvaluep;
+#endif
+{
+  if (yytype < YYNTOKENS)
+    YYFPRINTF (yyoutput, "token %s (", yytname[yytype]);
+  else
+    YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]);
+
+  yy_symbol_value_print (yyoutput, yytype, yyvaluep);
+  YYFPRINTF (yyoutput, ")");
+}
+
+/*------------------------------------------------------------------.
+| yy_stack_print -- Print the state stack from its BOTTOM up to its |
+| TOP (included).                                                   |
+`------------------------------------------------------------------*/
+
+#if (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+static void
+yy_stack_print (yytype_int16 *bottom, yytype_int16 *top)
+#else
+static void
+yy_stack_print (bottom, top)
+    yytype_int16 *bottom;
+    yytype_int16 *top;
+#endif
+{
+  YYFPRINTF (stderr, "Stack now");
+  for (; bottom <= top; ++bottom)
+    YYFPRINTF (stderr, " %d", *bottom);
+  YYFPRINTF (stderr, "\n");
+}
+
+# define YY_STACK_PRINT(Bottom, Top)				\
+do {								\
+  if (yydebug)							\
+    yy_stack_print ((Bottom), (Top));				\
+} while (YYID (0))
+
+
+/*------------------------------------------------.
+| Report that the YYRULE is going to be reduced.  |
+`------------------------------------------------*/
+
+#if (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+static void
+yy_reduce_print (YYSTYPE *yyvsp, int yyrule)
+#else
+static void
+yy_reduce_print (yyvsp, yyrule)
+    YYSTYPE *yyvsp;
+    int yyrule;
+#endif
+{
+  int yynrhs = yyr2[yyrule];
+  int yyi;
+  unsigned long int yylno = yyrline[yyrule];
+  YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n",
+	     yyrule - 1, yylno);
+  /* The symbols being reduced.  */
+  for (yyi = 0; yyi < yynrhs; yyi++)
+    {
+      fprintf (stderr, "   $%d = ", yyi + 1);
+      yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi],
+		       &(yyvsp[(yyi + 1) - (yynrhs)])
+		       		       );
+      fprintf (stderr, "\n");
+    }
+}
+
+# define YY_REDUCE_PRINT(Rule)		\
+do {					\
+  if (yydebug)				\
+    yy_reduce_print (yyvsp, Rule); \
+} while (YYID (0))
+
+/* Nonzero means print parse trace.  It is left uninitialized so that
+   multiple parsers can coexist.  */
+int yydebug;
+#else /* !YYDEBUG */
+# define YYDPRINTF(Args)
+# define YY_SYMBOL_PRINT(Title, Type, Value, Location)
+# define YY_STACK_PRINT(Bottom, Top)
+# define YY_REDUCE_PRINT(Rule)
+#endif /* !YYDEBUG */
+
+
+/* YYINITDEPTH -- initial size of the parser's stacks.  */
+#ifndef	YYINITDEPTH
+# define YYINITDEPTH 200
+#endif
+
+/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only
+   if the built-in stack extension method is used).
+
+   Do not make this value too large; the results are undefined if
+   YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH)
+   evaluated with infinite-precision integer arithmetic.  */
+
+#ifndef YYMAXDEPTH
+# define YYMAXDEPTH 10000
+#endif
+
+
+
+#if YYERROR_VERBOSE
+
+# ifndef yystrlen
+#  if defined __GLIBC__ && defined _STRING_H
+#   define yystrlen strlen
+#  else
+/* Return the length of YYSTR.  */
+#if (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+static YYSIZE_T
+yystrlen (const char *yystr)
+#else
+static YYSIZE_T
+yystrlen (yystr)
+    const char *yystr;
+#endif
+{
+  YYSIZE_T yylen;
+  for (yylen = 0; yystr[yylen]; yylen++)
+    continue;
+  return yylen;
+}
+#  endif
+# endif
+
+# ifndef yystpcpy
+#  if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE
+#   define yystpcpy stpcpy
+#  else
+/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in
+   YYDEST.  */
+#if (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+static char *
+yystpcpy (char *yydest, const char *yysrc)
+#else
+static char *
+yystpcpy (yydest, yysrc)
+    char *yydest;
+    const char *yysrc;
+#endif
+{
+  char *yyd = yydest;
+  const char *yys = yysrc;
+
+  while ((*yyd++ = *yys++) != '\0')
+    continue;
+
+  return yyd - 1;
+}
+#  endif
+# endif
+
+# ifndef yytnamerr
+/* Copy to YYRES the contents of YYSTR after stripping away unnecessary
+   quotes and backslashes, so that it's suitable for yyerror.  The
+   heuristic is that double-quoting is unnecessary unless the string
+   contains an apostrophe, a comma, or backslash (other than
+   backslash-backslash).  YYSTR is taken from yytname.  If YYRES is
+   null, do not copy; instead, return the length of what the result
+   would have been.  */
+static YYSIZE_T
+yytnamerr (char *yyres, const char *yystr)
+{
+  if (*yystr == '"')
+    {
+      YYSIZE_T yyn = 0;
+      char const *yyp = yystr;
+
+      for (;;)
+	switch (*++yyp)
+	  {
+	  case '\'':
+	  case ',':
+	    goto do_not_strip_quotes;
+
+	  case '\\':
+	    if (*++yyp != '\\')
+	      goto do_not_strip_quotes;
+	    /* Fall through.  */
+	  default:
+	    if (yyres)
+	      yyres[yyn] = *yyp;
+	    yyn++;
+	    break;
+
+	  case '"':
+	    if (yyres)
+	      yyres[yyn] = '\0';
+	    return yyn;
+	  }
+    do_not_strip_quotes: ;
+    }
+
+  if (! yyres)
+    return yystrlen (yystr);
+
+  return yystpcpy (yyres, yystr) - yyres;
+}
+# endif
+
+/* Copy into YYRESULT an error message about the unexpected token
+   YYCHAR while in state YYSTATE.  Return the number of bytes copied,
+   including the terminating null byte.  If YYRESULT is null, do not
+   copy anything; just return the number of bytes that would be
+   copied.  As a special case, return 0 if an ordinary "syntax error"
+   message will do.  Return YYSIZE_MAXIMUM if overflow occurs during
+   size calculation.  */
+static YYSIZE_T
+yysyntax_error (char *yyresult, int yystate, int yychar)
+{
+  int yyn = yypact[yystate];
+
+  if (! (YYPACT_NINF < yyn && yyn <= YYLAST))
+    return 0;
+  else
+    {
+      int yytype = YYTRANSLATE (yychar);
+      YYSIZE_T yysize0 = yytnamerr (0, yytname[yytype]);
+      YYSIZE_T yysize = yysize0;
+      YYSIZE_T yysize1;
+      int yysize_overflow = 0;
+      enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 };
+      char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM];
+      int yyx;
+
+# if 0
+      /* This is so xgettext sees the translatable formats that are
+	 constructed on the fly.  */
+      YY_("syntax error, unexpected %s");
+      YY_("syntax error, unexpected %s, expecting %s");
+      YY_("syntax error, unexpected %s, expecting %s or %s");
+      YY_("syntax error, unexpected %s, expecting %s or %s or %s");
+      YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s");
+# endif
+      char *yyfmt;
+      char const *yyf;
+      static char const yyunexpected[] = "syntax error, unexpected %s";
+      static char const yyexpecting[] = ", expecting %s";
+      static char const yyor[] = " or %s";
+      char yyformat[sizeof yyunexpected
+		    + sizeof yyexpecting - 1
+		    + ((YYERROR_VERBOSE_ARGS_MAXIMUM - 2)
+		       * (sizeof yyor - 1))];
+      char const *yyprefix = yyexpecting;
+
+      /* Start YYX at -YYN if negative to avoid negative indexes in
+	 YYCHECK.  */
+      int yyxbegin = yyn < 0 ? -yyn : 0;
+
+      /* Stay within bounds of both yycheck and yytname.  */
+      int yychecklim = YYLAST - yyn + 1;
+      int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
+      int yycount = 1;
+
+      yyarg[0] = yytname[yytype];
+      yyfmt = yystpcpy (yyformat, yyunexpected);
+
+      for (yyx = yyxbegin; yyx < yyxend; ++yyx)
+	if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR)
+	  {
+	    if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM)
+	      {
+		yycount = 1;
+		yysize = yysize0;
+		yyformat[sizeof yyunexpected - 1] = '\0';
+		break;
+	      }
+	    yyarg[yycount++] = yytname[yyx];
+	    yysize1 = yysize + yytnamerr (0, yytname[yyx]);
+	    yysize_overflow |= (yysize1 < yysize);
+	    yysize = yysize1;
+	    yyfmt = yystpcpy (yyfmt, yyprefix);
+	    yyprefix = yyor;
+	  }
+
+      yyf = YY_(yyformat);
+      yysize1 = yysize + yystrlen (yyf);
+      yysize_overflow |= (yysize1 < yysize);
+      yysize = yysize1;
+
+      if (yysize_overflow)
+	return YYSIZE_MAXIMUM;
+
+      if (yyresult)
+	{
+	  /* Avoid sprintf, as that infringes on the user's name space.
+	     Don't have undefined behavior even if the translation
+	     produced a string with the wrong number of "%s"s.  */
+	  char *yyp = yyresult;
+	  int yyi = 0;
+	  while ((*yyp = *yyf) != '\0')
+	    {
+	      if (*yyp == '%' && yyf[1] == 's' && yyi < yycount)
+		{
+		  yyp += yytnamerr (yyp, yyarg[yyi++]);
+		  yyf += 2;
+		}
+	      else
+		{
+		  yyp++;
+		  yyf++;
+		}
+	    }
+	}
+      return yysize;
+    }
+}
+#endif /* YYERROR_VERBOSE */
+
+
+/*-----------------------------------------------.
+| Release the memory associated to this symbol.  |
+`-----------------------------------------------*/
+
+/*ARGSUSED*/
+#if (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+static void
+yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep)
+#else
+static void
+yydestruct (yymsg, yytype, yyvaluep)
+    const char *yymsg;
+    int yytype;
+    YYSTYPE *yyvaluep;
+#endif
+{
+  YYUSE (yyvaluep);
+
+  if (!yymsg)
+    yymsg = "Deleting";
+  YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp);
+
+  switch (yytype)
+    {
+
+      default:
+	break;
+    }
+}
+
+
+/* Prevent warnings from -Wmissing-prototypes.  */
+
+#ifdef YYPARSE_PARAM
+#if defined __STDC__ || defined __cplusplus
+int yyparse (void *YYPARSE_PARAM);
+#else
+int yyparse ();
+#endif
+#else /* ! YYPARSE_PARAM */
+#if defined __STDC__ || defined __cplusplus
+int yyparse (void);
+#else
+int yyparse ();
+#endif
+#endif /* ! YYPARSE_PARAM */
+
+
+
+/* The look-ahead symbol.  */
+int yychar;
+
+/* The semantic value of the look-ahead symbol.  */
+YYSTYPE yylval;
+
+/* Number of syntax errors so far.  */
+int yynerrs;
+
+
+
+/*----------.
+| yyparse.  |
+`----------*/
+
+#ifdef YYPARSE_PARAM
+#if (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+int
+yyparse (void *YYPARSE_PARAM)
+#else
+int
+yyparse (YYPARSE_PARAM)
+    void *YYPARSE_PARAM;
+#endif
+#else /* ! YYPARSE_PARAM */
+#if (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+int
+yyparse (void)
+#else
+int
+yyparse ()
+
+#endif
+#endif
+{
+  
+  int yystate;
+  int yyn;
+  int yyresult;
+  /* Number of tokens to shift before error messages enabled.  */
+  int yyerrstatus;
+  /* Look-ahead token as an internal (translated) token number.  */
+  int yytoken = 0;
+#if YYERROR_VERBOSE
+  /* Buffer for error messages, and its allocated size.  */
+  char yymsgbuf[128];
+  char *yymsg = yymsgbuf;
+  YYSIZE_T yymsg_alloc = sizeof yymsgbuf;
+#endif
+
+  /* Three stacks and their tools:
+     `yyss': related to states,
+     `yyvs': related to semantic values,
+     `yyls': related to locations.
+
+     Refer to the stacks thru separate pointers, to allow yyoverflow
+     to reallocate them elsewhere.  */
+
+  /* The state stack.  */
+  yytype_int16 yyssa[YYINITDEPTH];
+  yytype_int16 *yyss = yyssa;
+  yytype_int16 *yyssp;
+
+  /* The semantic value stack.  */
+  YYSTYPE yyvsa[YYINITDEPTH];
+  YYSTYPE *yyvs = yyvsa;
+  YYSTYPE *yyvsp;
+
+
+
+#define YYPOPSTACK(N)   (yyvsp -= (N), yyssp -= (N))
+
+  YYSIZE_T yystacksize = YYINITDEPTH;
+
+  /* The variables used to return semantic value and location from the
+     action routines.  */
+  YYSTYPE yyval;
+
+
+  /* The number of symbols on the RHS of the reduced rule.
+     Keep to zero when no symbol should be popped.  */
+  int yylen = 0;
+
+  YYDPRINTF ((stderr, "Starting parse\n"));
+
+  yystate = 0;
+  yyerrstatus = 0;
+  yynerrs = 0;
+  yychar = YYEMPTY;		/* Cause a token to be read.  */
+
+  /* Initialize stack pointers.
+     Waste one element of value and location stack
+     so that they stay on the same level as the state stack.
+     The wasted elements are never initialized.  */
+
+  yyssp = yyss;
+  yyvsp = yyvs;
+
+  goto yysetstate;
+
+/*------------------------------------------------------------.
+| yynewstate -- Push a new state, which is found in yystate.  |
+`------------------------------------------------------------*/
+ yynewstate:
+  /* In all cases, when you get here, the value and location stacks
+     have just been pushed.  So pushing a state here evens the stacks.  */
+  yyssp++;
+
+ yysetstate:
+  *yyssp = yystate;
+
+  if (yyss + yystacksize - 1 <= yyssp)
+    {
+      /* Get the current used size of the three stacks, in elements.  */
+      YYSIZE_T yysize = yyssp - yyss + 1;
+
+#ifdef yyoverflow
+      {
+	/* Give user a chance to reallocate the stack.  Use copies of
+	   these so that the &'s don't force the real ones into
+	   memory.  */
+	YYSTYPE *yyvs1 = yyvs;
+	yytype_int16 *yyss1 = yyss;
+
+
+	/* Each stack pointer address is followed by the size of the
+	   data in use in that stack, in bytes.  This used to be a
+	   conditional around just the two extra args, but that might
+	   be undefined if yyoverflow is a macro.  */
+	yyoverflow (YY_("memory exhausted"),
+		    &yyss1, yysize * sizeof (*yyssp),
+		    &yyvs1, yysize * sizeof (*yyvsp),
+
+		    &yystacksize);
+
+	yyss = yyss1;
+	yyvs = yyvs1;
+      }
+#else /* no yyoverflow */
+# ifndef YYSTACK_RELOCATE
+      goto yyexhaustedlab;
+# else
+      /* Extend the stack our own way.  */
+      if (YYMAXDEPTH <= yystacksize)
+	goto yyexhaustedlab;
+      yystacksize *= 2;
+      if (YYMAXDEPTH < yystacksize)
+	yystacksize = YYMAXDEPTH;
+
+      {
+	yytype_int16 *yyss1 = yyss;
+	union yyalloc *yyptr =
+	  (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
+	if (! yyptr)
+	  goto yyexhaustedlab;
+	YYSTACK_RELOCATE (yyss);
+	YYSTACK_RELOCATE (yyvs);
+
+#  undef YYSTACK_RELOCATE
+	if (yyss1 != yyssa)
+	  YYSTACK_FREE (yyss1);
+      }
+# endif
+#endif /* no yyoverflow */
+
+      yyssp = yyss + yysize - 1;
+      yyvsp = yyvs + yysize - 1;
+
+
+      YYDPRINTF ((stderr, "Stack size increased to %lu\n",
+		  (unsigned long int) yystacksize));
+
+      if (yyss + yystacksize - 1 <= yyssp)
+	YYABORT;
+    }
+
+  YYDPRINTF ((stderr, "Entering state %d\n", yystate));
+
+  goto yybackup;
+
+/*-----------.
+| yybackup.  |
+`-----------*/
+yybackup:
+
+  /* Do appropriate processing given the current state.  Read a
+     look-ahead token if we need one and don't already have one.  */
+
+  /* First try to decide what to do without reference to look-ahead token.  */
+  yyn = yypact[yystate];
+  if (yyn == YYPACT_NINF)
+    goto yydefault;
+
+  /* Not known => get a look-ahead token if don't already have one.  */
+
+  /* YYCHAR is either YYEMPTY or YYEOF or a valid look-ahead symbol.  */
+  if (yychar == YYEMPTY)
+    {
+      YYDPRINTF ((stderr, "Reading a token: "));
+      yychar = YYLEX;
+    }
+
+  if (yychar <= YYEOF)
+    {
+      yychar = yytoken = YYEOF;
+      YYDPRINTF ((stderr, "Now at end of input.\n"));
+    }
+  else
+    {
+      yytoken = YYTRANSLATE (yychar);
+      YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc);
+    }
+
+  /* If the proper action on seeing token YYTOKEN is to reduce or to
+     detect an error, take that action.  */
+  yyn += yytoken;
+  if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken)
+    goto yydefault;
+  yyn = yytable[yyn];
+  if (yyn <= 0)
+    {
+      if (yyn == 0 || yyn == YYTABLE_NINF)
+	goto yyerrlab;
+      yyn = -yyn;
+      goto yyreduce;
+    }
+
+  if (yyn == YYFINAL)
+    YYACCEPT;
+
+  /* Count tokens shifted since error; after three, turn off error
+     status.  */
+  if (yyerrstatus)
+    yyerrstatus--;
+
+  /* Shift the look-ahead token.  */
+  YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc);
+
+  /* Discard the shifted token unless it is eof.  */
+  if (yychar != YYEOF)
+    yychar = YYEMPTY;
+
+  yystate = yyn;
+  *++yyvsp = yylval;
+
+  goto yynewstate;
+
+
+/*-----------------------------------------------------------.
+| yydefault -- do the default action for the current state.  |
+`-----------------------------------------------------------*/
+yydefault:
+  yyn = yydefact[yystate];
+  if (yyn == 0)
+    goto yyerrlab;
+  goto yyreduce;
+
+
+/*-----------------------------.
+| yyreduce -- Do a reduction.  |
+`-----------------------------*/
+yyreduce:
+  /* yyn is the number of a rule to reduce with.  */
+  yylen = yyr2[yyn];
+
+  /* If YYLEN is nonzero, implement the default value of the action:
+     `$$ = $1'.
+
+     Otherwise, the following line sets YYVAL to garbage.
+     This behavior is undocumented and Bison
+     users should not rely upon it.  Assigning to YYVAL
+     unconditionally makes the parser a bit smaller, and it avoids a
+     GCC warning that YYVAL may be used uninitialized.  */
+  yyval = yyvsp[1-yylen];
+
+
+  YY_REDUCE_PRINT (yyn);
+  switch (yyn)
+    {
+        case 2:
+#line 151 "policy_parse.y"
+    {
+			p_dir = (yyvsp[(1) - (2)].num);
+			p_type = (yyvsp[(2) - (2)].num);
+
+#ifdef HAVE_PFKEY_POLICY_PRIORITY
+			p_priority = PRIORITY_DEFAULT;
+#else
+			p_priority = 0;
+#endif
+
+			if (init_x_policy())
+				return -1;
+		}
+    break;
+
+  case 4:
+#line 166 "policy_parse.y"
+    {
+			char *offset_buf;
+
+			p_dir = (yyvsp[(1) - (4)].num);
+			p_type = (yyvsp[(4) - (4)].num);
+
+			/* buffer big enough to hold a prepended negative sign */
+			offset_buf = malloc((yyvsp[(3) - (4)].val).len + 2);
+			if (offset_buf == NULL) 
+			{
+				__ipsec_errcode = EIPSEC_NO_BUFS;
+				return -1;
+			}
+
+			/* positive input value means higher priority, therefore lower
+			   actual value so that is closer to the beginning of the list */
+			sprintf (offset_buf, "-%s", (yyvsp[(3) - (4)].val).buf);
+
+			errno = 0;
+			p_priority_offset = atol(offset_buf);
+
+			free(offset_buf);
+
+			if (errno != 0 || p_priority_offset < INT32_MIN)
+			{
+				__ipsec_errcode = EIPSEC_INVAL_PRIORITY_OFFSET;
+				return -1;
+			}
+
+			p_priority = PRIORITY_DEFAULT + (u_int32_t) p_priority_offset;
+
+			if (init_x_policy())
+				return -1;
+		}
+    break;
+
+  case 6:
+#line 202 "policy_parse.y"
+    {
+			p_dir = (yyvsp[(1) - (5)].num);
+			p_type = (yyvsp[(5) - (5)].num);
+
+			errno = 0;
+			p_priority_offset = atol((yyvsp[(4) - (5)].val).buf);
+
+			if (errno != 0 || p_priority_offset > INT32_MAX)
+			{
+				__ipsec_errcode = EIPSEC_INVAL_PRIORITY_OFFSET;
+				return -1;
+			}
+
+			/* negative input value means lower priority, therefore higher
+			   actual value so that is closer to the end of the list */
+			p_priority = PRIORITY_DEFAULT + (u_int32_t) p_priority_offset;
+
+			if (init_x_policy())
+				return -1;
+		}
+    break;
+
+  case 8:
+#line 224 "policy_parse.y"
+    {
+			p_dir = (yyvsp[(1) - (4)].num);
+			p_type = (yyvsp[(4) - (4)].num);
+
+			p_priority = (yyvsp[(3) - (4)].num32);
+
+			if (init_x_policy())
+				return -1;
+		}
+    break;
+
+  case 10:
+#line 235 "policy_parse.y"
+    {
+			p_dir = (yyvsp[(1) - (6)].num);
+			p_type = (yyvsp[(6) - (6)].num);
+
+			errno = 0;
+			p_priority_offset = atol((yyvsp[(5) - (6)].val).buf);
+
+			if (errno != 0 || p_priority_offset > PRIORITY_OFFSET_NEGATIVE_MAX)
+			{
+				__ipsec_errcode = EIPSEC_INVAL_PRIORITY_BASE_OFFSET;
+				return -1;
+			}
+
+			/* adding value means higher priority, therefore lower
+			   actual value so that is closer to the beginning of the list */
+			p_priority = (yyvsp[(3) - (6)].num32) - (u_int32_t) p_priority_offset;
+
+			if (init_x_policy())
+				return -1;
+		}
+    break;
+
+  case 12:
+#line 257 "policy_parse.y"
+    {
+			p_dir = (yyvsp[(1) - (6)].num);
+			p_type = (yyvsp[(6) - (6)].num);
+
+			errno = 0;
+			p_priority_offset = atol((yyvsp[(5) - (6)].val).buf);
+
+			if (errno != 0 || p_priority_offset > PRIORITY_OFFSET_POSITIVE_MAX)
+			{
+				__ipsec_errcode = EIPSEC_INVAL_PRIORITY_BASE_OFFSET;
+				return -1;
+			}
+
+			/* subtracting value means lower priority, therefore higher
+			   actual value so that is closer to the end of the list */
+			p_priority = (yyvsp[(3) - (6)].num32) + (u_int32_t) p_priority_offset;
+
+			if (init_x_policy())
+				return -1;
+		}
+    break;
+
+  case 14:
+#line 279 "policy_parse.y"
+    {
+			p_dir = (yyvsp[(1) - (1)].num);
+			p_type = 0;	/* ignored it by kernel */
+
+			p_priority = 0;
+
+			if (init_x_policy())
+				return -1;
+		}
+    break;
+
+  case 16:
+#line 292 "policy_parse.y"
+    {
+			if (rule_check() < 0)
+				return -1;
+
+			if (set_x_request(p_src, p_dst) < 0)
+				return -1;
+
+			policy_parse_request_init();
+		}
+    break;
+
+  case 23:
+#line 310 "policy_parse.y"
+    {
+			__ipsec_errcode = EIPSEC_FEW_ARGUMENTS;
+			return -1;
+		}
+    break;
+
+  case 24:
+#line 314 "policy_parse.y"
+    {
+			__ipsec_errcode = EIPSEC_FEW_ARGUMENTS;
+			return -1;
+		}
+    break;
+
+  case 25:
+#line 321 "policy_parse.y"
+    { p_protocol = (yyvsp[(1) - (1)].num); }
+    break;
+
+  case 26:
+#line 325 "policy_parse.y"
+    { p_mode = (yyvsp[(1) - (1)].num); }
+    break;
+
+  case 27:
+#line 329 "policy_parse.y"
+    {
+			p_level = (yyvsp[(1) - (1)].num);
+			p_reqid = 0;
+		}
+    break;
+
+  case 28:
+#line 333 "policy_parse.y"
+    {
+			p_level = IPSEC_LEVEL_UNIQUE;
+			p_reqid = atol((yyvsp[(1) - (1)].val).buf);	/* atol() is good. */
+		}
+    break;
+
+  case 29:
+#line 340 "policy_parse.y"
+    {
+			p_src = parse_sockaddr(&(yyvsp[(1) - (1)].val), NULL);
+			if (p_src == NULL)
+				return -1;
+		}
+    break;
+
+  case 30:
+#line 346 "policy_parse.y"
+    {
+			p_dst = parse_sockaddr(&(yyvsp[(4) - (4)].val), NULL);
+			if (p_dst == NULL)
+				return -1;
+		}
+    break;
+
+  case 31:
+#line 351 "policy_parse.y"
+    {
+			p_src = parse_sockaddr(&(yyvsp[(1) - (2)].val), &(yyvsp[(2) - (2)].val));
+			if (p_src == NULL)
+				return -1;
+		}
+    break;
+
+  case 32:
+#line 357 "policy_parse.y"
+    {
+			p_dst = parse_sockaddr(&(yyvsp[(5) - (6)].val), &(yyvsp[(6) - (6)].val));
+			if (p_dst == NULL)
+				return -1;
+		}
+    break;
+
+  case 33:
+#line 362 "policy_parse.y"
+    {
+			if (p_dir != IPSEC_DIR_OUTBOUND) {
+				__ipsec_errcode = EIPSEC_INVAL_DIR;
+				return -1;
+			}
+		}
+    break;
+
+  case 34:
+#line 368 "policy_parse.y"
+    {
+			if (p_dir != IPSEC_DIR_INBOUND) {
+				__ipsec_errcode = EIPSEC_INVAL_DIR;
+				return -1;
+			}
+		}
+    break;
+
+
+/* Line 1267 of yacc.c.  */
+#line 1725 "policy_parse.c"
+      default: break;
+    }
+  YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
+
+  YYPOPSTACK (yylen);
+  yylen = 0;
+  YY_STACK_PRINT (yyss, yyssp);
+
+  *++yyvsp = yyval;
+
+
+  /* Now `shift' the result of the reduction.  Determine what state
+     that goes to, based on the state we popped back to and the rule
+     number reduced by.  */
+
+  yyn = yyr1[yyn];
+
+  yystate = yypgoto[yyn - YYNTOKENS] + *yyssp;
+  if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp)
+    yystate = yytable[yystate];
+  else
+    yystate = yydefgoto[yyn - YYNTOKENS];
+
+  goto yynewstate;
+
+
+/*------------------------------------.
+| yyerrlab -- here on detecting error |
+`------------------------------------*/
+yyerrlab:
+  /* If not already recovering from an error, report this error.  */
+  if (!yyerrstatus)
+    {
+      ++yynerrs;
+#if ! YYERROR_VERBOSE
+      yyerror (YY_("syntax error"));
+#else
+      {
+	YYSIZE_T yysize = yysyntax_error (0, yystate, yychar);
+	if (yymsg_alloc < yysize && yymsg_alloc < YYSTACK_ALLOC_MAXIMUM)
+	  {
+	    YYSIZE_T yyalloc = 2 * yysize;
+	    if (! (yysize <= yyalloc && yyalloc <= YYSTACK_ALLOC_MAXIMUM))
+	      yyalloc = YYSTACK_ALLOC_MAXIMUM;
+	    if (yymsg != yymsgbuf)
+	      YYSTACK_FREE (yymsg);
+	    yymsg = (char *) YYSTACK_ALLOC (yyalloc);
+	    if (yymsg)
+	      yymsg_alloc = yyalloc;
+	    else
+	      {
+		yymsg = yymsgbuf;
+		yymsg_alloc = sizeof yymsgbuf;
+	      }
+	  }
+
+	if (0 < yysize && yysize <= yymsg_alloc)
+	  {
+	    (void) yysyntax_error (yymsg, yystate, yychar);
+	    yyerror (yymsg);
+	  }
+	else
+	  {
+	    yyerror (YY_("syntax error"));
+	    if (yysize != 0)
+	      goto yyexhaustedlab;
+	  }
+      }
+#endif
+    }
+
+
+
+  if (yyerrstatus == 3)
+    {
+      /* If just tried and failed to reuse look-ahead token after an
+	 error, discard it.  */
+
+      if (yychar <= YYEOF)
+	{
+	  /* Return failure if at end of input.  */
+	  if (yychar == YYEOF)
+	    YYABORT;
+	}
+      else
+	{
+	  yydestruct ("Error: discarding",
+		      yytoken, &yylval);
+	  yychar = YYEMPTY;
+	}
+    }
+
+  /* Else will try to reuse look-ahead token after shifting the error
+     token.  */
+  goto yyerrlab1;
+
+
+/*---------------------------------------------------.
+| yyerrorlab -- error raised explicitly by YYERROR.  |
+`---------------------------------------------------*/
+yyerrorlab:
+
+  /* Pacify compilers like GCC when the user code never invokes
+     YYERROR and the label yyerrorlab therefore never appears in user
+     code.  */
+  if (/*CONSTCOND*/ 0)
+     goto yyerrorlab;
+
+  /* Do not reclaim the symbols of the rule which action triggered
+     this YYERROR.  */
+  YYPOPSTACK (yylen);
+  yylen = 0;
+  YY_STACK_PRINT (yyss, yyssp);
+  yystate = *yyssp;
+  goto yyerrlab1;
+
+
+/*-------------------------------------------------------------.
+| yyerrlab1 -- common code for both syntax error and YYERROR.  |
+`-------------------------------------------------------------*/
+yyerrlab1:
+  yyerrstatus = 3;	/* Each real token shifted decrements this.  */
+
+  for (;;)
+    {
+      yyn = yypact[yystate];
+      if (yyn != YYPACT_NINF)
+	{
+	  yyn += YYTERROR;
+	  if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR)
+	    {
+	      yyn = yytable[yyn];
+	      if (0 < yyn)
+		break;
+	    }
+	}
+
+      /* Pop the current state because it cannot handle the error token.  */
+      if (yyssp == yyss)
+	YYABORT;
+
+
+      yydestruct ("Error: popping",
+		  yystos[yystate], yyvsp);
+      YYPOPSTACK (1);
+      yystate = *yyssp;
+      YY_STACK_PRINT (yyss, yyssp);
+    }
+
+  if (yyn == YYFINAL)
+    YYACCEPT;
+
+  *++yyvsp = yylval;
+
+
+  /* Shift the error token.  */
+  YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp);
+
+  yystate = yyn;
+  goto yynewstate;
+
+
+/*-------------------------------------.
+| yyacceptlab -- YYACCEPT comes here.  |
+`-------------------------------------*/
+yyacceptlab:
+  yyresult = 0;
+  goto yyreturn;
+
+/*-----------------------------------.
+| yyabortlab -- YYABORT comes here.  |
+`-----------------------------------*/
+yyabortlab:
+  yyresult = 1;
+  goto yyreturn;
+
+#ifndef yyoverflow
+/*-------------------------------------------------.
+| yyexhaustedlab -- memory exhaustion comes here.  |
+`-------------------------------------------------*/
+yyexhaustedlab:
+  yyerror (YY_("memory exhausted"));
+  yyresult = 2;
+  /* Fall through.  */
+#endif
+
+yyreturn:
+  if (yychar != YYEOF && yychar != YYEMPTY)
+     yydestruct ("Cleanup: discarding lookahead",
+		 yytoken, &yylval);
+  /* Do not reclaim the symbols of the rule which action triggered
+     this YYABORT or YYACCEPT.  */
+  YYPOPSTACK (yylen);
+  YY_STACK_PRINT (yyss, yyssp);
+  while (yyssp != yyss)
+    {
+      yydestruct ("Cleanup: popping",
+		  yystos[*yyssp], yyvsp);
+      YYPOPSTACK (1);
+    }
+#ifndef yyoverflow
+  if (yyss != yyssa)
+    YYSTACK_FREE (yyss);
+#endif
+#if YYERROR_VERBOSE
+  if (yymsg != yymsgbuf)
+    YYSTACK_FREE (yymsg);
+#endif
+  /* Make sure YYID is used.  */
+  return YYID (yyresult);
+}
+
+
+#line 379 "policy_parse.y"
+
+
+void
+yyerror(msg)
+	char *msg;
+{
+	fprintf(stderr, "libipsec: %s while parsing \"%s\"\n",
+		msg, __libipsectext);
+
+	return;
+}
+
+static struct sockaddr *
+parse_sockaddr(addrbuf, portbuf)
+	struct _val *addrbuf;
+	struct _val *portbuf;
+{
+	struct addrinfo hints, *res;
+	char *addr;
+	char *serv = NULL;
+	int error;
+	struct sockaddr *newaddr = NULL;
+
+	if ((addr = malloc(addrbuf->len + 1)) == NULL) {
+		yyerror("malloc failed");
+		__ipsec_set_strerror(strerror(errno));
+		return NULL;
+	}
+
+	if (portbuf && ((serv = malloc(portbuf->len + 1)) == NULL)) {
+		free(addr);
+		yyerror("malloc failed");
+		__ipsec_set_strerror(strerror(errno));
+		return NULL;
+	}
+
+	strncpy(addr, addrbuf->buf, addrbuf->len);
+	addr[addrbuf->len] = '\0';
+
+	if (portbuf) {
+		strncpy(serv, portbuf->buf, portbuf->len);
+		serv[portbuf->len] = '\0';
+	}
+
+	memset(&hints, 0, sizeof(hints));
+	hints.ai_family = PF_UNSPEC;
+	hints.ai_flags = AI_NUMERICHOST;
+	hints.ai_socktype = SOCK_DGRAM;
+	error = getaddrinfo(addr, serv, &hints, &res);
+	free(addr);
+	if (serv != NULL)
+		free(serv);
+	if (error != 0) {
+		yyerror("invalid IP address");
+		__ipsec_set_strerror(gai_strerror(error));
+		return NULL;
+	}
+
+	if (res->ai_addr == NULL) {
+		yyerror("invalid IP address");
+		__ipsec_set_strerror(gai_strerror(error));
+		return NULL;
+	}
+
+	newaddr = malloc(res->ai_addrlen);
+	if (newaddr == NULL) {
+		__ipsec_errcode = EIPSEC_NO_BUFS;
+		freeaddrinfo(res);
+		return NULL;
+	}
+	memcpy(newaddr, res->ai_addr, res->ai_addrlen);
+
+	freeaddrinfo(res);
+
+	__ipsec_errcode = EIPSEC_NO_ERROR;
+	return newaddr;
+}
+
+static int
+rule_check()
+{
+	if (p_type == IPSEC_POLICY_IPSEC) {
+		if (p_protocol == IPPROTO_IP) {
+			__ipsec_errcode = EIPSEC_NO_PROTO;
+			return -1;
+		}
+
+		if (p_mode != IPSEC_MODE_TRANSPORT
+		 && p_mode != IPSEC_MODE_TUNNEL) {
+			__ipsec_errcode = EIPSEC_INVAL_MODE;
+			return -1;
+		}
+
+		if (p_src == NULL && p_dst == NULL) {
+			 if (p_mode != IPSEC_MODE_TRANSPORT) {
+				__ipsec_errcode = EIPSEC_INVAL_ADDRESS;
+				return -1;
+			}
+		}
+		else if (p_src->sa_family != p_dst->sa_family) {
+			__ipsec_errcode = EIPSEC_FAMILY_MISMATCH;
+			return -1;
+		}
+	}
+
+	__ipsec_errcode = EIPSEC_NO_ERROR;
+	return 0;
+}
+
+static int
+init_x_policy()
+{
+	struct sadb_x_policy *p;
+
+	if (pbuf) {
+		free(pbuf);
+		tlen = 0;
+	}
+	pbuf = malloc(sizeof(struct sadb_x_policy));
+	if (pbuf == NULL) {
+		__ipsec_errcode = EIPSEC_NO_BUFS;
+		return -1;
+	}
+	tlen = sizeof(struct sadb_x_policy);
+
+	memset(pbuf, 0, tlen);
+	p = (struct sadb_x_policy *)pbuf;
+	p->sadb_x_policy_len = 0;	/* must update later */
+	p->sadb_x_policy_exttype = SADB_X_EXT_POLICY;
+	p->sadb_x_policy_type = p_type;
+	p->sadb_x_policy_dir = p_dir;
+	p->sadb_x_policy_id = 0;
+#ifdef HAVE_PFKEY_POLICY_PRIORITY
+	p->sadb_x_policy_priority = p_priority;
+#else
+    /* fail if given a priority and libipsec was not compiled with 
+	   priority support */
+	if (p_priority != 0)
+	{
+		__ipsec_errcode = EIPSEC_PRIORITY_NOT_COMPILED;
+		return -1;
+	}
+#endif
+
+	offset = tlen;
+
+	__ipsec_errcode = EIPSEC_NO_ERROR;
+	return 0;
+}
+
+static int
+set_x_request(src, dst)
+	struct sockaddr *src, *dst;
+{
+	struct sadb_x_ipsecrequest *p;
+	int reqlen;
+	u_int8_t *n;
+
+	reqlen = sizeof(*p)
+		+ (src ? sysdep_sa_len(src) : 0)
+		+ (dst ? sysdep_sa_len(dst) : 0);
+	tlen += reqlen;		/* increment to total length */
+
+	n = realloc(pbuf, tlen);
+	if (n == NULL) {
+		__ipsec_errcode = EIPSEC_NO_BUFS;
+		return -1;
+	}
+	pbuf = n;
+
+	p = (struct sadb_x_ipsecrequest *)&pbuf[offset];
+	p->sadb_x_ipsecrequest_len = reqlen;
+	p->sadb_x_ipsecrequest_proto = p_protocol;
+	p->sadb_x_ipsecrequest_mode = p_mode;
+	p->sadb_x_ipsecrequest_level = p_level;
+	p->sadb_x_ipsecrequest_reqid = p_reqid;
+	offset += sizeof(*p);
+
+	if (set_sockaddr(src) || set_sockaddr(dst))
+		return -1;
+
+	__ipsec_errcode = EIPSEC_NO_ERROR;
+	return 0;
+}
+
+static int
+set_sockaddr(addr)
+	struct sockaddr *addr;
+{
+	if (addr == NULL) {
+		__ipsec_errcode = EIPSEC_NO_ERROR;
+		return 0;
+	}
+
+	/* tlen has already incremented */
+
+	memcpy(&pbuf[offset], addr, sysdep_sa_len(addr));
+
+	offset += sysdep_sa_len(addr);
+
+	__ipsec_errcode = EIPSEC_NO_ERROR;
+	return 0;
+}
+
+static void
+policy_parse_request_init()
+{
+	p_protocol = IPPROTO_IP;
+	p_mode = IPSEC_MODE_ANY;
+	p_level = IPSEC_LEVEL_DEFAULT;
+	p_reqid = 0;
+	if (p_src != NULL) {
+		free(p_src);
+		p_src = NULL;
+	}
+	if (p_dst != NULL) {
+		free(p_dst);
+		p_dst = NULL;
+	}
+
+	return;
+}
+
+static void *
+policy_parse(msg, msglen)
+	const char *msg;
+	int msglen;
+{
+	int error;
+
+	pbuf = NULL;
+	tlen = 0;
+
+	/* initialize */
+	p_dir = IPSEC_DIR_INVALID;
+	p_type = IPSEC_POLICY_DISCARD;
+	policy_parse_request_init();
+	__policy__strbuffer__init__(msg);
+
+	error = yyparse();	/* it must be set errcode. */
+	__policy__strbuffer__free__();
+
+	if (error) {
+		if (pbuf != NULL)
+			free(pbuf);
+		return NULL;
+	}
+
+	/* update total length */
+	((struct sadb_x_policy *)pbuf)->sadb_x_policy_len = PFKEY_UNIT64(tlen);
+
+	__ipsec_errcode = EIPSEC_NO_ERROR;
+
+	return pbuf;
+}
+
+ipsec_policy_t
+ipsec_set_policy(msg, msglen)
+	__ipsec_const char *msg;
+	int msglen;
+{
+	caddr_t policy;
+
+	policy = policy_parse(msg, msglen);
+	if (policy == NULL) {
+		if (__ipsec_errcode == EIPSEC_NO_ERROR)
+			__ipsec_errcode = EIPSEC_INVAL_ARGUMENT;
+		return NULL;
+	}
+
+	__ipsec_errcode = EIPSEC_NO_ERROR;
+	return policy;
+}
+
diff --git a/src/libipsec/policy_parse.h b/src/libipsec/policy_parse.h
new file mode 100644
index 0000000..a4c1d0b
--- /dev/null
+++ b/src/libipsec/policy_parse.h
@@ -0,0 +1,101 @@
+/* A Bison parser, made by GNU Bison 2.3.  */
+
+/* Skeleton interface for Bison's Yacc-like parsers in C
+
+   Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
+   Free Software Foundation, Inc.
+
+   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, or (at your option)
+   any later version.
+
+   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.
+
+   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., 51 Franklin Street, Fifth Floor,
+   Boston, MA 02110-1301, USA.  */
+
+/* As a special exception, you may create a larger work that contains
+   part or all of the Bison parser skeleton and distribute that work
+   under terms of your choice, so long as that work isn't itself a
+   parser generator using the skeleton or a modified version thereof
+   as a parser skeleton.  Alternatively, if you modify or redistribute
+   the parser skeleton itself, you may (at your option) remove this
+   special exception, which will cause the skeleton and the resulting
+   Bison output files to be licensed under the GNU General Public
+   License without this special exception.
+
+   This special exception was added by the Free Software Foundation in
+   version 2.2 of Bison.  */
+
+/* Tokens.  */
+#ifndef YYTOKENTYPE
+# define YYTOKENTYPE
+   /* Put the tokens into the symbol table, so that GDB and other debuggers
+      know about them.  */
+   enum yytokentype {
+     DIR = 258,
+     PRIORITY = 259,
+     PLUS = 260,
+     PRIO_BASE = 261,
+     PRIO_OFFSET = 262,
+     ACTION = 263,
+     PROTOCOL = 264,
+     MODE = 265,
+     LEVEL = 266,
+     LEVEL_SPECIFY = 267,
+     IPADDRESS = 268,
+     PORT = 269,
+     ME = 270,
+     ANY = 271,
+     SLASH = 272,
+     HYPHEN = 273
+   };
+#endif
+/* Tokens.  */
+#define DIR 258
+#define PRIORITY 259
+#define PLUS 260
+#define PRIO_BASE 261
+#define PRIO_OFFSET 262
+#define ACTION 263
+#define PROTOCOL 264
+#define MODE 265
+#define LEVEL 266
+#define LEVEL_SPECIFY 267
+#define IPADDRESS 268
+#define PORT 269
+#define ME 270
+#define ANY 271
+#define SLASH 272
+#define HYPHEN 273
+
+
+
+
+#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
+typedef union YYSTYPE
+#line 129 "policy_parse.y"
+{
+	u_int num;
+	u_int32_t num32;
+	struct _val {
+		int len;
+		char *buf;
+	} val;
+}
+/* Line 1489 of yacc.c.  */
+#line 94 "policy_parse.h"
+	YYSTYPE;
+# define yystype YYSTYPE /* obsolescent; will be withdrawn */
+# define YYSTYPE_IS_DECLARED 1
+# define YYSTYPE_IS_TRIVIAL 1
+#endif
+
+extern YYSTYPE __libipseclval;
+
diff --git a/src/libipsec/policy_parse.y b/src/libipsec/policy_parse.y
new file mode 100644
index 0000000..fda901d
--- /dev/null
+++ b/src/libipsec/policy_parse.y
@@ -0,0 +1,651 @@
+/*	$NetBSD: policy_parse.y,v 1.9.6.1 2007/08/01 11:52:18 vanhu Exp $	*/
+
+/*	$KAME: policy_parse.y,v 1.21 2003/12/12 08:01:26 itojun Exp $	*/
+
+/*
+ * Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * IN/OUT bound policy configuration take place such below:
+ *	in <priority> <policy>
+ *	out <priority> <policy>
+ *
+ * <priority> is one of the following:
+ * priority <signed int> where the integer is an offset from the default
+ *                       priority, where negative numbers indicate lower
+ *                       priority (towards end of list) and positive numbers 
+ *                       indicate higher priority (towards beginning of list)
+ *
+ * priority {low,def,high} {+,-} <unsigned int>  where low and high are
+ *                                               constants which are closer
+ *                                               to the end of the list and
+ *                                               beginning of the list,
+ *                                               respectively
+ *
+ * <policy> is one of following:
+ *	"discard", "none", "ipsec <requests>", "entrust", "bypass",
+ *
+ * The following requests are accepted as <requests>:
+ *
+ *	protocol/mode/src-dst/level
+ *	protocol/mode/src-dst		parsed as protocol/mode/src-dst/default
+ *	protocol/mode/src-dst/		parsed as protocol/mode/src-dst/default
+ *	protocol/transport		parsed as protocol/mode/any-any/default
+ *	protocol/transport//level	parsed as protocol/mode/any-any/level
+ *
+ * You can concatenate these requests with either ' '(single space) or '\n'.
+ */
+
+%{
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+
+#include <netinet/in.h>
+#include PATH_IPSEC_H
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <netdb.h>
+
+#include <errno.h>
+
+#include "config.h"
+
+#include "ipsec_strerror.h"
+#include "libpfkey.h"
+
+#ifndef INT32_MAX
+#define INT32_MAX	(0xffffffff)
+#endif
+
+#ifndef INT32_MIN
+#define INT32_MIN	(-INT32_MAX-1)
+#endif
+
+#define ATOX(c) \
+  (isdigit(c) ? (c - '0') : (isupper(c) ? (c - 'A' + 10) : (c - 'a' + 10) ))
+
+static u_int8_t *pbuf = NULL;		/* sadb_x_policy buffer */
+static int tlen = 0;			/* total length of pbuf */
+static int offset = 0;			/* offset of pbuf */
+static int p_dir, p_type, p_protocol, p_mode, p_level, p_reqid;
+static u_int32_t p_priority = 0;
+static long p_priority_offset = 0;
+static struct sockaddr *p_src = NULL;
+static struct sockaddr *p_dst = NULL;
+
+struct _val;
+extern void yyerror __P((char *msg));
+static struct sockaddr *parse_sockaddr __P((struct _val *addrbuf,
+    struct _val *portbuf));
+static int rule_check __P((void));
+static int init_x_policy __P((void));
+static int set_x_request __P((struct sockaddr *, struct sockaddr *));
+static int set_sockaddr __P((struct sockaddr *));
+static void policy_parse_request_init __P((void));
+static void *policy_parse __P((const char *, int));
+
+extern void __policy__strbuffer__init__ __P((const char *));
+extern void __policy__strbuffer__free__ __P((void));
+extern int yyparse __P((void));
+extern int yylex __P((void));
+
+extern char *__libipsectext;	/*XXX*/
+
+%}
+
+%union {
+	u_int num;
+	u_int32_t num32;
+	struct _val {
+		int len;
+		char *buf;
+	} val;
+}
+
+%token DIR 
+%token PRIORITY PLUS
+%token <num32> PRIO_BASE 
+%token <val> PRIO_OFFSET 
+%token ACTION PROTOCOL MODE LEVEL LEVEL_SPECIFY IPADDRESS PORT
+%token ME ANY
+%token SLASH HYPHEN
+%type <num> DIR PRIORITY ACTION PROTOCOL MODE LEVEL
+%type <val> IPADDRESS LEVEL_SPECIFY PORT
+
+%%
+policy_spec
+	:	DIR ACTION
+		{
+			p_dir = $1;
+			p_type = $2;
+
+#ifdef HAVE_PFKEY_POLICY_PRIORITY
+			p_priority = PRIORITY_DEFAULT;
+#else
+			p_priority = 0;
+#endif
+
+			if (init_x_policy())
+				return -1;
+		}
+		rules
+	|	DIR PRIORITY PRIO_OFFSET ACTION
+		{
+			char *offset_buf;
+
+			p_dir = $1;
+			p_type = $4;
+
+			/* buffer big enough to hold a prepended negative sign */
+			offset_buf = malloc($3.len + 2);
+			if (offset_buf == NULL) 
+			{
+				__ipsec_errcode = EIPSEC_NO_BUFS;
+				return -1;
+			}
+
+			/* positive input value means higher priority, therefore lower
+			   actual value so that is closer to the beginning of the list */
+			sprintf (offset_buf, "-%s", $3.buf);
+
+			errno = 0;
+			p_priority_offset = atol(offset_buf);
+
+			free(offset_buf);
+
+			if (errno != 0 || p_priority_offset < INT32_MIN)
+			{
+				__ipsec_errcode = EIPSEC_INVAL_PRIORITY_OFFSET;
+				return -1;
+			}
+
+			p_priority = PRIORITY_DEFAULT + (u_int32_t) p_priority_offset;
+
+			if (init_x_policy())
+				return -1;
+		}
+		rules
+	|	DIR PRIORITY HYPHEN PRIO_OFFSET ACTION
+		{
+			p_dir = $1;
+			p_type = $5;
+
+			errno = 0;
+			p_priority_offset = atol($4.buf);
+
+			if (errno != 0 || p_priority_offset > INT32_MAX)
+			{
+				__ipsec_errcode = EIPSEC_INVAL_PRIORITY_OFFSET;
+				return -1;
+			}
+
+			/* negative input value means lower priority, therefore higher
+			   actual value so that is closer to the end of the list */
+			p_priority = PRIORITY_DEFAULT + (u_int32_t) p_priority_offset;
+
+			if (init_x_policy())
+				return -1;
+		}
+		rules
+	|	DIR PRIORITY PRIO_BASE ACTION
+		{
+			p_dir = $1;
+			p_type = $4;
+
+			p_priority = $3;
+
+			if (init_x_policy())
+				return -1;
+		}
+		rules
+	|	DIR PRIORITY PRIO_BASE PLUS PRIO_OFFSET ACTION
+		{
+			p_dir = $1;
+			p_type = $6;
+
+			errno = 0;
+			p_priority_offset = atol($5.buf);
+
+			if (errno != 0 || p_priority_offset > PRIORITY_OFFSET_NEGATIVE_MAX)
+			{
+				__ipsec_errcode = EIPSEC_INVAL_PRIORITY_BASE_OFFSET;
+				return -1;
+			}
+
+			/* adding value means higher priority, therefore lower
+			   actual value so that is closer to the beginning of the list */
+			p_priority = $3 - (u_int32_t) p_priority_offset;
+
+			if (init_x_policy())
+				return -1;
+		}
+		rules
+	|	DIR PRIORITY PRIO_BASE HYPHEN PRIO_OFFSET ACTION
+		{
+			p_dir = $1;
+			p_type = $6;
+
+			errno = 0;
+			p_priority_offset = atol($5.buf);
+
+			if (errno != 0 || p_priority_offset > PRIORITY_OFFSET_POSITIVE_MAX)
+			{
+				__ipsec_errcode = EIPSEC_INVAL_PRIORITY_BASE_OFFSET;
+				return -1;
+			}
+
+			/* subtracting value means lower priority, therefore higher
+			   actual value so that is closer to the end of the list */
+			p_priority = $3 + (u_int32_t) p_priority_offset;
+
+			if (init_x_policy())
+				return -1;
+		}
+		rules
+	|	DIR
+		{
+			p_dir = $1;
+			p_type = 0;	/* ignored it by kernel */
+
+			p_priority = 0;
+
+			if (init_x_policy())
+				return -1;
+		}
+	;
+
+rules
+	:	/*NOTHING*/
+	|	rules rule {
+			if (rule_check() < 0)
+				return -1;
+
+			if (set_x_request(p_src, p_dst) < 0)
+				return -1;
+
+			policy_parse_request_init();
+		}
+	;
+
+rule
+	:	protocol SLASH mode SLASH addresses SLASH level
+	|	protocol SLASH mode SLASH addresses SLASH
+	|	protocol SLASH mode SLASH addresses
+	|	protocol SLASH mode SLASH
+	|	protocol SLASH mode SLASH SLASH level
+	|	protocol SLASH mode
+	|	protocol SLASH {
+			__ipsec_errcode = EIPSEC_FEW_ARGUMENTS;
+			return -1;
+		}
+	|	protocol {
+			__ipsec_errcode = EIPSEC_FEW_ARGUMENTS;
+			return -1;
+		}
+	;
+
+protocol
+	:	PROTOCOL { p_protocol = $1; }
+	;
+
+mode
+	:	MODE { p_mode = $1; }
+	;
+
+level
+	:	LEVEL {
+			p_level = $1;
+			p_reqid = 0;
+		}
+	|	LEVEL_SPECIFY {
+			p_level = IPSEC_LEVEL_UNIQUE;
+			p_reqid = atol($1.buf);	/* atol() is good. */
+		}
+	;
+
+addresses
+	:	IPADDRESS {
+			p_src = parse_sockaddr(&$1, NULL);
+			if (p_src == NULL)
+				return -1;
+		}
+		HYPHEN
+		IPADDRESS {
+			p_dst = parse_sockaddr(&$4, NULL);
+			if (p_dst == NULL)
+				return -1;
+		}
+	|	IPADDRESS PORT {
+			p_src = parse_sockaddr(&$1, &$2);
+			if (p_src == NULL)
+				return -1;
+		}
+		HYPHEN
+		IPADDRESS PORT {
+			p_dst = parse_sockaddr(&$5, &$6);
+			if (p_dst == NULL)
+				return -1;
+		}
+	|	ME HYPHEN ANY {
+			if (p_dir != IPSEC_DIR_OUTBOUND) {
+				__ipsec_errcode = EIPSEC_INVAL_DIR;
+				return -1;
+			}
+		}
+	|	ANY HYPHEN ME {
+			if (p_dir != IPSEC_DIR_INBOUND) {
+				__ipsec_errcode = EIPSEC_INVAL_DIR;
+				return -1;
+			}
+		}
+		/*
+	|	ME HYPHEN ME
+		*/
+	;
+
+%%
+
+void
+yyerror(msg)
+	char *msg;
+{
+	fprintf(stderr, "libipsec: %s while parsing \"%s\"\n",
+		msg, __libipsectext);
+
+	return;
+}
+
+static struct sockaddr *
+parse_sockaddr(addrbuf, portbuf)
+	struct _val *addrbuf;
+	struct _val *portbuf;
+{
+	struct addrinfo hints, *res;
+	char *addr;
+	char *serv = NULL;
+	int error;
+	struct sockaddr *newaddr = NULL;
+
+	if ((addr = malloc(addrbuf->len + 1)) == NULL) {
+		yyerror("malloc failed");
+		__ipsec_set_strerror(strerror(errno));
+		return NULL;
+	}
+
+	if (portbuf && ((serv = malloc(portbuf->len + 1)) == NULL)) {
+		free(addr);
+		yyerror("malloc failed");
+		__ipsec_set_strerror(strerror(errno));
+		return NULL;
+	}
+
+	strncpy(addr, addrbuf->buf, addrbuf->len);
+	addr[addrbuf->len] = '\0';
+
+	if (portbuf) {
+		strncpy(serv, portbuf->buf, portbuf->len);
+		serv[portbuf->len] = '\0';
+	}
+
+	memset(&hints, 0, sizeof(hints));
+	hints.ai_family = PF_UNSPEC;
+	hints.ai_flags = AI_NUMERICHOST;
+	hints.ai_socktype = SOCK_DGRAM;
+	error = getaddrinfo(addr, serv, &hints, &res);
+	free(addr);
+	if (serv != NULL)
+		free(serv);
+	if (error != 0) {
+		yyerror("invalid IP address");
+		__ipsec_set_strerror(gai_strerror(error));
+		return NULL;
+	}
+
+	if (res->ai_addr == NULL) {
+		yyerror("invalid IP address");
+		__ipsec_set_strerror(gai_strerror(error));
+		return NULL;
+	}
+
+	newaddr = malloc(res->ai_addrlen);
+	if (newaddr == NULL) {
+		__ipsec_errcode = EIPSEC_NO_BUFS;
+		freeaddrinfo(res);
+		return NULL;
+	}
+	memcpy(newaddr, res->ai_addr, res->ai_addrlen);
+
+	freeaddrinfo(res);
+
+	__ipsec_errcode = EIPSEC_NO_ERROR;
+	return newaddr;
+}
+
+static int
+rule_check()
+{
+	if (p_type == IPSEC_POLICY_IPSEC) {
+		if (p_protocol == IPPROTO_IP) {
+			__ipsec_errcode = EIPSEC_NO_PROTO;
+			return -1;
+		}
+
+		if (p_mode != IPSEC_MODE_TRANSPORT
+		 && p_mode != IPSEC_MODE_TUNNEL) {
+			__ipsec_errcode = EIPSEC_INVAL_MODE;
+			return -1;
+		}
+
+		if (p_src == NULL && p_dst == NULL) {
+			 if (p_mode != IPSEC_MODE_TRANSPORT) {
+				__ipsec_errcode = EIPSEC_INVAL_ADDRESS;
+				return -1;
+			}
+		}
+		else if (p_src->sa_family != p_dst->sa_family) {
+			__ipsec_errcode = EIPSEC_FAMILY_MISMATCH;
+			return -1;
+		}
+	}
+
+	__ipsec_errcode = EIPSEC_NO_ERROR;
+	return 0;
+}
+
+static int
+init_x_policy()
+{
+	struct sadb_x_policy *p;
+
+	if (pbuf) {
+		free(pbuf);
+		tlen = 0;
+	}
+	pbuf = malloc(sizeof(struct sadb_x_policy));
+	if (pbuf == NULL) {
+		__ipsec_errcode = EIPSEC_NO_BUFS;
+		return -1;
+	}
+	tlen = sizeof(struct sadb_x_policy);
+
+	memset(pbuf, 0, tlen);
+	p = (struct sadb_x_policy *)pbuf;
+	p->sadb_x_policy_len = 0;	/* must update later */
+	p->sadb_x_policy_exttype = SADB_X_EXT_POLICY;
+	p->sadb_x_policy_type = p_type;
+	p->sadb_x_policy_dir = p_dir;
+	p->sadb_x_policy_id = 0;
+#ifdef HAVE_PFKEY_POLICY_PRIORITY
+	p->sadb_x_policy_priority = p_priority;
+#else
+    /* fail if given a priority and libipsec was not compiled with 
+	   priority support */
+	if (p_priority != 0)
+	{
+		__ipsec_errcode = EIPSEC_PRIORITY_NOT_COMPILED;
+		return -1;
+	}
+#endif
+
+	offset = tlen;
+
+	__ipsec_errcode = EIPSEC_NO_ERROR;
+	return 0;
+}
+
+static int
+set_x_request(src, dst)
+	struct sockaddr *src, *dst;
+{
+	struct sadb_x_ipsecrequest *p;
+	int reqlen;
+	u_int8_t *n;
+
+	reqlen = sizeof(*p)
+		+ (src ? sysdep_sa_len(src) : 0)
+		+ (dst ? sysdep_sa_len(dst) : 0);
+	tlen += reqlen;		/* increment to total length */
+
+	n = realloc(pbuf, tlen);
+	if (n == NULL) {
+		__ipsec_errcode = EIPSEC_NO_BUFS;
+		return -1;
+	}
+	pbuf = n;
+
+	p = (struct sadb_x_ipsecrequest *)&pbuf[offset];
+	p->sadb_x_ipsecrequest_len = reqlen;
+	p->sadb_x_ipsecrequest_proto = p_protocol;
+	p->sadb_x_ipsecrequest_mode = p_mode;
+	p->sadb_x_ipsecrequest_level = p_level;
+	p->sadb_x_ipsecrequest_reqid = p_reqid;
+	offset += sizeof(*p);
+
+	if (set_sockaddr(src) || set_sockaddr(dst))
+		return -1;
+
+	__ipsec_errcode = EIPSEC_NO_ERROR;
+	return 0;
+}
+
+static int
+set_sockaddr(addr)
+	struct sockaddr *addr;
+{
+	if (addr == NULL) {
+		__ipsec_errcode = EIPSEC_NO_ERROR;
+		return 0;
+	}
+
+	/* tlen has already incremented */
+
+	memcpy(&pbuf[offset], addr, sysdep_sa_len(addr));
+
+	offset += sysdep_sa_len(addr);
+
+	__ipsec_errcode = EIPSEC_NO_ERROR;
+	return 0;
+}
+
+static void
+policy_parse_request_init()
+{
+	p_protocol = IPPROTO_IP;
+	p_mode = IPSEC_MODE_ANY;
+	p_level = IPSEC_LEVEL_DEFAULT;
+	p_reqid = 0;
+	if (p_src != NULL) {
+		free(p_src);
+		p_src = NULL;
+	}
+	if (p_dst != NULL) {
+		free(p_dst);
+		p_dst = NULL;
+	}
+
+	return;
+}
+
+static void *
+policy_parse(msg, msglen)
+	const char *msg;
+	int msglen;
+{
+	int error;
+
+	pbuf = NULL;
+	tlen = 0;
+
+	/* initialize */
+	p_dir = IPSEC_DIR_INVALID;
+	p_type = IPSEC_POLICY_DISCARD;
+	policy_parse_request_init();
+	__policy__strbuffer__init__(msg);
+
+	error = yyparse();	/* it must be set errcode. */
+	__policy__strbuffer__free__();
+
+	if (error) {
+		if (pbuf != NULL)
+			free(pbuf);
+		return NULL;
+	}
+
+	/* update total length */
+	((struct sadb_x_policy *)pbuf)->sadb_x_policy_len = PFKEY_UNIT64(tlen);
+
+	__ipsec_errcode = EIPSEC_NO_ERROR;
+
+	return pbuf;
+}
+
+ipsec_policy_t
+ipsec_set_policy(msg, msglen)
+	__ipsec_const char *msg;
+	int msglen;
+{
+	caddr_t policy;
+
+	policy = policy_parse(msg, msglen);
+	if (policy == NULL) {
+		if (__ipsec_errcode == EIPSEC_NO_ERROR)
+			__ipsec_errcode = EIPSEC_INVAL_ARGUMENT;
+		return NULL;
+	}
+
+	__ipsec_errcode = EIPSEC_NO_ERROR;
+	return policy;
+}
diff --git a/src/libipsec/policy_token.c b/src/libipsec/policy_token.c
new file mode 100644
index 0000000..608ede1
--- /dev/null
+++ b/src/libipsec/policy_token.c
@@ -0,0 +1,2079 @@
+#line 2 "policy_token.c"
+
+#line 4 "policy_token.c"
+
+#define  YY_INT_ALIGNED short int
+
+/* A lexical scanner generated by flex */
+
+#define yy_create_buffer __libipsec_create_buffer
+#define yy_delete_buffer __libipsec_delete_buffer
+#define yy_flex_debug __libipsec_flex_debug
+#define yy_init_buffer __libipsec_init_buffer
+#define yy_flush_buffer __libipsec_flush_buffer
+#define yy_load_buffer_state __libipsec_load_buffer_state
+#define yy_switch_to_buffer __libipsec_switch_to_buffer
+#define yyin __libipsecin
+#define yyleng __libipsecleng
+#define yylex __libipseclex
+#define yylineno __libipseclineno
+#define yyout __libipsecout
+#define yyrestart __libipsecrestart
+#define yytext __libipsectext
+#define yywrap __libipsecwrap
+#define yyalloc __libipsecalloc
+#define yyrealloc __libipsecrealloc
+#define yyfree __libipsecfree
+
+#define FLEX_SCANNER
+#define YY_FLEX_MAJOR_VERSION 2
+#define YY_FLEX_MINOR_VERSION 5
+#define YY_FLEX_SUBMINOR_VERSION 35
+#if YY_FLEX_SUBMINOR_VERSION > 0
+#define FLEX_BETA
+#endif
+
+/* First, we deal with  platform-specific or compiler-specific issues. */
+
+/* begin standard C headers. */
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <stdlib.h>
+
+/* end standard C headers. */
+
+/* flex integer type definitions */
+
+#ifndef FLEXINT_H
+#define FLEXINT_H
+
+/* C99 systems have <inttypes.h>. Non-C99 systems may or may not. */
+
+#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
+
+/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h,
+ * if you want the limit (max/min) macros for int types. 
+ */
+#ifndef __STDC_LIMIT_MACROS
+#define __STDC_LIMIT_MACROS 1
+#endif
+
+#include <inttypes.h>
+typedef int8_t flex_int8_t;
+typedef uint8_t flex_uint8_t;
+typedef int16_t flex_int16_t;
+typedef uint16_t flex_uint16_t;
+typedef int32_t flex_int32_t;
+typedef uint32_t flex_uint32_t;
+#else
+typedef signed char flex_int8_t;
+typedef short int flex_int16_t;
+typedef int flex_int32_t;
+typedef unsigned char flex_uint8_t; 
+typedef unsigned short int flex_uint16_t;
+typedef unsigned int flex_uint32_t;
+
+/* Limits of integral types. */
+#ifndef INT8_MIN
+#define INT8_MIN               (-128)
+#endif
+#ifndef INT16_MIN
+#define INT16_MIN              (-32767-1)
+#endif
+#ifndef INT32_MIN
+#define INT32_MIN              (-2147483647-1)
+#endif
+#ifndef INT8_MAX
+#define INT8_MAX               (127)
+#endif
+#ifndef INT16_MAX
+#define INT16_MAX              (32767)
+#endif
+#ifndef INT32_MAX
+#define INT32_MAX              (2147483647)
+#endif
+#ifndef UINT8_MAX
+#define UINT8_MAX              (255U)
+#endif
+#ifndef UINT16_MAX
+#define UINT16_MAX             (65535U)
+#endif
+#ifndef UINT32_MAX
+#define UINT32_MAX             (4294967295U)
+#endif
+
+#endif /* ! C99 */
+
+#endif /* ! FLEXINT_H */
+
+#ifdef __cplusplus
+
+/* The "const" storage-class-modifier is valid. */
+#define YY_USE_CONST
+
+#else	/* ! __cplusplus */
+
+/* C99 requires __STDC__ to be defined as 1. */
+#if defined (__STDC__)
+
+#define YY_USE_CONST
+
+#endif	/* defined (__STDC__) */
+#endif	/* ! __cplusplus */
+
+#ifdef YY_USE_CONST
+#define yyconst const
+#else
+#define yyconst
+#endif
+
+/* Returned upon end-of-file. */
+#define YY_NULL 0
+
+/* Promotes a possibly negative, possibly signed char to an unsigned
+ * integer for use as an array index.  If the signed char is negative,
+ * we want to instead treat it as an 8-bit unsigned char, hence the
+ * double cast.
+ */
+#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c)
+
+/* Enter a start condition.  This macro really ought to take a parameter,
+ * but we do it the disgusting crufty way forced on us by the ()-less
+ * definition of BEGIN.
+ */
+#define BEGIN (yy_start) = 1 + 2 *
+
+/* Translate the current start state into a value that can be later handed
+ * to BEGIN to return to the state.  The YYSTATE alias is for lex
+ * compatibility.
+ */
+#define YY_START (((yy_start) - 1) / 2)
+#define YYSTATE YY_START
+
+/* Action number for EOF rule of a given start state. */
+#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1)
+
+/* Special action meaning "start processing a new file". */
+#define YY_NEW_FILE __libipsecrestart(__libipsecin  )
+
+#define YY_END_OF_BUFFER_CHAR 0
+
+/* Size of default input buffer. */
+#ifndef YY_BUF_SIZE
+#define YY_BUF_SIZE 16384
+#endif
+
+/* The state buf must be large enough to hold one state per character in the main buffer.
+ */
+#define YY_STATE_BUF_SIZE   ((YY_BUF_SIZE + 2) * sizeof(yy_state_type))
+
+#ifndef YY_TYPEDEF_YY_BUFFER_STATE
+#define YY_TYPEDEF_YY_BUFFER_STATE
+typedef struct yy_buffer_state *YY_BUFFER_STATE;
+#endif
+
+extern int __libipsecleng;
+
+extern FILE *__libipsecin, *__libipsecout;
+
+#define EOB_ACT_CONTINUE_SCAN 0
+#define EOB_ACT_END_OF_FILE 1
+#define EOB_ACT_LAST_MATCH 2
+
+    #define YY_LESS_LINENO(n)
+    
+/* Return all but the first "n" matched characters back to the input stream. */
+#define yyless(n) \
+	do \
+		{ \
+		/* Undo effects of setting up __libipsectext. */ \
+        int yyless_macro_arg = (n); \
+        YY_LESS_LINENO(yyless_macro_arg);\
+		*yy_cp = (yy_hold_char); \
+		YY_RESTORE_YY_MORE_OFFSET \
+		(yy_c_buf_p) = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \
+		YY_DO_BEFORE_ACTION; /* set up __libipsectext again */ \
+		} \
+	while ( 0 )
+
+#define unput(c) yyunput( c, (yytext_ptr)  )
+
+#ifndef YY_TYPEDEF_YY_SIZE_T
+#define YY_TYPEDEF_YY_SIZE_T
+typedef size_t yy_size_t;
+#endif
+
+#ifndef YY_STRUCT_YY_BUFFER_STATE
+#define YY_STRUCT_YY_BUFFER_STATE
+struct yy_buffer_state
+	{
+	FILE *yy_input_file;
+
+	char *yy_ch_buf;		/* input buffer */
+	char *yy_buf_pos;		/* current position in input buffer */
+
+	/* Size of input buffer in bytes, not including room for EOB
+	 * characters.
+	 */
+	yy_size_t yy_buf_size;
+
+	/* Number of characters read into yy_ch_buf, not including EOB
+	 * characters.
+	 */
+	int yy_n_chars;
+
+	/* Whether we "own" the buffer - i.e., we know we created it,
+	 * and can realloc() it to grow it, and should free() it to
+	 * delete it.
+	 */
+	int yy_is_our_buffer;
+
+	/* Whether this is an "interactive" input source; if so, and
+	 * if we're using stdio for input, then we want to use getc()
+	 * instead of fread(), to make sure we stop fetching input after
+	 * each newline.
+	 */
+	int yy_is_interactive;
+
+	/* Whether we're considered to be at the beginning of a line.
+	 * If so, '^' rules will be active on the next match, otherwise
+	 * not.
+	 */
+	int yy_at_bol;
+
+    int yy_bs_lineno; /**< The line count. */
+    int yy_bs_column; /**< The column count. */
+    
+	/* Whether to try to fill the input buffer when we reach the
+	 * end of it.
+	 */
+	int yy_fill_buffer;
+
+	int yy_buffer_status;
+
+#define YY_BUFFER_NEW 0
+#define YY_BUFFER_NORMAL 1
+	/* When an EOF's been seen but there's still some text to process
+	 * then we mark the buffer as YY_EOF_PENDING, to indicate that we
+	 * shouldn't try reading from the input source any more.  We might
+	 * still have a bunch of tokens to match, though, because of
+	 * possible backing-up.
+	 *
+	 * When we actually see the EOF, we change the status to "new"
+	 * (via __libipsecrestart()), so that the user can continue scanning by
+	 * just pointing __libipsecin at a new input file.
+	 */
+#define YY_BUFFER_EOF_PENDING 2
+
+	};
+#endif /* !YY_STRUCT_YY_BUFFER_STATE */
+
+/* Stack of input buffers. */
+static size_t yy_buffer_stack_top = 0; /**< index of top of stack. */
+static size_t yy_buffer_stack_max = 0; /**< capacity of stack. */
+static YY_BUFFER_STATE * yy_buffer_stack = 0; /**< Stack as an array. */
+
+/* We provide macros for accessing buffer states in case in the
+ * future we want to put the buffer states in a more general
+ * "scanner state".
+ *
+ * Returns the top of the stack, or NULL.
+ */
+#define YY_CURRENT_BUFFER ( (yy_buffer_stack) \
+                          ? (yy_buffer_stack)[(yy_buffer_stack_top)] \
+                          : NULL)
+
+/* Same as previous macro, but useful when we know that the buffer stack is not
+ * NULL or when we need an lvalue. For internal use only.
+ */
+#define YY_CURRENT_BUFFER_LVALUE (yy_buffer_stack)[(yy_buffer_stack_top)]
+
+/* yy_hold_char holds the character lost when __libipsectext is formed. */
+static char yy_hold_char;
+static int yy_n_chars;		/* number of characters read into yy_ch_buf */
+int __libipsecleng;
+
+/* Points to current character in buffer. */
+static char *yy_c_buf_p = (char *) 0;
+static int yy_init = 0;		/* whether we need to initialize */
+static int yy_start = 0;	/* start state number */
+
+/* Flag which is used to allow __libipsecwrap()'s to do buffer switches
+ * instead of setting up a fresh __libipsecin.  A bit of a hack ...
+ */
+static int yy_did_buffer_switch_on_eof;
+
+void __libipsecrestart (FILE *input_file  );
+void __libipsec_switch_to_buffer (YY_BUFFER_STATE new_buffer  );
+YY_BUFFER_STATE __libipsec_create_buffer (FILE *file,int size  );
+void __libipsec_delete_buffer (YY_BUFFER_STATE b  );
+void __libipsec_flush_buffer (YY_BUFFER_STATE b  );
+void __libipsecpush_buffer_state (YY_BUFFER_STATE new_buffer  );
+void __libipsecpop_buffer_state (void );
+
+static void __libipsecensure_buffer_stack (void );
+static void __libipsec_load_buffer_state (void );
+static void __libipsec_init_buffer (YY_BUFFER_STATE b,FILE *file  );
+
+#define YY_FLUSH_BUFFER __libipsec_flush_buffer(YY_CURRENT_BUFFER )
+
+YY_BUFFER_STATE __libipsec_scan_buffer (char *base,yy_size_t size  );
+YY_BUFFER_STATE __libipsec_scan_string (yyconst char *yy_str  );
+YY_BUFFER_STATE __libipsec_scan_bytes (yyconst char *bytes,int len  );
+
+void *__libipsecalloc (yy_size_t  );
+void *__libipsecrealloc (void *,yy_size_t  );
+void __libipsecfree (void *  );
+
+#define yy_new_buffer __libipsec_create_buffer
+
+#define yy_set_interactive(is_interactive) \
+	{ \
+	if ( ! YY_CURRENT_BUFFER ){ \
+        __libipsecensure_buffer_stack (); \
+		YY_CURRENT_BUFFER_LVALUE =    \
+            __libipsec_create_buffer(__libipsecin,YY_BUF_SIZE ); \
+	} \
+	YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \
+	}
+
+#define yy_set_bol(at_bol) \
+	{ \
+	if ( ! YY_CURRENT_BUFFER ){\
+        __libipsecensure_buffer_stack (); \
+		YY_CURRENT_BUFFER_LVALUE =    \
+            __libipsec_create_buffer(__libipsecin,YY_BUF_SIZE ); \
+	} \
+	YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \
+	}
+
+#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol)
+
+/* Begin user sect3 */
+
+#define __libipsecwrap(n) 1
+#define YY_SKIP_YYWRAP
+
+typedef unsigned char YY_CHAR;
+
+FILE *__libipsecin = (FILE *) 0, *__libipsecout = (FILE *) 0;
+
+typedef int yy_state_type;
+
+extern int __libipseclineno;
+
+int __libipseclineno = 1;
+
+extern char *__libipsectext;
+#define yytext_ptr __libipsectext
+
+static yy_state_type yy_get_previous_state (void );
+static yy_state_type yy_try_NUL_trans (yy_state_type current_state  );
+static int yy_get_next_buffer (void );
+static void yy_fatal_error (yyconst char msg[]  );
+
+/* Done after the current pattern has been matched and before the
+ * corresponding action - sets up __libipsectext.
+ */
+#define YY_DO_BEFORE_ACTION \
+	(yytext_ptr) = yy_bp; \
+	__libipsecleng = (size_t) (yy_cp - yy_bp); \
+	(yy_hold_char) = *yy_cp; \
+	*yy_cp = '\0'; \
+	(yy_c_buf_p) = yy_cp;
+
+#define YY_NUM_RULES 34
+#define YY_END_OF_BUFFER 35
+/* This struct is not used in this scanner,
+   but its presence is necessary. */
+struct yy_trans_info
+	{
+	flex_int32_t yy_verify;
+	flex_int32_t yy_nxt;
+	};
+static yyconst flex_int16_t yy_accept[121] =
+    {   0,
+        0,    0,   35,   34,   32,   33,    9,   30,   29,   28,
+       10,   34,   29,   29,   29,   29,   29,   29,   29,   29,
+       29,   29,   29,   29,   29,   29,   29,   32,    0,   29,
+       10,    0,   17,   29,   29,   29,   29,   29,   29,   29,
+       29,    1,   29,   29,   21,   29,   29,   29,   29,   29,
+       29,   29,   29,   29,   31,   22,   29,    7,   29,   29,
+       16,    3,   29,   29,   29,    6,   29,    2,   29,   29,
+       29,   29,   29,   24,   29,   29,   29,   29,    8,   29,
+       29,   12,    5,   29,   29,   29,   29,   29,   29,   29,
+       29,   29,   13,   29,   29,   29,   29,   29,   14,   29,
+
+       29,   29,   18,   29,   29,   29,   20,   27,   23,   11,
+       15,   29,   25,   29,   29,    4,   29,   26,   19,    0
+    } ;
+
+static yyconst flex_int32_t yy_ec[256] =
+    {   0,
+        1,    1,    1,    1,    1,    1,    1,    1,    2,    3,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    2,    1,    1,    1,    1,    4,    1,    1,    1,
+        1,    1,    5,    1,    6,    7,    8,    9,    9,    9,
+        9,    9,    9,    9,    9,    9,    9,   10,    1,    1,
+        1,    1,    1,    1,   11,   11,   11,   11,   11,   11,
+       11,   11,   11,   11,   11,   11,   11,   11,   11,   11,
+       11,   11,   11,   11,   11,   11,   11,   11,   11,   11,
+       12,    1,   13,    1,    7,    1,   14,   15,   16,   17,
+
+       18,   19,   20,   21,   22,   11,   11,   23,   24,   25,
+       26,   27,   28,   29,   30,   31,   32,   11,   33,   11,
+       34,   11,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1
+    } ;
+
+static yyconst flex_int32_t yy_meta[35] =
+    {   0,
+        1,    1,    1,    2,    1,    1,    2,    1,    3,    2,
+        3,    1,    1,    3,    3,    3,    3,    3,    3,    3,
+        3,    3,    3,    3,    3,    3,    3,    3,    3,    3,
+        3,    3,    3,    3
+    } ;
+
+static yyconst flex_int16_t yy_base[123] =
+    {   0,
+        0,    0,  235,  236,  232,  236,  236,  236,  229,  236,
+       31,  223,   32,   33,   34,   35,   37,   39,   41,   38,
+       40,   43,   42,   44,   45,   46,   47,  229,    0,  226,
+       50,   67,  225,   51,   67,   77,   58,   75,   78,   80,
+       79,  224,   82,   83,  223,   85,   86,   87,   91,   88,
+       89,   96,   97,    0,  236,  222,   99,  107,  104,  100,
+      221,  220,  103,  118,  119,  219,  121,  218,  122,  123,
+      124,  126,  128,  217,  127,  129,  131,  130,  216,  134,
+      136,  215,  137,  132,  138,  142,  139,  143,  146,  149,
+      155,  159,  214,  160,  161,  166,  168,  163,  213,  170,
+
+      171,  172,  212,  173,  176,  179,  211,  185,  206,  204,
+      202,  175,  196,  183,  188,  195,  180,  198,  194,  236,
+      211,  193
+    } ;
+
+static yyconst flex_int16_t yy_def[123] =
+    {   0,
+      120,    1,  120,  120,  120,  120,  120,  120,  121,  120,
+      121,  120,  121,  121,  121,  121,  121,  121,  121,  121,
+      121,  121,  121,  121,  121,  121,  121,  120,  122,  121,
+      121,  120,  121,  121,  121,  121,  121,  121,  121,  121,
+      121,  121,  121,  121,  121,  121,  121,  121,  121,  121,
+      121,  121,  121,  122,  120,  121,  121,  121,  121,  121,
+      121,  121,  121,  121,  121,  121,  121,  121,  121,  121,
+      121,  121,  121,  121,  121,  121,  121,  121,  121,  121,
+      121,  121,  121,  121,  121,  121,  121,  121,  121,  121,
+      121,  121,  121,  121,  121,  121,  121,  121,  121,  121,
+
+      121,  121,  121,  121,  121,  121,  121,  121,  121,  121,
+      121,  121,  121,  121,  121,  121,  121,  121,  121,    0,
+      120,  120
+    } ;
+
+static yyconst flex_int16_t yy_nxt[271] =
+    {   0,
+        4,    5,    6,    4,    7,    8,    9,   10,   11,    9,
+        9,   12,    4,   13,   14,    9,   15,   16,   17,    9,
+       18,   19,   20,   21,   22,   23,   24,    9,   25,    9,
+       26,   27,    9,    9,   29,   29,   29,   29,   29,   31,
+       29,   29,   29,   29,   29,   29,   29,   29,   29,   29,
+       29,   36,   33,   29,   29,   37,   34,   45,   31,   38,
+       41,   29,   49,   44,   39,   42,   35,   43,   46,   40,
+       29,   52,   48,   47,   50,   32,   53,   51,   29,   55,
+       29,   29,   29,   29,   56,   29,   29,   59,   29,   29,
+       29,   29,   29,   57,   29,   58,   62,   64,   63,   29,
+
+       29,   71,   29,   29,   61,   60,   29,   29,   69,   67,
+       29,   65,   75,   72,   74,   66,   68,   73,   70,   77,
+       76,   29,   29,   79,   29,   29,   29,   29,   78,   29,
+       29,   29,   29,   29,   29,   29,   81,   29,   82,   29,
+       29,   29,   29,   80,   90,   29,   29,   83,   85,   29,
+       86,   93,   29,   95,   84,   87,   88,   92,   29,   97,
+       89,   91,   29,   29,   29,   94,   29,   96,  100,   29,
+       98,   29,   99,   29,   29,   29,   29,  101,   29,   29,
+      108,  104,   29,   29,  102,  103,   29,  110,   29,  105,
+      107,   29,  106,  113,  115,   54,  118,   29,   29,   29,
+
+      109,   29,  111,  112,  114,   29,  118,   29,  116,   29,
+      119,  117,   30,   30,   29,   29,   29,   29,   29,   29,
+       29,   29,   29,   29,   29,   29,   29,   29,   29,   29,
+       28,   32,   29,   28,  120,    3,  120,  120,  120,  120,
+      120,  120,  120,  120,  120,  120,  120,  120,  120,  120,
+      120,  120,  120,  120,  120,  120,  120,  120,  120,  120,
+      120,  120,  120,  120,  120,  120,  120,  120,  120,  120
+    } ;
+
+static yyconst flex_int16_t yy_chk[271] =
+    {   0,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,   11,   13,   14,   15,   16,   11,
+       17,   20,   18,   21,   19,   23,   22,   24,   25,   26,
+       27,   15,   13,   31,   34,   15,   13,   21,   31,   16,
+       18,   37,   25,   20,   16,   19,   14,   19,   22,   17,
+       35,   27,   24,   23,   26,   32,   27,   26,   38,   32,
+       36,   39,   41,   40,   34,   43,   44,   37,   46,   47,
+       48,   50,   51,   35,   49,   36,   40,   43,   41,   52,
+
+       53,   50,   57,   60,   39,   38,   63,   59,   48,   46,
+       58,   43,   57,   51,   53,   44,   47,   52,   49,   59,
+       58,   64,   65,   63,   67,   69,   70,   71,   60,   72,
+       75,   73,   76,   78,   77,   84,   65,   80,   67,   81,
+       83,   85,   87,   64,   77,   86,   88,   69,   71,   89,
+       72,   81,   90,   84,   70,   73,   75,   80,   91,   86,
+       76,   78,   92,   94,   95,   83,   98,   85,   89,   96,
+       87,   97,   88,  100,  101,  102,  104,   90,  112,  105,
+       98,   94,  106,  117,   91,   92,  114,  101,  108,   95,
+       97,  115,   96,  105,  108,  122,  115,  119,  116,  113,
+
+      100,  118,  102,  104,  106,  111,  118,  110,  112,  109,
+      117,  114,  121,  121,  107,  103,   99,   93,   82,   79,
+       74,   68,   66,   62,   61,   56,   45,   42,   33,   30,
+       28,   12,    9,    5,    3,  120,  120,  120,  120,  120,
+      120,  120,  120,  120,  120,  120,  120,  120,  120,  120,
+      120,  120,  120,  120,  120,  120,  120,  120,  120,  120,
+      120,  120,  120,  120,  120,  120,  120,  120,  120,  120
+    } ;
+
+static yy_state_type yy_last_accepting_state;
+static char *yy_last_accepting_cpos;
+
+extern int __libipsec_flex_debug;
+int __libipsec_flex_debug = 0;
+
+/* The intent behind this definition is that it'll catch
+ * any uses of REJECT which flex missed.
+ */
+#define REJECT reject_used_but_not_detected
+#define yymore() yymore_used_but_not_detected
+#define YY_MORE_ADJ 0
+#define YY_RESTORE_YY_MORE_OFFSET
+char *__libipsectext;
+#line 1 "policy_token.l"
+/*	$NetBSD: policy_token.l,v 1.6.6.1 2007/08/01 11:52:19 vanhu Exp $	*/
+/* Id: policy_token.l,v 1.12 2005/05/05 12:32:18 manubsd Exp */
+/*
+ * Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#line 35 "policy_token.l"
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <net/pfkeyv2.h>
+#include <netinet/in.h>
+#include PATH_IPSEC_H
+
+#include <stdlib.h>
+#include <limits.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include "libpfkey.h"
+
+#if !defined(__NetBSD__) && !defined(__FreeBSD__) && !defined(__linux__)  && \
+!defined(__APPLE__) && !defined(__MACH__)
+#include "y.tab.h"
+#else
+#include "policy_parse.h"
+#endif
+#define yylval __libipseclval	/* XXX */
+
+int __libipseclex __P((void));
+/* common section */
+#line 630 "policy_token.c"
+
+#define INITIAL 0
+
+#ifndef YY_NO_UNISTD_H
+/* Special case for "unistd.h", since it is non-ANSI. We include it way
+ * down here because we want the user's section 1 to have been scanned first.
+ * The user has a chance to override it with an option.
+ */
+#include <unistd.h>
+#endif
+
+#ifndef YY_EXTRA_TYPE
+#define YY_EXTRA_TYPE void *
+#endif
+
+static int yy_init_globals (void );
+
+/* Accessor methods to globals.
+   These are made visible to non-reentrant scanners for convenience. */
+
+int __libipseclex_destroy (void );
+
+int __libipsecget_debug (void );
+
+void __libipsecset_debug (int debug_flag  );
+
+YY_EXTRA_TYPE __libipsecget_extra (void );
+
+void __libipsecset_extra (YY_EXTRA_TYPE user_defined  );
+
+FILE *__libipsecget_in (void );
+
+void __libipsecset_in  (FILE * in_str  );
+
+FILE *__libipsecget_out (void );
+
+void __libipsecset_out  (FILE * out_str  );
+
+int __libipsecget_leng (void );
+
+char *__libipsecget_text (void );
+
+int __libipsecget_lineno (void );
+
+void __libipsecset_lineno (int line_number  );
+
+/* Macros after this point can all be overridden by user definitions in
+ * section 1.
+ */
+
+#ifndef YY_SKIP_YYWRAP
+#ifdef __cplusplus
+extern "C" int __libipsecwrap (void );
+#else
+extern int __libipsecwrap (void );
+#endif
+#endif
+
+#ifndef yytext_ptr
+static void yy_flex_strncpy (char *,yyconst char *,int );
+#endif
+
+#ifdef YY_NEED_STRLEN
+static int yy_flex_strlen (yyconst char * );
+#endif
+
+#ifndef YY_NO_INPUT
+
+#ifdef __cplusplus
+static int yyinput (void );
+#else
+static int input (void );
+#endif
+
+#endif
+
+/* Amount of stuff to slurp up with each read. */
+#ifndef YY_READ_BUF_SIZE
+#define YY_READ_BUF_SIZE 8192
+#endif
+
+/* Copy whatever the last rule matched to the standard output. */
+#ifndef ECHO
+/* This used to be an fputs(), but since the string might contain NUL's,
+ * we now use fwrite().
+ */
+#define ECHO fwrite( __libipsectext, __libipsecleng, 1, __libipsecout )
+#endif
+
+/* Gets input and stuffs it into "buf".  number of characters read, or YY_NULL,
+ * is returned in "result".
+ */
+#ifndef YY_INPUT
+#define YY_INPUT(buf,result,max_size) \
+	if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \
+		{ \
+		int c = '*'; \
+		size_t n; \
+		for ( n = 0; n < max_size && \
+			     (c = getc( __libipsecin )) != EOF && c != '\n'; ++n ) \
+			buf[n] = (char) c; \
+		if ( c == '\n' ) \
+			buf[n++] = (char) c; \
+		if ( c == EOF && ferror( __libipsecin ) ) \
+			YY_FATAL_ERROR( "input in flex scanner failed" ); \
+		result = n; \
+		} \
+	else \
+		{ \
+		errno=0; \
+		while ( (result = fread(buf, 1, max_size, __libipsecin))==0 && ferror(__libipsecin)) \
+			{ \
+			if( errno != EINTR) \
+				{ \
+				YY_FATAL_ERROR( "input in flex scanner failed" ); \
+				break; \
+				} \
+			errno=0; \
+			clearerr(__libipsecin); \
+			} \
+		}\
+\
+
+#endif
+
+/* No semi-colon after return; correct usage is to write "yyterminate();" -
+ * we don't want an extra ';' after the "return" because that will cause
+ * some compilers to complain about unreachable statements.
+ */
+#ifndef yyterminate
+#define yyterminate() return YY_NULL
+#endif
+
+/* Number of entries by which start-condition stack grows. */
+#ifndef YY_START_STACK_INCR
+#define YY_START_STACK_INCR 25
+#endif
+
+/* Report a fatal error. */
+#ifndef YY_FATAL_ERROR
+#define YY_FATAL_ERROR(msg) yy_fatal_error( msg )
+#endif
+
+/* end tables serialization structures and prototypes */
+
+/* Default declaration of generated scanner - a define so the user can
+ * easily add parameters.
+ */
+#ifndef YY_DECL
+#define YY_DECL_IS_OURS 1
+
+extern int __libipseclex (void);
+
+#define YY_DECL int __libipseclex (void)
+#endif /* !YY_DECL */
+
+/* Code executed at the beginning of each rule, after __libipsectext and __libipsecleng
+ * have been set up.
+ */
+#ifndef YY_USER_ACTION
+#define YY_USER_ACTION
+#endif
+
+/* Code executed at the end of each rule. */
+#ifndef YY_BREAK
+#define YY_BREAK break;
+#endif
+
+#define YY_RULE_SETUP \
+	YY_USER_ACTION
+
+/** The main scanner function which does all the work.
+ */
+YY_DECL
+{
+	register yy_state_type yy_current_state;
+	register char *yy_cp, *yy_bp;
+	register int yy_act;
+    
+#line 97 "policy_token.l"
+
+
+#line 813 "policy_token.c"
+
+	if ( !(yy_init) )
+		{
+		(yy_init) = 1;
+
+#ifdef YY_USER_INIT
+		YY_USER_INIT;
+#endif
+
+		if ( ! (yy_start) )
+			(yy_start) = 1;	/* first start state */
+
+		if ( ! __libipsecin )
+			__libipsecin = stdin;
+
+		if ( ! __libipsecout )
+			__libipsecout = stdout;
+
+		if ( ! YY_CURRENT_BUFFER ) {
+			__libipsecensure_buffer_stack ();
+			YY_CURRENT_BUFFER_LVALUE =
+				__libipsec_create_buffer(__libipsecin,YY_BUF_SIZE );
+		}
+
+		__libipsec_load_buffer_state( );
+		}
+
+	while ( 1 )		/* loops until end-of-file is reached */
+		{
+		yy_cp = (yy_c_buf_p);
+
+		/* Support of __libipsectext. */
+		*yy_cp = (yy_hold_char);
+
+		/* yy_bp points to the position in yy_ch_buf of the start of
+		 * the current run.
+		 */
+		yy_bp = yy_cp;
+
+		yy_current_state = (yy_start);
+yy_match:
+		do
+			{
+			register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)];
+			if ( yy_accept[yy_current_state] )
+				{
+				(yy_last_accepting_state) = yy_current_state;
+				(yy_last_accepting_cpos) = yy_cp;
+				}
+			while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+				{
+				yy_current_state = (int) yy_def[yy_current_state];
+				if ( yy_current_state >= 121 )
+					yy_c = yy_meta[(unsigned int) yy_c];
+				}
+			yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+			++yy_cp;
+			}
+		while ( yy_base[yy_current_state] != 236 );
+
+yy_find_action:
+		yy_act = yy_accept[yy_current_state];
+		if ( yy_act == 0 )
+			{ /* have to back up */
+			yy_cp = (yy_last_accepting_cpos);
+			yy_current_state = (yy_last_accepting_state);
+			yy_act = yy_accept[yy_current_state];
+			}
+
+		YY_DO_BEFORE_ACTION;
+
+do_action:	/* This label is used only to access EOF actions. */
+
+		switch ( yy_act )
+	{ /* beginning of action switch */
+			case 0: /* must back up */
+			/* undo the effects of YY_DO_BEFORE_ACTION */
+			*yy_cp = (yy_hold_char);
+			yy_cp = (yy_last_accepting_cpos);
+			yy_current_state = (yy_last_accepting_state);
+			goto yy_find_action;
+
+case 1:
+YY_RULE_SETUP
+#line 99 "policy_token.l"
+{ yylval.num = IPSEC_DIR_INBOUND; return(DIR); }
+	YY_BREAK
+case 2:
+YY_RULE_SETUP
+#line 100 "policy_token.l"
+{ yylval.num = IPSEC_DIR_OUTBOUND; return(DIR); }
+	YY_BREAK
+case 3:
+YY_RULE_SETUP
+#line 101 "policy_token.l"
+{ 
+#ifdef HAVE_POLICY_FWD
+		  yylval.num = IPSEC_DIR_FWD; return(DIR); 
+#else
+		  yylval.num = IPSEC_DIR_INBOUND; return(DIR); 
+#endif
+		}
+	YY_BREAK
+case 4:
+YY_RULE_SETUP
+#line 109 "policy_token.l"
+{ return(PRIORITY); }
+	YY_BREAK
+case 5:
+YY_RULE_SETUP
+#line 110 "policy_token.l"
+{ return(PRIORITY); }
+	YY_BREAK
+case 6:
+YY_RULE_SETUP
+#line 111 "policy_token.l"
+{ yylval.num32 = PRIORITY_LOW; return(PRIO_BASE); }
+	YY_BREAK
+case 7:
+YY_RULE_SETUP
+#line 112 "policy_token.l"
+{ yylval.num32 = PRIORITY_DEFAULT; return(PRIO_BASE); }
+	YY_BREAK
+case 8:
+YY_RULE_SETUP
+#line 113 "policy_token.l"
+{ yylval.num32 = PRIORITY_HIGH; return(PRIO_BASE); }
+	YY_BREAK
+case 9:
+YY_RULE_SETUP
+#line 114 "policy_token.l"
+{ return(PLUS); }
+	YY_BREAK
+case 10:
+YY_RULE_SETUP
+#line 115 "policy_token.l"
+{
+			yylval.val.len = strlen(__libipsectext);
+			yylval.val.buf = __libipsectext;
+			return(PRIO_OFFSET);
+}
+	YY_BREAK
+case 11:
+YY_RULE_SETUP
+#line 121 "policy_token.l"
+{ yylval.num = IPSEC_POLICY_DISCARD; return(ACTION); }
+	YY_BREAK
+case 12:
+YY_RULE_SETUP
+#line 122 "policy_token.l"
+{ yylval.num = IPSEC_POLICY_NONE; return(ACTION); }
+	YY_BREAK
+case 13:
+YY_RULE_SETUP
+#line 123 "policy_token.l"
+{ yylval.num = IPSEC_POLICY_IPSEC; return(ACTION); }
+	YY_BREAK
+case 14:
+YY_RULE_SETUP
+#line 124 "policy_token.l"
+{ yylval.num = IPSEC_POLICY_BYPASS; return(ACTION); }
+	YY_BREAK
+case 15:
+YY_RULE_SETUP
+#line 125 "policy_token.l"
+{ yylval.num = IPSEC_POLICY_ENTRUST; return(ACTION); }
+	YY_BREAK
+case 16:
+YY_RULE_SETUP
+#line 127 "policy_token.l"
+{ yylval.num = IPPROTO_ESP; return(PROTOCOL); }
+	YY_BREAK
+case 17:
+YY_RULE_SETUP
+#line 128 "policy_token.l"
+{ yylval.num = IPPROTO_AH; return(PROTOCOL); }
+	YY_BREAK
+case 18:
+YY_RULE_SETUP
+#line 129 "policy_token.l"
+{ yylval.num = IPPROTO_IPCOMP; return(PROTOCOL); }
+	YY_BREAK
+case 19:
+YY_RULE_SETUP
+#line 131 "policy_token.l"
+{ yylval.num = IPSEC_MODE_TRANSPORT; return(MODE); }
+	YY_BREAK
+case 20:
+YY_RULE_SETUP
+#line 132 "policy_token.l"
+{ yylval.num = IPSEC_MODE_TUNNEL; return(MODE); }
+	YY_BREAK
+case 21:
+YY_RULE_SETUP
+#line 134 "policy_token.l"
+{ return(ME); }
+	YY_BREAK
+case 22:
+YY_RULE_SETUP
+#line 135 "policy_token.l"
+{ return(ANY); }
+	YY_BREAK
+case 23:
+YY_RULE_SETUP
+#line 137 "policy_token.l"
+{ yylval.num = IPSEC_LEVEL_DEFAULT; return(LEVEL); }
+	YY_BREAK
+case 24:
+YY_RULE_SETUP
+#line 138 "policy_token.l"
+{ yylval.num = IPSEC_LEVEL_USE; return(LEVEL); }
+	YY_BREAK
+case 25:
+YY_RULE_SETUP
+#line 139 "policy_token.l"
+{ yylval.num = IPSEC_LEVEL_REQUIRE; return(LEVEL); }
+	YY_BREAK
+case 26:
+YY_RULE_SETUP
+#line 140 "policy_token.l"
+{
+			yylval.val.len = strlen(__libipsectext + 7);
+			yylval.val.buf = __libipsectext + 7;
+			return(LEVEL_SPECIFY);
+		}
+	YY_BREAK
+case 27:
+YY_RULE_SETUP
+#line 145 "policy_token.l"
+{ yylval.num = IPSEC_LEVEL_UNIQUE; return(LEVEL); }
+	YY_BREAK
+case 28:
+YY_RULE_SETUP
+#line 146 "policy_token.l"
+{ return(SLASH); }
+	YY_BREAK
+case 29:
+YY_RULE_SETUP
+#line 148 "policy_token.l"
+{
+			yylval.val.len = strlen(__libipsectext);
+			yylval.val.buf = __libipsectext;
+			return(IPADDRESS);
+		}
+	YY_BREAK
+case 30:
+YY_RULE_SETUP
+#line 154 "policy_token.l"
+{ return(HYPHEN); }
+	YY_BREAK
+case 31:
+YY_RULE_SETUP
+#line 156 "policy_token.l"
+{
+			/* Remove leading '[' and trailing ']' */
+			yylval.val.buf = __libipsectext + 1;
+			yylval.val.len = strlen(__libipsectext) - 2;
+
+			return(PORT);
+		}
+	YY_BREAK
+case 32:
+YY_RULE_SETUP
+#line 164 "policy_token.l"
+{ ; }
+	YY_BREAK
+case 33:
+/* rule 33 can match eol */
+YY_RULE_SETUP
+#line 165 "policy_token.l"
+{ ; }
+	YY_BREAK
+case 34:
+YY_RULE_SETUP
+#line 167 "policy_token.l"
+ECHO;
+	YY_BREAK
+#line 1091 "policy_token.c"
+case YY_STATE_EOF(INITIAL):
+	yyterminate();
+
+	case YY_END_OF_BUFFER:
+		{
+		/* Amount of text matched not including the EOB char. */
+		int yy_amount_of_matched_text = (int) (yy_cp - (yytext_ptr)) - 1;
+
+		/* Undo the effects of YY_DO_BEFORE_ACTION. */
+		*yy_cp = (yy_hold_char);
+		YY_RESTORE_YY_MORE_OFFSET
+
+		if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW )
+			{
+			/* We're scanning a new file or input source.  It's
+			 * possible that this happened because the user
+			 * just pointed __libipsecin at a new source and called
+			 * __libipseclex().  If so, then we have to assure
+			 * consistency between YY_CURRENT_BUFFER and our
+			 * globals.  Here is the right place to do so, because
+			 * this is the first action (other than possibly a
+			 * back-up) that will match for the new input source.
+			 */
+			(yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
+			YY_CURRENT_BUFFER_LVALUE->yy_input_file = __libipsecin;
+			YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL;
+			}
+
+		/* Note that here we test for yy_c_buf_p "<=" to the position
+		 * of the first EOB in the buffer, since yy_c_buf_p will
+		 * already have been incremented past the NUL character
+		 * (since all states make transitions on EOB to the
+		 * end-of-buffer state).  Contrast this with the test
+		 * in input().
+		 */
+		if ( (yy_c_buf_p) <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] )
+			{ /* This was really a NUL. */
+			yy_state_type yy_next_state;
+
+			(yy_c_buf_p) = (yytext_ptr) + yy_amount_of_matched_text;
+
+			yy_current_state = yy_get_previous_state(  );
+
+			/* Okay, we're now positioned to make the NUL
+			 * transition.  We couldn't have
+			 * yy_get_previous_state() go ahead and do it
+			 * for us because it doesn't know how to deal
+			 * with the possibility of jamming (and we don't
+			 * want to build jamming into it because then it
+			 * will run more slowly).
+			 */
+
+			yy_next_state = yy_try_NUL_trans( yy_current_state );
+
+			yy_bp = (yytext_ptr) + YY_MORE_ADJ;
+
+			if ( yy_next_state )
+				{
+				/* Consume the NUL. */
+				yy_cp = ++(yy_c_buf_p);
+				yy_current_state = yy_next_state;
+				goto yy_match;
+				}
+
+			else
+				{
+				yy_cp = (yy_c_buf_p);
+				goto yy_find_action;
+				}
+			}
+
+		else switch ( yy_get_next_buffer(  ) )
+			{
+			case EOB_ACT_END_OF_FILE:
+				{
+				(yy_did_buffer_switch_on_eof) = 0;
+
+				if ( __libipsecwrap( ) )
+					{
+					/* Note: because we've taken care in
+					 * yy_get_next_buffer() to have set up
+					 * __libipsectext, we can now set up
+					 * yy_c_buf_p so that if some total
+					 * hoser (like flex itself) wants to
+					 * call the scanner after we return the
+					 * YY_NULL, it'll still work - another
+					 * YY_NULL will get returned.
+					 */
+					(yy_c_buf_p) = (yytext_ptr) + YY_MORE_ADJ;
+
+					yy_act = YY_STATE_EOF(YY_START);
+					goto do_action;
+					}
+
+				else
+					{
+					if ( ! (yy_did_buffer_switch_on_eof) )
+						YY_NEW_FILE;
+					}
+				break;
+				}
+
+			case EOB_ACT_CONTINUE_SCAN:
+				(yy_c_buf_p) =
+					(yytext_ptr) + yy_amount_of_matched_text;
+
+				yy_current_state = yy_get_previous_state(  );
+
+				yy_cp = (yy_c_buf_p);
+				yy_bp = (yytext_ptr) + YY_MORE_ADJ;
+				goto yy_match;
+
+			case EOB_ACT_LAST_MATCH:
+				(yy_c_buf_p) =
+				&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)];
+
+				yy_current_state = yy_get_previous_state(  );
+
+				yy_cp = (yy_c_buf_p);
+				yy_bp = (yytext_ptr) + YY_MORE_ADJ;
+				goto yy_find_action;
+			}
+		break;
+		}
+
+	default:
+		YY_FATAL_ERROR(
+			"fatal flex scanner internal error--no action found" );
+	} /* end of action switch */
+		} /* end of scanning one token */
+} /* end of __libipseclex */
+
+/* yy_get_next_buffer - try to read in a new buffer
+ *
+ * Returns a code representing an action:
+ *	EOB_ACT_LAST_MATCH -
+ *	EOB_ACT_CONTINUE_SCAN - continue scanning from current position
+ *	EOB_ACT_END_OF_FILE - end of file
+ */
+static int yy_get_next_buffer (void)
+{
+    	register char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf;
+	register char *source = (yytext_ptr);
+	register int number_to_move, i;
+	int ret_val;
+
+	if ( (yy_c_buf_p) > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] )
+		YY_FATAL_ERROR(
+		"fatal flex scanner internal error--end of buffer missed" );
+
+	if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 )
+		{ /* Don't try to fill the buffer, so this is an EOF. */
+		if ( (yy_c_buf_p) - (yytext_ptr) - YY_MORE_ADJ == 1 )
+			{
+			/* We matched a single character, the EOB, so
+			 * treat this as a final EOF.
+			 */
+			return EOB_ACT_END_OF_FILE;
+			}
+
+		else
+			{
+			/* We matched some text prior to the EOB, first
+			 * process it.
+			 */
+			return EOB_ACT_LAST_MATCH;
+			}
+		}
+
+	/* Try to read more data. */
+
+	/* First move last chars to start of buffer. */
+	number_to_move = (int) ((yy_c_buf_p) - (yytext_ptr)) - 1;
+
+	for ( i = 0; i < number_to_move; ++i )
+		*(dest++) = *(source++);
+
+	if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING )
+		/* don't do the read, it's not guaranteed to return an EOF,
+		 * just force an EOF
+		 */
+		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars) = 0;
+
+	else
+		{
+			int num_to_read =
+			YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1;
+
+		while ( num_to_read <= 0 )
+			{ /* Not enough room in the buffer - grow it. */
+
+			/* just a shorter name for the current buffer */
+			YY_BUFFER_STATE b = YY_CURRENT_BUFFER;
+
+			int yy_c_buf_p_offset =
+				(int) ((yy_c_buf_p) - b->yy_ch_buf);
+
+			if ( b->yy_is_our_buffer )
+				{
+				int new_size = b->yy_buf_size * 2;
+
+				if ( new_size <= 0 )
+					b->yy_buf_size += b->yy_buf_size / 8;
+				else
+					b->yy_buf_size *= 2;
+
+				b->yy_ch_buf = (char *)
+					/* Include room in for 2 EOB chars. */
+					__libipsecrealloc((void *) b->yy_ch_buf,b->yy_buf_size + 2  );
+				}
+			else
+				/* Can't grow it, we don't own it. */
+				b->yy_ch_buf = 0;
+
+			if ( ! b->yy_ch_buf )
+				YY_FATAL_ERROR(
+				"fatal error - scanner input buffer overflow" );
+
+			(yy_c_buf_p) = &b->yy_ch_buf[yy_c_buf_p_offset];
+
+			num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size -
+						number_to_move - 1;
+
+			}
+
+		if ( num_to_read > YY_READ_BUF_SIZE )
+			num_to_read = YY_READ_BUF_SIZE;
+
+		/* Read in more data. */
+		YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]),
+			(yy_n_chars), (size_t) num_to_read );
+
+		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
+		}
+
+	if ( (yy_n_chars) == 0 )
+		{
+		if ( number_to_move == YY_MORE_ADJ )
+			{
+			ret_val = EOB_ACT_END_OF_FILE;
+			__libipsecrestart(__libipsecin  );
+			}
+
+		else
+			{
+			ret_val = EOB_ACT_LAST_MATCH;
+			YY_CURRENT_BUFFER_LVALUE->yy_buffer_status =
+				YY_BUFFER_EOF_PENDING;
+			}
+		}
+
+	else
+		ret_val = EOB_ACT_CONTINUE_SCAN;
+
+	if ((yy_size_t) ((yy_n_chars) + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) {
+		/* Extend the array by 50%, plus the number we really need. */
+		yy_size_t new_size = (yy_n_chars) + number_to_move + ((yy_n_chars) >> 1);
+		YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) __libipsecrealloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size  );
+		if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
+			YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" );
+	}
+
+	(yy_n_chars) += number_to_move;
+	YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] = YY_END_OF_BUFFER_CHAR;
+	YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] = YY_END_OF_BUFFER_CHAR;
+
+	(yytext_ptr) = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0];
+
+	return ret_val;
+}
+
+/* yy_get_previous_state - get the state just before the EOB char was reached */
+
+    static yy_state_type yy_get_previous_state (void)
+{
+	register yy_state_type yy_current_state;
+	register char *yy_cp;
+    
+	yy_current_state = (yy_start);
+
+	for ( yy_cp = (yytext_ptr) + YY_MORE_ADJ; yy_cp < (yy_c_buf_p); ++yy_cp )
+		{
+		register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1);
+		if ( yy_accept[yy_current_state] )
+			{
+			(yy_last_accepting_state) = yy_current_state;
+			(yy_last_accepting_cpos) = yy_cp;
+			}
+		while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+			{
+			yy_current_state = (int) yy_def[yy_current_state];
+			if ( yy_current_state >= 121 )
+				yy_c = yy_meta[(unsigned int) yy_c];
+			}
+		yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+		}
+
+	return yy_current_state;
+}
+
+/* yy_try_NUL_trans - try to make a transition on the NUL character
+ *
+ * synopsis
+ *	next_state = yy_try_NUL_trans( current_state );
+ */
+    static yy_state_type yy_try_NUL_trans  (yy_state_type yy_current_state )
+{
+	register int yy_is_jam;
+    	register char *yy_cp = (yy_c_buf_p);
+
+	register YY_CHAR yy_c = 1;
+	if ( yy_accept[yy_current_state] )
+		{
+		(yy_last_accepting_state) = yy_current_state;
+		(yy_last_accepting_cpos) = yy_cp;
+		}
+	while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+		{
+		yy_current_state = (int) yy_def[yy_current_state];
+		if ( yy_current_state >= 121 )
+			yy_c = yy_meta[(unsigned int) yy_c];
+		}
+	yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+	yy_is_jam = (yy_current_state == 120);
+
+	return yy_is_jam ? 0 : yy_current_state;
+}
+
+#ifndef YY_NO_INPUT
+#ifdef __cplusplus
+    static int yyinput (void)
+#else
+    static int input  (void)
+#endif
+
+{
+	int c;
+    
+	*(yy_c_buf_p) = (yy_hold_char);
+
+	if ( *(yy_c_buf_p) == YY_END_OF_BUFFER_CHAR )
+		{
+		/* yy_c_buf_p now points to the character we want to return.
+		 * If this occurs *before* the EOB characters, then it's a
+		 * valid NUL; if not, then we've hit the end of the buffer.
+		 */
+		if ( (yy_c_buf_p) < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] )
+			/* This was really a NUL. */
+			*(yy_c_buf_p) = '\0';
+
+		else
+			{ /* need more input */
+			int offset = (yy_c_buf_p) - (yytext_ptr);
+			++(yy_c_buf_p);
+
+			switch ( yy_get_next_buffer(  ) )
+				{
+				case EOB_ACT_LAST_MATCH:
+					/* This happens because yy_g_n_b()
+					 * sees that we've accumulated a
+					 * token and flags that we need to
+					 * try matching the token before
+					 * proceeding.  But for input(),
+					 * there's no matching to consider.
+					 * So convert the EOB_ACT_LAST_MATCH
+					 * to EOB_ACT_END_OF_FILE.
+					 */
+
+					/* Reset buffer status. */
+					__libipsecrestart(__libipsecin );
+
+					/*FALLTHROUGH*/
+
+				case EOB_ACT_END_OF_FILE:
+					{
+					if ( __libipsecwrap( ) )
+						return EOF;
+
+					if ( ! (yy_did_buffer_switch_on_eof) )
+						YY_NEW_FILE;
+#ifdef __cplusplus
+					return yyinput();
+#else
+					return input();
+#endif
+					}
+
+				case EOB_ACT_CONTINUE_SCAN:
+					(yy_c_buf_p) = (yytext_ptr) + offset;
+					break;
+				}
+			}
+		}
+
+	c = *(unsigned char *) (yy_c_buf_p);	/* cast for 8-bit char's */
+	*(yy_c_buf_p) = '\0';	/* preserve __libipsectext */
+	(yy_hold_char) = *++(yy_c_buf_p);
+
+	return c;
+}
+#endif	/* ifndef YY_NO_INPUT */
+
+/** Immediately switch to a different input stream.
+ * @param input_file A readable stream.
+ * 
+ * @note This function does not reset the start condition to @c INITIAL .
+ */
+    void __libipsecrestart  (FILE * input_file )
+{
+    
+	if ( ! YY_CURRENT_BUFFER ){
+        __libipsecensure_buffer_stack ();
+		YY_CURRENT_BUFFER_LVALUE =
+            __libipsec_create_buffer(__libipsecin,YY_BUF_SIZE );
+	}
+
+	__libipsec_init_buffer(YY_CURRENT_BUFFER,input_file );
+	__libipsec_load_buffer_state( );
+}
+
+/** Switch to a different input buffer.
+ * @param new_buffer The new input buffer.
+ * 
+ */
+    void __libipsec_switch_to_buffer  (YY_BUFFER_STATE  new_buffer )
+{
+    
+	/* TODO. We should be able to replace this entire function body
+	 * with
+	 *		__libipsecpop_buffer_state();
+	 *		__libipsecpush_buffer_state(new_buffer);
+     */
+	__libipsecensure_buffer_stack ();
+	if ( YY_CURRENT_BUFFER == new_buffer )
+		return;
+
+	if ( YY_CURRENT_BUFFER )
+		{
+		/* Flush out information for old buffer. */
+		*(yy_c_buf_p) = (yy_hold_char);
+		YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p);
+		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
+		}
+
+	YY_CURRENT_BUFFER_LVALUE = new_buffer;
+	__libipsec_load_buffer_state( );
+
+	/* We don't actually know whether we did this switch during
+	 * EOF (__libipsecwrap()) processing, but the only time this flag
+	 * is looked at is after __libipsecwrap() is called, so it's safe
+	 * to go ahead and always set it.
+	 */
+	(yy_did_buffer_switch_on_eof) = 1;
+}
+
+static void __libipsec_load_buffer_state  (void)
+{
+    	(yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
+	(yytext_ptr) = (yy_c_buf_p) = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos;
+	__libipsecin = YY_CURRENT_BUFFER_LVALUE->yy_input_file;
+	(yy_hold_char) = *(yy_c_buf_p);
+}
+
+/** Allocate and initialize an input buffer state.
+ * @param file A readable stream.
+ * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE.
+ * 
+ * @return the allocated buffer state.
+ */
+    YY_BUFFER_STATE __libipsec_create_buffer  (FILE * file, int  size )
+{
+	YY_BUFFER_STATE b;
+    
+	b = (YY_BUFFER_STATE) __libipsecalloc(sizeof( struct yy_buffer_state )  );
+	if ( ! b )
+		YY_FATAL_ERROR( "out of dynamic memory in __libipsec_create_buffer()" );
+
+	b->yy_buf_size = size;
+
+	/* yy_ch_buf has to be 2 characters longer than the size given because
+	 * we need to put in 2 end-of-buffer characters.
+	 */
+	b->yy_ch_buf = (char *) __libipsecalloc(b->yy_buf_size + 2  );
+	if ( ! b->yy_ch_buf )
+		YY_FATAL_ERROR( "out of dynamic memory in __libipsec_create_buffer()" );
+
+	b->yy_is_our_buffer = 1;
+
+	__libipsec_init_buffer(b,file );
+
+	return b;
+}
+
+/** Destroy the buffer.
+ * @param b a buffer created with __libipsec_create_buffer()
+ * 
+ */
+    void __libipsec_delete_buffer (YY_BUFFER_STATE  b )
+{
+    
+	if ( ! b )
+		return;
+
+	if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */
+		YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0;
+
+	if ( b->yy_is_our_buffer )
+		__libipsecfree((void *) b->yy_ch_buf  );
+
+	__libipsecfree((void *) b  );
+}
+
+#ifndef __cplusplus
+extern int isatty (int );
+#endif /* __cplusplus */
+    
+/* Initializes or reinitializes a buffer.
+ * This function is sometimes called more than once on the same buffer,
+ * such as during a __libipsecrestart() or at EOF.
+ */
+    static void __libipsec_init_buffer  (YY_BUFFER_STATE  b, FILE * file )
+
+{
+	int oerrno = errno;
+    
+	__libipsec_flush_buffer(b );
+
+	b->yy_input_file = file;
+	b->yy_fill_buffer = 1;
+
+    /* If b is the current buffer, then __libipsec_init_buffer was _probably_
+     * called from __libipsecrestart() or through yy_get_next_buffer.
+     * In that case, we don't want to reset the lineno or column.
+     */
+    if (b != YY_CURRENT_BUFFER){
+        b->yy_bs_lineno = 1;
+        b->yy_bs_column = 0;
+    }
+
+        b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0;
+    
+	errno = oerrno;
+}
+
+/** Discard all buffered characters. On the next scan, YY_INPUT will be called.
+ * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER.
+ * 
+ */
+    void __libipsec_flush_buffer (YY_BUFFER_STATE  b )
+{
+    	if ( ! b )
+		return;
+
+	b->yy_n_chars = 0;
+
+	/* We always need two end-of-buffer characters.  The first causes
+	 * a transition to the end-of-buffer state.  The second causes
+	 * a jam in that state.
+	 */
+	b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR;
+	b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR;
+
+	b->yy_buf_pos = &b->yy_ch_buf[0];
+
+	b->yy_at_bol = 1;
+	b->yy_buffer_status = YY_BUFFER_NEW;
+
+	if ( b == YY_CURRENT_BUFFER )
+		__libipsec_load_buffer_state( );
+}
+
+/** Pushes the new state onto the stack. The new state becomes
+ *  the current state. This function will allocate the stack
+ *  if necessary.
+ *  @param new_buffer The new state.
+ *  
+ */
+void __libipsecpush_buffer_state (YY_BUFFER_STATE new_buffer )
+{
+    	if (new_buffer == NULL)
+		return;
+
+	__libipsecensure_buffer_stack();
+
+	/* This block is copied from __libipsec_switch_to_buffer. */
+	if ( YY_CURRENT_BUFFER )
+		{
+		/* Flush out information for old buffer. */
+		*(yy_c_buf_p) = (yy_hold_char);
+		YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p);
+		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
+		}
+
+	/* Only push if top exists. Otherwise, replace top. */
+	if (YY_CURRENT_BUFFER)
+		(yy_buffer_stack_top)++;
+	YY_CURRENT_BUFFER_LVALUE = new_buffer;
+
+	/* copied from __libipsec_switch_to_buffer. */
+	__libipsec_load_buffer_state( );
+	(yy_did_buffer_switch_on_eof) = 1;
+}
+
+/** Removes and deletes the top of the stack, if present.
+ *  The next element becomes the new top.
+ *  
+ */
+void __libipsecpop_buffer_state (void)
+{
+    	if (!YY_CURRENT_BUFFER)
+		return;
+
+	__libipsec_delete_buffer(YY_CURRENT_BUFFER );
+	YY_CURRENT_BUFFER_LVALUE = NULL;
+	if ((yy_buffer_stack_top) > 0)
+		--(yy_buffer_stack_top);
+
+	if (YY_CURRENT_BUFFER) {
+		__libipsec_load_buffer_state( );
+		(yy_did_buffer_switch_on_eof) = 1;
+	}
+}
+
+/* Allocates the stack if it does not exist.
+ *  Guarantees space for at least one push.
+ */
+static void __libipsecensure_buffer_stack (void)
+{
+	int num_to_alloc;
+    
+	if (!(yy_buffer_stack)) {
+
+		/* First allocation is just for 2 elements, since we don't know if this
+		 * scanner will even need a stack. We use 2 instead of 1 to avoid an
+		 * immediate realloc on the next call.
+         */
+		num_to_alloc = 1;
+		(yy_buffer_stack) = (struct yy_buffer_state**)__libipsecalloc
+								(num_to_alloc * sizeof(struct yy_buffer_state*)
+								);
+		if ( ! (yy_buffer_stack) )
+			YY_FATAL_ERROR( "out of dynamic memory in __libipsecensure_buffer_stack()" );
+								  
+		memset((yy_buffer_stack), 0, num_to_alloc * sizeof(struct yy_buffer_state*));
+				
+		(yy_buffer_stack_max) = num_to_alloc;
+		(yy_buffer_stack_top) = 0;
+		return;
+	}
+
+	if ((yy_buffer_stack_top) >= ((yy_buffer_stack_max)) - 1){
+
+		/* Increase the buffer to prepare for a possible push. */
+		int grow_size = 8 /* arbitrary grow size */;
+
+		num_to_alloc = (yy_buffer_stack_max) + grow_size;
+		(yy_buffer_stack) = (struct yy_buffer_state**)__libipsecrealloc
+								((yy_buffer_stack),
+								num_to_alloc * sizeof(struct yy_buffer_state*)
+								);
+		if ( ! (yy_buffer_stack) )
+			YY_FATAL_ERROR( "out of dynamic memory in __libipsecensure_buffer_stack()" );
+
+		/* zero only the new slots.*/
+		memset((yy_buffer_stack) + (yy_buffer_stack_max), 0, grow_size * sizeof(struct yy_buffer_state*));
+		(yy_buffer_stack_max) = num_to_alloc;
+	}
+}
+
+/** Setup the input buffer state to scan directly from a user-specified character buffer.
+ * @param base the character buffer
+ * @param size the size in bytes of the character buffer
+ * 
+ * @return the newly allocated buffer state object. 
+ */
+YY_BUFFER_STATE __libipsec_scan_buffer  (char * base, yy_size_t  size )
+{
+	YY_BUFFER_STATE b;
+    
+	if ( size < 2 ||
+	     base[size-2] != YY_END_OF_BUFFER_CHAR ||
+	     base[size-1] != YY_END_OF_BUFFER_CHAR )
+		/* They forgot to leave room for the EOB's. */
+		return 0;
+
+	b = (YY_BUFFER_STATE) __libipsecalloc(sizeof( struct yy_buffer_state )  );
+	if ( ! b )
+		YY_FATAL_ERROR( "out of dynamic memory in __libipsec_scan_buffer()" );
+
+	b->yy_buf_size = size - 2;	/* "- 2" to take care of EOB's */
+	b->yy_buf_pos = b->yy_ch_buf = base;
+	b->yy_is_our_buffer = 0;
+	b->yy_input_file = 0;
+	b->yy_n_chars = b->yy_buf_size;
+	b->yy_is_interactive = 0;
+	b->yy_at_bol = 1;
+	b->yy_fill_buffer = 0;
+	b->yy_buffer_status = YY_BUFFER_NEW;
+
+	__libipsec_switch_to_buffer(b  );
+
+	return b;
+}
+
+/** Setup the input buffer state to scan a string. The next call to __libipseclex() will
+ * scan from a @e copy of @a str.
+ * @param yystr a NUL-terminated string to scan
+ * 
+ * @return the newly allocated buffer state object.
+ * @note If you want to scan bytes that may contain NUL values, then use
+ *       __libipsec_scan_bytes() instead.
+ */
+YY_BUFFER_STATE __libipsec_scan_string (yyconst char * yystr )
+{
+    
+	return __libipsec_scan_bytes(yystr,strlen(yystr) );
+}
+
+/** Setup the input buffer state to scan the given bytes. The next call to __libipseclex() will
+ * scan from a @e copy of @a bytes.
+ * @param bytes the byte buffer to scan
+ * @param len the number of bytes in the buffer pointed to by @a bytes.
+ * 
+ * @return the newly allocated buffer state object.
+ */
+YY_BUFFER_STATE __libipsec_scan_bytes  (yyconst char * yybytes, int  _yybytes_len )
+{
+	YY_BUFFER_STATE b;
+	char *buf;
+	yy_size_t n;
+	int i;
+    
+	/* Get memory for full buffer, including space for trailing EOB's. */
+	n = _yybytes_len + 2;
+	buf = (char *) __libipsecalloc(n  );
+	if ( ! buf )
+		YY_FATAL_ERROR( "out of dynamic memory in __libipsec_scan_bytes()" );
+
+	for ( i = 0; i < _yybytes_len; ++i )
+		buf[i] = yybytes[i];
+
+	buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR;
+
+	b = __libipsec_scan_buffer(buf,n );
+	if ( ! b )
+		YY_FATAL_ERROR( "bad buffer in __libipsec_scan_bytes()" );
+
+	/* It's okay to grow etc. this buffer, and we should throw it
+	 * away when we're done.
+	 */
+	b->yy_is_our_buffer = 1;
+
+	return b;
+}
+
+#ifndef YY_EXIT_FAILURE
+#define YY_EXIT_FAILURE 2
+#endif
+
+static void yy_fatal_error (yyconst char* msg )
+{
+    	(void) fprintf( stderr, "%s\n", msg );
+	exit( YY_EXIT_FAILURE );
+}
+
+/* Redefine yyless() so it works in section 3 code. */
+
+#undef yyless
+#define yyless(n) \
+	do \
+		{ \
+		/* Undo effects of setting up __libipsectext. */ \
+        int yyless_macro_arg = (n); \
+        YY_LESS_LINENO(yyless_macro_arg);\
+		__libipsectext[__libipsecleng] = (yy_hold_char); \
+		(yy_c_buf_p) = __libipsectext + yyless_macro_arg; \
+		(yy_hold_char) = *(yy_c_buf_p); \
+		*(yy_c_buf_p) = '\0'; \
+		__libipsecleng = yyless_macro_arg; \
+		} \
+	while ( 0 )
+
+/* Accessor  methods (get/set functions) to struct members. */
+
+/** Get the current line number.
+ * 
+ */
+int __libipsecget_lineno  (void)
+{
+        
+    return __libipseclineno;
+}
+
+/** Get the input stream.
+ * 
+ */
+FILE *__libipsecget_in  (void)
+{
+        return __libipsecin;
+}
+
+/** Get the output stream.
+ * 
+ */
+FILE *__libipsecget_out  (void)
+{
+        return __libipsecout;
+}
+
+/** Get the length of the current token.
+ * 
+ */
+int __libipsecget_leng  (void)
+{
+        return __libipsecleng;
+}
+
+/** Get the current token.
+ * 
+ */
+
+char *__libipsecget_text  (void)
+{
+        return __libipsectext;
+}
+
+/** Set the current line number.
+ * @param line_number
+ * 
+ */
+void __libipsecset_lineno (int  line_number )
+{
+    
+    __libipseclineno = line_number;
+}
+
+/** Set the input stream. This does not discard the current
+ * input buffer.
+ * @param in_str A readable stream.
+ * 
+ * @see __libipsec_switch_to_buffer
+ */
+void __libipsecset_in (FILE *  in_str )
+{
+        __libipsecin = in_str ;
+}
+
+void __libipsecset_out (FILE *  out_str )
+{
+        __libipsecout = out_str ;
+}
+
+int __libipsecget_debug  (void)
+{
+        return __libipsec_flex_debug;
+}
+
+void __libipsecset_debug (int  bdebug )
+{
+        __libipsec_flex_debug = bdebug ;
+}
+
+static int yy_init_globals (void)
+{
+        /* Initialization is the same as for the non-reentrant scanner.
+     * This function is called from __libipseclex_destroy(), so don't allocate here.
+     */
+
+    (yy_buffer_stack) = 0;
+    (yy_buffer_stack_top) = 0;
+    (yy_buffer_stack_max) = 0;
+    (yy_c_buf_p) = (char *) 0;
+    (yy_init) = 0;
+    (yy_start) = 0;
+
+/* Defined in main.c */
+#ifdef YY_STDINIT
+    __libipsecin = stdin;
+    __libipsecout = stdout;
+#else
+    __libipsecin = (FILE *) 0;
+    __libipsecout = (FILE *) 0;
+#endif
+
+    /* For future reference: Set errno on error, since we are called by
+     * __libipseclex_init()
+     */
+    return 0;
+}
+
+/* __libipseclex_destroy is for both reentrant and non-reentrant scanners. */
+int __libipseclex_destroy  (void)
+{
+    
+    /* Pop the buffer stack, destroying each element. */
+	while(YY_CURRENT_BUFFER){
+		__libipsec_delete_buffer(YY_CURRENT_BUFFER  );
+		YY_CURRENT_BUFFER_LVALUE = NULL;
+		__libipsecpop_buffer_state();
+	}
+
+	/* Destroy the stack itself. */
+	__libipsecfree((yy_buffer_stack) );
+	(yy_buffer_stack) = NULL;
+
+    /* Reset the globals. This is important in a non-reentrant scanner so the next time
+     * __libipseclex() is called, initialization will occur. */
+    yy_init_globals( );
+
+    return 0;
+}
+
+/*
+ * Internal utility routines.
+ */
+
+#ifndef yytext_ptr
+static void yy_flex_strncpy (char* s1, yyconst char * s2, int n )
+{
+	register int i;
+	for ( i = 0; i < n; ++i )
+		s1[i] = s2[i];
+}
+#endif
+
+#ifdef YY_NEED_STRLEN
+static int yy_flex_strlen (yyconst char * s )
+{
+	register int n;
+	for ( n = 0; s[n]; ++n )
+		;
+
+	return n;
+}
+#endif
+
+void *__libipsecalloc (yy_size_t  size )
+{
+	return (void *) malloc( size );
+}
+
+void *__libipsecrealloc  (void * ptr, yy_size_t  size )
+{
+	/* The cast to (char *) in the following accommodates both
+	 * implementations that use char* generic pointers, and those
+	 * that use void* generic pointers.  It works with the latter
+	 * because both ANSI C and C++ allow castless assignment from
+	 * any pointer type to void*, and deal with argument conversions
+	 * as though doing an assignment.
+	 */
+	return (void *) realloc( (char *) ptr, size );
+}
+
+void __libipsecfree (void * ptr )
+{
+	free( (char *) ptr );	/* see __libipsecrealloc() for (char *) cast */
+}
+
+#define YYTABLES_NAME "yytables"
+
+#line 167 "policy_token.l"
+
+
+
+void __policy__strbuffer__init__ __P((char *));
+void __policy__strbuffer__free__ __P((void));
+
+static YY_BUFFER_STATE strbuffer;
+
+void
+__policy__strbuffer__init__(msg)
+	char *msg;
+{
+	if (YY_CURRENT_BUFFER)
+		__libipsec_delete_buffer(YY_CURRENT_BUFFER);
+	strbuffer = (YY_BUFFER_STATE)__libipsec_scan_string(msg);
+	__libipsec_switch_to_buffer(strbuffer);
+
+	return;
+}
+
+void
+__policy__strbuffer__free__()
+{
+	__libipsec_delete_buffer(strbuffer);
+
+	return;
+}
+
diff --git a/src/libipsec/policy_token.l b/src/libipsec/policy_token.l
new file mode 100644
index 0000000..0833c20
--- /dev/null
+++ b/src/libipsec/policy_token.l
@@ -0,0 +1,192 @@
+/*	$NetBSD: policy_token.l,v 1.6.6.1 2007/08/01 11:52:19 vanhu Exp $	*/
+
+/* Id: policy_token.l,v 1.12 2005/05/05 12:32:18 manubsd Exp */
+
+/*
+ * Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+%{
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <net/pfkeyv2.h>
+#include <netinet/in.h>
+#include PATH_IPSEC_H
+
+#include <stdlib.h>
+#include <limits.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include "libpfkey.h"
+
+#if !defined(__NetBSD__) && !defined(__FreeBSD__) && !defined(__linux__)  && \
+!defined(__APPLE__) && !defined(__MACH__)
+#include "y.tab.h"
+#else
+#include "policy_parse.h"
+#endif
+#define yylval __libipseclval	/* XXX */
+
+int yylex __P((void));
+%}
+
+%option noyywrap
+%option nounput
+
+/* common section */
+nl		\n
+ws		[ \t]+
+digit		[0-9]
+hexdigit	[0-9A-Fa-f]
+special		[()+\|\?\*,]
+dot		\.
+comma		\,
+hyphen		\-
+colon		\:
+slash		\/
+bcl		\{
+ecl		\}
+blcl		\[
+elcl		\]
+percent		\%
+semi		\;
+plus	\+
+usec		{dot}{digit}{1,6}
+comment		\#.*
+ccomment	"/*"
+bracketstring	\<[^>]*\>
+quotedstring	\"[^"]*\"
+decstring	{digit}+
+hexpair		{hexdigit}{hexdigit}
+hexstring	0[xX]{hexdigit}+
+octetstring	{octet}({dot}{octet})+
+ipaddress	[a-zA-Z0-9:\._][a-zA-Z0-9:\._]*(%[a-zA-Z0-9]+)?
+
+%%
+
+in		{ yylval.num = IPSEC_DIR_INBOUND; return(DIR); }
+out		{ yylval.num = IPSEC_DIR_OUTBOUND; return(DIR); }
+fwd		{ 
+#ifdef HAVE_POLICY_FWD
+		  yylval.num = IPSEC_DIR_FWD; return(DIR); 
+#else
+		  yylval.num = IPSEC_DIR_INBOUND; return(DIR); 
+#endif
+		}
+
+priority	{ return(PRIORITY); }
+prio	{ return(PRIORITY); }
+low	{ yylval.num32 = PRIORITY_LOW; return(PRIO_BASE); }
+def { yylval.num32 = PRIORITY_DEFAULT; return(PRIO_BASE); }
+high	{ yylval.num32 = PRIORITY_HIGH; return(PRIO_BASE); }
+{plus}	{ return(PLUS); }
+{decstring}	{
+			yylval.val.len = strlen(yytext);
+			yylval.val.buf = yytext;
+			return(PRIO_OFFSET);
+}
+
+discard		{ yylval.num = IPSEC_POLICY_DISCARD; return(ACTION); }
+none		{ yylval.num = IPSEC_POLICY_NONE; return(ACTION); }
+ipsec		{ yylval.num = IPSEC_POLICY_IPSEC; return(ACTION); }
+bypass		{ yylval.num = IPSEC_POLICY_BYPASS; return(ACTION); }
+entrust		{ yylval.num = IPSEC_POLICY_ENTRUST; return(ACTION); }
+
+esp		{ yylval.num = IPPROTO_ESP; return(PROTOCOL); }
+ah		{ yylval.num = IPPROTO_AH; return(PROTOCOL); }
+ipcomp		{ yylval.num = IPPROTO_IPCOMP; return(PROTOCOL); }
+
+transport	{ yylval.num = IPSEC_MODE_TRANSPORT; return(MODE); }
+tunnel		{ yylval.num = IPSEC_MODE_TUNNEL; return(MODE); }
+
+me		{ return(ME); }
+any		{ return(ANY); }
+
+default		{ yylval.num = IPSEC_LEVEL_DEFAULT; return(LEVEL); }
+use		{ yylval.num = IPSEC_LEVEL_USE; return(LEVEL); }
+require		{ yylval.num = IPSEC_LEVEL_REQUIRE; return(LEVEL); }
+unique{colon}{decstring} {
+			yylval.val.len = strlen(yytext + 7);
+			yylval.val.buf = yytext + 7;
+			return(LEVEL_SPECIFY);
+		}
+unique		{ yylval.num = IPSEC_LEVEL_UNIQUE; return(LEVEL); }
+{slash}		{ return(SLASH); }
+
+{ipaddress}	{
+			yylval.val.len = strlen(yytext);
+			yylval.val.buf = yytext;
+			return(IPADDRESS);
+		}
+
+{hyphen}	{ return(HYPHEN); }
+
+{blcl}{decstring}{elcl} {
+			/* Remove leading '[' and trailing ']' */
+			yylval.val.buf = yytext + 1;
+			yylval.val.len = strlen(yytext) - 2;
+
+			return(PORT);
+		}
+
+{ws}		{ ; }
+{nl}		{ ; }
+
+%%
+
+void __policy__strbuffer__init__ __P((char *));
+void __policy__strbuffer__free__ __P((void));
+
+static YY_BUFFER_STATE strbuffer;
+
+void
+__policy__strbuffer__init__(msg)
+	char *msg;
+{
+	if (YY_CURRENT_BUFFER)
+		yy_delete_buffer(YY_CURRENT_BUFFER);
+	strbuffer = (YY_BUFFER_STATE)yy_scan_string(msg);
+	yy_switch_to_buffer(strbuffer);
+
+	return;
+}
+
+void
+__policy__strbuffer__free__()
+{
+	yy_delete_buffer(strbuffer);
+
+	return;
+}
diff --git a/src/libipsec/test-policy.c b/src/libipsec/test-policy.c
new file mode 100644
index 0000000..a6e6efc
--- /dev/null
+++ b/src/libipsec/test-policy.c
@@ -0,0 +1,332 @@
+/*	$NetBSD: test-policy.c,v 1.4 2006/09/09 16:22:09 manu Exp $	*/
+
+/*	$KAME: test-policy.c,v 1.16 2003/08/26 03:24:08 itojun Exp $	*/
+
+/*
+ * Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+
+#include <netinet/in.h>
+#include <net/pfkeyv2.h>
+#include <netinet/ipsec.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <err.h>
+
+#include "libpfkey.h"
+
+struct req_t {
+	int result;	/* expected result; 0:ok 1:ng */
+	char *str;
+} reqs[] = {
+{ 0, "out ipsec" },
+{ 1, "must_error" },
+{ 1, "in ipsec must_error" },
+{ 1, "out ipsec esp/must_error" },
+{ 1, "out discard" },
+{ 1, "out none" },
+{ 0, "in entrust" },
+{ 0, "out entrust" },
+{ 1, "out ipsec esp" },
+{ 0, "in ipsec ah/transport" },
+{ 1, "in ipsec ah/tunnel" },
+{ 0, "out ipsec ah/transport/" },
+{ 1, "out ipsec ah/tunnel/" },
+{ 0, "in ipsec esp / transport / 10.0.0.1-10.0.0.2" },
+{ 0, "in ipsec esp/tunnel/::1-::2" },
+{ 1, "in ipsec esp/tunnel/10.0.0.1-::2" },
+{ 0, "in ipsec esp/tunnel/::1-::2/require" },
+{ 0, "out ipsec ah/transport//use" },
+{ 1, "out ipsec ah/transport esp/use" },
+{ 1, "in ipsec ah/transport esp/tunnel" },
+{ 0, "in ipsec ah/transport esp/tunnel/::1-::1" },
+{ 0, "in ipsec
+	ah / transport
+	esp / tunnel / ::1-::2" },
+{ 0, "out ipsec
+	ah/transport/::1-::2 esp/tunnel/::3-::4/use ah/transport/::5-::6/require
+	ah/transport/::1-::2 esp/tunnel/::3-::4/use ah/transport/::5-::6/require
+	ah/transport/::1-::2 esp/tunnel/::3-::4/use ah/transport/::5-::6/require
+	" },
+{ 0, "out ipsec esp/transport/fec0::10-fec0::11/use" },
+};
+
+int test1 __P((void));
+int test1sub1 __P((struct req_t *));
+int test1sub2 __P((char *, int));
+int test2 __P((void));
+int test2sub __P((int));
+
+int
+main(ac, av)
+	int ac;
+	char **av;
+{
+	test1();
+	test2();
+
+	exit(0);
+}
+
+int
+test1()
+{
+	int i;
+	int result;
+
+	printf("TEST1\n");
+	for (i = 0; i < sizeof(reqs)/sizeof(reqs[0]); i++) {
+		printf("#%d [%s]\n", i + 1, reqs[i].str);
+
+		result = test1sub1(&reqs[i]);
+		if (result == 0 && reqs[i].result == 1) {
+			warnx("ERROR: expecting failure.");
+		} else if (result == 1 && reqs[i].result == 0) {
+			warnx("ERROR: expecting success.");
+		}
+	}
+
+	return 0;
+}
+
+int
+test1sub1(req)
+	struct req_t *req;
+{
+	char *buf;
+
+	buf = ipsec_set_policy(req->str, strlen(req->str));
+	if (buf == NULL) {
+		printf("ipsec_set_policy: %s\n", ipsec_strerror());
+		return 1;
+	}
+
+	if (test1sub2(buf, PF_INET) != 0
+	 || test1sub2(buf, PF_INET6) != 0) {
+		free(buf);
+		return 1;
+	}
+#if 0
+	kdebug_sadb_x_policy((struct sadb_ext *)buf);
+#endif
+
+	free(buf);
+	return 0;
+}
+
+int
+test1sub2(policy, family)
+	char *policy;
+	int family;
+{
+	int so;
+	int proto = 0, optname = 0;
+	int len;
+	char getbuf[1024];
+
+	switch (family) {
+	case PF_INET:
+		proto = IPPROTO_IP;
+		optname = IP_IPSEC_POLICY;
+		break;
+	case PF_INET6:
+		proto = IPPROTO_IPV6;
+		optname = IPV6_IPSEC_POLICY;
+		break;
+	}
+
+	if ((so = socket(family, SOCK_DGRAM, 0)) < 0)
+		err(1, "socket");
+
+	len = ipsec_get_policylen(policy);
+#if 0
+	printf("\tsetlen:%d\n", len);
+#endif
+
+	if (setsockopt(so, proto, optname, policy, len) < 0) {
+		printf("fail to set sockopt; %s\n", strerror(errno));
+		close(so);
+		return 1;
+	}
+
+	memset(getbuf, 0, sizeof(getbuf));
+	memcpy(getbuf, policy, sizeof(struct sadb_x_policy));
+	if (getsockopt(so, proto, optname, getbuf, &len) < 0) {
+		printf("fail to get sockopt; %s\n", strerror(errno));
+		close(so);
+		return 1;
+	}
+
+    {
+	char *buf = NULL;
+
+#if 0
+	printf("\tgetlen:%d\n", len);
+#endif
+
+	if ((buf = ipsec_dump_policy(getbuf, NULL)) == NULL) {
+		printf("%s\n", ipsec_strerror());
+		close(so);
+		return 1;
+	}
+#if 0
+	printf("\t[%s]\n", buf);
+#endif
+	free(buf);
+    }
+
+	close (so);
+	return 0;
+}
+
+char addr[] = {
+	28, 28, 0, 0,
+	0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
+	0, 0, 0, 0,
+};
+
+int
+test2()
+{
+	int so;
+	char *pol1 = "out ipsec";
+	char *pol2 = "out ipsec ah/transport//use";
+	char *sp1, *sp2;
+	int splen1, splen2;
+	int spid;
+	struct sadb_msg *m;
+
+	printf("TEST2\n");
+	if (getuid() != 0)
+		errx(1, "root privilege required.");
+
+	sp1 = ipsec_set_policy(pol1, strlen(pol1));
+	splen1 = ipsec_get_policylen(sp1);
+	sp2 = ipsec_set_policy(pol2, strlen(pol2));
+	splen2 = ipsec_get_policylen(sp2);
+
+	if ((so = pfkey_open()) < 0)
+		errx(1, "ERROR: %s", ipsec_strerror());
+
+	printf("spdflush()\n");
+	if (pfkey_send_spdflush(so) < 0)
+		errx(1, "ERROR: %s", ipsec_strerror());
+	m = pfkey_recv(so);
+	free(m);
+
+	printf("spdsetidx()\n");
+	if (pfkey_send_spdsetidx(so, (struct sockaddr *)addr, 128,
+				(struct sockaddr *)addr, 128,
+				255, sp1, splen1, 0) < 0)
+		errx(1, "ERROR: %s", ipsec_strerror());
+	m = pfkey_recv(so);
+	free(m);
+	
+	printf("spdupdate()\n");
+	if (pfkey_send_spdupdate(so, (struct sockaddr *)addr, 128,
+				(struct sockaddr *)addr, 128,
+				255, sp2, splen2, 0) < 0)
+		errx(1, "ERROR: %s", ipsec_strerror());
+	m = pfkey_recv(so);
+	free(m);
+
+	printf("sleep(4)\n");
+	sleep(4);
+
+	printf("spddelete()\n");
+	if (pfkey_send_spddelete(so, (struct sockaddr *)addr, 128,
+				(struct sockaddr *)addr, 128,
+				255, sp1, splen1, 0) < 0)
+		errx(1, "ERROR: %s", ipsec_strerror());
+	m = pfkey_recv(so);
+	free(m);
+
+	printf("spdadd()\n");
+	if (pfkey_send_spdadd(so, (struct sockaddr *)addr, 128,
+				(struct sockaddr *)addr, 128,
+				255, sp2, splen2, 0) < 0)
+		errx(1, "ERROR: %s", ipsec_strerror());
+	spid = test2sub(so);
+
+	printf("spdget(%u)\n", spid);
+	if (pfkey_send_spdget(so, spid) < 0)
+		errx(1, "ERROR: %s", ipsec_strerror());
+	m = pfkey_recv(so);
+	free(m);
+
+	printf("sleep(4)\n");
+	sleep(4);
+
+	printf("spddelete2()\n");
+	if (pfkey_send_spddelete2(so, spid) < 0)
+		errx(1, "ERROR: %s", ipsec_strerror());
+	m = pfkey_recv(so);
+	free(m);
+
+	printf("spdadd() with lifetime's 10(s)\n");
+	if (pfkey_send_spdadd2(so, (struct sockaddr *)addr, 128,
+				(struct sockaddr *)addr, 128,
+				255, 0, 10, sp2, splen2, 0) < 0)
+		errx(1, "ERROR: %s", ipsec_strerror());
+	spid = test2sub(so);
+
+	/* expecting failure */
+	printf("spdupdate()\n");
+	if (pfkey_send_spdupdate(so, (struct sockaddr *)addr, 128,
+				(struct sockaddr *)addr, 128,
+				255, sp2, splen2, 0) == 0) {
+		warnx("ERROR: expecting failure.");
+	}
+
+	return 0;
+}
+
+int
+test2sub(so)
+	int so;
+{
+	struct sadb_msg *msg;
+	caddr_t mhp[SADB_EXT_MAX + 1];
+
+	if ((msg = pfkey_recv(so)) == NULL)
+		errx(1, "ERROR: pfkey_recv failure.");
+	if (pfkey_align(msg, mhp) < 0)
+		errx(1, "ERROR: pfkey_align failure.");
+
+	return ((struct sadb_x_policy *)mhp[SADB_X_EXT_POLICY])->sadb_x_policy_id;
+}
+
diff --git a/src/racoon/Android.mk b/src/racoon/Android.mk
new file mode 100755
index 0000000..b8c2236
--- /dev/null
+++ b/src/racoon/Android.mk
@@ -0,0 +1,56 @@
+LOCAL_PATH:= $(call my-dir)
+
+# We need to build this for both the device (as a shared library)
+# and the host (as a static library for tools to use).
+
+L_CFLAGS += -O3 -DANDROID_CHANGES -DHAVE_CONFIG_H -DMAXNS=3
+
+
+lib_SRC_FILES := kmpstat.c vmbuf.c sockmisc.c misc.c
+
+DAEMON_SRC_FILES := main.c session.c isakmp.c handler.c isakmp_ident.c \
+  isakmp_agg.c isakmp_base.c isakmp_quick.c isakmp_inf.c isakmp_newg.c \
+  gssapi.c dnssec.c getcertsbyname.c privsep.c pfkey.c admin.c evt.c \
+  ipsec_doi.c oakley.c grabmyaddr.c vendorid.c policy.c localconf.c \
+  remoteconf.c crypto_openssl.c algorithm.c proposal.c sainfo.c strnames.c \
+  plog.c logger.c schedule.c str2val.c safefile.c backupsa.c genlist.c \
+  rsalist.c cftoken.c cfparse.c prsa_tok.c prsa_par.c vmbuf.c sockmisc.c \
+  misc.c nattraversal.c
+
+DAEMON_STATIC_LIBS := libipsec libracoon
+DAEMON_SHARED_LIBS := libcutils libcrypto libssl
+
+common_C_INCLUDES += $(LOCAL_PATH)/../..
+
+L_CFLAGS += -include $(LOCAL_PATH)/../../src/include-glibc/glibc-bugs.h \
+  -I$(LOCAL_PATH)/../../src/include-glibc -I$(LOCAL_PATH)/../../src/libipsec \
+  -I$(LOCAL_PATH)/missing -Iexternal/openssl/include -I bionic/libc/private \
+  -DSYSCONFDIR=\"/etc\" -DADMINPORTDIR=\"/var/racoon\" -g -O2
+
+common_SHARED_LIBRARIES := libipsec
+
+# For libracoon
+# =====================================================
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := $(lib_SRC_FILES)
+LOCAL_C_INCLUDES += $(common_C_INCLUDES)
+LOCAL_SHARED_LIBRARIES += $(common_SHARED_LIBRARIES)
+LOCAL_CFLAGS += $(L_CFLAGS)
+LOCAL_MODULE:= libracoon
+
+include $(BUILD_STATIC_LIBRARY)
+
+# For daemon racoon
+# =====================================================
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := $(DAEMON_SRC_FILES)
+LOCAL_C_INCLUDES += $(common_C_INCLUDES)
+LOCAL_SHARED_LIBRARIES += $(DAEMON_SHARED_LIBS)
+LOCAL_STATIC_LIBRARIES += $(DAEMON_STATIC_LIBS)
+LOCAL_CFLAGS += $(L_CFLAGS)
+LOCAL_MODULE := racoon
+include $(BUILD_EXECUTABLE)
diff --git a/src/racoon/Makefile.am b/src/racoon/Makefile.am
new file mode 100644
index 0000000..202a18e
--- /dev/null
+++ b/src/racoon/Makefile.am
@@ -0,0 +1,127 @@
+# Id: Makefile.am,v 1.23 2005/07/01 08:57:50 manubsd Exp
+
+sbin_PROGRAMS = racoon racoonctl plainrsa-gen
+noinst_PROGRAMS = eaytest
+include_racoon_HEADERS = racoonctl.h var.h vmbuf.h misc.h gcmalloc.h admin.h \
+	schedule.h sockmisc.h vmbuf.h isakmp_var.h isakmp.h isakmp_xauth.h \
+	isakmp_cfg.h isakmp_unity.h ipsec_doi.h evt.h
+lib_LTLIBRARIES = libracoon.la
+
+adminsockdir=${localstatedir}/racoon
+
+BUILT_SOURCES = cfparse.h prsa_par.h
+INCLUDES = -I${srcdir}/../libipsec 
+AM_CFLAGS = -D_GNU_SOURCE @GLIBC_BUGS@ -DSYSCONFDIR=\"${sysconfdir}\" \
+	-DADMINPORTDIR=\"${adminsockdir}\"
+AM_LDFLAGS = @EXTRA_CRYPTO@ -lcrypto
+AM_YFLAGS = -d ${$*_YFLAGS}
+AM_LFLAGS = ${$*_LFLAGS}
+
+prsa_par_YFLAGS = -p prsa
+prsa_tok_LFLAGS = -Pprsa -olex.yy.c
+
+MISSING_ALGOS = \
+	missing/crypto/sha2/sha2.c \
+	missing/crypto/rijndael/rijndael-api-fst.c \
+	missing/crypto/rijndael/rijndael-alg-fst.c
+
+racoon_SOURCES = \
+	main.c session.c isakmp.c handler.c \
+	isakmp_ident.c isakmp_agg.c isakmp_base.c \
+	isakmp_quick.c isakmp_inf.c isakmp_newg.c \
+	gssapi.c dnssec.c getcertsbyname.c privsep.c \
+	pfkey.c admin.c evt.c ipsec_doi.c oakley.c grabmyaddr.c vendorid.c \
+	policy.c localconf.c remoteconf.c crypto_openssl.c algorithm.c \
+	proposal.c sainfo.c strnames.c \
+	plog.c logger.c schedule.c str2val.c \
+	safefile.c backupsa.c genlist.c rsalist.c \
+	cftoken.l cfparse.y prsa_tok.l prsa_par.y 
+EXTRA_racoon_SOURCES = isakmp_xauth.c isakmp_cfg.c isakmp_unity.c throttle.c \
+	isakmp_frag.c nattraversal.c security.c $(MISSING_ALGOS)
+racoon_LDADD = $(CRYPTOBJS) $(HYBRID_OBJS) $(NATT_OBJS) $(FRAG_OBJS) $(LEXLIB) \
+	 $(SECCTX_OBJS) vmbuf.o sockmisc.o misc.o ../libipsec/libipsec.la
+racoon_DEPENDENCIES = \
+	$(CRYPTOBJS) $(HYBRID_OBJS) $(NATT_OBJS) $(FRAG_OBJS) $(SECCTX_OBJS) \
+	vmbuf.o sockmisc.o misc.o
+
+racoonctl_SOURCES = racoonctl.c str2val.c 
+racoonctl_LDADD = libracoon.la ../libipsec/libipsec.la 
+
+libracoon_la_SOURCES = kmpstat.c vmbuf.c sockmisc.c misc.c
+
+plainrsa_gen_SOURCES = plainrsa-gen.c plog.c \
+	crypto_openssl.c logger.c 
+EXTRA_plainrsa_gen_SOURCES = $(MISSING_ALGOS)
+plainrsa_gen_LDADD = $(CRYPTOBJS) vmbuf.o misc.o
+plainrsa_gen_DEPENDENCIES = $(CRYPTOBJS) vmbuf.o misc.o
+
+eaytest_SOURCES = eaytest.c plog.c logger.c
+EXTRA_eaytest_SOURCES = missing/crypto/sha2/sha2.c
+eaytest_LDADD =	crypto_openssl_test.o vmbuf.o str2val.o misc_noplog.o \
+	$(CRYPTOBJS)
+eaytest_DEPENDENCIES = crypto_openssl_test.o vmbuf.o str2val.o \
+	misc_noplog.o $(CRYPTOBJS)
+
+noinst_HEADERS = \
+	admin.h           dnssec.h      isakmp_base.h   oakley.h      session.h \
+	admin_var.h       dump.h        isakmp_ident.h  pfkey.h       sockmisc.h \
+	algorithm.h       gcmalloc.h    isakmp_inf.h    plog.h        str2val.h \
+	backupsa.h        gnuc.h        isakmp_newg.h   policy.h      strnames.h \
+	grabmyaddr.h      isakmp_quick.h  proposal.h    var.h         evt.h \
+	gssapi.h          isakmp_var.h	vendorid.h      nattraversal.h\
+	crypto_openssl.h  handler.h     localconf.h     remoteconf.h  vmbuf.h \
+	debug.h           ipsec_doi.h   logger.h        safefile.h \
+	debugrm.h         isakmp.h      misc.h          sainfo.h \
+	dhgroup.h         isakmp_agg.h  netdb_dnssec.h  schedule.h \
+	isakmp_cfg.h      isakmp_xauth.h isakmp_unity.h isakmp_frag.h \
+	throttle.h	  privsep.h \
+	cfparse_proto.h	  cftoken_proto.h genlist.h     rsalist.h \
+	missing/crypto/sha2/sha2.h missing/crypto/rijndael/rijndael_local.h \
+	missing/crypto/rijndael/rijndael-api-fst.h \
+	missing/crypto/rijndael/rijndael-alg-fst.h \
+	missing/crypto/rijndael/rijndael.h
+
+man5_MANS = racoon.conf.5
+man8_MANS = racoon.8 racoonctl.8 plainrsa-gen.8
+
+EXTRA_DIST = \
+   ${man5_MANS} ${man8_MANS} \
+   missing/crypto/rijndael/boxes-fst.dat \
+   doc/FAQ doc/README.certificate doc/README.gssapi doc/README.plainrsa \
+   contrib/sp.pl stats.pl \
+   samples/psk.txt.sample  samples/racoon.conf.sample \
+   samples/psk.txt.in samples/racoon.conf.in \
+   samples/racoon.conf.sample-gssapi samples/racoon.conf.sample-natt \
+   samples/racoon.conf.sample-inherit samples/racoon.conf.sample-plainrsa \
+   samples/roadwarrior/README \
+   samples/roadwarrior/client/phase1-down.sh \
+   samples/roadwarrior/client/phase1-up.sh \
+   samples/roadwarrior/client/racoon.conf \
+   samples/roadwarrior/server/racoon.conf \
+   samples/roadwarrior/server/racoon.conf-radius
+
+TESTS = eaytest
+
+install-exec-local:
+	${mkinstalldirs} $(DESTDIR)${adminsockdir}
+
+# special object rules
+crypto_openssl_test.o: crypto_openssl.c
+	$(COMPILE) -DEAYDEBUG -o crypto_openssl_test.o -c $(srcdir)/crypto_openssl.c
+
+misc_noplog.o: misc.c
+	$(COMPILE) -DNOUSE_PLOG -o misc_noplog.o -c $(srcdir)/misc.c
+
+# missing/*.c
+strdup.o:	$(srcdir)/missing/strdup.c
+	$(COMPILE) -c $(srcdir)/missing/$*.c
+getaddrinfo.o:	$(srcdir)/missing/getaddrinfo.c
+	$(COMPILE) -c $(srcdir)/missing/$*.c
+getnameinfo.o:	$(srcdir)/missing/getnameinfo.c
+	$(COMPILE) -c $(srcdir)/missing/$*.c
+rijndael-api-fst.o: $(srcdir)/missing/crypto/rijndael/rijndael-api-fst.c
+	$(COMPILE) -c $(srcdir)/missing/crypto/rijndael/$*.c
+rijndael-alg-fst.o: $(srcdir)/missing/crypto/rijndael/rijndael-alg-fst.c
+	$(COMPILE) -c $(srcdir)/missing/crypto/rijndael/$*.c
+sha2.o: $(srcdir)/missing/crypto/sha2/sha2.c
+	$(COMPILE) -c $(srcdir)/missing/crypto/sha2/$*.c
diff --git a/src/racoon/Makefile.in b/src/racoon/Makefile.in
new file mode 100644
index 0000000..47e997b
--- /dev/null
+++ b/src/racoon/Makefile.in
@@ -0,0 +1,1000 @@
+# Makefile.in generated by automake 1.10.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008  Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+# Id: Makefile.am,v 1.23 2005/07/01 08:57:50 manubsd Exp
+
+
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+sbin_PROGRAMS = racoon$(EXEEXT) racoonctl$(EXEEXT) \
+	plainrsa-gen$(EXEEXT)
+noinst_PROGRAMS = eaytest$(EXEEXT)
+TESTS = eaytest$(EXEEXT)
+subdir = src/racoon
+DIST_COMMON = $(include_racoon_HEADERS) $(noinst_HEADERS) \
+	$(srcdir)/Makefile.am $(srcdir)/Makefile.in TODO cfparse.c \
+	cfparse.h cftoken.c prsa_par.c prsa_par.h prsa_tok.c
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/acracoon.m4 \
+	$(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+	$(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+    $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+    *) f=$$p;; \
+  esac;
+am__strip_dir = `echo $$p | sed -e 's|^.*/||'`;
+am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(sbindir)" \
+	"$(DESTDIR)$(man5dir)" "$(DESTDIR)$(man8dir)" \
+	"$(DESTDIR)$(include_racoondir)"
+libLTLIBRARIES_INSTALL = $(INSTALL)
+LTLIBRARIES = $(lib_LTLIBRARIES)
+libracoon_la_LIBADD =
+am_libracoon_la_OBJECTS = kmpstat.lo vmbuf.lo sockmisc.lo misc.lo
+libracoon_la_OBJECTS = $(am_libracoon_la_OBJECTS)
+sbinPROGRAMS_INSTALL = $(INSTALL_PROGRAM)
+PROGRAMS = $(noinst_PROGRAMS) $(sbin_PROGRAMS)
+am_eaytest_OBJECTS = eaytest.$(OBJEXT) plog.$(OBJEXT) logger.$(OBJEXT)
+eaytest_OBJECTS = $(am_eaytest_OBJECTS)
+am__DEPENDENCIES_1 =
+am_plainrsa_gen_OBJECTS = plainrsa-gen.$(OBJEXT) plog.$(OBJEXT) \
+	crypto_openssl.$(OBJEXT) logger.$(OBJEXT)
+plainrsa_gen_OBJECTS = $(am_plainrsa_gen_OBJECTS)
+am_racoon_OBJECTS = main.$(OBJEXT) session.$(OBJEXT) isakmp.$(OBJEXT) \
+	handler.$(OBJEXT) isakmp_ident.$(OBJEXT) isakmp_agg.$(OBJEXT) \
+	isakmp_base.$(OBJEXT) isakmp_quick.$(OBJEXT) \
+	isakmp_inf.$(OBJEXT) isakmp_newg.$(OBJEXT) gssapi.$(OBJEXT) \
+	dnssec.$(OBJEXT) getcertsbyname.$(OBJEXT) privsep.$(OBJEXT) \
+	pfkey.$(OBJEXT) admin.$(OBJEXT) evt.$(OBJEXT) \
+	ipsec_doi.$(OBJEXT) oakley.$(OBJEXT) grabmyaddr.$(OBJEXT) \
+	vendorid.$(OBJEXT) policy.$(OBJEXT) localconf.$(OBJEXT) \
+	remoteconf.$(OBJEXT) crypto_openssl.$(OBJEXT) \
+	algorithm.$(OBJEXT) proposal.$(OBJEXT) sainfo.$(OBJEXT) \
+	strnames.$(OBJEXT) plog.$(OBJEXT) logger.$(OBJEXT) \
+	schedule.$(OBJEXT) str2val.$(OBJEXT) safefile.$(OBJEXT) \
+	backupsa.$(OBJEXT) genlist.$(OBJEXT) rsalist.$(OBJEXT) \
+	cftoken.$(OBJEXT) cfparse.$(OBJEXT) prsa_tok.$(OBJEXT) \
+	prsa_par.$(OBJEXT)
+racoon_OBJECTS = $(am_racoon_OBJECTS)
+am_racoonctl_OBJECTS = racoonctl.$(OBJEXT) str2val.$(OBJEXT)
+racoonctl_OBJECTS = $(am_racoonctl_OBJECTS)
+racoonctl_DEPENDENCIES = libracoon.la ../libipsec/libipsec.la
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+	$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+	--mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+	$(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+	--mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+	$(LDFLAGS) -o $@
+LEXCOMPILE = $(LEX) $(LFLAGS) $(AM_LFLAGS)
+LTLEXCOMPILE = $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+	--mode=compile $(LEX) $(LFLAGS) $(AM_LFLAGS)
+YLWRAP = $(top_srcdir)/ylwrap
+YACCCOMPILE = $(YACC) $(YFLAGS) $(AM_YFLAGS)
+LTYACCCOMPILE = $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+	--mode=compile $(YACC) $(YFLAGS) $(AM_YFLAGS)
+SOURCES = $(libracoon_la_SOURCES) $(eaytest_SOURCES) \
+	$(EXTRA_eaytest_SOURCES) $(plainrsa_gen_SOURCES) \
+	$(EXTRA_plainrsa_gen_SOURCES) $(racoon_SOURCES) \
+	$(EXTRA_racoon_SOURCES) $(racoonctl_SOURCES)
+DIST_SOURCES = $(libracoon_la_SOURCES) $(eaytest_SOURCES) \
+	$(EXTRA_eaytest_SOURCES) $(plainrsa_gen_SOURCES) \
+	$(EXTRA_plainrsa_gen_SOURCES) $(racoon_SOURCES) \
+	$(EXTRA_racoon_SOURCES) $(racoonctl_SOURCES)
+man5dir = $(mandir)/man5
+man8dir = $(mandir)/man8
+NROFF = nroff
+MANS = $(man5_MANS) $(man8_MANS)
+include_racoonHEADERS_INSTALL = $(INSTALL_HEADER)
+HEADERS = $(include_racoon_HEADERS) $(noinst_HEADERS)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CONFIGURE_AMFLAGS = @CONFIGURE_AMFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CRYPTOBJS = @CRYPTOBJS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DSYMUTIL = @DSYMUTIL@
+ECHO = @ECHO@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+EXTRA_CRYPTO = @EXTRA_CRYPTO@
+F77 = @F77@
+FFLAGS = @FFLAGS@
+FRAG_OBJS = @FRAG_OBJS@
+GLIBC_BUGS = @GLIBC_BUGS@
+GREP = @GREP@
+HYBRID_OBJS = @HYBRID_OBJS@
+INCLUDE_GLIBC = @INCLUDE_GLIBC@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_OPTS = @INSTALL_OPTS@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+KERNEL_INCLUDE = @KERNEL_INCLUDE@
+KRB5_CONFIG = @KRB5_CONFIG@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+NATT_OBJS = @NATT_OBJS@
+NMEDIT = @NMEDIT@
+OBJEXT = @OBJEXT@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+RANLIB = @RANLIB@
+RPM = @RPM@
+SECCTX_OBJS = @SECCTX_OBJS@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+YACC = @YACC@
+YFLAGS = @YFLAGS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_F77 = @ac_ct_F77@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+include_racoondir = @include_racoondir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+include_racoon_HEADERS = racoonctl.h var.h vmbuf.h misc.h gcmalloc.h admin.h \
+	schedule.h sockmisc.h vmbuf.h isakmp_var.h isakmp.h isakmp_xauth.h \
+	isakmp_cfg.h isakmp_unity.h ipsec_doi.h evt.h
+
+lib_LTLIBRARIES = libracoon.la
+adminsockdir = ${localstatedir}/racoon
+BUILT_SOURCES = cfparse.h prsa_par.h
+INCLUDES = -I${srcdir}/../libipsec 
+AM_CFLAGS = -D_GNU_SOURCE @GLIBC_BUGS@ -DSYSCONFDIR=\"${sysconfdir}\" \
+	-DADMINPORTDIR=\"${adminsockdir}\"
+
+AM_LDFLAGS = @EXTRA_CRYPTO@ -lcrypto
+AM_YFLAGS = -d ${$*_YFLAGS}
+AM_LFLAGS = ${$*_LFLAGS}
+prsa_par_YFLAGS = -p prsa
+prsa_tok_LFLAGS = -Pprsa -olex.yy.c
+MISSING_ALGOS = \
+	missing/crypto/sha2/sha2.c \
+	missing/crypto/rijndael/rijndael-api-fst.c \
+	missing/crypto/rijndael/rijndael-alg-fst.c
+
+racoon_SOURCES = \
+	main.c session.c isakmp.c handler.c \
+	isakmp_ident.c isakmp_agg.c isakmp_base.c \
+	isakmp_quick.c isakmp_inf.c isakmp_newg.c \
+	gssapi.c dnssec.c getcertsbyname.c privsep.c \
+	pfkey.c admin.c evt.c ipsec_doi.c oakley.c grabmyaddr.c vendorid.c \
+	policy.c localconf.c remoteconf.c crypto_openssl.c algorithm.c \
+	proposal.c sainfo.c strnames.c \
+	plog.c logger.c schedule.c str2val.c \
+	safefile.c backupsa.c genlist.c rsalist.c \
+	cftoken.l cfparse.y prsa_tok.l prsa_par.y 
+
+EXTRA_racoon_SOURCES = isakmp_xauth.c isakmp_cfg.c isakmp_unity.c throttle.c \
+	isakmp_frag.c nattraversal.c security.c $(MISSING_ALGOS)
+
+racoon_LDADD = $(CRYPTOBJS) $(HYBRID_OBJS) $(NATT_OBJS) $(FRAG_OBJS) $(LEXLIB) \
+	 $(SECCTX_OBJS) vmbuf.o sockmisc.o misc.o ../libipsec/libipsec.la
+
+racoon_DEPENDENCIES = \
+	$(CRYPTOBJS) $(HYBRID_OBJS) $(NATT_OBJS) $(FRAG_OBJS) $(SECCTX_OBJS) \
+	vmbuf.o sockmisc.o misc.o
+
+racoonctl_SOURCES = racoonctl.c str2val.c 
+racoonctl_LDADD = libracoon.la ../libipsec/libipsec.la 
+libracoon_la_SOURCES = kmpstat.c vmbuf.c sockmisc.c misc.c
+plainrsa_gen_SOURCES = plainrsa-gen.c plog.c \
+	crypto_openssl.c logger.c 
+
+EXTRA_plainrsa_gen_SOURCES = $(MISSING_ALGOS)
+plainrsa_gen_LDADD = $(CRYPTOBJS) vmbuf.o misc.o
+plainrsa_gen_DEPENDENCIES = $(CRYPTOBJS) vmbuf.o misc.o
+eaytest_SOURCES = eaytest.c plog.c logger.c
+EXTRA_eaytest_SOURCES = missing/crypto/sha2/sha2.c
+eaytest_LDADD = crypto_openssl_test.o vmbuf.o str2val.o misc_noplog.o \
+	$(CRYPTOBJS)
+
+eaytest_DEPENDENCIES = crypto_openssl_test.o vmbuf.o str2val.o \
+	misc_noplog.o $(CRYPTOBJS)
+
+noinst_HEADERS = \
+	admin.h           dnssec.h      isakmp_base.h   oakley.h      session.h \
+	admin_var.h       dump.h        isakmp_ident.h  pfkey.h       sockmisc.h \
+	algorithm.h       gcmalloc.h    isakmp_inf.h    plog.h        str2val.h \
+	backupsa.h        gnuc.h        isakmp_newg.h   policy.h      strnames.h \
+	grabmyaddr.h      isakmp_quick.h  proposal.h    var.h         evt.h \
+	gssapi.h          isakmp_var.h	vendorid.h      nattraversal.h\
+	crypto_openssl.h  handler.h     localconf.h     remoteconf.h  vmbuf.h \
+	debug.h           ipsec_doi.h   logger.h        safefile.h \
+	debugrm.h         isakmp.h      misc.h          sainfo.h \
+	dhgroup.h         isakmp_agg.h  netdb_dnssec.h  schedule.h \
+	isakmp_cfg.h      isakmp_xauth.h isakmp_unity.h isakmp_frag.h \
+	throttle.h	  privsep.h \
+	cfparse_proto.h	  cftoken_proto.h genlist.h     rsalist.h \
+	missing/crypto/sha2/sha2.h missing/crypto/rijndael/rijndael_local.h \
+	missing/crypto/rijndael/rijndael-api-fst.h \
+	missing/crypto/rijndael/rijndael-alg-fst.h \
+	missing/crypto/rijndael/rijndael.h
+
+man5_MANS = racoon.conf.5
+man8_MANS = racoon.8 racoonctl.8 plainrsa-gen.8
+EXTRA_DIST = \
+   ${man5_MANS} ${man8_MANS} \
+   missing/crypto/rijndael/boxes-fst.dat \
+   doc/FAQ doc/README.certificate doc/README.gssapi doc/README.plainrsa \
+   contrib/sp.pl stats.pl \
+   samples/psk.txt.sample  samples/racoon.conf.sample \
+   samples/psk.txt.in samples/racoon.conf.in \
+   samples/racoon.conf.sample-gssapi samples/racoon.conf.sample-natt \
+   samples/racoon.conf.sample-inherit samples/racoon.conf.sample-plainrsa \
+   samples/roadwarrior/README \
+   samples/roadwarrior/client/phase1-down.sh \
+   samples/roadwarrior/client/phase1-up.sh \
+   samples/roadwarrior/client/racoon.conf \
+   samples/roadwarrior/server/racoon.conf \
+   samples/roadwarrior/server/racoon.conf-radius
+
+all: $(BUILT_SOURCES)
+	$(MAKE) $(AM_MAKEFLAGS) all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .l .lo .o .obj .y
+$(srcdir)/Makefile.in:  $(srcdir)/Makefile.am  $(am__configure_deps)
+	@for dep in $?; do \
+	  case '$(am__configure_deps)' in \
+	    *$$dep*) \
+	      cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
+		&& exit 0; \
+	      exit 1;; \
+	  esac; \
+	done; \
+	echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign  src/racoon/Makefile'; \
+	cd $(top_srcdir) && \
+	  $(AUTOMAKE) --foreign  src/racoon/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+	@case '$?' in \
+	  *config.status*) \
+	    cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+	  *) \
+	    echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+	    cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+	esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure:  $(am__configure_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4):  $(am__aclocal_m4_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+install-libLTLIBRARIES: $(lib_LTLIBRARIES)
+	@$(NORMAL_INSTALL)
+	test -z "$(libdir)" || $(MKDIR_P) "$(DESTDIR)$(libdir)"
+	@list='$(lib_LTLIBRARIES)'; for p in $$list; do \
+	  if test -f $$p; then \
+	    f=$(am__strip_dir) \
+	    echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(libLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) '$$p' '$(DESTDIR)$(libdir)/$$f'"; \
+	    $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(libLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) "$$p" "$(DESTDIR)$(libdir)/$$f"; \
+	  else :; fi; \
+	done
+
+uninstall-libLTLIBRARIES:
+	@$(NORMAL_UNINSTALL)
+	@list='$(lib_LTLIBRARIES)'; for p in $$list; do \
+	  p=$(am__strip_dir) \
+	  echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$p'"; \
+	  $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$p"; \
+	done
+
+clean-libLTLIBRARIES:
+	-test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES)
+	@list='$(lib_LTLIBRARIES)'; for p in $$list; do \
+	  dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+	  test "$$dir" != "$$p" || dir=.; \
+	  echo "rm -f \"$${dir}/so_locations\""; \
+	  rm -f "$${dir}/so_locations"; \
+	done
+libracoon.la: $(libracoon_la_OBJECTS) $(libracoon_la_DEPENDENCIES) 
+	$(LINK) -rpath $(libdir) $(libracoon_la_OBJECTS) $(libracoon_la_LIBADD) $(LIBS)
+
+clean-noinstPROGRAMS:
+	@list='$(noinst_PROGRAMS)'; for p in $$list; do \
+	  f=`echo $$p|sed 's/$(EXEEXT)$$//'`; \
+	  echo " rm -f $$p $$f"; \
+	  rm -f $$p $$f ; \
+	done
+install-sbinPROGRAMS: $(sbin_PROGRAMS)
+	@$(NORMAL_INSTALL)
+	test -z "$(sbindir)" || $(MKDIR_P) "$(DESTDIR)$(sbindir)"
+	@list='$(sbin_PROGRAMS)'; for p in $$list; do \
+	  p1=`echo $$p|sed 's/$(EXEEXT)$$//'`; \
+	  if test -f $$p \
+	     || test -f $$p1 \
+	  ; then \
+	    f=`echo "$$p1" | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'`; \
+	   echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(sbinPROGRAMS_INSTALL) '$$p' '$(DESTDIR)$(sbindir)/$$f'"; \
+	   $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(sbinPROGRAMS_INSTALL) "$$p" "$(DESTDIR)$(sbindir)/$$f" || exit 1; \
+	  else :; fi; \
+	done
+
+uninstall-sbinPROGRAMS:
+	@$(NORMAL_UNINSTALL)
+	@list='$(sbin_PROGRAMS)'; for p in $$list; do \
+	  f=`echo "$$p" | sed 's,^.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \
+	  echo " rm -f '$(DESTDIR)$(sbindir)/$$f'"; \
+	  rm -f "$(DESTDIR)$(sbindir)/$$f"; \
+	done
+
+clean-sbinPROGRAMS:
+	@list='$(sbin_PROGRAMS)'; for p in $$list; do \
+	  f=`echo $$p|sed 's/$(EXEEXT)$$//'`; \
+	  echo " rm -f $$p $$f"; \
+	  rm -f $$p $$f ; \
+	done
+eaytest$(EXEEXT): $(eaytest_OBJECTS) $(eaytest_DEPENDENCIES) 
+	@rm -f eaytest$(EXEEXT)
+	$(LINK) $(eaytest_OBJECTS) $(eaytest_LDADD) $(LIBS)
+plainrsa-gen$(EXEEXT): $(plainrsa_gen_OBJECTS) $(plainrsa_gen_DEPENDENCIES) 
+	@rm -f plainrsa-gen$(EXEEXT)
+	$(LINK) $(plainrsa_gen_OBJECTS) $(plainrsa_gen_LDADD) $(LIBS)
+cfparse.h: cfparse.c
+	@if test ! -f $@; then \
+	  rm -f cfparse.c; \
+	  $(MAKE) $(AM_MAKEFLAGS) cfparse.c; \
+	else :; fi
+prsa_par.h: prsa_par.c
+	@if test ! -f $@; then \
+	  rm -f prsa_par.c; \
+	  $(MAKE) $(AM_MAKEFLAGS) prsa_par.c; \
+	else :; fi
+racoon$(EXEEXT): $(racoon_OBJECTS) $(racoon_DEPENDENCIES) 
+	@rm -f racoon$(EXEEXT)
+	$(LINK) $(racoon_OBJECTS) $(racoon_LDADD) $(LIBS)
+racoonctl$(EXEEXT): $(racoonctl_OBJECTS) $(racoonctl_DEPENDENCIES) 
+	@rm -f racoonctl$(EXEEXT)
+	$(LINK) $(racoonctl_OBJECTS) $(racoonctl_LDADD) $(LIBS)
+
+mostlyclean-compile:
+	-rm -f *.$(OBJEXT)
+
+distclean-compile:
+	-rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/admin.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/algorithm.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/backupsa.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cfparse.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cftoken.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/crypto_openssl.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dnssec.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eaytest.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/evt.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/genlist.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/getcertsbyname.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/grabmyaddr.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gssapi.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/handler.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ipsec_doi.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/isakmp.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/isakmp_agg.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/isakmp_base.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/isakmp_cfg.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/isakmp_frag.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/isakmp_ident.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/isakmp_inf.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/isakmp_newg.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/isakmp_quick.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/isakmp_unity.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/isakmp_xauth.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/kmpstat.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/localconf.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/logger.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/main.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/misc.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nattraversal.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/oakley.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pfkey.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/plainrsa-gen.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/plog.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/policy.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/privsep.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/proposal.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/prsa_par.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/prsa_tok.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/racoonctl.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/remoteconf.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rijndael-alg-fst.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rijndael-api-fst.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rsalist.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/safefile.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sainfo.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/schedule.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/security.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/session.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sha2.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sockmisc.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/str2val.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/strnames.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/throttle.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vendorid.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vmbuf.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@	$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@	mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@	$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@	mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@	$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@	mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LTCOMPILE) -c -o $@ $<
+
+sha2.obj: missing/crypto/sha2/sha2.c
+@am__fastdepCC_TRUE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sha2.obj -MD -MP -MF $(DEPDIR)/sha2.Tpo -c -o sha2.obj `if test -f 'missing/crypto/sha2/sha2.c'; then $(CYGPATH_W) 'missing/crypto/sha2/sha2.c'; else $(CYGPATH_W) '$(srcdir)/missing/crypto/sha2/sha2.c'; fi`
+@am__fastdepCC_TRUE@	mv -f $(DEPDIR)/sha2.Tpo $(DEPDIR)/sha2.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='missing/crypto/sha2/sha2.c' object='sha2.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sha2.obj `if test -f 'missing/crypto/sha2/sha2.c'; then $(CYGPATH_W) 'missing/crypto/sha2/sha2.c'; else $(CYGPATH_W) '$(srcdir)/missing/crypto/sha2/sha2.c'; fi`
+
+rijndael-api-fst.obj: missing/crypto/rijndael/rijndael-api-fst.c
+@am__fastdepCC_TRUE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT rijndael-api-fst.obj -MD -MP -MF $(DEPDIR)/rijndael-api-fst.Tpo -c -o rijndael-api-fst.obj `if test -f 'missing/crypto/rijndael/rijndael-api-fst.c'; then $(CYGPATH_W) 'missing/crypto/rijndael/rijndael-api-fst.c'; else $(CYGPATH_W) '$(srcdir)/missing/crypto/rijndael/rijndael-api-fst.c'; fi`
+@am__fastdepCC_TRUE@	mv -f $(DEPDIR)/rijndael-api-fst.Tpo $(DEPDIR)/rijndael-api-fst.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='missing/crypto/rijndael/rijndael-api-fst.c' object='rijndael-api-fst.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o rijndael-api-fst.obj `if test -f 'missing/crypto/rijndael/rijndael-api-fst.c'; then $(CYGPATH_W) 'missing/crypto/rijndael/rijndael-api-fst.c'; else $(CYGPATH_W) '$(srcdir)/missing/crypto/rijndael/rijndael-api-fst.c'; fi`
+
+rijndael-alg-fst.obj: missing/crypto/rijndael/rijndael-alg-fst.c
+@am__fastdepCC_TRUE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT rijndael-alg-fst.obj -MD -MP -MF $(DEPDIR)/rijndael-alg-fst.Tpo -c -o rijndael-alg-fst.obj `if test -f 'missing/crypto/rijndael/rijndael-alg-fst.c'; then $(CYGPATH_W) 'missing/crypto/rijndael/rijndael-alg-fst.c'; else $(CYGPATH_W) '$(srcdir)/missing/crypto/rijndael/rijndael-alg-fst.c'; fi`
+@am__fastdepCC_TRUE@	mv -f $(DEPDIR)/rijndael-alg-fst.Tpo $(DEPDIR)/rijndael-alg-fst.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='missing/crypto/rijndael/rijndael-alg-fst.c' object='rijndael-alg-fst.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o rijndael-alg-fst.obj `if test -f 'missing/crypto/rijndael/rijndael-alg-fst.c'; then $(CYGPATH_W) 'missing/crypto/rijndael/rijndael-alg-fst.c'; else $(CYGPATH_W) '$(srcdir)/missing/crypto/rijndael/rijndael-alg-fst.c'; fi`
+
+.l.c:
+	$(am__skiplex) $(SHELL) $(YLWRAP) $< $(LEX_OUTPUT_ROOT).c $@ -- $(LEXCOMPILE)
+
+.y.c:
+	$(am__skipyacc) $(SHELL) $(YLWRAP) $< y.tab.c $@ y.tab.h $*.h y.output $*.output -- $(YACCCOMPILE)
+
+mostlyclean-libtool:
+	-rm -f *.lo
+
+clean-libtool:
+	-rm -rf .libs _libs
+install-man5: $(man5_MANS) $(man_MANS)
+	@$(NORMAL_INSTALL)
+	test -z "$(man5dir)" || $(MKDIR_P) "$(DESTDIR)$(man5dir)"
+	@list='$(man5_MANS) $(dist_man5_MANS) $(nodist_man5_MANS)'; \
+	l2='$(man_MANS) $(dist_man_MANS) $(nodist_man_MANS)'; \
+	for i in $$l2; do \
+	  case "$$i" in \
+	    *.5*) list="$$list $$i" ;; \
+	  esac; \
+	done; \
+	for i in $$list; do \
+	  if test -f $(srcdir)/$$i; then file=$(srcdir)/$$i; \
+	  else file=$$i; fi; \
+	  ext=`echo $$i | sed -e 's/^.*\\.//'`; \
+	  case "$$ext" in \
+	    5*) ;; \
+	    *) ext='5' ;; \
+	  esac; \
+	  inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \
+	  inst=`echo $$inst | sed -e 's/^.*\///'`; \
+	  inst=`echo $$inst | sed '$(transform)'`.$$ext; \
+	  echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man5dir)/$$inst'"; \
+	  $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man5dir)/$$inst"; \
+	done
+uninstall-man5:
+	@$(NORMAL_UNINSTALL)
+	@list='$(man5_MANS) $(dist_man5_MANS) $(nodist_man5_MANS)'; \
+	l2='$(man_MANS) $(dist_man_MANS) $(nodist_man_MANS)'; \
+	for i in $$l2; do \
+	  case "$$i" in \
+	    *.5*) list="$$list $$i" ;; \
+	  esac; \
+	done; \
+	for i in $$list; do \
+	  ext=`echo $$i | sed -e 's/^.*\\.//'`; \
+	  case "$$ext" in \
+	    5*) ;; \
+	    *) ext='5' ;; \
+	  esac; \
+	  inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \
+	  inst=`echo $$inst | sed -e 's/^.*\///'`; \
+	  inst=`echo $$inst | sed '$(transform)'`.$$ext; \
+	  echo " rm -f '$(DESTDIR)$(man5dir)/$$inst'"; \
+	  rm -f "$(DESTDIR)$(man5dir)/$$inst"; \
+	done
+install-man8: $(man8_MANS) $(man_MANS)
+	@$(NORMAL_INSTALL)
+	test -z "$(man8dir)" || $(MKDIR_P) "$(DESTDIR)$(man8dir)"
+	@list='$(man8_MANS) $(dist_man8_MANS) $(nodist_man8_MANS)'; \
+	l2='$(man_MANS) $(dist_man_MANS) $(nodist_man_MANS)'; \
+	for i in $$l2; do \
+	  case "$$i" in \
+	    *.8*) list="$$list $$i" ;; \
+	  esac; \
+	done; \
+	for i in $$list; do \
+	  if test -f $(srcdir)/$$i; then file=$(srcdir)/$$i; \
+	  else file=$$i; fi; \
+	  ext=`echo $$i | sed -e 's/^.*\\.//'`; \
+	  case "$$ext" in \
+	    8*) ;; \
+	    *) ext='8' ;; \
+	  esac; \
+	  inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \
+	  inst=`echo $$inst | sed -e 's/^.*\///'`; \
+	  inst=`echo $$inst | sed '$(transform)'`.$$ext; \
+	  echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man8dir)/$$inst'"; \
+	  $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man8dir)/$$inst"; \
+	done
+uninstall-man8:
+	@$(NORMAL_UNINSTALL)
+	@list='$(man8_MANS) $(dist_man8_MANS) $(nodist_man8_MANS)'; \
+	l2='$(man_MANS) $(dist_man_MANS) $(nodist_man_MANS)'; \
+	for i in $$l2; do \
+	  case "$$i" in \
+	    *.8*) list="$$list $$i" ;; \
+	  esac; \
+	done; \
+	for i in $$list; do \
+	  ext=`echo $$i | sed -e 's/^.*\\.//'`; \
+	  case "$$ext" in \
+	    8*) ;; \
+	    *) ext='8' ;; \
+	  esac; \
+	  inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \
+	  inst=`echo $$inst | sed -e 's/^.*\///'`; \
+	  inst=`echo $$inst | sed '$(transform)'`.$$ext; \
+	  echo " rm -f '$(DESTDIR)$(man8dir)/$$inst'"; \
+	  rm -f "$(DESTDIR)$(man8dir)/$$inst"; \
+	done
+install-include_racoonHEADERS: $(include_racoon_HEADERS)
+	@$(NORMAL_INSTALL)
+	test -z "$(include_racoondir)" || $(MKDIR_P) "$(DESTDIR)$(include_racoondir)"
+	@list='$(include_racoon_HEADERS)'; for p in $$list; do \
+	  if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+	  f=$(am__strip_dir) \
+	  echo " $(include_racoonHEADERS_INSTALL) '$$d$$p' '$(DESTDIR)$(include_racoondir)/$$f'"; \
+	  $(include_racoonHEADERS_INSTALL) "$$d$$p" "$(DESTDIR)$(include_racoondir)/$$f"; \
+	done
+
+uninstall-include_racoonHEADERS:
+	@$(NORMAL_UNINSTALL)
+	@list='$(include_racoon_HEADERS)'; for p in $$list; do \
+	  f=$(am__strip_dir) \
+	  echo " rm -f '$(DESTDIR)$(include_racoondir)/$$f'"; \
+	  rm -f "$(DESTDIR)$(include_racoondir)/$$f"; \
+	done
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+	list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '{ files[$$0] = 1; nonemtpy = 1; } \
+	      END { if (nonempty) { for (i in files) print i; }; }'`; \
+	mkid -fID $$unique
+tags: TAGS
+
+TAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+		$(TAGS_FILES) $(LISP)
+	tags=; \
+	here=`pwd`; \
+	list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+	      END { if (nonempty) { for (i in files) print i; }; }'`; \
+	if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
+	  test -n "$$unique" || unique=$$empty_fix; \
+	  $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+	    $$tags $$unique; \
+	fi
+ctags: CTAGS
+CTAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+		$(TAGS_FILES) $(LISP)
+	tags=; \
+	list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+	      END { if (nonempty) { for (i in files) print i; }; }'`; \
+	test -z "$(CTAGS_ARGS)$$tags$$unique" \
+	  || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+	     $$tags $$unique
+
+GTAGS:
+	here=`$(am__cd) $(top_builddir) && pwd` \
+	  && cd $(top_srcdir) \
+	  && gtags -i $(GTAGS_ARGS) $$here
+
+distclean-tags:
+	-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+check-TESTS: $(TESTS)
+	@failed=0; all=0; xfail=0; xpass=0; skip=0; ws='[	 ]'; \
+	srcdir=$(srcdir); export srcdir; \
+	list=' $(TESTS) '; \
+	if test -n "$$list"; then \
+	  for tst in $$list; do \
+	    if test -f ./$$tst; then dir=./; \
+	    elif test -f $$tst; then dir=; \
+	    else dir="$(srcdir)/"; fi; \
+	    if $(TESTS_ENVIRONMENT) $${dir}$$tst; then \
+	      all=`expr $$all + 1`; \
+	      case " $(XFAIL_TESTS) " in \
+	      *$$ws$$tst$$ws*) \
+		xpass=`expr $$xpass + 1`; \
+		failed=`expr $$failed + 1`; \
+		echo "XPASS: $$tst"; \
+	      ;; \
+	      *) \
+		echo "PASS: $$tst"; \
+	      ;; \
+	      esac; \
+	    elif test $$? -ne 77; then \
+	      all=`expr $$all + 1`; \
+	      case " $(XFAIL_TESTS) " in \
+	      *$$ws$$tst$$ws*) \
+		xfail=`expr $$xfail + 1`; \
+		echo "XFAIL: $$tst"; \
+	      ;; \
+	      *) \
+		failed=`expr $$failed + 1`; \
+		echo "FAIL: $$tst"; \
+	      ;; \
+	      esac; \
+	    else \
+	      skip=`expr $$skip + 1`; \
+	      echo "SKIP: $$tst"; \
+	    fi; \
+	  done; \
+	  if test "$$failed" -eq 0; then \
+	    if test "$$xfail" -eq 0; then \
+	      banner="All $$all tests passed"; \
+	    else \
+	      banner="All $$all tests behaved as expected ($$xfail expected failures)"; \
+	    fi; \
+	  else \
+	    if test "$$xpass" -eq 0; then \
+	      banner="$$failed of $$all tests failed"; \
+	    else \
+	      banner="$$failed of $$all tests did not behave as expected ($$xpass unexpected passes)"; \
+	    fi; \
+	  fi; \
+	  dashes="$$banner"; \
+	  skipped=""; \
+	  if test "$$skip" -ne 0; then \
+	    skipped="($$skip tests were not run)"; \
+	    test `echo "$$skipped" | wc -c` -le `echo "$$banner" | wc -c` || \
+	      dashes="$$skipped"; \
+	  fi; \
+	  report=""; \
+	  if test "$$failed" -ne 0 && test -n "$(PACKAGE_BUGREPORT)"; then \
+	    report="Please report to $(PACKAGE_BUGREPORT)"; \
+	    test `echo "$$report" | wc -c` -le `echo "$$banner" | wc -c` || \
+	      dashes="$$report"; \
+	  fi; \
+	  dashes=`echo "$$dashes" | sed s/./=/g`; \
+	  echo "$$dashes"; \
+	  echo "$$banner"; \
+	  test -z "$$skipped" || echo "$$skipped"; \
+	  test -z "$$report" || echo "$$report"; \
+	  echo "$$dashes"; \
+	  test "$$failed" -eq 0; \
+	else :; fi
+
+distdir: $(DISTFILES)
+	@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+	topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+	list='$(DISTFILES)'; \
+	  dist_files=`for file in $$list; do echo $$file; done | \
+	  sed -e "s|^$$srcdirstrip/||;t" \
+	      -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+	case $$dist_files in \
+	  */*) $(MKDIR_P) `echo "$$dist_files" | \
+			   sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+			   sort -u` ;; \
+	esac; \
+	for file in $$dist_files; do \
+	  if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+	  if test -d $$d/$$file; then \
+	    dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+	    if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+	      cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+	    fi; \
+	    cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
+	  else \
+	    test -f $(distdir)/$$file \
+	    || cp -p $$d/$$file $(distdir)/$$file \
+	    || exit 1; \
+	  fi; \
+	done
+check-am: all-am
+	$(MAKE) $(AM_MAKEFLAGS) check-TESTS
+check: $(BUILT_SOURCES)
+	$(MAKE) $(AM_MAKEFLAGS) check-am
+all-am: Makefile $(LTLIBRARIES) $(PROGRAMS) $(MANS) $(HEADERS)
+installdirs:
+	for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(sbindir)" "$(DESTDIR)$(man5dir)" "$(DESTDIR)$(man8dir)" "$(DESTDIR)$(include_racoondir)"; do \
+	  test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+	done
+install: $(BUILT_SOURCES)
+	$(MAKE) $(AM_MAKEFLAGS) install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+	@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+	$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+	  install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+	  `test -z '$(STRIP)' || \
+	    echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+	-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+	@echo "This command is intended for maintainers to use"
+	@echo "it deletes files that may require special tools to rebuild."
+	-rm -f cfparse.c
+	-rm -f cfparse.h
+	-rm -f cftoken.c
+	-rm -f prsa_par.c
+	-rm -f prsa_par.h
+	-rm -f prsa_tok.c
+	-test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES)
+clean: clean-am
+
+clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \
+	clean-noinstPROGRAMS clean-sbinPROGRAMS mostlyclean-am
+
+distclean: distclean-am
+	-rm -rf ./$(DEPDIR)
+	-rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+	distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+info: info-am
+
+info-am:
+
+install-data-am: install-include_racoonHEADERS install-man
+
+install-dvi: install-dvi-am
+
+install-exec-am: install-exec-local install-libLTLIBRARIES \
+	install-sbinPROGRAMS
+
+install-html: install-html-am
+
+install-info: install-info-am
+
+install-man: install-man5 install-man8
+
+install-pdf: install-pdf-am
+
+install-ps: install-ps-am
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+	-rm -rf ./$(DEPDIR)
+	-rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+	mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-include_racoonHEADERS uninstall-libLTLIBRARIES \
+	uninstall-man uninstall-sbinPROGRAMS
+
+uninstall-man: uninstall-man5 uninstall-man8
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-TESTS check-am clean \
+	clean-generic clean-libLTLIBRARIES clean-libtool \
+	clean-noinstPROGRAMS clean-sbinPROGRAMS ctags distclean \
+	distclean-compile distclean-generic distclean-libtool \
+	distclean-tags distdir dvi dvi-am html html-am info info-am \
+	install install-am install-data install-data-am install-dvi \
+	install-dvi-am install-exec install-exec-am install-exec-local \
+	install-html install-html-am install-include_racoonHEADERS \
+	install-info install-info-am install-libLTLIBRARIES \
+	install-man install-man5 install-man8 install-pdf \
+	install-pdf-am install-ps install-ps-am install-sbinPROGRAMS \
+	install-strip installcheck installcheck-am installdirs \
+	maintainer-clean maintainer-clean-generic mostlyclean \
+	mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+	pdf pdf-am ps ps-am tags uninstall uninstall-am \
+	uninstall-include_racoonHEADERS uninstall-libLTLIBRARIES \
+	uninstall-man uninstall-man5 uninstall-man8 \
+	uninstall-sbinPROGRAMS
+
+
+install-exec-local:
+	${mkinstalldirs} $(DESTDIR)${adminsockdir}
+
+# special object rules
+crypto_openssl_test.o: crypto_openssl.c
+	$(COMPILE) -DEAYDEBUG -o crypto_openssl_test.o -c $(srcdir)/crypto_openssl.c
+
+misc_noplog.o: misc.c
+	$(COMPILE) -DNOUSE_PLOG -o misc_noplog.o -c $(srcdir)/misc.c
+
+# missing/*.c
+strdup.o:	$(srcdir)/missing/strdup.c
+	$(COMPILE) -c $(srcdir)/missing/$*.c
+getaddrinfo.o:	$(srcdir)/missing/getaddrinfo.c
+	$(COMPILE) -c $(srcdir)/missing/$*.c
+getnameinfo.o:	$(srcdir)/missing/getnameinfo.c
+	$(COMPILE) -c $(srcdir)/missing/$*.c
+rijndael-api-fst.o: $(srcdir)/missing/crypto/rijndael/rijndael-api-fst.c
+	$(COMPILE) -c $(srcdir)/missing/crypto/rijndael/$*.c
+rijndael-alg-fst.o: $(srcdir)/missing/crypto/rijndael/rijndael-alg-fst.c
+	$(COMPILE) -c $(srcdir)/missing/crypto/rijndael/$*.c
+sha2.o: $(srcdir)/missing/crypto/sha2/sha2.c
+	$(COMPILE) -c $(srcdir)/missing/crypto/sha2/$*.c
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/src/racoon/TODO b/src/racoon/TODO
new file mode 100644
index 0000000..1507167
--- /dev/null
+++ b/src/racoon/TODO
@@ -0,0 +1,131 @@
+$KAME: TODO,v 1.36 2001/09/19 09:41:39 sakane Exp $
+
+Please send any questions or bug reports to snap-users@kame.net.
+
+TODO list
+
+URGENT
+o The documents for users convenience.
+o split log file based on client.  printf-like config directive, i.e.
+  "logfile racoon.%s.log", should be useful here.
+  -> beware of possible security issue, don't use sprintf() directly!
+     make validation before giving a string to sprintf().
+o save decrypted IKE packet in tcpdump format
+o IPComp SA with wellknown CPI in CPI field.  how to handle it?
+o better rekey
+
+MUST
+o multiple certificate payload handling.
+o To consider the use with certificate infrastructure.  PXIX ???
+o kmstat should be improved.
+o Informational Exchange processing properly.
+o require less configuration.  phase 2 is easier (as kernel presents racoon
+  some hints), phase 1 is harder.  for example,
+  - grab phase 2 lifetime and algorith configuration from sadb_comb payloads in
+    ACQUIRE message.
+  - give reasonable default behavior when no configuration file is present.
+  - difficult items:
+	how to guess a reasonable phase 1 SA lifetime
+		(hardcoded default?  guess from phase 2 lifetime?)
+	guess what kind of ID payload to use
+	guess what kind of authentication to be used
+	guess phase 1 DH group (for aggressive mode, we cannot negotiate it)
+	guess if we need phase 2 PFS or not (we cannot negotiate it. so
+		we may need to pick from "no PFS" or "same as phase 1 DH group")
+	guess how we should negotiate lifetime
+		(is "strict" a reasonable default?)
+	guess which mode to use for phase 1 negotiation (is main mode useful?
+		is base mode popular enough?)
+o more acceptable check.
+
+SHOULD
+o psk.txt should be a database? (psk.db?)  psk_mkdb?
+o Dynamically retry to exchange and resend the packet per nodes.
+o To make the list of supported algorithm by sadb_supported payload
+  in the SADB_REGISTER message which happens asynchronously.
+o fix the structure of ph2handle.
+  We can handle the below case.
+
+  node A                            node B
+    +--------------SA1----------------+
+    +--------------SA2----------------+
+
+  at node A:
+  kernel
+    acquire(A-B) ------> ph2handle(A=B) -----> ph1handle
+                              |
+                            policy
+                             A=B
+                             A=B
+
+  But we can not handle the below case because there is no x?handle.
+
+  node A                            node B                           node C
+    +--------------SA1----------------+
+    +------------------------------------------------SA2---------------+
+
+  at node A:
+  kernel
+    acquire(A-C) ---+---> x?handle ---+---> ph2handle(A=B) -------> ph1handle
+                    |        |        |
+    acquire(A-B) ---+      policy     +---> ph2handle(A=C) -------> ph1handle
+                            A=B
+                            A=C
+
+o consistency of function name.
+o deep copy configuration entry to hander.  It's easy to reload configuration.
+o don't keep to hold keymat values, do it ?
+o local address's field in isakmpsa handler must be kicked out to rmconf.
+o responder policy and initiator policy should be separated.
+o for lifetime and key length, something like this should be useful.
+  - propose N
+  - accept between X and Y
+o wildcard "accept any proposal" policy should be allowed.
+o replay prevention
+  - limited total number of session
+  - limited session per peer
+  - number of proposal
+o full support for variable length SPI.  quickhack support for IPComp is done.
+
+MAY
+o Effective code.
+o interaction between IKE/IPsec and socket layer.
+  at this moment, IKE/IPsec failure is modeled as total packet loss to other
+  part of network subsystem, including socket layer.  this presents the
+  following behaviors:
+  - annoyingly long timeouts on tcp connection attempt, and IKE failure;
+    need to wait till tcp socket timeouts.
+  - blackhole if there's mismatching SAs.
+  we may be able to give socket layer some feedback from IKE/IPsec layer.
+  still not sure if those make sense or not.
+  for example:
+  - send PRU_HOSTDEAD to sockets if IKE negotiation failed
+    (sys/netkey/key.c:key_acquire2)
+    to do this, we need to remember which ACQUIRE was caused by which socket,
+    possibly into larval SAs.
+  - PRU_QUENCH on "no SA found on output"
+  - kick tcp retransmission timer on first SA establishment
+o IKE daemon should handle situations where peer does not run IKE daemon
+  (UDP port unreach for port 500) better.
+  should use connected UDP sockets for sending IKE datagrams.
+o rate-limit log messages from kernel IPsec errors, like "no SA found".
+
+TO BE TESTED.
+o IKE retransmit behavior
+	see, draft-*-ipsec-rekeying*.txt
+o Reboot recovery (peer reboot losing it's security associations)
+	see, draft-*-ipsec-rekeying*.txt
+o Scenarios
+	- End-to-End transport long lived security associations
+	  (over night, data transfer >1Gb) with frequent dynamic rekey
+	- End-to-GW tunnel long lived security associations
+	  (over night, data transfer >1Gb) with frequent dynamic rekey
+	- Policy change events while under SA load
+	- End-to-End SA through IPsec tunnels, initiation both ways
+	- Client End-to-End through client-to-GW tunnel SA, initiate from
+	  client for tunnel, then initiation both ways for end-to-end
+	- Client-to-GW transport SA for secure management
+o behavior to receive multiple auth method proposals and AND proposal
+
+and to be written many many.
+
diff --git a/src/racoon/admin.c b/src/racoon/admin.c
new file mode 100644
index 0000000..ef03ae6
--- /dev/null
+++ b/src/racoon/admin.c
@@ -0,0 +1,629 @@
+/*	$NetBSD: admin.c,v 1.17.6.2 2008/06/18 07:30:19 mgrooms Exp $	*/
+
+/* Id: admin.c,v 1.25 2006/04/06 14:31:04 manubsd Exp */
+
+/*
+ * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+#ifndef ANDROID_CHANGES
+#include <sys/signal.h>
+#else
+#define SIGHUP	1
+#endif
+#include <sys/stat.h>
+#include <sys/un.h>
+
+#include <net/pfkeyv2.h>
+
+#include <netinet/in.h>
+#include PATH_IPSEC_H
+
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <netdb.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef ENABLE_HYBRID
+#include <resolv.h>
+#endif
+
+#include "var.h"
+#include "misc.h"
+#include "vmbuf.h"
+#include "plog.h"
+#include "sockmisc.h"
+#include "debug.h"
+
+#include "schedule.h"
+#include "localconf.h"
+#include "remoteconf.h"
+#include "grabmyaddr.h"
+#include "isakmp_var.h"
+#include "isakmp.h"
+#include "oakley.h"
+#include "handler.h"
+#include "evt.h"
+#include "pfkey.h"
+#include "ipsec_doi.h"
+#include "admin.h"
+#include "admin_var.h"
+#include "isakmp_inf.h"
+#ifdef ENABLE_HYBRID
+#include "isakmp_cfg.h"
+#endif
+#include "session.h"
+#include "gcmalloc.h"
+
+#ifdef ENABLE_ADMINPORT
+char *adminsock_path = ADMINSOCK_PATH;
+uid_t adminsock_owner = 0;
+gid_t adminsock_group = 0;
+mode_t adminsock_mode = 0600;
+
+static struct sockaddr_un sunaddr;
+static int admin_process __P((int, char *));
+static int admin_reply __P((int, struct admin_com *, vchar_t *));
+
+int
+admin_handler()
+{
+	int so2;
+	struct sockaddr_storage from;
+	socklen_t fromlen = sizeof(from);
+	struct admin_com com;
+	char *combuf = NULL;
+	int len, error = -1;
+
+	so2 = accept(lcconf->sock_admin, (struct sockaddr *)&from, &fromlen);
+	if (so2 < 0) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"failed to accept admin command: %s\n",
+			strerror(errno));
+		return -1;
+	}
+
+	/* get buffer length */
+	while ((len = recv(so2, (char *)&com, sizeof(com), MSG_PEEK)) < 0) {
+		if (errno == EINTR)
+			continue;
+		plog(LLV_ERROR, LOCATION, NULL,
+			"failed to recv admin command: %s\n",
+			strerror(errno));
+		goto end;
+	}
+
+	/* sanity check */
+	if (len < sizeof(com)) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"invalid header length of admin command\n");
+		goto end;
+	}
+
+	/* get buffer to receive */
+	if ((combuf = racoon_malloc(com.ac_len)) == 0) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"failed to alloc buffer for admin command\n");
+		goto end;
+	}
+
+	/* get real data */
+	while ((len = recv(so2, combuf, com.ac_len, 0)) < 0) {
+		if (errno == EINTR)
+			continue;
+		plog(LLV_ERROR, LOCATION, NULL,
+			"failed to recv admin command: %s\n",
+			strerror(errno));
+		goto end;
+	}
+
+	if (com.ac_cmd == ADMIN_RELOAD_CONF) {
+		/* reload does not work at all! */
+		signal_handler(SIGHUP);
+		goto end;
+	}
+
+	error = admin_process(so2, combuf);
+
+    end:
+	(void)close(so2);
+	if (combuf)
+		racoon_free(combuf);
+
+	return error;
+}
+
+/*
+ * main child's process.
+ */
+static int
+admin_process(so2, combuf)
+	int so2;
+	char *combuf;
+{
+	struct admin_com *com = (struct admin_com *)combuf;
+	vchar_t *buf = NULL;
+	vchar_t *id = NULL;
+	vchar_t *key = NULL;
+	int idtype = 0;
+	int error = -1;
+
+	com->ac_errno = 0;
+
+	switch (com->ac_cmd) {
+	case ADMIN_RELOAD_CONF:
+		/* don't entered because of proccessing it in other place. */
+		plog(LLV_ERROR, LOCATION, NULL, "should never reach here\n");
+		goto out;
+
+	case ADMIN_SHOW_SCHED:
+	{
+		caddr_t p = NULL;
+		int len;
+
+		com->ac_errno = -1;
+
+		if (sched_dump(&p, &len) == -1)
+			goto out2;
+
+		if ((buf = vmalloc(len)) == NULL)
+			goto out2;
+
+		memcpy(buf->v, p, len);
+
+		com->ac_errno = 0;
+out2:
+		racoon_free(p);
+		break;
+	}
+
+	case ADMIN_SHOW_EVT:
+		/* It's not really an error, don't force racoonctl to quit */
+		if ((buf = evt_dump()) == NULL)
+			com->ac_errno = 0; 
+		break;
+
+	case ADMIN_SHOW_SA:
+	case ADMIN_FLUSH_SA:
+	    {
+		switch (com->ac_proto) {
+		case ADMIN_PROTO_ISAKMP:
+			switch (com->ac_cmd) {
+			case ADMIN_SHOW_SA:
+				buf = dumpph1();
+				if (buf == NULL)
+					com->ac_errno = -1;
+				break;
+			case ADMIN_FLUSH_SA:
+				flushph1();
+				break;
+			}
+			break;
+		case ADMIN_PROTO_IPSEC:
+		case ADMIN_PROTO_AH:
+		case ADMIN_PROTO_ESP:
+			switch (com->ac_cmd) {
+			case ADMIN_SHOW_SA:
+			    {
+				u_int p;
+				p = admin2pfkey_proto(com->ac_proto);
+				if (p == -1)
+					goto out;
+				buf = pfkey_dump_sadb(p);
+				if (buf == NULL)
+					com->ac_errno = -1;
+			    }
+				break;
+			case ADMIN_FLUSH_SA:
+				pfkey_flush_sadb(com->ac_proto);
+				break;
+			}
+			break;
+
+		case ADMIN_PROTO_INTERNAL:
+			switch (com->ac_cmd) {
+			case ADMIN_SHOW_SA:
+				buf = NULL; /*XXX dumpph2(&error);*/
+				if (buf == NULL)
+					com->ac_errno = error;
+				break;
+			case ADMIN_FLUSH_SA:
+				/*XXX flushph2();*/
+				com->ac_errno = 0;
+				break;
+			}
+			break;
+
+		default:
+			/* ignore */
+			com->ac_errno = -1;
+		}
+	    }
+		break;
+
+	case ADMIN_DELETE_SA: {
+		struct ph1handle *iph1;
+		struct sockaddr *dst;
+		struct sockaddr *src;
+		char *loc, *rem;
+
+		src = (struct sockaddr *)
+			&((struct admin_com_indexes *)
+			    ((caddr_t)com + sizeof(*com)))->src;
+		dst = (struct sockaddr *)
+			&((struct admin_com_indexes *)
+			    ((caddr_t)com + sizeof(*com)))->dst;
+
+		loc = racoon_strdup(saddrwop2str(src));
+		rem = racoon_strdup(saddrwop2str(dst));
+		STRDUP_FATAL(loc);
+		STRDUP_FATAL(rem);
+
+		if ((iph1 = getph1byaddrwop(src, dst)) == NULL) {
+			plog(LLV_ERROR, LOCATION, NULL, 
+			    "phase 1 for %s -> %s not found\n", loc, rem);
+		} else {
+			if (iph1->status == PHASE1ST_ESTABLISHED)
+				isakmp_info_send_d1(iph1);
+			purge_remote(iph1);
+		}
+
+		racoon_free(loc);
+		racoon_free(rem);
+
+		break;
+	}
+
+#ifdef ENABLE_HYBRID
+	case ADMIN_LOGOUT_USER: {
+		struct ph1handle *iph1;
+		char *user;
+		int found = 0;
+
+		if (com->ac_len > sizeof(com) + LOGINLEN + 1) {
+			plog(LLV_ERROR, LOCATION, NULL,
+			    "malformed message (login too long)\n");
+			break;
+		}
+
+		user = (char *)(com + 1);
+		found = purgeph1bylogin(user);
+		plog(LLV_INFO, LOCATION, NULL, 
+		    "deleted %d SA for user \"%s\"\n", found, user);
+
+		break;
+	}
+#endif
+
+	case ADMIN_DELETE_ALL_SA_DST: {
+		struct ph1handle *iph1;
+		struct sockaddr *dst;
+		char *loc, *rem;
+
+		dst = (struct sockaddr *)
+			&((struct admin_com_indexes *)
+			    ((caddr_t)com + sizeof(*com)))->dst;
+
+		rem = racoon_strdup(saddrwop2str(dst));
+		STRDUP_FATAL(rem);
+
+		plog(LLV_INFO, LOCATION, NULL, 
+		    "Flushing all SAs for peer %s\n", rem);
+
+		while ((iph1 = getph1bydstaddrwop(dst)) != NULL) {
+			loc = racoon_strdup(saddrwop2str(iph1->local));
+			STRDUP_FATAL(loc);
+
+			if (iph1->status == PHASE1ST_ESTABLISHED)
+				isakmp_info_send_d1(iph1);
+			purge_remote(iph1);
+
+			racoon_free(loc);
+		}
+		
+		racoon_free(rem);
+
+		break;
+	}
+
+	case ADMIN_ESTABLISH_SA_PSK: {
+		struct admin_com_psk *acp;
+		char *data;
+
+		com->ac_cmd = ADMIN_ESTABLISH_SA;
+
+		acp = (struct admin_com_psk *)
+		    ((char *)com + sizeof(*com) + 
+		    sizeof(struct admin_com_indexes));
+
+		idtype = acp->id_type;
+
+		if ((id = vmalloc(acp->id_len)) == NULL) {
+			plog(LLV_ERROR, LOCATION, NULL,
+			    "cannot allocate memory: %s\n", 
+			    strerror(errno));
+			break;
+		}
+		data = (char *)(acp + 1);
+		memcpy(id->v, data, id->l);
+
+		if ((key = vmalloc(acp->key_len)) == NULL) {
+			plog(LLV_ERROR, LOCATION, NULL,
+			    "cannot allocate memory: %s\n", 
+			    strerror(errno));
+			vfree(id);
+			id = NULL;
+			break;
+		}
+		data = (char *)(data + acp->id_len);
+		memcpy(key->v, data, key->l);
+	}
+	/* FALLTHROUGH */
+	case ADMIN_ESTABLISH_SA:
+	    {
+		struct sockaddr *dst;
+		struct sockaddr *src;
+		src = (struct sockaddr *)
+			&((struct admin_com_indexes *)
+			    ((caddr_t)com + sizeof(*com)))->src;
+		dst = (struct sockaddr *)
+			&((struct admin_com_indexes *)
+			    ((caddr_t)com + sizeof(*com)))->dst;
+
+		switch (com->ac_proto) {
+		case ADMIN_PROTO_ISAKMP: {
+			struct remoteconf *rmconf;
+			struct sockaddr *remote = NULL;
+			struct sockaddr *local = NULL;
+			u_int16_t port;
+
+			com->ac_errno = -1;
+
+			/* search appropreate configuration */
+			rmconf = getrmconf(dst);
+			if (rmconf == NULL) {
+				plog(LLV_ERROR, LOCATION, NULL,
+					"no configuration found "
+					"for %s\n", saddrwop2str(dst));
+				goto out1;
+			}
+
+			/* get remote IP address and port number. */
+			if ((remote = dupsaddr(dst)) == NULL)
+				goto out1;
+
+			port = extract_port(rmconf->remote);
+			if (set_port(remote, port) == NULL)
+				goto out1;
+
+			/* get local address */
+			if ((local = dupsaddr(src)) == NULL)
+				goto out1;
+
+			port = getmyaddrsport(local);
+			if (set_port(local, port) == NULL)
+				goto out1;
+
+#ifdef ENABLE_HYBRID
+			/* Set the id and key */
+			if (id && key) {
+				if (xauth_rmconf_used(&rmconf->xauth) == -1)
+					goto out1;
+
+				if (rmconf->xauth->login != NULL) {
+					vfree(rmconf->xauth->login);
+					rmconf->xauth->login = NULL;
+				}
+				if (rmconf->xauth->pass != NULL) {
+					vfree(rmconf->xauth->pass);
+					rmconf->xauth->pass = NULL;
+				}
+
+				rmconf->xauth->login = id;
+				rmconf->xauth->pass = key;
+			}
+#endif
+ 
+			plog(LLV_INFO, LOCATION, NULL,
+				"accept a request to establish IKE-SA: "
+				"%s\n", saddrwop2str(remote));
+
+			/* begin ident mode */
+			if (isakmp_ph1begin_i(rmconf, remote, local) < 0)
+				goto out1;
+
+			com->ac_errno = 0;
+out1:
+			if (local != NULL)
+				racoon_free(local);
+			if (remote != NULL)
+				racoon_free(remote);
+			break;
+		}
+		case ADMIN_PROTO_AH:
+		case ADMIN_PROTO_ESP:
+			break;
+		default:
+			/* ignore */
+			com->ac_errno = -1;
+		}
+	    }
+		break;
+
+	default:
+		plog(LLV_ERROR, LOCATION, NULL,
+			"invalid command: %d\n", com->ac_cmd);
+		com->ac_errno = -1;
+	}
+
+	if ((error = admin_reply(so2, com, buf)) != 0)
+		goto out;
+
+	error = 0;
+out:
+	if (buf != NULL)
+		vfree(buf);
+
+	return error;
+}
+
+static int
+admin_reply(so, combuf, buf)
+	int so;
+	struct admin_com *combuf;
+	vchar_t *buf;
+{
+	int tlen;
+	char *retbuf = NULL;
+
+	if (buf != NULL)
+		tlen = sizeof(*combuf) + buf->l;
+	else
+		tlen = sizeof(*combuf);
+
+	retbuf = racoon_calloc(1, tlen);
+	if (retbuf == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"failed to allocate admin buffer\n");
+		return -1;
+	}
+
+	memcpy(retbuf, combuf, sizeof(*combuf));
+	((struct admin_com *)retbuf)->ac_len = tlen;
+
+	if (buf != NULL)
+		memcpy(retbuf + sizeof(*combuf), buf->v, buf->l);
+
+	tlen = send(so, retbuf, tlen, 0);
+	racoon_free(retbuf);
+	if (tlen < 0) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"failed to send admin command: %s\n",
+			strerror(errno));
+		return -1;
+	}
+
+	return 0;
+}
+
+/* ADMIN_PROTO -> SADB_SATYPE */
+int
+admin2pfkey_proto(proto)
+	u_int proto;
+{
+	switch (proto) {
+	case ADMIN_PROTO_IPSEC:
+		return SADB_SATYPE_UNSPEC;
+	case ADMIN_PROTO_AH:
+		return SADB_SATYPE_AH;
+	case ADMIN_PROTO_ESP:
+		return SADB_SATYPE_ESP;
+	default:
+		plog(LLV_ERROR, LOCATION, NULL,
+			"unsupported proto for admin: %d\n", proto);
+		return -1;
+	}
+	/*NOTREACHED*/
+}
+
+int
+admin_init()
+{
+	if (adminsock_path == NULL) {
+		lcconf->sock_admin = -1;
+		return 0;
+	}
+
+	memset(&sunaddr, 0, sizeof(sunaddr));
+	sunaddr.sun_family = AF_UNIX;
+	snprintf(sunaddr.sun_path, sizeof(sunaddr.sun_path),
+		"%s", adminsock_path);
+
+	lcconf->sock_admin = socket(AF_UNIX, SOCK_STREAM, 0);
+	if (lcconf->sock_admin == -1) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"socket: %s\n", strerror(errno));
+		return -1;
+	}
+
+	unlink(sunaddr.sun_path);
+	if (bind(lcconf->sock_admin, (struct sockaddr *)&sunaddr,
+			sizeof(sunaddr)) != 0) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"bind(sockname:%s): %s\n",
+			sunaddr.sun_path, strerror(errno));
+		(void)close(lcconf->sock_admin);
+		return -1;
+	}
+
+	if (chown(sunaddr.sun_path, adminsock_owner, adminsock_group) != 0) {
+		plog(LLV_ERROR, LOCATION, NULL, 
+		    "chown(%s, %d, %d): %s\n", 
+		    sunaddr.sun_path, adminsock_owner, 
+		    adminsock_group, strerror(errno));
+		(void)close(lcconf->sock_admin);
+		return -1;
+	}
+
+	if (chmod(sunaddr.sun_path, adminsock_mode) != 0) {
+		plog(LLV_ERROR, LOCATION, NULL, 
+		    "chmod(%s, 0%03o): %s\n", 
+		    sunaddr.sun_path, adminsock_mode, strerror(errno));
+		(void)close(lcconf->sock_admin);
+		return -1;
+	}
+
+	if (listen(lcconf->sock_admin, 5) != 0) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"listen(sockname:%s): %s\n",
+			sunaddr.sun_path, strerror(errno));
+		(void)close(lcconf->sock_admin);
+		return -1;
+	}
+	plog(LLV_DEBUG, LOCATION, NULL,
+		"open %s as racoon management.\n", sunaddr.sun_path);
+
+	return 0;
+}
+
+int
+admin_close()
+{
+	close(lcconf->sock_admin);
+	return 0;
+}
+#endif
diff --git a/src/racoon/admin.h b/src/racoon/admin.h
new file mode 100644
index 0000000..cbc19e8
--- /dev/null
+++ b/src/racoon/admin.h
@@ -0,0 +1,114 @@
+/*	$NetBSD: admin.h,v 1.4 2006/09/09 16:22:09 manu Exp $	*/
+
+/* Id: admin.h,v 1.11 2005/06/19 22:37:47 manubsd Exp */
+
+/*
+ * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _ADMIN_H
+#define _ADMIN_H
+
+#define ADMINSOCK_PATH ADMINPORTDIR "/racoon.sock"
+
+extern char *adminsock_path;
+extern uid_t adminsock_owner;
+extern gid_t adminsock_group;
+extern mode_t adminsock_mode;
+
+/* command for administration. */
+/* NOTE: host byte order. */
+struct admin_com {
+	u_int16_t ac_len;	/* total packet length including data */
+	u_int16_t ac_cmd;
+	int16_t ac_errno;
+	u_int16_t ac_proto;
+};
+
+/*
+ * No data follows as the data.
+ * These don't use proto field.
+ */
+#define ADMIN_RELOAD_CONF	0x0001
+#define ADMIN_SHOW_SCHED	0x0002
+#define ADMIN_SHOW_EVT		0x0003
+
+/*
+ * No data follows as the data.
+ * These use proto field.
+ */
+#define ADMIN_SHOW_SA		0x0101
+#define ADMIN_FLUSH_SA		0x0102
+
+/*
+ * The admin_com_indexes follows, see below.
+ */
+#define ADMIN_DELETE_SA		0x0201
+#define ADMIN_ESTABLISH_SA	0x0202
+#define ADMIN_DELETE_ALL_SA_DST	0x0204	/* All SA for a given peer */
+
+/*
+ * The admin_com_indexes and admin_com_psk follow, see below.
+ */
+#define ADMIN_ESTABLISH_SA_PSK	0x0203
+
+/*
+ * user login follows
+ */
+#define ADMIN_LOGOUT_USER	0x0205  /* Delete SA for a given Xauth user */
+
+/*
+ * Range 0x08xx is reserved for privilege separation, see privsep.h 
+ */
+
+/* the value of proto */
+#define ADMIN_PROTO_ISAKMP	0x01ff
+#define ADMIN_PROTO_IPSEC	0x02ff
+#define ADMIN_PROTO_AH		0x0201
+#define ADMIN_PROTO_ESP		0x0202
+#define ADMIN_PROTO_INTERNAL	0x0301
+
+struct admin_com_indexes {
+	u_int8_t prefs;
+	u_int8_t prefd;
+	u_int8_t ul_proto;
+	u_int8_t reserved;
+	struct sockaddr_storage src;
+	struct sockaddr_storage dst;
+};
+
+struct admin_com_psk { 
+	int id_type;
+	size_t id_len;
+	size_t key_len;
+	/* Followed by id and key */
+}; 
+
+extern int admin2pfkey_proto __P((u_int));
+
+#endif /* _ADMIN_H */
diff --git a/src/racoon/admin_var.h b/src/racoon/admin_var.h
new file mode 100644
index 0000000..6d7ba81
--- /dev/null
+++ b/src/racoon/admin_var.h
@@ -0,0 +1,41 @@
+/*	$NetBSD: admin_var.h,v 1.4 2006/09/09 16:22:09 manu Exp $	*/
+
+/* Id: admin_var.h,v 1.7 2004/12/30 00:08:30 manubsd Exp */
+
+/*
+ * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _ADMIN_VAR_H
+#define _ADMIN_VAR_H
+
+extern int admin_handler __P((void));
+extern int admin_init __P((void));
+extern int admin_close __P((void));
+
+#endif /* _ADMIN_VAR_H */
diff --git a/src/racoon/algorithm.c b/src/racoon/algorithm.c
new file mode 100644
index 0000000..3fd50f6
--- /dev/null
+++ b/src/racoon/algorithm.c
@@ -0,0 +1,957 @@
+/*	$NetBSD: algorithm.c,v 1.8 2006/10/06 12:02:27 manu Exp $	*/
+
+/* Id: algorithm.c,v 1.15 2006/05/23 20:23:09 manubsd Exp */
+
+/*
+ * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <stdlib.h>
+
+#include "var.h"
+#include "misc.h"
+#include "vmbuf.h"
+#include "plog.h"
+#include "debug.h"
+
+#include "crypto_openssl.h"
+#include "dhgroup.h"
+#include "algorithm.h"
+#include "oakley.h"
+#include "isakmp_var.h"
+#include "isakmp.h"
+#include "ipsec_doi.h"
+#include "gcmalloc.h"
+
+static struct hash_algorithm oakley_hashdef[] = {
+{ "md5",	algtype_md5,		OAKLEY_ATTR_HASH_ALG_MD5,
+		eay_md5_init,		eay_md5_update,
+		eay_md5_final,		eay_md5_hashlen,
+		eay_md5_one, },
+{ "sha1",	algtype_sha1,		OAKLEY_ATTR_HASH_ALG_SHA,
+		eay_sha1_init,		eay_sha1_update,
+		eay_sha1_final,		eay_sha1_hashlen,
+		eay_sha1_one, },
+#ifdef WITH_SHA2
+{ "sha2_256",	algtype_sha2_256,	OAKLEY_ATTR_HASH_ALG_SHA2_256,
+		eay_sha2_256_init,	eay_sha2_256_update,
+		eay_sha2_256_final,	eay_sha2_256_hashlen,
+		eay_sha2_256_one, },
+{ "sha2_384",	algtype_sha2_384,	OAKLEY_ATTR_HASH_ALG_SHA2_384,
+		eay_sha2_384_init,	eay_sha2_384_update,
+		eay_sha2_384_final,	eay_sha2_384_hashlen,
+		eay_sha2_384_one, },
+{ "sha2_512",	algtype_sha2_512,	OAKLEY_ATTR_HASH_ALG_SHA2_512,
+		eay_sha2_512_init,	eay_sha2_512_update,
+		eay_sha2_512_final,	eay_sha2_512_hashlen,
+		eay_sha2_512_one, },
+#endif
+};
+
+static struct hmac_algorithm oakley_hmacdef[] = {
+{ "hmac_md5",	algtype_md5,		OAKLEY_ATTR_HASH_ALG_MD5,
+		eay_hmacmd5_init,	eay_hmacmd5_update,
+		eay_hmacmd5_final,	NULL,
+		eay_hmacmd5_one, },
+{ "hmac_sha1",	algtype_sha1,		OAKLEY_ATTR_HASH_ALG_SHA,
+		eay_hmacsha1_init,	eay_hmacsha1_update,
+		eay_hmacsha1_final,	NULL,
+		eay_hmacsha1_one, },
+#ifdef WITH_SHA2
+{ "hmac_sha2_256",	algtype_sha2_256,	OAKLEY_ATTR_HASH_ALG_SHA2_256,
+		eay_hmacsha2_256_init,	eay_hmacsha2_256_update,
+		eay_hmacsha2_256_final,	NULL,
+		eay_hmacsha2_256_one, },
+{ "hmac_sha2_384",	algtype_sha2_384,	OAKLEY_ATTR_HASH_ALG_SHA2_384,
+		eay_hmacsha2_384_init,	eay_hmacsha2_384_update,
+		eay_hmacsha2_384_final,	NULL,
+		eay_hmacsha2_384_one, },
+{ "hmac_sha2_512",	algtype_sha2_512,	OAKLEY_ATTR_HASH_ALG_SHA2_512,
+		eay_hmacsha2_512_init,	eay_hmacsha2_512_update,
+		eay_hmacsha2_512_final,	NULL,
+		eay_hmacsha2_512_one, },
+#endif
+};
+
+static struct enc_algorithm oakley_encdef[] = {
+{ "des",	algtype_des,		OAKLEY_ATTR_ENC_ALG_DES,	8,
+		eay_des_encrypt,	eay_des_decrypt,
+		eay_des_weakkey,	eay_des_keylen, },
+#ifdef HAVE_OPENSSL_IDEA_H
+{ "idea",	algtype_idea,		OAKLEY_ATTR_ENC_ALG_IDEA,	8,
+		eay_idea_encrypt,	eay_idea_decrypt,
+		eay_idea_weakkey,	eay_idea_keylen, },
+#endif
+{ "blowfish",	algtype_blowfish,	OAKLEY_ATTR_ENC_ALG_BLOWFISH,	8,
+		eay_bf_encrypt,		eay_bf_decrypt,
+		eay_bf_weakkey,		eay_bf_keylen, },
+#ifdef HAVE_OPENSSL_RC5_H
+{ "rc5",	algtype_rc5,		OAKLEY_ATTR_ENC_ALG_RC5,	8,
+		eay_rc5_encrypt,	eay_rc5_decrypt,
+		eay_rc5_weakkey,	eay_rc5_keylen, },
+#endif
+{ "3des",	algtype_3des,		OAKLEY_ATTR_ENC_ALG_3DES,	8,
+		eay_3des_encrypt,	eay_3des_decrypt,
+		eay_3des_weakkey,	eay_3des_keylen, },
+{ "cast",	algtype_cast128,	OAKLEY_ATTR_ENC_ALG_CAST,	8,
+		eay_cast_encrypt,	eay_cast_decrypt,
+		eay_cast_weakkey,	eay_cast_keylen, },
+{ "aes",	algtype_aes,	OAKLEY_ATTR_ENC_ALG_AES,	16,
+		eay_aes_encrypt,	eay_aes_decrypt,
+		eay_aes_weakkey,	eay_aes_keylen, },
+#ifdef HAVE_OPENSSL_CAMELLIA_H
+{ "camellia",	algtype_camellia,	OAKLEY_ATTR_ENC_ALG_CAMELLIA,	16,
+		eay_camellia_encrypt,	eay_camellia_decrypt,
+		eay_camellia_weakkey,	eay_camellia_keylen, },
+#endif
+};
+
+static struct enc_algorithm ipsec_encdef[] = {
+{ "des-iv64",	algtype_des_iv64,	IPSECDOI_ESP_DES_IV64,		8,
+		NULL,			NULL,
+		NULL,			eay_des_keylen, },
+{ "des",	algtype_des,		IPSECDOI_ESP_DES,		8,
+		NULL,			NULL,
+		NULL,			eay_des_keylen, },
+{ "3des",	algtype_3des,		IPSECDOI_ESP_3DES,		8,
+		NULL,			NULL,
+		NULL,			eay_3des_keylen, },
+#ifdef HAVE_OPENSSL_RC5_H
+{ "rc5",	algtype_rc5,		IPSECDOI_ESP_RC5,		8,
+		NULL,			NULL,
+		NULL,			eay_rc5_keylen, },
+#endif
+{ "cast",	algtype_cast128,	IPSECDOI_ESP_CAST,		8,
+		NULL,			NULL,
+		NULL,			eay_cast_keylen, },
+{ "blowfish",	algtype_blowfish,	IPSECDOI_ESP_BLOWFISH,		8,
+		NULL,			NULL,
+		NULL,			eay_bf_keylen, },
+{ "des-iv32",	algtype_des_iv32,	IPSECDOI_ESP_DES_IV32,		8,
+		NULL,			NULL,
+		NULL,			eay_des_keylen, },
+{ "null",	algtype_null_enc,	IPSECDOI_ESP_NULL,		8,
+		NULL,			NULL,
+		NULL,			eay_null_keylen, },
+{ "aes",	algtype_aes,		IPSECDOI_ESP_AES,		16,
+		NULL,			NULL,
+		NULL,			eay_aes_keylen, },
+{ "twofish",	algtype_twofish,	IPSECDOI_ESP_TWOFISH,		16,
+		NULL,			NULL,
+		NULL,			eay_twofish_keylen, },
+#ifdef HAVE_OPENSSL_IDEA_H
+{ "3idea",	algtype_3idea,		IPSECDOI_ESP_3IDEA,		8,
+		NULL,			NULL,
+		NULL,			NULL, },
+{ "idea",	algtype_idea,		IPSECDOI_ESP_IDEA,		8,
+		NULL,			NULL,
+		NULL,			NULL, },
+#endif
+{ "rc4",	algtype_rc4,		IPSECDOI_ESP_RC4,		8,
+		NULL,			NULL,
+		NULL,			NULL, },
+#ifdef HAVE_OPENSSL_CAMELLIA_H
+{ "camellia",	algtype_camellia,	IPSECDOI_ESP_CAMELLIA,		16,
+		NULL,			NULL,
+		NULL,			eay_camellia_keylen, },
+#endif
+};
+
+static struct hmac_algorithm ipsec_hmacdef[] = {
+{ "md5",	algtype_hmac_md5,	IPSECDOI_ATTR_AUTH_HMAC_MD5,
+		NULL,			NULL,
+		NULL,			eay_md5_hashlen,
+		NULL, },
+{ "sha1",	algtype_hmac_sha1,	IPSECDOI_ATTR_AUTH_HMAC_SHA1,
+		NULL,			NULL,
+		NULL,			eay_sha1_hashlen,
+		NULL, },
+{ "kpdk",	algtype_kpdk,		IPSECDOI_ATTR_AUTH_KPDK,
+		NULL,			NULL,
+		NULL,			eay_kpdk_hashlen,
+		NULL, },
+{ "null",	algtype_non_auth,	IPSECDOI_ATTR_AUTH_NONE,
+		NULL,			NULL,
+		NULL,			eay_null_hashlen,
+		NULL, },
+#ifdef WITH_SHA2
+{ "hmac_sha2_256",	algtype_hmac_sha2_256,IPSECDOI_ATTR_AUTH_HMAC_SHA2_256,
+		NULL,			NULL,
+		NULL,			eay_sha2_256_hashlen,
+		NULL, },
+{ "hmac_sha2_384",	algtype_hmac_sha2_384,IPSECDOI_ATTR_AUTH_HMAC_SHA2_384,
+		NULL,			NULL,
+		NULL,			eay_sha2_384_hashlen,
+		NULL, },
+{ "hmac_sha2_512",	algtype_hmac_sha2_512,IPSECDOI_ATTR_AUTH_HMAC_SHA2_512,
+		NULL,			NULL,
+		NULL,			eay_sha2_512_hashlen,
+		NULL, },
+#endif
+};
+
+static struct misc_algorithm ipsec_compdef[] = {
+{ "oui",	algtype_oui,		IPSECDOI_IPCOMP_OUI, },
+{ "deflate",	algtype_deflate,	IPSECDOI_IPCOMP_DEFLATE, },
+{ "lzs",	algtype_lzs,		IPSECDOI_IPCOMP_LZS, },
+};
+
+/*
+ * In case of asymetric modes (hybrid xauth), what's racoon mode of
+ * operations ; it seems that the proposal should always use the
+ * initiator half (unless a server initiates a connection, which is
+ * not handled, and probably not useful).
+ */
+static struct misc_algorithm oakley_authdef[] = {
+{ "pre_shared_key",	algtype_psk,	OAKLEY_ATTR_AUTH_METHOD_PSKEY, },
+{ "dsssig",		algtype_dsssig,	OAKLEY_ATTR_AUTH_METHOD_DSSSIG, },
+{ "rsasig",		algtype_rsasig,	OAKLEY_ATTR_AUTH_METHOD_RSASIG, },
+{ "rsaenc",		algtype_rsaenc,	OAKLEY_ATTR_AUTH_METHOD_RSAENC, },
+{ "rsarev",		algtype_rsarev,	OAKLEY_ATTR_AUTH_METHOD_RSAREV, },
+
+{ "gssapi_krb",		algtype_gssapikrb,
+    OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB, },
+
+#ifdef ENABLE_HYBRID
+{ "hybrid_rsa_server",	algtype_hybrid_rsa_s,	
+    OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_R, },
+
+{ "hybrid_dss_server",	algtype_hybrid_dss_s,	
+    OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_R, },
+
+{ "xauth_psk_server", 	algtype_xauth_psk_s,	
+    OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_R, },
+
+{ "xauth_rsa_server", 	algtype_xauth_rsa_s,	
+    OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_R, },
+
+{ "hybrid_rsa_client",	algtype_hybrid_rsa_c,	
+    OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_I, },
+
+{ "hybrid_dss_client",	algtype_hybrid_dss_c,	
+    OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_I, },
+
+{ "xauth_psk_client",	algtype_xauth_psk_c,	
+    OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_I, },
+
+{ "xauth_rsa_client",	algtype_xauth_rsa_c,	
+    OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_I, },
+#endif
+};
+
+static struct dh_algorithm oakley_dhdef[] = {
+{ "modp768",	algtype_modp768,	OAKLEY_ATTR_GRP_DESC_MODP768,
+		&dh_modp768, },
+{ "modp1024",	algtype_modp1024,	OAKLEY_ATTR_GRP_DESC_MODP1024,
+		&dh_modp1024, },
+{ "modp1536",	algtype_modp1536,	OAKLEY_ATTR_GRP_DESC_MODP1536,
+		&dh_modp1536, },
+{ "modp2048",	algtype_modp2048,	OAKLEY_ATTR_GRP_DESC_MODP2048,
+		&dh_modp2048, },
+{ "modp3072",	algtype_modp3072,	OAKLEY_ATTR_GRP_DESC_MODP3072,
+		&dh_modp3072, },
+{ "modp4096",	algtype_modp4096,	OAKLEY_ATTR_GRP_DESC_MODP4096,
+		&dh_modp4096, },
+{ "modp6144",	algtype_modp6144,	OAKLEY_ATTR_GRP_DESC_MODP6144,
+		&dh_modp6144, },
+{ "modp8192",	algtype_modp8192,	OAKLEY_ATTR_GRP_DESC_MODP8192,
+		&dh_modp8192, },
+};
+
+static struct hash_algorithm *alg_oakley_hashdef __P((int));
+static struct hmac_algorithm *alg_oakley_hmacdef __P((int));
+static struct enc_algorithm *alg_oakley_encdef __P((int));
+static struct enc_algorithm *alg_ipsec_encdef __P((int));
+static struct hmac_algorithm *alg_ipsec_hmacdef __P((int));
+static struct dh_algorithm *alg_oakley_dhdef __P((int));
+
+/* oakley hash algorithm */
+static struct hash_algorithm *
+alg_oakley_hashdef(doi)
+	int doi;
+{
+	int i;
+
+	for (i = 0; i < ARRAYLEN(oakley_hashdef); i++)
+		if (doi == oakley_hashdef[i].doi) {
+			plog(LLV_DEBUG, LOCATION, NULL, "hash(%s)\n",
+				oakley_hashdef[i].name);
+			return &oakley_hashdef[i];
+		}
+	return NULL;
+}
+
+int
+alg_oakley_hashdef_ok(doi)
+	int doi;
+{
+	struct hash_algorithm *f;
+
+	f = alg_oakley_hashdef(doi);
+	if (f == NULL)
+		return 0;
+
+	return 1;
+}
+
+int
+alg_oakley_hashdef_doi(type)
+	int type;
+{
+	int i, res = -1;
+
+	for (i = 0; i < ARRAYLEN(oakley_hashdef); i++)
+		if (type == oakley_hashdef[i].type) {
+			res = oakley_hashdef[i].doi;
+			break;
+		}
+	return res;
+}
+
+int
+alg_oakley_hashdef_hashlen(doi)
+	int doi;
+{
+	struct hash_algorithm *f;
+
+	f = alg_oakley_hashdef(doi);
+	if (f == NULL || f->hashlen == NULL)
+		return 0;
+
+	return (f->hashlen)();
+}
+
+const char *
+alg_oakley_hashdef_name (doi)
+	int doi;
+{
+	struct hash_algorithm *f;
+
+	f = alg_oakley_hashdef(doi);
+	if (f == NULL)
+		return "*UNKNOWN*";
+
+	return f->name;
+}
+
+vchar_t *
+alg_oakley_hashdef_one(doi, buf)
+	int doi;
+	vchar_t *buf;
+{
+	struct hash_algorithm *f;
+
+	f = alg_oakley_hashdef(doi);
+	if (f == NULL || f->hashlen == NULL)
+		return NULL;
+
+	return (f->one)(buf);
+}
+
+/* oakley hmac algorithm */
+static struct hmac_algorithm *
+alg_oakley_hmacdef(doi)
+	int doi;
+{
+	int i;
+
+	for (i = 0; i < ARRAYLEN(oakley_hmacdef); i++)
+		if (doi == oakley_hmacdef[i].doi) {
+			plog(LLV_DEBUG, LOCATION, NULL, "hmac(%s)\n",
+				oakley_hmacdef[i].name);
+			return &oakley_hmacdef[i];
+		}
+	return NULL;
+}
+
+int
+alg_oakley_hmacdef_doi(type)
+	int type;
+{
+	int i, res = -1;
+
+	for (i = 0; i < ARRAYLEN(oakley_hmacdef); i++)
+		if (type == oakley_hmacdef[i].type) {
+			res = oakley_hmacdef[i].doi;
+			break;
+		}
+	return res;
+}
+
+vchar_t *
+alg_oakley_hmacdef_one(doi, key, buf)
+	int doi;
+	vchar_t *key, *buf;
+{
+	struct hmac_algorithm *f;
+	vchar_t *res;
+#ifdef ENABLE_STATS
+	struct timeval start, end;
+#endif
+
+	f = alg_oakley_hmacdef(doi);
+	if (f == NULL || f->one == NULL)
+		return NULL;
+
+#ifdef ENABLE_STATS
+	gettimeofday(&start, NULL);
+#endif
+
+	res = (f->one)(key, buf);
+
+#ifdef ENABLE_STATS
+	gettimeofday(&end, NULL);
+	syslog(LOG_NOTICE, "%s(%s size=%zu): %8.6f", __func__,
+		f->name, buf->l, timedelta(&start, &end));
+#endif
+
+	return res;
+}
+
+/* oakley encryption algorithm */
+static struct enc_algorithm *
+alg_oakley_encdef(doi)
+	int doi;
+{
+	int i;
+
+	for (i = 0; i < ARRAYLEN(oakley_encdef); i++)
+		if (doi == oakley_encdef[i].doi) {
+			plog(LLV_DEBUG, LOCATION, NULL, "encryption(%s)\n",
+				oakley_encdef[i].name);
+			return &oakley_encdef[i];
+		}
+	return NULL;
+}
+
+int
+alg_oakley_encdef_ok(doi)
+	int doi;
+{
+	struct enc_algorithm *f;
+
+	f = alg_oakley_encdef(doi);
+	if (f == NULL)
+		return 0;
+
+	return 1;
+}
+
+int
+alg_oakley_encdef_doi(type)
+	int type;
+{
+	int i, res = -1;
+
+	for (i = 0; i < ARRAYLEN(oakley_encdef); i++)
+		if (type == oakley_encdef[i].type) {
+			res = oakley_encdef[i].doi;
+			break;
+		}
+	return res;
+}
+
+int
+alg_oakley_encdef_keylen(doi, len)
+	int doi, len;
+{
+	struct enc_algorithm *f;
+
+	f = alg_oakley_encdef(doi);
+	if (f == NULL || f->keylen == NULL)
+		return -1;
+
+	return (f->keylen)(len);
+}
+
+int
+alg_oakley_encdef_blocklen(doi)
+	int doi;
+{
+	struct enc_algorithm *f;
+
+	f = alg_oakley_encdef(doi);
+	if (f == NULL)
+		return -1;
+
+	return f->blocklen;
+}
+
+const char *
+alg_oakley_encdef_name (doi)
+	int doi;
+{
+	struct enc_algorithm *f;
+
+	f = alg_oakley_encdef(doi);
+	if (f == NULL)
+		return "*UNKNOWN*";
+
+	return f->name;
+}
+
+vchar_t *
+alg_oakley_encdef_decrypt(doi, buf, key, iv)
+	int doi;
+	vchar_t *buf, *key, *iv;
+{
+	vchar_t *res;
+	struct enc_algorithm *f;
+#ifdef ENABLE_STATS
+	struct timeval start, end;
+#endif
+
+	f = alg_oakley_encdef(doi);
+	if (f == NULL || f->decrypt == NULL)
+		return NULL;
+
+#ifdef ENABLE_STATS
+	gettimeofday(&start, NULL);
+#endif
+
+	res = (f->decrypt)(buf, key, iv);
+
+#ifdef ENABLE_STATS
+	gettimeofday(&end, NULL);
+	syslog(LOG_NOTICE, "%s(%s klen=%zu size=%zu): %8.6f", __func__,
+		f->name, key->l << 3, buf->l, timedelta(&start, &end));
+#endif
+	return res;
+}
+
+vchar_t *
+alg_oakley_encdef_encrypt(doi, buf, key, iv)
+	int doi;
+	vchar_t *buf, *key, *iv;
+{
+	vchar_t *res;
+	struct enc_algorithm *f;
+#ifdef ENABLE_STATS
+	struct timeval start, end;
+#endif
+
+	f = alg_oakley_encdef(doi);
+	if (f == NULL || f->encrypt == NULL)
+		return NULL;
+
+#ifdef ENABLE_STATS
+	gettimeofday(&start, NULL);
+#endif
+
+	res = (f->encrypt)(buf, key, iv);
+
+#ifdef ENABLE_STATS
+	gettimeofday(&end, NULL);
+	syslog(LOG_NOTICE, "%s(%s klen=%zu size=%zu): %8.6f", __func__,
+		f->name, key->l << 3, buf->l, timedelta(&start, &end));
+#endif
+	return res;
+}
+
+/* ipsec encryption algorithm */
+static struct enc_algorithm *
+alg_ipsec_encdef(doi)
+	int doi;
+{
+	int i;
+
+	for (i = 0; i < ARRAYLEN(ipsec_encdef); i++)
+		if (doi == ipsec_encdef[i].doi) {
+			plog(LLV_DEBUG, LOCATION, NULL, "encryption(%s)\n",
+				ipsec_encdef[i].name);
+			return &ipsec_encdef[i];
+		}
+	return NULL;
+}
+
+int
+alg_ipsec_encdef_doi(type)
+	int type;
+{
+	int i, res = -1;
+
+	for (i = 0; i < ARRAYLEN(ipsec_encdef); i++)
+		if (type == ipsec_encdef[i].type) {
+			res = ipsec_encdef[i].doi;
+			break;
+		}
+	return res;
+}
+
+int
+alg_ipsec_encdef_keylen(doi, len)
+	int doi, len;
+{
+	struct enc_algorithm *f;
+
+	f = alg_ipsec_encdef(doi);
+	if (f == NULL || f->keylen == NULL)
+		return -1;
+
+	return (f->keylen)(len);
+}
+
+/* ipsec hmac algorithm */
+static struct hmac_algorithm *
+alg_ipsec_hmacdef(doi)
+	int doi;
+{
+	int i;
+
+	for (i = 0; i < ARRAYLEN(ipsec_hmacdef); i++)
+		if (doi == ipsec_hmacdef[i].doi) {
+			plog(LLV_DEBUG, LOCATION, NULL, "hmac(%s)\n",
+				ipsec_hmacdef[i].name);
+			return &ipsec_hmacdef[i];
+		}
+	return NULL;
+}
+
+int
+alg_ipsec_hmacdef_doi(type)
+	int type;
+{
+	int i, res = -1;
+
+	for (i = 0; i < ARRAYLEN(ipsec_hmacdef); i++)
+		if (type == ipsec_hmacdef[i].type) {
+			res = ipsec_hmacdef[i].doi;
+			break;
+		}
+	return res;
+}
+
+int
+alg_ipsec_hmacdef_hashlen(doi)
+	int doi;
+{
+	struct hmac_algorithm *f;
+
+	f = alg_ipsec_hmacdef(doi);
+	if (f == NULL || f->hashlen == NULL)
+		return -1;
+
+	return (f->hashlen)();
+}
+
+/* ip compression */
+int
+alg_ipsec_compdef_doi(type)
+	int type;
+{
+	int i, res = -1;
+
+	for (i = 0; i < ARRAYLEN(ipsec_compdef); i++)
+		if (type == ipsec_compdef[i].type) {
+			res = ipsec_compdef[i].doi;
+			break;
+		}
+	return res;
+}
+
+/* dh algorithm */
+static struct dh_algorithm *
+alg_oakley_dhdef(doi)
+	int doi;
+{
+	int i;
+
+	for (i = 0; i < ARRAYLEN(oakley_dhdef); i++)
+		if (doi == oakley_dhdef[i].doi) {
+			plog(LLV_DEBUG, LOCATION, NULL, "hmac(%s)\n",
+				oakley_dhdef[i].name);
+			return &oakley_dhdef[i];
+		}
+	return NULL;
+}
+
+int
+alg_oakley_dhdef_ok(doi)
+	int doi;
+{
+	struct dh_algorithm *f;
+
+	f = alg_oakley_dhdef(doi);
+	if (f == NULL)
+		return 0;
+
+	return 1;
+}
+
+int
+alg_oakley_dhdef_doi(type)
+	int type;
+{
+	int i, res = -1;
+
+	for (i = 0; i < ARRAYLEN(oakley_dhdef); i++)
+		if (type == oakley_dhdef[i].type) {
+			res = oakley_dhdef[i].doi;
+			break;
+		}
+	return res;
+}
+
+struct dhgroup *
+alg_oakley_dhdef_group(doi)
+	int doi;
+{
+	struct dh_algorithm *f;
+
+	f = alg_oakley_dhdef(doi);
+	if (f == NULL || f->dhgroup == NULL)
+		return NULL;
+
+	return f->dhgroup;
+}
+
+const char *
+alg_oakley_dhdef_name (doi)
+	int doi;
+{
+	struct dh_algorithm *f;
+	
+	f = alg_oakley_dhdef(doi);
+	if (f == NULL)
+		return "*UNKNOWN*";
+	return f->name;
+}
+
+/* authentication method */
+int
+alg_oakley_authdef_doi(type)
+	int type;
+{
+	int i, res = -1;
+
+	for (i = 0; i < ARRAYLEN(oakley_authdef); i++)
+		if (type == oakley_authdef[i].type) {
+			res = oakley_authdef[i].doi;
+			break;
+		}
+	return res;
+}
+
+const char *
+alg_oakley_authdef_name (doi)
+	int doi;
+{
+	int i;
+
+	for (i = 0; i < ARRAYLEN(oakley_authdef); i++)
+		if (doi == oakley_authdef[i].doi) {
+			return oakley_authdef[i].name;
+		}
+	return "*UNKNOWN*";
+}
+
+/*
+ * give the default key length
+ * OUT:	-1:		NG
+ *	0:		fixed key cipher, key length not allowed
+ *	positive:	default key length
+ */
+int
+default_keylen(class, type)
+	int class, type;
+{
+
+	switch (class) {
+	case algclass_isakmp_enc:
+	case algclass_ipsec_enc:
+		break;
+	default:
+		return 0;
+	}
+
+	switch (type) {
+	case algtype_blowfish:
+	case algtype_rc5:
+	case algtype_cast128:
+	case algtype_aes:
+	case algtype_twofish:
+	case algtype_camellia:
+		return 128;
+	default:
+		return 0;
+	}
+}
+
+/*
+ * check key length
+ * OUT:	-1:	NG
+ *	0:	OK
+ */
+int
+check_keylen(class, type, len)
+	int class, type, len;
+{
+	int badrange;
+
+	switch (class) {
+	case algclass_isakmp_enc:
+	case algclass_ipsec_enc:
+		break;
+	default:
+		/* unknown class, punt */
+		plog(LLV_ERROR, LOCATION, NULL,
+			"unknown algclass %d\n", class);
+		return -1;
+	}
+
+	/* key length must be multiple of 8 bytes - RFC2451 2.2 */
+	switch (type) {
+	case algtype_blowfish:
+	case algtype_rc5:
+	case algtype_cast128:
+	case algtype_aes:
+	case algtype_twofish:
+	case algtype_camellia:
+		if (len % 8 != 0) {
+			plog(LLV_ERROR, LOCATION, NULL,
+				"key length %d is not multiple of 8\n", len);
+			return -1;
+		}
+		break;
+	}
+
+	/* key length range */
+	badrange = 0;
+	switch (type) {
+	case algtype_blowfish:
+		if (len < 40 || 448 < len)
+			badrange++;
+		break;
+	case algtype_rc5:
+		if (len < 40 || 2040 < len)
+			badrange++;
+		break;
+	case algtype_cast128:
+		if (len < 40 || 128 < len)
+			badrange++;
+		break;
+	case algtype_aes:
+		if (!(len == 128 || len == 192 || len == 256))
+			badrange++;
+		break;
+	case algtype_twofish:
+		if (len < 40 || 256 < len)
+			badrange++;
+		break;
+	case algtype_camellia:
+		if (!(len == 128 || len == 192 || len == 256))
+			badrange++;
+		break;
+	default:
+		if (len) {
+			plog(LLV_ERROR, LOCATION, NULL,
+				"key length is not allowed");
+			return -1;
+		}
+		break;
+	}
+	if (badrange) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"key length out of range\n");
+		return -1;
+	}
+
+	return 0;
+}
+
+/*
+ * convert algorithm type to DOI value.
+ * OUT	-1   : NG
+ *	other: converted.
+ */
+int
+algtype2doi(class, type)
+	int class, type;
+{
+	int res = -1;
+
+	switch (class) {
+	case algclass_ipsec_enc:
+		res = alg_ipsec_encdef_doi(type);
+		break;
+	case algclass_ipsec_auth:
+		res = alg_ipsec_hmacdef_doi(type);
+		break;
+	case algclass_ipsec_comp:
+		res = alg_ipsec_compdef_doi(type);
+		break;
+	case algclass_isakmp_enc:
+		res =  alg_oakley_encdef_doi(type);
+		break;
+	case algclass_isakmp_hash:
+		res = alg_oakley_hashdef_doi(type);
+		break;
+	case algclass_isakmp_dh:
+		res = alg_oakley_dhdef_doi(type);
+		break;
+	case algclass_isakmp_ameth:
+		res = alg_oakley_authdef_doi(type);
+		break;
+	}
+	return res;
+}
+
+/*
+ * convert algorithm class to DOI value.
+ * OUT	-1   : NG
+ *	other: converted.
+ */
+int
+algclass2doi(class)
+	int class;
+{
+	switch (class) {
+	case algclass_ipsec_enc:
+		return IPSECDOI_PROTO_IPSEC_ESP;
+	case algclass_ipsec_auth:
+		return IPSECDOI_ATTR_AUTH;
+	case algclass_ipsec_comp:
+		return IPSECDOI_PROTO_IPCOMP;
+	case algclass_isakmp_enc:
+		return OAKLEY_ATTR_ENC_ALG;
+	case algclass_isakmp_hash:
+		return OAKLEY_ATTR_HASH_ALG;
+	case algclass_isakmp_dh:
+		return OAKLEY_ATTR_GRP_DESC;
+	case algclass_isakmp_ameth:
+		return OAKLEY_ATTR_AUTH_METHOD;
+	default:
+		return -1;
+	}
+	/*NOTREACHED*/
+	return -1;
+}
diff --git a/src/racoon/algorithm.h b/src/racoon/algorithm.h
new file mode 100644
index 0000000..8b631b6
--- /dev/null
+++ b/src/racoon/algorithm.h
@@ -0,0 +1,216 @@
+/*	$NetBSD: algorithm.h,v 1.5 2006/10/06 12:02:27 manu Exp $	*/
+
+/* Id: algorithm.h,v 1.10 2005/04/09 16:25:23 manubsd Exp */
+
+/*
+ * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _ALGORITHM_H
+#define _ALGORITHM_H
+
+#include <gnuc.h>
+
+/* algorithm class */
+enum {
+	algclass_ipsec_enc,
+	algclass_ipsec_auth,
+	algclass_ipsec_comp,
+	algclass_isakmp_enc,
+	algclass_isakmp_hash,
+	algclass_isakmp_dh,
+	algclass_isakmp_ameth,	/* authentication method. */
+#define MAXALGCLASS	7
+};
+
+#define ALG_DEFAULT_KEYLEN	64
+
+#define ALGTYPE_NOTHING		0
+
+/* algorithm type */
+enum algtype {
+	algtype_nothing = 0,
+
+	/* enc */
+	algtype_des_iv64,
+	algtype_des,
+	algtype_3des,
+	algtype_rc5,
+	algtype_idea,
+	algtype_cast128,
+	algtype_blowfish,
+	algtype_3idea,
+	algtype_des_iv32,
+	algtype_rc4,
+	algtype_null_enc,
+	algtype_aes,
+	algtype_twofish,
+	algtype_camellia,
+
+	/* ipsec auth */
+	algtype_hmac_md5,
+	algtype_hmac_sha1,
+	algtype_des_mac,
+	algtype_kpdk,
+	algtype_non_auth,
+	algtype_hmac_sha2_256,
+	algtype_hmac_sha2_384,
+	algtype_hmac_sha2_512,
+
+	/* ipcomp */
+	algtype_oui,
+	algtype_deflate,
+	algtype_lzs,
+
+	/* hash */
+	algtype_md5,
+	algtype_sha1,
+	algtype_tiger,
+	algtype_sha2_256,
+	algtype_sha2_384,
+	algtype_sha2_512,
+
+	/* dh_group */
+	algtype_modp768,
+	algtype_modp1024,
+	algtype_ec2n155,
+	algtype_ec2n185,
+	algtype_modp1536,
+	algtype_modp2048,
+	algtype_modp3072,
+	algtype_modp4096,
+	algtype_modp6144,
+	algtype_modp8192,
+
+	/* authentication method. */
+	algtype_psk,
+	algtype_dsssig,
+	algtype_rsasig,
+	algtype_rsaenc,
+	algtype_rsarev,
+	algtype_gssapikrb,
+#ifdef ENABLE_HYBRID
+	algtype_hybrid_rsa_s,
+	algtype_hybrid_dss_s,
+	algtype_hybrid_rsa_c,
+	algtype_hybrid_dss_c,
+	algtype_xauth_psk_s,
+	algtype_xauth_psk_c,
+	algtype_xauth_rsa_s,
+	algtype_xauth_rsa_c,
+#endif
+};
+
+struct hmac_algorithm {
+	char *name;
+	int type;
+	int doi;
+	caddr_t (*init) __P((vchar_t *));
+	void (*update) __P((caddr_t, vchar_t *));
+	vchar_t *(*final) __P((caddr_t));
+	int (*hashlen) __P((void));
+	vchar_t *(*one) __P((vchar_t *, vchar_t *));
+};
+
+struct hash_algorithm {
+	char *name;
+	int type;
+	int doi;
+	caddr_t (*init) __P((void));
+	void (*update) __P((caddr_t, vchar_t *));
+	vchar_t *(*final) __P((caddr_t));
+	int (*hashlen) __P((void));
+	vchar_t *(*one) __P((vchar_t *));
+};
+
+struct enc_algorithm {
+	char *name;
+	int type;
+	int doi;
+	int blocklen;
+	vchar_t *(*encrypt) __P((vchar_t *, vchar_t *, vchar_t *));
+	vchar_t *(*decrypt) __P((vchar_t *, vchar_t *, vchar_t *));
+	int (*weakkey) __P((vchar_t *));
+	int (*keylen) __P((int));
+};
+
+/* dh group */
+struct dh_algorithm {
+	char *name;
+	int type;
+	int doi;
+	struct dhgroup *dhgroup;
+};
+
+/* ipcomp, auth meth, dh group */
+struct misc_algorithm {
+	char *name;
+	int type;
+	int doi;
+};
+
+extern int alg_oakley_hashdef_ok __P((int));
+extern int alg_oakley_hashdef_doi __P((int));
+extern int alg_oakley_hashdef_hashlen __P((int));
+extern vchar_t *alg_oakley_hashdef_one __P((int, vchar_t *));
+
+extern int alg_oakley_hmacdef_doi __P((int));
+extern vchar_t *alg_oakley_hmacdef_one __P((int, vchar_t *, vchar_t *));
+
+extern int alg_oakley_encdef_ok __P((int));
+extern int alg_oakley_encdef_doi __P((int));
+extern int alg_oakley_encdef_keylen __P((int, int));
+extern int alg_oakley_encdef_blocklen __P((int));
+extern vchar_t *alg_oakley_encdef_decrypt __P((int, vchar_t *, vchar_t *, vchar_t *));
+extern vchar_t *alg_oakley_encdef_encrypt __P((int, vchar_t *, vchar_t *, vchar_t *));
+
+extern int alg_ipsec_encdef_doi __P((int));
+extern int alg_ipsec_encdef_keylen __P((int, int));
+
+extern int alg_ipsec_hmacdef_doi __P((int));
+extern int alg_ipsec_hmacdef_hashlen __P((int));
+
+extern int alg_ipsec_compdef_doi __P((int));
+
+extern int alg_oakley_dhdef_doi __P((int));
+extern int alg_oakley_dhdef_ok __P((int));
+extern struct dhgroup *alg_oakley_dhdef_group __P((int));
+
+extern int alg_oakley_authdef_doi __P((int));
+
+extern int default_keylen __P((int, int));
+extern int check_keylen __P((int, int, int));
+extern int algtype2doi __P((int, int));
+extern int algclass2doi __P((int));
+
+extern const char *alg_oakley_encdef_name __P((int));
+extern const char *alg_oakley_hashdef_name __P((int));
+extern const char *alg_oakley_dhdef_name __P((int));
+extern const char *alg_oakley_authdef_name __P((int));
+
+#endif /* _ALGORITHM_H */
diff --git a/src/racoon/backupsa.c b/src/racoon/backupsa.c
new file mode 100644
index 0000000..7b51154
--- /dev/null
+++ b/src/racoon/backupsa.c
@@ -0,0 +1,474 @@
+/*	$NetBSD: backupsa.c,v 1.8.4.1 2007/08/01 11:52:19 vanhu Exp $	*/
+
+/*	$KAME: backupsa.c,v 1.16 2001/12/31 20:13:40 thorpej Exp $	*/
+
+/*
+ * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+
+#include <netinet/in.h>
+#include PATH_IPSEC_H
+
+#if TIME_WITH_SYS_TIME
+# include <sys/time.h>
+# include <time.h>
+#else
+# if HAVE_SYS_TIME_H
+#  include <sys/time.h>
+# else
+#  include <time.h>
+# endif
+#endif
+
+#include "var.h"
+#include "misc.h"
+#include "vmbuf.h"
+#include "str2val.h"
+#include "plog.h"
+#include "debug.h"
+
+#include "localconf.h"
+#include "sockmisc.h"
+#include "safefile.h"
+#include "backupsa.h"
+#include "libpfkey.h"
+
+/*
+ * (time string)%(sa parameter)
+ * (time string) := ex. Nov 24 18:22:48 1986
+ * (sa parameter) :=
+ *    src dst satype spi mode reqid wsize \
+ *    e_type e_keylen a_type a_keylen flags \
+ *    l_alloc l_bytes l_addtime l_usetime seq keymat
+ */
+static char *format = "%b %d %T %Y";	/* time format */
+static char *strmon[12] = {
+        "Jan", "Feb", "Mar", "Apr", "May", "Jun",
+        "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
+};
+
+static char *str2tmx __P((char *, struct tm *));
+static int str2num __P((char *, int));
+
+#ifdef ANDROID_CHANGES
+#include <linux/coda.h>
+u_quad_t strtouq(char *nptr, char **endptr, int base) {
+	return strtoul(nptr, endptr, base);
+}
+#endif
+/*
+ * output the sa parameter.
+ */
+int
+backupsa_to_file(sa_args)
+	struct pfkey_send_sa_args *sa_args;
+{
+	char buf[1024];
+	struct tm *tm;
+	time_t t;
+	char *p, *k;
+	int len, l, i;
+	FILE *fp;
+
+	p = buf;
+	len = sizeof(buf);
+
+	t = time(NULL);
+	tm = localtime(&t);
+	l = strftime(p, len, format, tm);
+	p += l;
+	len -= l;
+	if (len < 0)
+		goto err;
+
+	l = snprintf(p, len, "%%");
+	if (l < 0 || l >= len)
+		goto err;
+	p += l;
+	len -= l;
+	if (len < 0)
+		goto err;
+
+        i = getnameinfo(sa_args->src, sysdep_sa_len(sa_args->src), p, len, NULL, 0, NIFLAGS);
+	if (i != 0)
+		goto err;
+	l = strlen(p);
+	p += l;
+	len -= l;
+	if (len < 0)
+		goto err;
+
+	l = snprintf(p, len, " ");
+	if (l < 0 || l >= len)
+		goto err;
+	p += l;
+	len -= l;
+	if (len < 0)
+		goto err;
+
+        i = getnameinfo(sa_args->dst, sysdep_sa_len(sa_args->dst), p, len, NULL, 0, NIFLAGS);
+	if (i != 0)
+		goto err;
+	l = strlen(p);
+	p += l;
+	len -= l;
+	if (len < 0)
+		goto err;
+
+	l = snprintf(p, len,
+		" %u %lu %u %u %u "
+		"%u %u %u %u %u "
+		"%u %llu %llu %llu %u",
+		sa_args->satype, (unsigned long)ntohl(sa_args->spi), 
+		sa_args->mode, sa_args->reqid, sa_args->wsize, sa_args->e_type, 
+		sa_args->e_keylen, sa_args->a_type, sa_args->a_keylen, 
+		sa_args->flags, sa_args->l_alloc, 
+		(unsigned long long)sa_args->l_bytes, 
+		(unsigned long long)sa_args->l_addtime, 
+		(unsigned long long)sa_args->l_usetime, sa_args->seq);
+
+	if (l < 0 || l >= len)
+		goto err;
+	p += l;
+	len -= l;
+	if (len < 0)
+		goto err;
+
+	k = val2str(sa_args->keymat, sa_args->e_keylen + sa_args->a_keylen);
+	l = snprintf(p, len, " %s", k);
+	racoon_free(k);
+	if (l < 0 || l >= len)
+		goto err;
+	p += l;
+	len -= l;
+	if (len < 0)
+		goto err;
+
+	/* open the file and write the SA parameter */
+	if (safefile(lcconf->pathinfo[LC_PATHTYPE_BACKUPSA], 1) != 0 ||
+	    (fp = fopen(lcconf->pathinfo[LC_PATHTYPE_BACKUPSA], "a")) == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"failed to open the backup file %s.\n",
+			lcconf->pathinfo[LC_PATHTYPE_BACKUPSA]);
+		return -1;
+	}
+	fprintf(fp, "%s\n", buf);
+	fclose(fp);
+
+	return 0;
+
+err:
+	plog(LLV_ERROR, LOCATION, NULL,
+		"SA cannot be saved to a file.\n");
+	return -1;
+}
+
+int
+backupsa_from_file()
+{
+	FILE *fp;
+	char buf[512];
+	struct tm tm;
+	time_t created, current;
+	char *p, *q;
+	size_t keymatlen;
+	int line;
+	struct pfkey_send_sa_args sa_args;
+
+	memset(&sa_args, 0, sizeof(sa_args));
+
+	if (safefile(lcconf->pathinfo[LC_PATHTYPE_BACKUPSA], 1) == 0)
+		fp = fopen(lcconf->pathinfo[LC_PATHTYPE_BACKUPSA], "r");
+	else
+		fp = NULL;
+	if (fp == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"failed to open the backup file %s.\n",
+			lcconf->pathinfo[LC_PATHTYPE_BACKUPSA]);
+		return -1;
+	}
+
+	current = time(NULL);
+
+	for(line = 1; fgets(buf, sizeof(buf), fp) != NULL; line++) {
+		/* comment line */
+		if (buf[0] == '#')
+			continue;
+
+		memset(&tm, 0, sizeof(tm));
+		p = str2tmx(buf, &tm);
+		if (*p != '%') {
+	err:
+			plog(LLV_ERROR, LOCATION, NULL,
+				"illegal format line#%d in %s: %s\n",
+				line, lcconf->pathinfo[LC_PATHTYPE_BACKUPSA], 
+				buf);
+			goto next;
+		}
+		created = mktime(&tm);
+		p++;
+
+		for (q = p; *q != '\0' && !isspace((int)*q); q++)
+			;
+		*q = '\0';
+		if ((sa_args.src = str2saddr(p, NULL)) == NULL)
+			goto next;
+		p = q + 1;
+
+		for (q = p; *q != '\0' && !isspace((int)*q); q++)
+			;
+		*q = '\0';
+		if ((sa_args.dst = str2saddr(p, NULL)) == NULL)
+			goto next;
+		p = q + 1;
+
+#define GETNEXTNUM(value, function) 				\
+do { 								\
+	char *y; 						\
+	for (q = p; *q != '\0' && !isspace((int)*q); q++) 	\
+		; 						\
+	*q = '\0'; 						\
+	(value) = function(p, &y, 10); 				\
+	if ((value) == 0 && *y != '\0') 			\
+		goto next; 					\
+	p = q + 1; 						\
+} while (/*CONSTCOND*/0);
+
+		GETNEXTNUM(sa_args.satype, strtoul);
+		GETNEXTNUM(sa_args.spi, strtoul);
+		sa_args.spi = ntohl(sa_args.spi);
+		GETNEXTNUM(sa_args.mode, strtoul);
+		GETNEXTNUM(sa_args.reqid, strtoul);
+		GETNEXTNUM(sa_args.wsize, strtoul);
+		GETNEXTNUM(sa_args.e_type, strtoul);
+		GETNEXTNUM(sa_args.e_keylen, strtoul);
+		GETNEXTNUM(sa_args.a_type, strtoul);
+		GETNEXTNUM(sa_args.a_keylen, strtoul);
+		GETNEXTNUM(sa_args.flags, strtoul);
+		GETNEXTNUM(sa_args.l_alloc, strtoul);
+		GETNEXTNUM(sa_args.l_bytes, strtouq);
+		GETNEXTNUM(sa_args.l_addtime, strtouq);
+		GETNEXTNUM(sa_args.l_usetime, strtouq);
+		GETNEXTNUM(sa_args.seq, strtoul);
+
+#undef GETNEXTNUM
+
+		sa_args.keymat = str2val(p, 16, &keymatlen);
+		if (sa_args.keymat == NULL) {
+			plog(LLV_ERROR, LOCATION, NULL,
+				"illegal format(keymat) line#%d in %s: %s\n",
+				line, lcconf->pathinfo[LC_PATHTYPE_BACKUPSA], 
+				buf);
+			goto next;
+		}
+
+		if (created + sa_args.l_addtime < current) {
+			plog(LLV_DEBUG, LOCATION, NULL,
+				"ignore this line#%d in %s due to expiration\n",
+				line, lcconf->pathinfo[LC_PATHTYPE_BACKUPSA]);
+			goto next;
+		}
+		sa_args.l_addtime -= current - created;
+
+		if (pfkey_send_add2(&sa_args) < 0) {
+			plog(LLV_ERROR, LOCATION, NULL,
+				"restore SA failed line#%d in %s: %s\n",
+				line, lcconf->pathinfo[LC_PATHTYPE_BACKUPSA], 
+				ipsec_strerror());
+		}
+
+next:
+	 	if (sa_args.src != NULL) {
+			racoon_free(sa_args.src);
+			sa_args.src = NULL;
+		}
+		if (sa_args.dst != NULL) {
+			racoon_free(sa_args.dst);
+			sa_args.dst = NULL;
+		}
+		if (sa_args.keymat != NULL) {
+			racoon_free(sa_args.keymat);
+			sa_args.keymat = NULL;
+		}
+	}
+
+	fclose(fp);
+
+	/*
+	 * There is a possibility that an abnormal system down will happen
+	 * again before new negotiation will be started.  so racoon clears
+	 * the backup file here.  it's ok that old SAs are remained in the
+	 * file.  any old SA will not be installed because racoon checks the
+	 * lifetime and compare with current time.
+	 */
+
+	return 0;
+}
+
+int
+backupsa_clean()
+{
+	FILE *fp;
+
+	/* simply return if the file is not defined. */
+	if (!lcconf->pathinfo[LC_PATHTYPE_BACKUPSA])
+		return 0;
+
+	fp = fopen(lcconf->pathinfo[LC_PATHTYPE_BACKUPSA], "w+");
+	if (fp == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"failed to clean the backup file %s.\n",
+			lcconf->pathinfo[LC_PATHTYPE_BACKUPSA]);
+		return -1;
+	}
+	fclose(fp);
+	return 0;
+}
+
+/*
+ * convert fixed string into the tm structure.
+ * The fixed string is like 'Nov 24 18:22:48 1986'.
+ * static char *format = "%b %d %T %Y";
+ */
+static char *
+str2tmx(char *p, struct tm *tm)
+{
+	int i, len;
+
+	/* Month */
+        for (i = 0; i < sizeof(strmon)/sizeof(strmon[0]); i++) {
+		if (strncasecmp(p, strmon[i], strlen(strmon[i])) == 0) {
+			tm->tm_mon = i;
+			break;
+		}
+	}
+	if (i == sizeof(strmon)/sizeof(strmon[0]))
+		return 0;
+	p += strlen(strmon[i]);
+	if (*p++ != ' ')
+		return 0;
+
+	/* Day */
+	len = 2;
+	tm->tm_mday = str2num(p, len);
+	if (tm->tm_mday == -1 || tm->tm_mday > 31)
+		return 0;
+	p += len;
+	if (*p++ != ' ')
+		return 0;
+
+	/* Hour */
+	len = 2;
+	tm->tm_hour = str2num(p, len);
+	if (tm->tm_hour == -1 || tm->tm_hour > 24)
+		return 0;
+	p += len;
+	if (*p++ != ':')
+		return 0;
+
+	/* Min */
+	len = 2;
+	tm->tm_min = str2num(p, len);
+	if (tm->tm_min == -1 || tm->tm_min > 60)
+		return 0;
+	p += len;
+	if (*p++ != ':')
+		return 0;
+
+	/* Sec */
+	len = 2;
+	tm->tm_sec = str2num(p, len);
+	if (tm->tm_sec == -1 || tm->tm_sec > 60)
+		return 0;
+	p += len;
+	if (*p++ != ' ')
+		return 0;
+
+	/* Year */
+	len = 4;
+	tm->tm_year = str2num(p, len);
+	if (tm->tm_year == -1 || tm->tm_year < 1900)
+		return 0;
+	tm->tm_year -= 1900;
+	p += len;
+
+	return p;
+}
+
+static int
+str2num(p, len)
+	char *p;
+	int len;
+{
+	int res, i;
+
+	res = 0;
+        for (i = len; i > 0; i--) {
+		if (!isdigit((int)*p))
+			return -1;
+		res *= 10;
+		res += *p - '0';
+		p++;
+	}
+
+	return res;
+}
+
+#ifdef TEST
+#include <stdio.h>
+int
+main()
+{
+	struct tm tm;
+	time_t t;
+	char *buf = "Nov 24 18:22:48 1986 ";
+	char *p;
+
+	memset(&tm, 0, sizeof(tm));
+	p = str2tmx(buf, &tm);
+	printf("[%x]\n", *p);
+	t = mktime(&tm);
+	if (t == -1)
+		printf("mktime failed.");
+	p = ctime(&t);
+	printf("[%s]\n", p);
+
+	exit(0);
+}
+#endif
diff --git a/src/racoon/backupsa.h b/src/racoon/backupsa.h
new file mode 100644
index 0000000..e563791
--- /dev/null
+++ b/src/racoon/backupsa.h
@@ -0,0 +1,41 @@
+/*	$NetBSD: backupsa.h,v 1.5 2006/12/09 05:52:57 manu Exp $	*/
+
+/* Id: backupsa.h,v 1.3 2004/06/11 16:00:15 ludvigm Exp */
+
+/*
+ * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _BACKUPSA_H
+#define _BACKUPSA_H
+
+extern int backupsa_to_file __P((struct pfkey_send_sa_args *));
+extern int backupsa_from_file __P((void));
+extern int backupsa_clean __P((void));
+
+#endif /* _BACKUPSA_H */
diff --git a/src/racoon/cfparse.c b/src/racoon/cfparse.c
new file mode 100644
index 0000000..43541df
--- /dev/null
+++ b/src/racoon/cfparse.c
@@ -0,0 +1,5286 @@
+/* A Bison parser, made by GNU Bison 2.3.  */
+
+/* Skeleton implementation for Bison's Yacc-like parsers in C
+
+   Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
+   Free Software Foundation, Inc.
+
+   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, or (at your option)
+   any later version.
+
+   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.
+
+   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., 51 Franklin Street, Fifth Floor,
+   Boston, MA 02110-1301, USA.  */
+
+/* As a special exception, you may create a larger work that contains
+   part or all of the Bison parser skeleton and distribute that work
+   under terms of your choice, so long as that work isn't itself a
+   parser generator using the skeleton or a modified version thereof
+   as a parser skeleton.  Alternatively, if you modify or redistribute
+   the parser skeleton itself, you may (at your option) remove this
+   special exception, which will cause the skeleton and the resulting
+   Bison output files to be licensed under the GNU General Public
+   License without this special exception.
+
+   This special exception was added by the Free Software Foundation in
+   version 2.2 of Bison.  */
+
+/* C LALR(1) parser skeleton written by Richard Stallman, by
+   simplifying the original so-called "semantic" parser.  */
+
+/* All symbols defined below should begin with yy or YY, to avoid
+   infringing on user name space.  This should be done even for local
+   variables, as they might otherwise be expanded by user macros.
+   There are some unavoidable exceptions within include files to
+   define necessary library symbols; they are noted "INFRINGES ON
+   USER NAME SPACE" below.  */
+
+/* Identify Bison output.  */
+#define YYBISON 1
+
+/* Bison version.  */
+#define YYBISON_VERSION "2.3"
+
+/* Skeleton name.  */
+#define YYSKELETON_NAME "yacc.c"
+
+/* Pure parsers.  */
+#define YYPURE 0
+
+/* Using locations.  */
+#define YYLSP_NEEDED 0
+
+
+
+/* Tokens.  */
+#ifndef YYTOKENTYPE
+# define YYTOKENTYPE
+   /* Put the tokens into the symbol table, so that GDB and other debuggers
+      know about them.  */
+   enum yytokentype {
+     PRIVSEP = 258,
+     USER = 259,
+     GROUP = 260,
+     CHROOT = 261,
+     PATH = 262,
+     PATHTYPE = 263,
+     INCLUDE = 264,
+     IDENTIFIER = 265,
+     VENDORID = 266,
+     LOGGING = 267,
+     LOGLEV = 268,
+     PADDING = 269,
+     PAD_RANDOMIZE = 270,
+     PAD_RANDOMIZELEN = 271,
+     PAD_MAXLEN = 272,
+     PAD_STRICT = 273,
+     PAD_EXCLTAIL = 274,
+     LISTEN = 275,
+     X_ISAKMP = 276,
+     X_ISAKMP_NATT = 277,
+     X_ADMIN = 278,
+     STRICT_ADDRESS = 279,
+     ADMINSOCK = 280,
+     DISABLED = 281,
+     LDAPCFG = 282,
+     LDAP_HOST = 283,
+     LDAP_PORT = 284,
+     LDAP_PVER = 285,
+     LDAP_BASE = 286,
+     LDAP_BIND_DN = 287,
+     LDAP_BIND_PW = 288,
+     LDAP_SUBTREE = 289,
+     LDAP_ATTR_USER = 290,
+     LDAP_ATTR_ADDR = 291,
+     LDAP_ATTR_MASK = 292,
+     LDAP_ATTR_GROUP = 293,
+     LDAP_ATTR_MEMBER = 294,
+     MODECFG = 295,
+     CFG_NET4 = 296,
+     CFG_MASK4 = 297,
+     CFG_DNS4 = 298,
+     CFG_NBNS4 = 299,
+     CFG_DEFAULT_DOMAIN = 300,
+     CFG_AUTH_SOURCE = 301,
+     CFG_AUTH_GROUPS = 302,
+     CFG_SYSTEM = 303,
+     CFG_RADIUS = 304,
+     CFG_PAM = 305,
+     CFG_LDAP = 306,
+     CFG_LOCAL = 307,
+     CFG_NONE = 308,
+     CFG_GROUP_SOURCE = 309,
+     CFG_ACCOUNTING = 310,
+     CFG_CONF_SOURCE = 311,
+     CFG_MOTD = 312,
+     CFG_POOL_SIZE = 313,
+     CFG_AUTH_THROTTLE = 314,
+     CFG_SPLIT_NETWORK = 315,
+     CFG_SPLIT_LOCAL = 316,
+     CFG_SPLIT_INCLUDE = 317,
+     CFG_SPLIT_DNS = 318,
+     CFG_PFS_GROUP = 319,
+     CFG_SAVE_PASSWD = 320,
+     RETRY = 321,
+     RETRY_COUNTER = 322,
+     RETRY_INTERVAL = 323,
+     RETRY_PERSEND = 324,
+     RETRY_PHASE1 = 325,
+     RETRY_PHASE2 = 326,
+     NATT_KA = 327,
+     ALGORITHM_CLASS = 328,
+     ALGORITHMTYPE = 329,
+     STRENGTHTYPE = 330,
+     SAINFO = 331,
+     FROM = 332,
+     REMOTE = 333,
+     ANONYMOUS = 334,
+     INHERIT = 335,
+     EXCHANGE_MODE = 336,
+     EXCHANGETYPE = 337,
+     DOI = 338,
+     DOITYPE = 339,
+     SITUATION = 340,
+     SITUATIONTYPE = 341,
+     CERTIFICATE_TYPE = 342,
+     CERTTYPE = 343,
+     PEERS_CERTFILE = 344,
+     CA_TYPE = 345,
+     VERIFY_CERT = 346,
+     SEND_CERT = 347,
+     SEND_CR = 348,
+     IDENTIFIERTYPE = 349,
+     IDENTIFIERQUAL = 350,
+     MY_IDENTIFIER = 351,
+     PEERS_IDENTIFIER = 352,
+     VERIFY_IDENTIFIER = 353,
+     DNSSEC = 354,
+     CERT_X509 = 355,
+     CERT_PLAINRSA = 356,
+     NONCE_SIZE = 357,
+     DH_GROUP = 358,
+     KEEPALIVE = 359,
+     PASSIVE = 360,
+     INITIAL_CONTACT = 361,
+     NAT_TRAVERSAL = 362,
+     REMOTE_FORCE_LEVEL = 363,
+     PROPOSAL_CHECK = 364,
+     PROPOSAL_CHECK_LEVEL = 365,
+     GENERATE_POLICY = 366,
+     GENERATE_LEVEL = 367,
+     SUPPORT_PROXY = 368,
+     PROPOSAL = 369,
+     EXEC_PATH = 370,
+     EXEC_COMMAND = 371,
+     EXEC_SUCCESS = 372,
+     EXEC_FAILURE = 373,
+     GSS_ID = 374,
+     GSS_ID_ENC = 375,
+     GSS_ID_ENCTYPE = 376,
+     COMPLEX_BUNDLE = 377,
+     DPD = 378,
+     DPD_DELAY = 379,
+     DPD_RETRY = 380,
+     DPD_MAXFAIL = 381,
+     PH1ID = 382,
+     XAUTH_LOGIN = 383,
+     WEAK_PHASE1_CHECK = 384,
+     PREFIX = 385,
+     PORT = 386,
+     PORTANY = 387,
+     UL_PROTO = 388,
+     ANY = 389,
+     IKE_FRAG = 390,
+     ESP_FRAG = 391,
+     MODE_CFG = 392,
+     PFS_GROUP = 393,
+     LIFETIME = 394,
+     LIFETYPE_TIME = 395,
+     LIFETYPE_BYTE = 396,
+     STRENGTH = 397,
+     REMOTEID = 398,
+     SCRIPT = 399,
+     PHASE1_UP = 400,
+     PHASE1_DOWN = 401,
+     NUMBER = 402,
+     SWITCH = 403,
+     BOOLEAN = 404,
+     HEXSTRING = 405,
+     QUOTEDSTRING = 406,
+     ADDRSTRING = 407,
+     ADDRRANGE = 408,
+     UNITTYPE_BYTE = 409,
+     UNITTYPE_KBYTES = 410,
+     UNITTYPE_MBYTES = 411,
+     UNITTYPE_TBYTES = 412,
+     UNITTYPE_SEC = 413,
+     UNITTYPE_MIN = 414,
+     UNITTYPE_HOUR = 415,
+     EOS = 416,
+     BOC = 417,
+     EOC = 418,
+     COMMA = 419
+   };
+#endif
+/* Tokens.  */
+#define PRIVSEP 258
+#define USER 259
+#define GROUP 260
+#define CHROOT 261
+#define PATH 262
+#define PATHTYPE 263
+#define INCLUDE 264
+#define IDENTIFIER 265
+#define VENDORID 266
+#define LOGGING 267
+#define LOGLEV 268
+#define PADDING 269
+#define PAD_RANDOMIZE 270
+#define PAD_RANDOMIZELEN 271
+#define PAD_MAXLEN 272
+#define PAD_STRICT 273
+#define PAD_EXCLTAIL 274
+#define LISTEN 275
+#define X_ISAKMP 276
+#define X_ISAKMP_NATT 277
+#define X_ADMIN 278
+#define STRICT_ADDRESS 279
+#define ADMINSOCK 280
+#define DISABLED 281
+#define LDAPCFG 282
+#define LDAP_HOST 283
+#define LDAP_PORT 284
+#define LDAP_PVER 285
+#define LDAP_BASE 286
+#define LDAP_BIND_DN 287
+#define LDAP_BIND_PW 288
+#define LDAP_SUBTREE 289
+#define LDAP_ATTR_USER 290
+#define LDAP_ATTR_ADDR 291
+#define LDAP_ATTR_MASK 292
+#define LDAP_ATTR_GROUP 293
+#define LDAP_ATTR_MEMBER 294
+#define MODECFG 295
+#define CFG_NET4 296
+#define CFG_MASK4 297
+#define CFG_DNS4 298
+#define CFG_NBNS4 299
+#define CFG_DEFAULT_DOMAIN 300
+#define CFG_AUTH_SOURCE 301
+#define CFG_AUTH_GROUPS 302
+#define CFG_SYSTEM 303
+#define CFG_RADIUS 304
+#define CFG_PAM 305
+#define CFG_LDAP 306
+#define CFG_LOCAL 307
+#define CFG_NONE 308
+#define CFG_GROUP_SOURCE 309
+#define CFG_ACCOUNTING 310
+#define CFG_CONF_SOURCE 311
+#define CFG_MOTD 312
+#define CFG_POOL_SIZE 313
+#define CFG_AUTH_THROTTLE 314
+#define CFG_SPLIT_NETWORK 315
+#define CFG_SPLIT_LOCAL 316
+#define CFG_SPLIT_INCLUDE 317
+#define CFG_SPLIT_DNS 318
+#define CFG_PFS_GROUP 319
+#define CFG_SAVE_PASSWD 320
+#define RETRY 321
+#define RETRY_COUNTER 322
+#define RETRY_INTERVAL 323
+#define RETRY_PERSEND 324
+#define RETRY_PHASE1 325
+#define RETRY_PHASE2 326
+#define NATT_KA 327
+#define ALGORITHM_CLASS 328
+#define ALGORITHMTYPE 329
+#define STRENGTHTYPE 330
+#define SAINFO 331
+#define FROM 332
+#define REMOTE 333
+#define ANONYMOUS 334
+#define INHERIT 335
+#define EXCHANGE_MODE 336
+#define EXCHANGETYPE 337
+#define DOI 338
+#define DOITYPE 339
+#define SITUATION 340
+#define SITUATIONTYPE 341
+#define CERTIFICATE_TYPE 342
+#define CERTTYPE 343
+#define PEERS_CERTFILE 344
+#define CA_TYPE 345
+#define VERIFY_CERT 346
+#define SEND_CERT 347
+#define SEND_CR 348
+#define IDENTIFIERTYPE 349
+#define IDENTIFIERQUAL 350
+#define MY_IDENTIFIER 351
+#define PEERS_IDENTIFIER 352
+#define VERIFY_IDENTIFIER 353
+#define DNSSEC 354
+#define CERT_X509 355
+#define CERT_PLAINRSA 356
+#define NONCE_SIZE 357
+#define DH_GROUP 358
+#define KEEPALIVE 359
+#define PASSIVE 360
+#define INITIAL_CONTACT 361
+#define NAT_TRAVERSAL 362
+#define REMOTE_FORCE_LEVEL 363
+#define PROPOSAL_CHECK 364
+#define PROPOSAL_CHECK_LEVEL 365
+#define GENERATE_POLICY 366
+#define GENERATE_LEVEL 367
+#define SUPPORT_PROXY 368
+#define PROPOSAL 369
+#define EXEC_PATH 370
+#define EXEC_COMMAND 371
+#define EXEC_SUCCESS 372
+#define EXEC_FAILURE 373
+#define GSS_ID 374
+#define GSS_ID_ENC 375
+#define GSS_ID_ENCTYPE 376
+#define COMPLEX_BUNDLE 377
+#define DPD 378
+#define DPD_DELAY 379
+#define DPD_RETRY 380
+#define DPD_MAXFAIL 381
+#define PH1ID 382
+#define XAUTH_LOGIN 383
+#define WEAK_PHASE1_CHECK 384
+#define PREFIX 385
+#define PORT 386
+#define PORTANY 387
+#define UL_PROTO 388
+#define ANY 389
+#define IKE_FRAG 390
+#define ESP_FRAG 391
+#define MODE_CFG 392
+#define PFS_GROUP 393
+#define LIFETIME 394
+#define LIFETYPE_TIME 395
+#define LIFETYPE_BYTE 396
+#define STRENGTH 397
+#define REMOTEID 398
+#define SCRIPT 399
+#define PHASE1_UP 400
+#define PHASE1_DOWN 401
+#define NUMBER 402
+#define SWITCH 403
+#define BOOLEAN 404
+#define HEXSTRING 405
+#define QUOTEDSTRING 406
+#define ADDRSTRING 407
+#define ADDRRANGE 408
+#define UNITTYPE_BYTE 409
+#define UNITTYPE_KBYTES 410
+#define UNITTYPE_MBYTES 411
+#define UNITTYPE_TBYTES 412
+#define UNITTYPE_SEC 413
+#define UNITTYPE_MIN 414
+#define UNITTYPE_HOUR 415
+#define EOS 416
+#define BOC 417
+#define EOC 418
+#define COMMA 419
+
+
+
+
+/* Copy the first part of user declarations.  */
+#line 5 "cfparse.y"
+
+/*
+ * Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002 and 2003 WIDE Project.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/queue.h>
+#include <sys/socket.h>
+
+#include <netinet/in.h>
+#include PATH_IPSEC_H
+
+#ifdef ENABLE_HYBRID
+#include <arpa/inet.h>
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <netdb.h>
+#include <pwd.h>
+#include <grp.h>
+
+#include "var.h"
+#include "misc.h"
+#include "vmbuf.h"
+#include "plog.h"
+#include "sockmisc.h"
+#include "str2val.h"
+#include "genlist.h"
+#include "debug.h"
+
+#include "admin.h"
+#include "privsep.h"
+#include "cfparse_proto.h"
+#include "cftoken_proto.h"
+#include "algorithm.h"
+#include "localconf.h"
+#include "policy.h"
+#include "sainfo.h"
+#include "oakley.h"
+#include "pfkey.h"
+#include "remoteconf.h"
+#include "grabmyaddr.h"
+#include "isakmp_var.h"
+#include "handler.h"
+#include "isakmp.h"
+#include "nattraversal.h"
+#include "isakmp_frag.h"
+#ifdef ENABLE_HYBRID
+#include "resolv.h"
+#include "isakmp_unity.h"
+#include "isakmp_xauth.h"
+#include "isakmp_cfg.h"
+#endif
+#include "ipsec_doi.h"
+#include "strnames.h"
+#include "gcmalloc.h"
+#ifdef HAVE_GSSAPI
+#include "gssapi.h"
+#endif
+#include "vendorid.h"
+#include "rsalist.h"
+
+struct proposalspec {
+	time_t lifetime;		/* for isakmp/ipsec */
+	int lifebyte;			/* for isakmp/ipsec */
+	struct secprotospec *spspec;	/* the head is always current spec. */
+	struct proposalspec *next;	/* the tail is the most prefered. */
+	struct proposalspec *prev;
+};
+
+struct secprotospec {
+	int prop_no;
+	int trns_no;
+	int strength;		/* for isakmp/ipsec */
+	int encklen;		/* for isakmp/ipsec */
+	time_t lifetime;	/* for isakmp */
+	int lifebyte;		/* for isakmp */
+	int proto_id;		/* for ipsec (isakmp?) */
+	int ipsec_level;	/* for ipsec */
+	int encmode;		/* for ipsec */
+	int vendorid;		/* for isakmp */
+	char *gssid;
+	struct sockaddr *remote;
+	int algclass[MAXALGCLASS];
+
+	struct secprotospec *next;	/* the tail is the most prefiered. */
+	struct secprotospec *prev;
+	struct proposalspec *back;
+};
+
+static int num2dhgroup[] = {
+	0,
+	OAKLEY_ATTR_GRP_DESC_MODP768,
+	OAKLEY_ATTR_GRP_DESC_MODP1024,
+	OAKLEY_ATTR_GRP_DESC_EC2N155,
+	OAKLEY_ATTR_GRP_DESC_EC2N185,
+	OAKLEY_ATTR_GRP_DESC_MODP1536,
+	0,
+	0,
+	0,
+	0,
+	0,
+	0,
+	0,
+	0,
+	OAKLEY_ATTR_GRP_DESC_MODP2048,
+	OAKLEY_ATTR_GRP_DESC_MODP3072,
+	OAKLEY_ATTR_GRP_DESC_MODP4096,
+	OAKLEY_ATTR_GRP_DESC_MODP6144,
+	OAKLEY_ATTR_GRP_DESC_MODP8192
+};
+
+static struct remoteconf *cur_rmconf;
+static int tmpalgtype[MAXALGCLASS];
+static struct sainfo *cur_sainfo;
+static int cur_algclass;
+static int oldloglevel = LLV_BASE;
+
+static struct proposalspec *newprspec __P((void));
+static void insprspec __P((struct proposalspec *, struct proposalspec **));
+static struct secprotospec *newspspec __P((void));
+static void insspspec __P((struct secprotospec *, struct proposalspec **));
+static void adminsock_conf __P((vchar_t *, vchar_t *, vchar_t *, int));
+
+static int set_isakmp_proposal
+	__P((struct remoteconf *, struct proposalspec *));
+static void clean_tmpalgtype __P((void));
+static int expand_isakmpspec __P((int, int, int *,
+	int, int, time_t, int, int, int, char *, struct remoteconf *));
+static int listen_addr __P((struct sockaddr *addr, int udp_encap));
+
+void freeetypes (struct etypes **etypes);
+
+#if 0
+static int fix_lifebyte __P((u_long));
+#endif
+
+
+/* Enabling traces.  */
+#ifndef YYDEBUG
+# define YYDEBUG 0
+#endif
+
+/* Enabling verbose error messages.  */
+#ifdef YYERROR_VERBOSE
+# undef YYERROR_VERBOSE
+# define YYERROR_VERBOSE 1
+#else
+# define YYERROR_VERBOSE 0
+#endif
+
+/* Enabling the token table.  */
+#ifndef YYTOKEN_TABLE
+# define YYTOKEN_TABLE 0
+#endif
+
+#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
+typedef union YYSTYPE
+#line 174 "cfparse.y"
+{
+	unsigned long num;
+	vchar_t *val;
+	struct remoteconf *rmconf;
+	struct sockaddr *saddr;
+	struct sainfoalg *alg;
+}
+/* Line 187 of yacc.c.  */
+#line 601 "cfparse.c"
+	YYSTYPE;
+# define yystype YYSTYPE /* obsolescent; will be withdrawn */
+# define YYSTYPE_IS_DECLARED 1
+# define YYSTYPE_IS_TRIVIAL 1
+#endif
+
+
+
+/* Copy the second part of user declarations.  */
+
+
+/* Line 216 of yacc.c.  */
+#line 614 "cfparse.c"
+
+#ifdef short
+# undef short
+#endif
+
+#ifdef YYTYPE_UINT8
+typedef YYTYPE_UINT8 yytype_uint8;
+#else
+typedef unsigned char yytype_uint8;
+#endif
+
+#ifdef YYTYPE_INT8
+typedef YYTYPE_INT8 yytype_int8;
+#elif (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+typedef signed char yytype_int8;
+#else
+typedef short int yytype_int8;
+#endif
+
+#ifdef YYTYPE_UINT16
+typedef YYTYPE_UINT16 yytype_uint16;
+#else
+typedef unsigned short int yytype_uint16;
+#endif
+
+#ifdef YYTYPE_INT16
+typedef YYTYPE_INT16 yytype_int16;
+#else
+typedef short int yytype_int16;
+#endif
+
+#ifndef YYSIZE_T
+# ifdef __SIZE_TYPE__
+#  define YYSIZE_T __SIZE_TYPE__
+# elif defined size_t
+#  define YYSIZE_T size_t
+# elif ! defined YYSIZE_T && (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+#  include <stddef.h> /* INFRINGES ON USER NAME SPACE */
+#  define YYSIZE_T size_t
+# else
+#  define YYSIZE_T unsigned int
+# endif
+#endif
+
+#define YYSIZE_MAXIMUM ((YYSIZE_T) -1)
+
+#ifndef YY_
+# if YYENABLE_NLS
+#  if ENABLE_NLS
+#   include <libintl.h> /* INFRINGES ON USER NAME SPACE */
+#   define YY_(msgid) dgettext ("bison-runtime", msgid)
+#  endif
+# endif
+# ifndef YY_
+#  define YY_(msgid) msgid
+# endif
+#endif
+
+/* Suppress unused-variable warnings by "using" E.  */
+#if ! defined lint || defined __GNUC__
+# define YYUSE(e) ((void) (e))
+#else
+# define YYUSE(e) /* empty */
+#endif
+
+/* Identity function, used to suppress warnings about constant conditions.  */
+#ifndef lint
+# define YYID(n) (n)
+#else
+#if (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+static int
+YYID (int i)
+#else
+static int
+YYID (i)
+    int i;
+#endif
+{
+  return i;
+}
+#endif
+
+#if ! defined yyoverflow || YYERROR_VERBOSE
+
+/* The parser invokes alloca or malloc; define the necessary symbols.  */
+
+# ifdef YYSTACK_USE_ALLOCA
+#  if YYSTACK_USE_ALLOCA
+#   ifdef __GNUC__
+#    define YYSTACK_ALLOC __builtin_alloca
+#   elif defined __BUILTIN_VA_ARG_INCR
+#    include <alloca.h> /* INFRINGES ON USER NAME SPACE */
+#   elif defined _AIX
+#    define YYSTACK_ALLOC __alloca
+#   elif defined _MSC_VER
+#    include <malloc.h> /* INFRINGES ON USER NAME SPACE */
+#    define alloca _alloca
+#   else
+#    define YYSTACK_ALLOC alloca
+#    if ! defined _ALLOCA_H && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+#     include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
+#     ifndef _STDLIB_H
+#      define _STDLIB_H 1
+#     endif
+#    endif
+#   endif
+#  endif
+# endif
+
+# ifdef YYSTACK_ALLOC
+   /* Pacify GCC's `empty if-body' warning.  */
+#  define YYSTACK_FREE(Ptr) do { /* empty */; } while (YYID (0))
+#  ifndef YYSTACK_ALLOC_MAXIMUM
+    /* The OS might guarantee only one guard page at the bottom of the stack,
+       and a page size can be as small as 4096 bytes.  So we cannot safely
+       invoke alloca (N) if N exceeds 4096.  Use a slightly smaller number
+       to allow for a few compiler-allocated temporary stack slots.  */
+#   define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */
+#  endif
+# else
+#  define YYSTACK_ALLOC YYMALLOC
+#  define YYSTACK_FREE YYFREE
+#  ifndef YYSTACK_ALLOC_MAXIMUM
+#   define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM
+#  endif
+#  if (defined __cplusplus && ! defined _STDLIB_H \
+       && ! ((defined YYMALLOC || defined malloc) \
+	     && (defined YYFREE || defined free)))
+#   include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
+#   ifndef _STDLIB_H
+#    define _STDLIB_H 1
+#   endif
+#  endif
+#  ifndef YYMALLOC
+#   define YYMALLOC malloc
+#   if ! defined malloc && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */
+#   endif
+#  endif
+#  ifndef YYFREE
+#   define YYFREE free
+#   if ! defined free && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+void free (void *); /* INFRINGES ON USER NAME SPACE */
+#   endif
+#  endif
+# endif
+#endif /* ! defined yyoverflow || YYERROR_VERBOSE */
+
+
+#if (! defined yyoverflow \
+     && (! defined __cplusplus \
+	 || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL)))
+
+/* A type that is properly aligned for any stack member.  */
+union yyalloc
+{
+  yytype_int16 yyss;
+  YYSTYPE yyvs;
+  };
+
+/* The size of the maximum gap between one aligned stack and the next.  */
+# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1)
+
+/* The size of an array large to enough to hold all stacks, each with
+   N elements.  */
+# define YYSTACK_BYTES(N) \
+     ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \
+      + YYSTACK_GAP_MAXIMUM)
+
+/* Copy COUNT objects from FROM to TO.  The source and destination do
+   not overlap.  */
+# ifndef YYCOPY
+#  if defined __GNUC__ && 1 < __GNUC__
+#   define YYCOPY(To, From, Count) \
+      __builtin_memcpy (To, From, (Count) * sizeof (*(From)))
+#  else
+#   define YYCOPY(To, From, Count)		\
+      do					\
+	{					\
+	  YYSIZE_T yyi;				\
+	  for (yyi = 0; yyi < (Count); yyi++)	\
+	    (To)[yyi] = (From)[yyi];		\
+	}					\
+      while (YYID (0))
+#  endif
+# endif
+
+/* Relocate STACK from its old location to the new one.  The
+   local variables YYSIZE and YYSTACKSIZE give the old and new number of
+   elements in the stack, and YYPTR gives the new location of the
+   stack.  Advance YYPTR to a properly aligned location for the next
+   stack.  */
+# define YYSTACK_RELOCATE(Stack)					\
+    do									\
+      {									\
+	YYSIZE_T yynewbytes;						\
+	YYCOPY (&yyptr->Stack, Stack, yysize);				\
+	Stack = &yyptr->Stack;						\
+	yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
+	yyptr += yynewbytes / sizeof (*yyptr);				\
+      }									\
+    while (YYID (0))
+
+#endif
+
+/* YYFINAL -- State number of the termination state.  */
+#define YYFINAL  2
+/* YYLAST -- Last index in YYTABLE.  */
+#define YYLAST   489
+
+/* YYNTOKENS -- Number of terminals.  */
+#define YYNTOKENS  165
+/* YYNNTS -- Number of nonterminals.  */
+#define YYNNTS  193
+/* YYNRULES -- Number of rules.  */
+#define YYNRULES  359
+/* YYNRULES -- Number of states.  */
+#define YYNSTATES  654
+
+/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX.  */
+#define YYUNDEFTOK  2
+#define YYMAXUTOK   419
+
+#define YYTRANSLATE(YYX)						\
+  ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
+
+/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX.  */
+static const yytype_uint8 yytranslate[] =
+{
+       0,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     1,     2,     3,     4,
+       5,     6,     7,     8,     9,    10,    11,    12,    13,    14,
+      15,    16,    17,    18,    19,    20,    21,    22,    23,    24,
+      25,    26,    27,    28,    29,    30,    31,    32,    33,    34,
+      35,    36,    37,    38,    39,    40,    41,    42,    43,    44,
+      45,    46,    47,    48,    49,    50,    51,    52,    53,    54,
+      55,    56,    57,    58,    59,    60,    61,    62,    63,    64,
+      65,    66,    67,    68,    69,    70,    71,    72,    73,    74,
+      75,    76,    77,    78,    79,    80,    81,    82,    83,    84,
+      85,    86,    87,    88,    89,    90,    91,    92,    93,    94,
+      95,    96,    97,    98,    99,   100,   101,   102,   103,   104,
+     105,   106,   107,   108,   109,   110,   111,   112,   113,   114,
+     115,   116,   117,   118,   119,   120,   121,   122,   123,   124,
+     125,   126,   127,   128,   129,   130,   131,   132,   133,   134,
+     135,   136,   137,   138,   139,   140,   141,   142,   143,   144,
+     145,   146,   147,   148,   149,   150,   151,   152,   153,   154,
+     155,   156,   157,   158,   159,   160,   161,   162,   163,   164
+};
+
+#if YYDEBUG
+/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in
+   YYRHS.  */
+static const yytype_uint16 yyprhs[] =
+{
+       0,     0,     3,     4,     7,     9,    11,    13,    15,    17,
+      19,    21,    23,    25,    27,    29,    31,    33,    35,    40,
+      41,    44,    45,    50,    51,    56,    57,    62,    63,    68,
+      69,    74,    75,    81,    82,    87,    91,    95,    98,    99,
+     104,   105,   110,   114,   116,   118,   123,   124,   127,   128,
+     133,   134,   139,   140,   145,   146,   151,   152,   157,   162,
+     163,   166,   167,   172,   173,   178,   179,   184,   185,   193,
+     194,   199,   200,   205,   206,   210,   213,   214,   216,   217,
+     223,   224,   227,   228,   233,   234,   239,   240,   245,   246,
+     251,   252,   257,   258,   263,   264,   269,   270,   275,   276,
+     281,   282,   287,   288,   293,   294,   299,   304,   305,   308,
+     309,   314,   315,   320,   324,   328,   329,   335,   336,   342,
+     343,   348,   349,   354,   355,   360,   361,   366,   367,   372,
+     373,   378,   379,   384,   385,   390,   391,   396,   397,   402,
+     403,   408,   409,   414,   415,   420,   421,   426,   427,   432,
+     433,   438,   439,   444,   445,   450,   451,   456,   457,   462,
+     463,   468,   470,   474,   476,   478,   482,   484,   486,   490,
+     493,   495,   499,   501,   503,   507,   509,   514,   515,   518,
+     519,   524,   525,   531,   532,   537,   538,   544,   545,   551,
+     552,   558,   559,   560,   569,   571,   574,   577,   580,   586,
+     593,   596,   597,   601,   604,   605,   608,   609,   614,   615,
+     620,   621,   628,   629,   636,   637,   642,   643,   648,   649,
+     655,   657,   658,   663,   666,   667,   669,   670,   672,   674,
+     676,   678,   680,   681,   683,   684,   691,   692,   697,   701,
+     704,   706,   707,   710,   711,   716,   717,   722,   723,   728,
+     731,   732,   737,   738,   744,   745,   751,   752,   758,   759,
+     764,   765,   770,   771,   776,   777,   782,   783,   789,   790,
+     797,   798,   803,   804,   810,   811,   818,   819,   824,   825,
+     830,   831,   836,   837,   842,   843,   848,   849,   854,   855,
+     860,   861,   867,   868,   874,   875,   880,   881,   886,   887,
+     892,   893,   898,   899,   904,   905,   910,   911,   916,   917,
+     922,   923,   928,   929,   934,   935,   940,   941,   946,   947,
+     952,   953,   960,   961,   966,   967,   974,   975,   981,   982,
+     985,   986,   992,   993,   998,  1000,  1002,  1003,  1005,  1007,
+    1008,  1011,  1012,  1017,  1018,  1025,  1026,  1033,  1034,  1039,
+    1040,  1045,  1046,  1052,  1054,  1056,  1058,  1060,  1062,  1064
+};
+
+/* YYRHS -- A `-1'-separated list of the rules' RHS.  */
+static const yytype_int16 yyrhs[] =
+{
+     166,     0,    -1,    -1,   166,   167,    -1,   168,    -1,   176,
+      -1,   180,    -1,   181,    -1,   182,    -1,   186,    -1,   188,
+      -1,   196,    -1,   208,    -1,   224,    -1,   262,    -1,   271,
+      -1,   293,    -1,   178,    -1,     3,   162,   169,   163,    -1,
+      -1,   169,   170,    -1,    -1,     4,   151,   171,   161,    -1,
+      -1,     4,   147,   172,   161,    -1,    -1,     5,   151,   173,
+     161,    -1,    -1,     5,   147,   174,   161,    -1,    -1,     6,
+     151,   175,   161,    -1,    -1,     7,     8,   151,   177,   161,
+      -1,    -1,   122,   148,   179,   161,    -1,     9,   151,   161,
+      -1,   120,   121,   161,    -1,    10,   183,    -1,    -1,    11,
+     184,   151,   161,    -1,    -1,    94,   151,   185,   161,    -1,
+      12,   187,   161,    -1,   150,    -1,    13,    -1,    14,   162,
+     189,   163,    -1,    -1,   189,   190,    -1,    -1,    15,   148,
+     191,   161,    -1,    -1,    16,   148,   192,   161,    -1,    -1,
+      17,   147,   193,   161,    -1,    -1,    18,   148,   194,   161,
+      -1,    -1,    19,   148,   195,   161,    -1,    20,   162,   197,
+     163,    -1,    -1,   197,   198,    -1,    -1,    21,   206,   199,
+     161,    -1,    -1,    22,   206,   200,   161,    -1,    -1,    23,
+     201,   131,   161,    -1,    -1,    25,   151,   151,   151,   147,
+     202,   161,    -1,    -1,    25,   151,   203,   161,    -1,    -1,
+      25,    26,   204,   161,    -1,    -1,    24,   205,   161,    -1,
+     152,   207,    -1,    -1,   131,    -1,    -1,    27,   209,   162,
+     210,   163,    -1,    -1,   210,   211,    -1,    -1,    30,   147,
+     212,   161,    -1,    -1,    28,   151,   213,   161,    -1,    -1,
+      29,   147,   214,   161,    -1,    -1,    31,   151,   215,   161,
+      -1,    -1,    34,   148,   216,   161,    -1,    -1,    32,   151,
+     217,   161,    -1,    -1,    33,   151,   218,   161,    -1,    -1,
+      35,   151,   219,   161,    -1,    -1,    36,   151,   220,   161,
+      -1,    -1,    37,   151,   221,   161,    -1,    -1,    38,   151,
+     222,   161,    -1,    -1,    39,   151,   223,   161,    -1,    40,
+     162,   225,   163,    -1,    -1,   225,   226,    -1,    -1,    41,
+     152,   227,   161,    -1,    -1,    42,   152,   228,   161,    -1,
+      43,   252,   161,    -1,    44,   254,   161,    -1,    -1,    60,
+      61,   256,   229,   161,    -1,    -1,    60,    62,   256,   230,
+     161,    -1,    -1,    63,   260,   231,   161,    -1,    -1,    45,
+     151,   232,   161,    -1,    -1,    46,    48,   233,   161,    -1,
+      -1,    46,    49,   234,   161,    -1,    -1,    46,    50,   235,
+     161,    -1,    -1,    46,    51,   236,   161,    -1,    -1,    47,
+     258,   237,   161,    -1,    -1,    54,    48,   238,   161,    -1,
+      -1,    54,    51,   239,   161,    -1,    -1,    55,    53,   240,
+     161,    -1,    -1,    55,    48,   241,   161,    -1,    -1,    55,
+      49,   242,   161,    -1,    -1,    55,    50,   243,   161,    -1,
+      -1,    58,   147,   244,   161,    -1,    -1,    64,   147,   245,
+     161,    -1,    -1,    65,   148,   246,   161,    -1,    -1,    59,
+     147,   247,   161,    -1,    -1,    56,    52,   248,   161,    -1,
+      -1,    56,    49,   249,   161,    -1,    -1,    56,    51,   250,
+     161,    -1,    -1,    57,   151,   251,   161,    -1,   253,    -1,
+     253,   164,   252,    -1,   152,    -1,   255,    -1,   255,   164,
+     254,    -1,   152,    -1,   257,    -1,   256,   164,   257,    -1,
+     152,   130,    -1,   259,    -1,   259,   164,   258,    -1,   151,
+      -1,   261,    -1,   261,   164,   260,    -1,   151,    -1,    66,
+     162,   263,   163,    -1,    -1,   263,   264,    -1,    -1,    67,
+     147,   265,   161,    -1,    -1,    68,   147,   356,   266,   161,
+      -1,    -1,    69,   147,   267,   161,    -1,    -1,    70,   147,
+     356,   268,   161,    -1,    -1,    71,   147,   356,   269,   161,
+      -1,    -1,    72,   147,   356,   270,   161,    -1,    -1,    -1,
+      76,   272,   274,   276,   162,   277,   273,   163,    -1,    79,
+      -1,    79,   275,    -1,   275,    79,    -1,   275,   275,    -1,
+      94,   152,   289,   290,   291,    -1,    94,   152,   153,   289,
+     290,   291,    -1,    94,   151,    -1,    -1,    77,    94,   347,
+      -1,     5,   151,    -1,    -1,   277,   278,    -1,    -1,   138,
+     346,   279,   161,    -1,    -1,   143,   147,   280,   161,    -1,
+      -1,   139,   140,   147,   356,   281,   161,    -1,    -1,   139,
+     141,   147,   357,   282,   161,    -1,    -1,    73,   283,   286,
+     161,    -1,    -1,    10,    94,   284,   161,    -1,    -1,    96,
+      94,   151,   285,   161,    -1,   288,    -1,    -1,   288,   287,
+     164,   286,    -1,    74,   292,    -1,    -1,   130,    -1,    -1,
+     131,    -1,   132,    -1,   147,    -1,   133,    -1,   134,    -1,
+      -1,   147,    -1,    -1,    78,   297,    80,   297,   294,   296,
+      -1,    -1,    78,   297,   295,   296,    -1,   162,   298,   163,
+      -1,    79,   207,    -1,   206,    -1,    -1,   298,   299,    -1,
+      -1,    81,   300,   342,   161,    -1,    -1,    83,    84,   301,
+     161,    -1,    -1,    85,    86,   302,   161,    -1,    87,   343,
+      -1,    -1,    89,   151,   303,   161,    -1,    -1,    90,   100,
+     151,   304,   161,    -1,    -1,    89,   100,   151,   305,   161,
+      -1,    -1,    89,   101,   151,   306,   161,    -1,    -1,    89,
+      99,   307,   161,    -1,    -1,    91,   148,   308,   161,    -1,
+      -1,    92,   148,   309,   161,    -1,    -1,    93,   148,   310,
+     161,    -1,    -1,    96,    94,   347,   311,   161,    -1,    -1,
+      96,    94,    95,   347,   312,   161,    -1,    -1,   128,   347,
+     313,   161,    -1,    -1,    97,    94,   347,   314,   161,    -1,
+      -1,    97,    94,    95,   347,   315,   161,    -1,    -1,    98,
+     148,   316,   161,    -1,    -1,   102,   147,   317,   161,    -1,
+      -1,   103,   318,   346,   161,    -1,    -1,   105,   148,   319,
+     161,    -1,    -1,   135,   148,   320,   161,    -1,    -1,   135,
+     108,   321,   161,    -1,    -1,   136,   147,   322,   161,    -1,
+      -1,   144,   151,   145,   323,   161,    -1,    -1,   144,   151,
+     146,   324,   161,    -1,    -1,   137,   148,   325,   161,    -1,
+      -1,   129,   148,   326,   161,    -1,    -1,   111,   148,   327,
+     161,    -1,    -1,   111,   112,   328,   161,    -1,    -1,   113,
+     148,   329,   161,    -1,    -1,   106,   148,   330,   161,    -1,
+      -1,   107,   148,   331,   161,    -1,    -1,   107,   108,   332,
+     161,    -1,    -1,   123,   148,   333,   161,    -1,    -1,   124,
+     147,   334,   161,    -1,    -1,   125,   147,   335,   161,    -1,
+      -1,   126,   147,   336,   161,    -1,    -1,   127,   147,   337,
+     161,    -1,    -1,   139,   140,   147,   356,   338,   161,    -1,
+      -1,   109,   110,   339,   161,    -1,    -1,   139,   141,   147,
+     357,   340,   161,    -1,    -1,   114,   341,   162,   348,   163,
+      -1,    -1,   342,    82,    -1,    -1,   100,   151,   151,   344,
+     161,    -1,    -1,   101,   151,   345,   161,    -1,    74,    -1,
+     147,    -1,    -1,   152,    -1,   151,    -1,    -1,   348,   349,
+      -1,    -1,   142,   350,    75,   161,    -1,    -1,   139,   140,
+     147,   356,   351,   161,    -1,    -1,   139,   141,   147,   357,
+     352,   161,    -1,    -1,   103,   346,   353,   161,    -1,    -1,
+     119,   151,   354,   161,    -1,    -1,    73,    74,   292,   355,
+     161,    -1,   158,    -1,   159,    -1,   160,    -1,   154,    -1,
+     155,    -1,   156,    -1,   157,    -1
+};
+
+/* YYRLINE[YYN] -- source line where rule number YYN was defined.  */
+static const yytype_uint16 yyrline[] =
+{
+       0,   260,   260,   262,   265,   266,   267,   268,   269,   270,
+     271,   272,   273,   274,   275,   276,   277,   278,   283,   285,
+     287,   291,   290,   301,   301,   303,   302,   313,   313,   314,
+     314,   320,   319,   340,   340,   345,   359,   371,   375,   374,
+     380,   379,   395,   398,   407,   421,   423,   425,   428,   428,
+     429,   429,   430,   430,   431,   431,   432,   432,   437,   439,
+     441,   445,   444,   450,   449,   459,   458,   464,   463,   473,
+     472,   482,   481,   490,   490,   493,   505,   506,   511,   511,
+     522,   524,   528,   527,   539,   538,   550,   549,   559,   558,
+     570,   569,   579,   578,   590,   589,   601,   600,   612,   611,
+     623,   622,   634,   633,   645,   644,   659,   661,   663,   667,
+     666,   678,   677,   688,   690,   693,   692,   702,   701,   711,
+     710,   718,   717,   730,   729,   739,   738,   752,   751,   765,
+     764,   778,   777,   785,   784,   794,   793,   807,   806,   816,
+     815,   825,   824,   838,   837,   851,   850,   861,   860,   870,
+     869,   879,   878,   888,   887,   897,   896,   910,   909,   923,
+     922,   936,   937,   940,   957,   958,   961,   978,   979,   982,
+    1005,  1006,  1009,  1039,  1040,  1043,  1076,  1078,  1080,  1084,
+    1083,  1089,  1088,  1094,  1093,  1099,  1098,  1104,  1103,  1109,
+    1108,  1125,  1133,  1124,  1168,  1173,  1178,  1183,  1190,  1239,
+    1304,  1333,  1336,  1361,  1374,  1376,  1380,  1379,  1385,  1384,
+    1390,  1389,  1395,  1394,  1406,  1406,  1411,  1410,  1416,  1415,
+    1423,  1428,  1427,  1434,  1490,  1491,  1494,  1495,  1496,  1499,
+    1500,  1501,  1504,  1505,  1511,  1510,  1537,  1536,  1560,  1631,
+    1637,  1646,  1648,  1652,  1651,  1656,  1656,  1657,  1657,  1658,
+    1660,  1659,  1673,  1672,  1684,  1683,  1694,  1693,  1717,  1716,
+    1726,  1726,  1727,  1727,  1728,  1728,  1730,  1729,  1739,  1738,
+    1748,  1747,  1765,  1764,  1782,  1781,  1798,  1798,  1799,  1799,
+    1801,  1800,  1806,  1806,  1807,  1807,  1808,  1808,  1809,  1809,
+    1819,  1819,  1826,  1826,  1833,  1833,  1834,  1834,  1837,  1837,
+    1838,  1838,  1839,  1839,  1840,  1840,  1842,  1841,  1853,  1852,
+    1864,  1863,  1872,  1871,  1881,  1880,  1890,  1889,  1899,  1898,
+    1904,  1903,  1908,  1908,  1910,  1909,  1924,  1923,  1934,  1936,
+    1960,  1959,  1975,  1974,  1996,  2004,  2016,  2017,  2018,  2020,
+    2022,  2026,  2025,  2030,  2029,  2035,  2034,  2047,  2046,  2052,
+    2051,  2065,  2064,  2162,  2163,  2164,  2167,  2168,  2169,  2170
+};
+#endif
+
+#if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE
+/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
+   First, the terminals, then, starting at YYNTOKENS, nonterminals.  */
+static const char *const yytname[] =
+{
+  "$end", "error", "$undefined", "PRIVSEP", "USER", "GROUP", "CHROOT",
+  "PATH", "PATHTYPE", "INCLUDE", "IDENTIFIER", "VENDORID", "LOGGING",
+  "LOGLEV", "PADDING", "PAD_RANDOMIZE", "PAD_RANDOMIZELEN", "PAD_MAXLEN",
+  "PAD_STRICT", "PAD_EXCLTAIL", "LISTEN", "X_ISAKMP", "X_ISAKMP_NATT",
+  "X_ADMIN", "STRICT_ADDRESS", "ADMINSOCK", "DISABLED", "LDAPCFG",
+  "LDAP_HOST", "LDAP_PORT", "LDAP_PVER", "LDAP_BASE", "LDAP_BIND_DN",
+  "LDAP_BIND_PW", "LDAP_SUBTREE", "LDAP_ATTR_USER", "LDAP_ATTR_ADDR",
+  "LDAP_ATTR_MASK", "LDAP_ATTR_GROUP", "LDAP_ATTR_MEMBER", "MODECFG",
+  "CFG_NET4", "CFG_MASK4", "CFG_DNS4", "CFG_NBNS4", "CFG_DEFAULT_DOMAIN",
+  "CFG_AUTH_SOURCE", "CFG_AUTH_GROUPS", "CFG_SYSTEM", "CFG_RADIUS",
+  "CFG_PAM", "CFG_LDAP", "CFG_LOCAL", "CFG_NONE", "CFG_GROUP_SOURCE",
+  "CFG_ACCOUNTING", "CFG_CONF_SOURCE", "CFG_MOTD", "CFG_POOL_SIZE",
+  "CFG_AUTH_THROTTLE", "CFG_SPLIT_NETWORK", "CFG_SPLIT_LOCAL",
+  "CFG_SPLIT_INCLUDE", "CFG_SPLIT_DNS", "CFG_PFS_GROUP", "CFG_SAVE_PASSWD",
+  "RETRY", "RETRY_COUNTER", "RETRY_INTERVAL", "RETRY_PERSEND",
+  "RETRY_PHASE1", "RETRY_PHASE2", "NATT_KA", "ALGORITHM_CLASS",
+  "ALGORITHMTYPE", "STRENGTHTYPE", "SAINFO", "FROM", "REMOTE", "ANONYMOUS",
+  "INHERIT", "EXCHANGE_MODE", "EXCHANGETYPE", "DOI", "DOITYPE",
+  "SITUATION", "SITUATIONTYPE", "CERTIFICATE_TYPE", "CERTTYPE",
+  "PEERS_CERTFILE", "CA_TYPE", "VERIFY_CERT", "SEND_CERT", "SEND_CR",
+  "IDENTIFIERTYPE", "IDENTIFIERQUAL", "MY_IDENTIFIER", "PEERS_IDENTIFIER",
+  "VERIFY_IDENTIFIER", "DNSSEC", "CERT_X509", "CERT_PLAINRSA",
+  "NONCE_SIZE", "DH_GROUP", "KEEPALIVE", "PASSIVE", "INITIAL_CONTACT",
+  "NAT_TRAVERSAL", "REMOTE_FORCE_LEVEL", "PROPOSAL_CHECK",
+  "PROPOSAL_CHECK_LEVEL", "GENERATE_POLICY", "GENERATE_LEVEL",
+  "SUPPORT_PROXY", "PROPOSAL", "EXEC_PATH", "EXEC_COMMAND", "EXEC_SUCCESS",
+  "EXEC_FAILURE", "GSS_ID", "GSS_ID_ENC", "GSS_ID_ENCTYPE",
+  "COMPLEX_BUNDLE", "DPD", "DPD_DELAY", "DPD_RETRY", "DPD_MAXFAIL",
+  "PH1ID", "XAUTH_LOGIN", "WEAK_PHASE1_CHECK", "PREFIX", "PORT", "PORTANY",
+  "UL_PROTO", "ANY", "IKE_FRAG", "ESP_FRAG", "MODE_CFG", "PFS_GROUP",
+  "LIFETIME", "LIFETYPE_TIME", "LIFETYPE_BYTE", "STRENGTH", "REMOTEID",
+  "SCRIPT", "PHASE1_UP", "PHASE1_DOWN", "NUMBER", "SWITCH", "BOOLEAN",
+  "HEXSTRING", "QUOTEDSTRING", "ADDRSTRING", "ADDRRANGE", "UNITTYPE_BYTE",
+  "UNITTYPE_KBYTES", "UNITTYPE_MBYTES", "UNITTYPE_TBYTES", "UNITTYPE_SEC",
+  "UNITTYPE_MIN", "UNITTYPE_HOUR", "EOS", "BOC", "EOC", "COMMA", "$accept",
+  "statements", "statement", "privsep_statement", "privsep_stmts",
+  "privsep_stmt", "@1", "@2", "@3", "@4", "@5", "path_statement", "@6",
+  "special_statement", "@7", "include_statement", "gssenc_statement",
+  "identifier_statement", "identifier_stmt", "@8", "@9",
+  "logging_statement", "log_level", "padding_statement", "padding_stmts",
+  "padding_stmt", "@10", "@11", "@12", "@13", "@14", "listen_statement",
+  "listen_stmts", "listen_stmt", "@15", "@16", "@17", "@18", "@19", "@20",
+  "@21", "ike_addrinfo_port", "ike_port", "ldapcfg_statement", "@22",
+  "ldapcfg_stmts", "ldapcfg_stmt", "@23", "@24", "@25", "@26", "@27",
+  "@28", "@29", "@30", "@31", "@32", "@33", "@34", "modecfg_statement",
+  "modecfg_stmts", "modecfg_stmt", "@35", "@36", "@37", "@38", "@39",
+  "@40", "@41", "@42", "@43", "@44", "@45", "@46", "@47", "@48", "@49",
+  "@50", "@51", "@52", "@53", "@54", "@55", "@56", "@57", "@58", "@59",
+  "addrdnslist", "addrdns", "addrwinslist", "addrwins", "splitnetlist",
+  "splitnet", "authgrouplist", "authgroup", "splitdnslist", "splitdns",
+  "timer_statement", "timer_stmts", "timer_stmt", "@60", "@61", "@62",
+  "@63", "@64", "@65", "sainfo_statement", "@66", "@67", "sainfo_name",
+  "sainfo_id", "sainfo_param", "sainfo_specs", "sainfo_spec", "@68", "@69",
+  "@70", "@71", "@72", "@73", "@74", "algorithms", "@75", "algorithm",
+  "prefix", "port", "ul_proto", "keylength", "remote_statement", "@76",
+  "@77", "remote_specs_block", "remote_index", "remote_specs",
+  "remote_spec", "@78", "@79", "@80", "@81", "@82", "@83", "@84", "@85",
+  "@86", "@87", "@88", "@89", "@90", "@91", "@92", "@93", "@94", "@95",
+  "@96", "@97", "@98", "@99", "@100", "@101", "@102", "@103", "@104",
+  "@105", "@106", "@107", "@108", "@109", "@110", "@111", "@112", "@113",
+  "@114", "@115", "@116", "@117", "@118", "@119", "exchange_types",
+  "cert_spec", "@120", "@121", "dh_group_num", "identifierstring",
+  "isakmpproposal_specs", "isakmpproposal_spec", "@122", "@123", "@124",
+  "@125", "@126", "@127", "unittype_time", "unittype_byte", 0
+};
+#endif
+
+# ifdef YYPRINT
+/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to
+   token YYLEX-NUM.  */
+static const yytype_uint16 yytoknum[] =
+{
+       0,   256,   257,   258,   259,   260,   261,   262,   263,   264,
+     265,   266,   267,   268,   269,   270,   271,   272,   273,   274,
+     275,   276,   277,   278,   279,   280,   281,   282,   283,   284,
+     285,   286,   287,   288,   289,   290,   291,   292,   293,   294,
+     295,   296,   297,   298,   299,   300,   301,   302,   303,   304,
+     305,   306,   307,   308,   309,   310,   311,   312,   313,   314,
+     315,   316,   317,   318,   319,   320,   321,   322,   323,   324,
+     325,   326,   327,   328,   329,   330,   331,   332,   333,   334,
+     335,   336,   337,   338,   339,   340,   341,   342,   343,   344,
+     345,   346,   347,   348,   349,   350,   351,   352,   353,   354,
+     355,   356,   357,   358,   359,   360,   361,   362,   363,   364,
+     365,   366,   367,   368,   369,   370,   371,   372,   373,   374,
+     375,   376,   377,   378,   379,   380,   381,   382,   383,   384,
+     385,   386,   387,   388,   389,   390,   391,   392,   393,   394,
+     395,   396,   397,   398,   399,   400,   401,   402,   403,   404,
+     405,   406,   407,   408,   409,   410,   411,   412,   413,   414,
+     415,   416,   417,   418,   419
+};
+# endif
+
+/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives.  */
+static const yytype_uint16 yyr1[] =
+{
+       0,   165,   166,   166,   167,   167,   167,   167,   167,   167,
+     167,   167,   167,   167,   167,   167,   167,   167,   168,   169,
+     169,   171,   170,   172,   170,   173,   170,   174,   170,   175,
+     170,   177,   176,   179,   178,   180,   181,   182,   184,   183,
+     185,   183,   186,   187,   187,   188,   189,   189,   191,   190,
+     192,   190,   193,   190,   194,   190,   195,   190,   196,   197,
+     197,   199,   198,   200,   198,   201,   198,   202,   198,   203,
+     198,   204,   198,   205,   198,   206,   207,   207,   209,   208,
+     210,   210,   212,   211,   213,   211,   214,   211,   215,   211,
+     216,   211,   217,   211,   218,   211,   219,   211,   220,   211,
+     221,   211,   222,   211,   223,   211,   224,   225,   225,   227,
+     226,   228,   226,   226,   226,   229,   226,   230,   226,   231,
+     226,   232,   226,   233,   226,   234,   226,   235,   226,   236,
+     226,   237,   226,   238,   226,   239,   226,   240,   226,   241,
+     226,   242,   226,   243,   226,   244,   226,   245,   226,   246,
+     226,   247,   226,   248,   226,   249,   226,   250,   226,   251,
+     226,   252,   252,   253,   254,   254,   255,   256,   256,   257,
+     258,   258,   259,   260,   260,   261,   262,   263,   263,   265,
+     264,   266,   264,   267,   264,   268,   264,   269,   264,   270,
+     264,   272,   273,   271,   274,   274,   274,   274,   275,   275,
+     275,   276,   276,   276,   277,   277,   279,   278,   280,   278,
+     281,   278,   282,   278,   283,   278,   284,   278,   285,   278,
+     286,   287,   286,   288,   289,   289,   290,   290,   290,   291,
+     291,   291,   292,   292,   294,   293,   295,   293,   296,   297,
+     297,   298,   298,   300,   299,   301,   299,   302,   299,   299,
+     303,   299,   304,   299,   305,   299,   306,   299,   307,   299,
+     308,   299,   309,   299,   310,   299,   311,   299,   312,   299,
+     313,   299,   314,   299,   315,   299,   316,   299,   317,   299,
+     318,   299,   319,   299,   320,   299,   321,   299,   322,   299,
+     323,   299,   324,   299,   325,   299,   326,   299,   327,   299,
+     328,   299,   329,   299,   330,   299,   331,   299,   332,   299,
+     333,   299,   334,   299,   335,   299,   336,   299,   337,   299,
+     338,   299,   339,   299,   340,   299,   341,   299,   342,   342,
+     344,   343,   345,   343,   346,   346,   347,   347,   347,   348,
+     348,   350,   349,   351,   349,   352,   349,   353,   349,   354,
+     349,   355,   349,   356,   356,   356,   357,   357,   357,   357
+};
+
+/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN.  */
+static const yytype_uint8 yyr2[] =
+{
+       0,     2,     0,     2,     1,     1,     1,     1,     1,     1,
+       1,     1,     1,     1,     1,     1,     1,     1,     4,     0,
+       2,     0,     4,     0,     4,     0,     4,     0,     4,     0,
+       4,     0,     5,     0,     4,     3,     3,     2,     0,     4,
+       0,     4,     3,     1,     1,     4,     0,     2,     0,     4,
+       0,     4,     0,     4,     0,     4,     0,     4,     4,     0,
+       2,     0,     4,     0,     4,     0,     4,     0,     7,     0,
+       4,     0,     4,     0,     3,     2,     0,     1,     0,     5,
+       0,     2,     0,     4,     0,     4,     0,     4,     0,     4,
+       0,     4,     0,     4,     0,     4,     0,     4,     0,     4,
+       0,     4,     0,     4,     0,     4,     4,     0,     2,     0,
+       4,     0,     4,     3,     3,     0,     5,     0,     5,     0,
+       4,     0,     4,     0,     4,     0,     4,     0,     4,     0,
+       4,     0,     4,     0,     4,     0,     4,     0,     4,     0,
+       4,     0,     4,     0,     4,     0,     4,     0,     4,     0,
+       4,     0,     4,     0,     4,     0,     4,     0,     4,     0,
+       4,     1,     3,     1,     1,     3,     1,     1,     3,     2,
+       1,     3,     1,     1,     3,     1,     4,     0,     2,     0,
+       4,     0,     5,     0,     4,     0,     5,     0,     5,     0,
+       5,     0,     0,     8,     1,     2,     2,     2,     5,     6,
+       2,     0,     3,     2,     0,     2,     0,     4,     0,     4,
+       0,     6,     0,     6,     0,     4,     0,     4,     0,     5,
+       1,     0,     4,     2,     0,     1,     0,     1,     1,     1,
+       1,     1,     0,     1,     0,     6,     0,     4,     3,     2,
+       1,     0,     2,     0,     4,     0,     4,     0,     4,     2,
+       0,     4,     0,     5,     0,     5,     0,     5,     0,     4,
+       0,     4,     0,     4,     0,     4,     0,     5,     0,     6,
+       0,     4,     0,     5,     0,     6,     0,     4,     0,     4,
+       0,     4,     0,     4,     0,     4,     0,     4,     0,     4,
+       0,     5,     0,     5,     0,     4,     0,     4,     0,     4,
+       0,     4,     0,     4,     0,     4,     0,     4,     0,     4,
+       0,     4,     0,     4,     0,     4,     0,     4,     0,     4,
+       0,     6,     0,     4,     0,     6,     0,     5,     0,     2,
+       0,     5,     0,     4,     1,     1,     0,     1,     1,     0,
+       2,     0,     4,     0,     6,     0,     6,     0,     4,     0,
+       4,     0,     5,     1,     1,     1,     1,     1,     1,     1
+};
+
+/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state
+   STATE-NUM when YYTABLE doesn't specify something else to do.  Zero
+   means the default is an error.  */
+static const yytype_uint16 yydefact[] =
+{
+       2,     0,     1,     0,     0,     0,     0,     0,     0,     0,
+      78,     0,     0,   191,     0,     0,     0,     3,     4,     5,
+      17,     6,     7,     8,     9,    10,    11,    12,    13,    14,
+      15,    16,    19,     0,     0,    38,     0,    37,    44,    43,
+       0,    46,    59,     0,   107,   177,     0,    76,    76,   240,
+     236,     0,    33,     0,    31,    35,     0,    40,    42,     0,
+       0,    80,     0,     0,   194,     0,   201,     0,    77,   239,
+      75,     0,     0,    36,     0,     0,     0,     0,    18,    20,
+       0,     0,     0,     0,     0,     0,     0,     0,    45,    47,
+       0,     0,    65,    73,     0,    58,    60,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,   106,   108,     0,     0,     0,
+       0,     0,     0,   176,   178,   195,   200,   224,     0,     0,
+       0,   196,   197,   234,   241,   237,    34,    23,    21,    27,
+      25,    29,    32,    39,    41,    48,    50,    52,    54,    56,
+      61,    63,     0,     0,    71,    69,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,    79,    81,
+     109,   111,   163,     0,   161,   166,     0,   164,   121,   123,
+     125,   127,   129,   172,   131,   170,   133,   135,   139,   141,
+     143,   137,   155,   157,   153,   159,   145,   151,     0,     0,
+     175,   119,   173,   147,   149,   179,     0,   183,     0,     0,
+       0,   225,   224,   226,   203,   336,   204,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,    74,     0,     0,     0,    84,    86,    82,    88,
+      92,    94,    90,    96,    98,   100,   102,   104,     0,     0,
+     113,     0,   114,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,   115,   167,   117,     0,     0,     0,
+       0,     0,   353,   354,   355,   181,     0,   185,   187,   189,
+     226,   227,   228,     0,   338,   337,   202,   192,   235,   243,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,   280,     0,     0,     0,     0,     0,     0,   326,
+       0,     0,     0,     0,     0,   336,     0,     0,     0,     0,
+       0,     0,   238,   242,    24,    22,    28,    26,    30,    49,
+      51,    53,    55,    57,    62,    64,    66,    72,     0,    70,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,   110,   112,   162,   165,   122,   124,   126,   128,
+     130,   132,   171,   134,   136,   140,   142,   144,   138,   156,
+     158,   154,   160,   146,   152,   169,     0,     0,     0,   120,
+     174,   148,   150,   180,     0,   184,     0,     0,     0,     0,
+     230,   231,   229,   198,     0,   214,     0,     0,     0,     0,
+       0,   205,   328,   245,   247,     0,     0,   249,   258,     0,
+       0,   250,     0,   260,   262,   264,   336,   336,   276,   278,
+       0,   282,   304,   308,   306,   322,   300,   298,   302,     0,
+     310,   312,   314,   316,   318,   270,   296,   286,   284,   288,
+     294,     0,     0,     0,    67,    85,    87,    83,    89,    93,
+      95,    91,    97,    99,   101,   103,   105,   168,   116,   118,
+     182,   186,   188,   190,   199,   216,     0,     0,   334,   335,
+     206,     0,     0,   208,   193,     0,     0,     0,     0,   332,
+       0,   254,   256,     0,   252,     0,     0,     0,   336,   266,
+     336,   272,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,   339,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,   290,   292,     0,
+       0,   232,     0,   220,   218,     0,     0,     0,     0,   329,
+     244,   246,   248,   330,     0,   259,     0,     0,   251,     0,
+     261,   263,   265,   268,     0,   274,     0,   277,   279,   281,
+     283,   305,   309,   307,   323,   301,   299,   303,     0,   311,
+     313,   315,   317,   319,   271,   297,   287,   285,   289,   295,
+     320,   356,   357,   358,   359,   324,     0,     0,    68,   217,
+     233,   223,   215,     0,     0,   207,   210,   212,   209,     0,
+     333,   255,   257,   253,     0,   267,     0,   273,     0,     0,
+       0,     0,   341,   327,   340,     0,     0,   291,   293,     0,
+     219,     0,     0,   331,   269,   275,   232,   347,   349,     0,
+       0,     0,   321,   325,   222,   211,   213,   351,     0,     0,
+       0,     0,     0,     0,   348,   350,   343,   345,   342,   352,
+       0,     0,   344,   346
+};
+
+/* YYDEFGOTO[NTERM-NUM].  */
+static const yytype_int16 yydefgoto[] =
+{
+      -1,     1,    17,    18,    53,    79,   220,   219,   222,   221,
+     223,    19,    80,    20,    74,    21,    22,    23,    37,    56,
+      82,    24,    40,    25,    59,    89,   224,   225,   226,   227,
+     228,    26,    60,    96,   229,   230,   152,   529,   235,   233,
+     153,    49,    69,    27,    43,    97,   169,   352,   350,   351,
+     353,   356,   354,   355,   357,   358,   359,   360,   361,    28,
+      62,   116,   248,   249,   387,   388,   277,   254,   255,   256,
+     257,   258,   259,   261,   262,   266,   263,   264,   265,   271,
+     279,   280,   272,   269,   267,   268,   270,   173,   174,   176,
+     177,   274,   275,   184,   185,   201,   202,    29,    63,   124,
+     281,   394,   286,   396,   397,   398,    30,    46,   410,    66,
+      67,   130,   297,   411,   535,   538,   621,   622,   476,   530,
+     594,   532,   593,   533,   213,   293,   403,   591,    31,   217,
+      72,   135,    50,   218,   333,   412,   486,   487,   493,   549,
+     546,   547,   490,   495,   496,   497,   554,   604,   519,   556,
+     606,   502,   503,   430,   505,   522,   521,   523,   586,   587,
+     524,   520,   511,   510,   512,   506,   508,   507,   514,   515,
+     516,   517,   518,   615,   509,   616,   439,   485,   417,   599,
+     544,   480,   296,   568,   614,   631,   650,   651,   638,   639,
+     643,   285,   585
+};
+
+/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
+   STATE-NUM.  */
+#define YYPACT_NINF -519
+static const yytype_int16 yypact[] =
+{
+    -519,    63,  -519,   -91,    74,   -67,    25,     7,   -63,   -51,
+    -519,   -49,   -44,  -519,   -57,    17,     6,  -519,  -519,  -519,
+    -519,  -519,  -519,  -519,  -519,  -519,  -519,  -519,  -519,  -519,
+    -519,  -519,  -519,    27,   -18,  -519,    38,  -519,  -519,  -519,
+      26,  -519,  -519,    29,  -519,  -519,    -1,    73,    73,  -519,
+     127,    50,  -519,     1,  -519,  -519,    62,  -519,  -519,    -7,
+      -8,  -519,    -4,   -23,   121,    -3,    59,     0,  -519,  -519,
+    -519,   -57,    56,  -519,    58,   -71,   -35,    70,  -519,  -519,
+      61,    64,    72,    75,    87,    77,    88,    89,  -519,  -519,
+      68,    68,  -519,  -519,     9,  -519,  -519,    -5,    82,    91,
+      92,    94,    90,    76,    97,    69,    48,    93,    98,   105,
+     106,   104,    99,   107,   108,  -519,  -519,   110,   111,   113,
+     114,   115,   116,  -519,  -519,  -519,  -519,   -62,   100,   151,
+     102,  -519,  -519,  -519,  -519,  -519,  -519,  -519,  -519,  -519,
+    -519,  -519,  -519,  -519,  -519,  -519,  -519,  -519,  -519,  -519,
+    -519,  -519,   124,   109,  -519,   117,   118,   120,   125,   122,
+     123,   126,   128,   129,   130,   131,   132,   133,  -519,  -519,
+    -519,  -519,  -519,   134,    95,  -519,   135,   101,  -519,  -519,
+    -519,  -519,  -519,  -519,  -519,   136,  -519,  -519,  -519,  -519,
+    -519,  -519,  -519,  -519,  -519,  -519,  -519,  -519,   119,   119,
+    -519,  -519,   137,  -519,  -519,  -519,     3,  -519,     3,     3,
+       3,  -519,   145,    36,  -519,    18,  -519,    56,   103,   138,
+     141,   142,   143,   144,   146,   147,   148,   149,   150,   152,
+     153,   154,  -519,   155,   139,   157,  -519,  -519,  -519,  -519,
+    -519,  -519,  -519,  -519,  -519,  -519,  -519,  -519,   158,   159,
+    -519,    92,  -519,    94,   160,   161,   162,   163,   164,   165,
+      97,   166,   168,   169,   170,   171,   172,   173,   174,   175,
+     176,   177,   178,   156,   179,  -519,   179,   180,    99,   181,
+     183,   184,  -519,  -519,  -519,  -519,   185,  -519,  -519,  -519,
+      36,  -519,  -519,   -45,  -519,  -519,  -519,     8,  -519,  -519,
+     194,   193,    71,   -14,   187,   140,   192,   199,   191,   195,
+     200,   202,  -519,   203,   204,   -41,   182,   -38,   205,  -519,
+     206,   208,   209,   210,   211,    18,   212,   -39,   214,   215,
+      33,   213,  -519,  -519,  -519,  -519,  -519,  -519,  -519,  -519,
+    -519,  -519,  -519,  -519,  -519,  -519,  -519,  -519,   218,  -519,
+     189,   198,   201,   207,   216,   217,   219,   220,   221,   222,
+     223,   224,  -519,  -519,  -519,  -519,  -519,  -519,  -519,  -519,
+    -519,  -519,  -519,  -519,  -519,  -519,  -519,  -519,  -519,  -519,
+    -519,  -519,  -519,  -519,  -519,  -519,   119,   225,   226,  -519,
+    -519,  -519,  -519,  -519,   227,  -519,   228,   229,   230,   -45,
+    -519,  -519,  -519,  -519,   197,  -519,   272,   -17,    35,   232,
+     231,  -519,  -519,  -519,  -519,   241,   242,  -519,  -519,   244,
+     245,  -519,   246,  -519,  -519,  -519,   -37,   -30,  -519,  -519,
+     -17,  -519,  -519,  -519,  -519,  -519,  -519,  -519,  -519,   236,
+    -519,  -519,  -519,  -519,  -519,  -519,  -519,  -519,  -519,  -519,
+    -519,   252,   253,    52,  -519,  -519,  -519,  -519,  -519,  -519,
+    -519,  -519,  -519,  -519,  -519,  -519,  -519,  -519,  -519,  -519,
+    -519,  -519,  -519,  -519,  -519,  -519,   238,   250,  -519,  -519,
+    -519,   255,   256,  -519,  -519,   -61,   243,   247,   254,  -519,
+     248,  -519,  -519,   249,  -519,   251,   257,   258,    18,  -519,
+      18,  -519,   259,   260,   261,   262,   263,   264,   265,   266,
+     267,   268,   269,  -519,   270,   273,   274,   275,   276,   277,
+     278,   279,   280,   281,   282,     3,   -22,  -519,  -519,   283,
+     284,   286,   285,   287,  -519,   288,     3,   -22,   289,  -519,
+    -519,  -519,  -519,  -519,   291,  -519,   292,   293,  -519,   294,
+    -519,  -519,  -519,  -519,   295,  -519,   296,  -519,  -519,  -519,
+    -519,  -519,  -519,  -519,  -519,  -519,  -519,  -519,   -11,  -519,
+    -519,  -519,  -519,  -519,  -519,  -519,  -519,  -519,  -519,  -519,
+    -519,  -519,  -519,  -519,  -519,  -519,   297,   298,  -519,  -519,
+    -519,  -519,  -519,   299,   300,  -519,  -519,  -519,  -519,   301,
+    -519,  -519,  -519,  -519,   303,  -519,   304,  -519,   302,   -17,
+     309,    40,  -519,  -519,  -519,   305,   306,  -519,  -519,   238,
+    -519,   307,   308,  -519,  -519,  -519,   286,  -519,  -519,   323,
+     324,   331,  -519,  -519,  -519,  -519,  -519,  -519,   311,   312,
+       3,   -22,   313,   314,  -519,  -519,  -519,  -519,  -519,  -519,
+     315,   316,  -519,  -519
+};
+
+/* YYPGOTO[NTERM-NUM].  */
+static const yytype_int16 yypgoto[] =
+{
+    -519,  -519,  -519,  -519,  -519,  -519,  -519,  -519,  -519,  -519,
+    -519,  -519,  -519,  -519,  -519,  -519,  -519,  -519,  -519,  -519,
+    -519,  -519,  -519,  -519,  -519,  -519,  -519,  -519,  -519,  -519,
+    -519,  -519,  -519,  -519,  -519,  -519,  -519,  -519,  -519,  -519,
+    -519,   112,   319,  -519,  -519,  -519,  -519,  -519,  -519,  -519,
+    -519,  -519,  -519,  -519,  -519,  -519,  -519,  -519,  -519,  -519,
+    -519,  -519,  -519,  -519,  -519,  -519,  -519,  -519,  -519,  -519,
+    -519,  -519,  -519,  -519,  -519,  -519,  -519,  -519,  -519,  -519,
+    -519,  -519,  -519,  -519,  -519,  -519,  -519,    42,  -519,    41,
+    -519,   290,   -89,    46,  -519,    20,  -519,  -519,  -519,  -519,
+    -519,  -519,  -519,  -519,  -519,  -519,  -519,  -519,  -519,  -519,
+      86,  -519,  -519,  -519,  -519,  -519,  -519,  -519,  -519,  -519,
+    -519,  -250,  -519,  -519,   235,    80,   -28,  -254,  -519,  -519,
+    -519,   190,   340,  -519,  -519,  -519,  -519,  -519,  -519,  -519,
+    -519,  -519,  -519,  -519,  -519,  -519,  -519,  -519,  -519,  -519,
+    -519,  -519,  -519,  -519,  -519,  -519,  -519,  -519,  -519,  -519,
+    -519,  -519,  -519,  -519,  -519,  -519,  -519,  -519,  -519,  -519,
+    -519,  -519,  -519,  -519,  -519,  -519,  -519,  -519,  -519,  -519,
+    -519,  -427,  -321,  -519,  -519,  -519,  -519,  -519,  -519,  -519,
+    -519,  -208,  -518
+};
+
+/* YYTABLE[YYPACT[STATE-NUM]].  What to do in state STATE-NUM.  If
+   positive, shift that token.  If negative, reduce the rule which
+   number is the opposite.  If zero, do what YYDEFACT says.
+   If YYTABLE_NINF, syntax error.  */
+#define YYTABLE_NINF -222
+static const yytype_int16 yytable[] =
+{
+     287,   288,   289,   504,   445,    75,    76,    77,    83,    84,
+      85,    86,    87,    90,    91,    92,    93,    94,   404,   597,
+      38,   539,    47,   156,   157,   158,   159,   160,   161,   162,
+     163,   164,   165,   166,   167,   154,    35,    98,    99,   100,
+     101,   102,   103,   104,   117,   118,   119,   120,   121,   122,
+     105,   106,   107,   108,   109,   110,   111,   478,   498,   112,
+     113,   114,   608,     2,   128,   500,     3,   433,   211,   447,
+       4,    32,     5,     6,   436,     7,   137,     8,    64,   131,
+     138,   405,    33,     9,    34,   418,   419,   420,   400,   401,
+      10,   212,   609,    65,    65,    48,   188,   189,   190,    41,
+     540,   191,   402,    11,   406,   499,   501,   434,   610,   448,
+     437,    42,   139,    44,   294,   295,   140,   186,    45,    36,
+     187,   294,   295,   647,   179,   180,   181,   182,   611,    12,
+     479,   612,   581,   582,   583,   584,   129,   421,    51,    13,
+     123,    14,   192,    55,   193,   194,   407,   408,   126,   127,
+     125,   409,   613,   132,    52,    95,    88,    39,   168,   115,
+     155,   282,   283,   284,    78,   198,   199,   291,   292,   294,
+     295,   415,   416,   451,   452,   481,   482,   553,    54,   555,
+     629,   630,   627,    15,   299,    16,   300,    58,   301,    57,
+     302,    61,   303,   304,   305,   306,   307,   527,   528,   308,
+     309,   310,   150,   151,    68,   311,   312,    71,   313,   314,
+     315,    73,   316,    81,   317,    65,   318,   319,   134,   136,
+      48,   141,   142,   145,   147,   143,   320,   321,   322,   323,
+     324,   325,   326,   144,   170,   146,   148,   149,   327,   328,
+     329,   178,   330,   171,   172,   215,   175,   331,   183,   195,
+     200,   214,   196,   197,   203,   231,   204,   205,   206,   251,
+     207,   208,   209,   210,   216,   253,   332,   237,   234,   236,
+     232,   273,   238,   239,   240,   211,   242,   241,   413,   414,
+     243,   244,   245,   246,   247,   426,   385,   422,   423,   427,
+     348,   475,   435,   364,   365,   250,   252,   467,   390,   334,
+     260,   278,   335,   336,   337,   338,   372,   339,   340,   341,
+     342,   343,   531,   344,   345,   346,   347,   580,   349,   362,
+     363,   366,   367,   368,   369,   370,   371,   373,   596,   374,
+     375,   376,   377,   378,   379,   380,   381,   382,   383,   384,
+     424,   389,   391,   386,   392,   393,   395,   425,   428,   429,
+     455,   431,   432,   438,   440,   441,   442,   443,   444,   456,
+     446,   449,   457,   450,   453,   454,   477,    70,   458,   634,
+     399,   474,   637,     0,     0,     0,   626,   459,   460,   483,
+     461,   462,   463,   464,   465,   466,   468,   469,   470,   471,
+     472,   473,   488,   489,   484,   491,   492,   494,   513,   525,
+     526,   534,   536,   537,   541,   543,   642,   298,   542,   545,
+     548,   133,   550,     0,     0,     0,     0,     0,   551,   552,
+     557,   558,   559,   560,   561,   562,   563,   564,   565,   566,
+     567,   569,   646,   590,   570,   571,   572,   573,   574,   575,
+     576,   577,   578,   579,   588,   589,   592,   290,     0,   595,
+     598,  -221,   600,   601,   602,   603,   605,   607,   617,   618,
+     628,   620,   623,   619,   624,   625,   632,   633,   635,   636,
+     640,   641,   644,   645,   648,   649,   652,   653,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,   276
+};
+
+static const yytype_int16 yycheck[] =
+{
+     208,   209,   210,   430,   325,     4,     5,     6,    15,    16,
+      17,    18,    19,    21,    22,    23,    24,    25,    10,   537,
+      13,    82,    79,    28,    29,    30,    31,    32,    33,    34,
+      35,    36,    37,    38,    39,    26,    11,    41,    42,    43,
+      44,    45,    46,    47,    67,    68,    69,    70,    71,    72,
+      54,    55,    56,    57,    58,    59,    60,    74,    95,    63,
+      64,    65,    73,     0,     5,    95,     3,   108,   130,   108,
+       7,   162,     9,    10,   112,    12,   147,    14,    79,    79,
+     151,    73,     8,    20,   151,    99,   100,   101,   133,   134,
+      27,   153,   103,    94,    94,   152,    48,    49,    50,   162,
+     161,    53,   147,    40,    96,   426,   427,   148,   119,   148,
+     148,   162,   147,   162,   151,   152,   151,    48,   162,    94,
+      51,   151,   152,   641,    48,    49,    50,    51,   139,    66,
+     147,   142,   154,   155,   156,   157,    77,   151,   121,    76,
+     163,    78,    49,   161,    51,    52,   138,   139,   151,   152,
+      64,   143,   163,    67,   148,   163,   163,   150,   163,   163,
+     151,   158,   159,   160,   163,    61,    62,   131,   132,   151,
+     152,   100,   101,   140,   141,   140,   141,   498,   151,   500,
+     140,   141,   609,   120,    81,   122,    83,   161,    85,   151,
+      87,   162,    89,    90,    91,    92,    93,   145,   146,    96,
+      97,    98,    90,    91,   131,   102,   103,    80,   105,   106,
+     107,   161,   109,   151,   111,    94,   113,   114,   162,   161,
+     152,   151,   161,   148,   147,   161,   123,   124,   125,   126,
+     127,   128,   129,   161,   152,   148,   148,   148,   135,   136,
+     137,   151,   139,   152,   152,    94,   152,   144,   151,   151,
+     151,   151,   147,   147,   147,   131,   148,   147,   147,   164,
+     147,   147,   147,   147,   162,   164,   163,   147,   151,   151,
+     161,   152,   147,   151,   151,   130,   148,   151,    84,    86,
+     151,   151,   151,   151,   151,    94,   130,   100,   148,    94,
+     151,    94,   110,   251,   253,   161,   161,   386,   278,   161,
+     164,   164,   161,   161,   161,   161,   260,   161,   161,   161,
+     161,   161,    74,   161,   161,   161,   161,   525,   161,   161,
+     161,   161,   161,   161,   161,   161,   161,   161,   536,   161,
+     161,   161,   161,   161,   161,   161,   161,   161,   161,   161,
+     148,   161,   161,   164,   161,   161,   161,   148,   148,   147,
+     161,   148,   148,   148,   148,   147,   147,   147,   147,   161,
+     148,   147,   161,   148,   151,   147,    94,    48,   161,   619,
+     290,   399,   626,    -1,    -1,    -1,    74,   161,   161,   147,
+     161,   161,   161,   161,   161,   161,   161,   161,   161,   161,
+     161,   161,   151,   151,   163,   151,   151,   151,   162,   147,
+     147,   151,   147,   147,   161,   151,    75,   217,   161,   161,
+     161,    71,   161,    -1,    -1,    -1,    -1,    -1,   161,   161,
+     161,   161,   161,   161,   161,   161,   161,   161,   161,   161,
+     161,   161,   640,   147,   161,   161,   161,   161,   161,   161,
+     161,   161,   161,   161,   161,   161,   161,   212,    -1,   161,
+     161,   164,   161,   161,   161,   161,   161,   161,   161,   161,
+     151,   161,   161,   164,   161,   161,   161,   161,   161,   161,
+     147,   147,   161,   161,   161,   161,   161,   161,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,   199
+};
+
+/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
+   symbol of state STATE-NUM.  */
+static const yytype_uint16 yystos[] =
+{
+       0,   166,     0,     3,     7,     9,    10,    12,    14,    20,
+      27,    40,    66,    76,    78,   120,   122,   167,   168,   176,
+     178,   180,   181,   182,   186,   188,   196,   208,   224,   262,
+     271,   293,   162,     8,   151,    11,    94,   183,    13,   150,
+     187,   162,   162,   209,   162,   162,   272,    79,   152,   206,
+     297,   121,   148,   169,   151,   161,   184,   151,   161,   189,
+     197,   162,   225,   263,    79,    94,   274,   275,   131,   207,
+     207,    80,   295,   161,   179,     4,     5,     6,   163,   170,
+     177,   151,   185,    15,    16,    17,    18,    19,   163,   190,
+      21,    22,    23,    24,    25,   163,   198,   210,    41,    42,
+      43,    44,    45,    46,    47,    54,    55,    56,    57,    58,
+      59,    60,    63,    64,    65,   163,   226,    67,    68,    69,
+      70,    71,    72,   163,   264,   275,   151,   152,     5,    77,
+     276,    79,   275,   297,   162,   296,   161,   147,   151,   147,
+     151,   151,   161,   161,   161,   148,   148,   147,   148,   148,
+     206,   206,   201,   205,    26,   151,    28,    29,    30,    31,
+      32,    33,    34,    35,    36,    37,    38,    39,   163,   211,
+     152,   152,   152,   252,   253,   152,   254,   255,   151,    48,
+      49,    50,    51,   151,   258,   259,    48,    51,    48,    49,
+      50,    53,    49,    51,    52,   151,   147,   147,    61,    62,
+     151,   260,   261,   147,   148,   147,   147,   147,   147,   147,
+     147,   130,   153,   289,   151,    94,   162,   294,   298,   172,
+     171,   174,   173,   175,   191,   192,   193,   194,   195,   199,
+     200,   131,   161,   204,   151,   203,   151,   147,   147,   151,
+     151,   151,   148,   151,   151,   151,   151,   151,   227,   228,
+     161,   164,   161,   164,   232,   233,   234,   235,   236,   237,
+     164,   238,   239,   241,   242,   243,   240,   249,   250,   248,
+     251,   244,   247,   152,   256,   257,   256,   231,   164,   245,
+     246,   265,   158,   159,   160,   356,   267,   356,   356,   356,
+     289,   131,   132,   290,   151,   152,   347,   277,   296,    81,
+      83,    85,    87,    89,    90,    91,    92,    93,    96,    97,
+      98,   102,   103,   105,   106,   107,   109,   111,   113,   114,
+     123,   124,   125,   126,   127,   128,   129,   135,   136,   137,
+     139,   144,   163,   299,   161,   161,   161,   161,   161,   161,
+     161,   161,   161,   161,   161,   161,   161,   161,   151,   161,
+     213,   214,   212,   215,   217,   218,   216,   219,   220,   221,
+     222,   223,   161,   161,   252,   254,   161,   161,   161,   161,
+     161,   161,   258,   161,   161,   161,   161,   161,   161,   161,
+     161,   161,   161,   161,   161,   130,   164,   229,   230,   161,
+     260,   161,   161,   161,   266,   161,   268,   269,   270,   290,
+     133,   134,   147,   291,    10,    73,    96,   138,   139,   143,
+     273,   278,   300,    84,    86,   100,   101,   343,    99,   100,
+     101,   151,   100,   148,   148,   148,    94,    94,   148,   147,
+     318,   148,   148,   108,   148,   110,   112,   148,   148,   341,
+     148,   147,   147,   147,   147,   347,   148,   108,   148,   147,
+     148,   140,   141,   151,   147,   161,   161,   161,   161,   161,
+     161,   161,   161,   161,   161,   161,   161,   257,   161,   161,
+     161,   161,   161,   161,   291,    94,   283,    94,    74,   147,
+     346,   140,   141,   147,   163,   342,   301,   302,   151,   151,
+     307,   151,   151,   303,   151,   308,   309,   310,    95,   347,
+      95,   347,   316,   317,   346,   319,   330,   332,   331,   339,
+     328,   327,   329,   162,   333,   334,   335,   336,   337,   313,
+     326,   321,   320,   322,   325,   147,   147,   145,   146,   202,
+     284,    74,   286,   288,   151,   279,   147,   147,   280,    82,
+     161,   161,   161,   151,   345,   161,   305,   306,   161,   304,
+     161,   161,   161,   347,   311,   347,   314,   161,   161,   161,
+     161,   161,   161,   161,   161,   161,   161,   161,   348,   161,
+     161,   161,   161,   161,   161,   161,   161,   161,   161,   161,
+     356,   154,   155,   156,   157,   357,   323,   324,   161,   161,
+     147,   292,   161,   287,   285,   161,   356,   357,   161,   344,
+     161,   161,   161,   161,   312,   161,   315,   161,    73,   103,
+     119,   139,   142,   163,   349,   338,   340,   161,   161,   164,
+     161,   281,   282,   161,   161,   161,    74,   346,   151,   140,
+     141,   350,   161,   161,   286,   161,   161,   292,   353,   354,
+     147,   147,    75,   355,   161,   161,   356,   357,   161,   161,
+     351,   352,   161,   161
+};
+
+#define yyerrok		(yyerrstatus = 0)
+#define yyclearin	(yychar = YYEMPTY)
+#define YYEMPTY		(-2)
+#define YYEOF		0
+
+#define YYACCEPT	goto yyacceptlab
+#define YYABORT		goto yyabortlab
+#define YYERROR		goto yyerrorlab
+
+
+/* Like YYERROR except do call yyerror.  This remains here temporarily
+   to ease the transition to the new meaning of YYERROR, for GCC.
+   Once GCC version 2 has supplanted version 1, this can go.  */
+
+#define YYFAIL		goto yyerrlab
+
+#define YYRECOVERING()  (!!yyerrstatus)
+
+#define YYBACKUP(Token, Value)					\
+do								\
+  if (yychar == YYEMPTY && yylen == 1)				\
+    {								\
+      yychar = (Token);						\
+      yylval = (Value);						\
+      yytoken = YYTRANSLATE (yychar);				\
+      YYPOPSTACK (1);						\
+      goto yybackup;						\
+    }								\
+  else								\
+    {								\
+      yyerror (YY_("syntax error: cannot back up")); \
+      YYERROR;							\
+    }								\
+while (YYID (0))
+
+
+#define YYTERROR	1
+#define YYERRCODE	256
+
+
+/* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N].
+   If N is 0, then set CURRENT to the empty location which ends
+   the previous symbol: RHS[0] (always defined).  */
+
+#define YYRHSLOC(Rhs, K) ((Rhs)[K])
+#ifndef YYLLOC_DEFAULT
+# define YYLLOC_DEFAULT(Current, Rhs, N)				\
+    do									\
+      if (YYID (N))                                                    \
+	{								\
+	  (Current).first_line   = YYRHSLOC (Rhs, 1).first_line;	\
+	  (Current).first_column = YYRHSLOC (Rhs, 1).first_column;	\
+	  (Current).last_line    = YYRHSLOC (Rhs, N).last_line;		\
+	  (Current).last_column  = YYRHSLOC (Rhs, N).last_column;	\
+	}								\
+      else								\
+	{								\
+	  (Current).first_line   = (Current).last_line   =		\
+	    YYRHSLOC (Rhs, 0).last_line;				\
+	  (Current).first_column = (Current).last_column =		\
+	    YYRHSLOC (Rhs, 0).last_column;				\
+	}								\
+    while (YYID (0))
+#endif
+
+
+/* YY_LOCATION_PRINT -- Print the location on the stream.
+   This macro was not mandated originally: define only if we know
+   we won't break user code: when these are the locations we know.  */
+
+#ifndef YY_LOCATION_PRINT
+# if YYLTYPE_IS_TRIVIAL
+#  define YY_LOCATION_PRINT(File, Loc)			\
+     fprintf (File, "%d.%d-%d.%d",			\
+	      (Loc).first_line, (Loc).first_column,	\
+	      (Loc).last_line,  (Loc).last_column)
+# else
+#  define YY_LOCATION_PRINT(File, Loc) ((void) 0)
+# endif
+#endif
+
+
+/* YYLEX -- calling `yylex' with the right arguments.  */
+
+#ifdef YYLEX_PARAM
+# define YYLEX yylex (YYLEX_PARAM)
+#else
+# define YYLEX yylex ()
+#endif
+
+/* Enable debugging if requested.  */
+#if YYDEBUG
+
+# ifndef YYFPRINTF
+#  include <stdio.h> /* INFRINGES ON USER NAME SPACE */
+#  define YYFPRINTF fprintf
+# endif
+
+# define YYDPRINTF(Args)			\
+do {						\
+  if (yydebug)					\
+    YYFPRINTF Args;				\
+} while (YYID (0))
+
+# define YY_SYMBOL_PRINT(Title, Type, Value, Location)			  \
+do {									  \
+  if (yydebug)								  \
+    {									  \
+      YYFPRINTF (stderr, "%s ", Title);					  \
+      yy_symbol_print (stderr,						  \
+		  Type, Value); \
+      YYFPRINTF (stderr, "\n");						  \
+    }									  \
+} while (YYID (0))
+
+
+/*--------------------------------.
+| Print this symbol on YYOUTPUT.  |
+`--------------------------------*/
+
+/*ARGSUSED*/
+#if (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+static void
+yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep)
+#else
+static void
+yy_symbol_value_print (yyoutput, yytype, yyvaluep)
+    FILE *yyoutput;
+    int yytype;
+    YYSTYPE const * const yyvaluep;
+#endif
+{
+  if (!yyvaluep)
+    return;
+# ifdef YYPRINT
+  if (yytype < YYNTOKENS)
+    YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep);
+# else
+  YYUSE (yyoutput);
+# endif
+  switch (yytype)
+    {
+      default:
+	break;
+    }
+}
+
+
+/*--------------------------------.
+| Print this symbol on YYOUTPUT.  |
+`--------------------------------*/
+
+#if (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+static void
+yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep)
+#else
+static void
+yy_symbol_print (yyoutput, yytype, yyvaluep)
+    FILE *yyoutput;
+    int yytype;
+    YYSTYPE const * const yyvaluep;
+#endif
+{
+  if (yytype < YYNTOKENS)
+    YYFPRINTF (yyoutput, "token %s (", yytname[yytype]);
+  else
+    YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]);
+
+  yy_symbol_value_print (yyoutput, yytype, yyvaluep);
+  YYFPRINTF (yyoutput, ")");
+}
+
+/*------------------------------------------------------------------.
+| yy_stack_print -- Print the state stack from its BOTTOM up to its |
+| TOP (included).                                                   |
+`------------------------------------------------------------------*/
+
+#if (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+static void
+yy_stack_print (yytype_int16 *bottom, yytype_int16 *top)
+#else
+static void
+yy_stack_print (bottom, top)
+    yytype_int16 *bottom;
+    yytype_int16 *top;
+#endif
+{
+  YYFPRINTF (stderr, "Stack now");
+  for (; bottom <= top; ++bottom)
+    YYFPRINTF (stderr, " %d", *bottom);
+  YYFPRINTF (stderr, "\n");
+}
+
+# define YY_STACK_PRINT(Bottom, Top)				\
+do {								\
+  if (yydebug)							\
+    yy_stack_print ((Bottom), (Top));				\
+} while (YYID (0))
+
+
+/*------------------------------------------------.
+| Report that the YYRULE is going to be reduced.  |
+`------------------------------------------------*/
+
+#if (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+static void
+yy_reduce_print (YYSTYPE *yyvsp, int yyrule)
+#else
+static void
+yy_reduce_print (yyvsp, yyrule)
+    YYSTYPE *yyvsp;
+    int yyrule;
+#endif
+{
+  int yynrhs = yyr2[yyrule];
+  int yyi;
+  unsigned long int yylno = yyrline[yyrule];
+  YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n",
+	     yyrule - 1, yylno);
+  /* The symbols being reduced.  */
+  for (yyi = 0; yyi < yynrhs; yyi++)
+    {
+      fprintf (stderr, "   $%d = ", yyi + 1);
+      yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi],
+		       &(yyvsp[(yyi + 1) - (yynrhs)])
+		       		       );
+      fprintf (stderr, "\n");
+    }
+}
+
+# define YY_REDUCE_PRINT(Rule)		\
+do {					\
+  if (yydebug)				\
+    yy_reduce_print (yyvsp, Rule); \
+} while (YYID (0))
+
+/* Nonzero means print parse trace.  It is left uninitialized so that
+   multiple parsers can coexist.  */
+int yydebug;
+#else /* !YYDEBUG */
+# define YYDPRINTF(Args)
+# define YY_SYMBOL_PRINT(Title, Type, Value, Location)
+# define YY_STACK_PRINT(Bottom, Top)
+# define YY_REDUCE_PRINT(Rule)
+#endif /* !YYDEBUG */
+
+
+/* YYINITDEPTH -- initial size of the parser's stacks.  */
+#ifndef	YYINITDEPTH
+# define YYINITDEPTH 200
+#endif
+
+/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only
+   if the built-in stack extension method is used).
+
+   Do not make this value too large; the results are undefined if
+   YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH)
+   evaluated with infinite-precision integer arithmetic.  */
+
+#ifndef YYMAXDEPTH
+# define YYMAXDEPTH 10000
+#endif
+
+
+
+#if YYERROR_VERBOSE
+
+# ifndef yystrlen
+#  if defined __GLIBC__ && defined _STRING_H
+#   define yystrlen strlen
+#  else
+/* Return the length of YYSTR.  */
+#if (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+static YYSIZE_T
+yystrlen (const char *yystr)
+#else
+static YYSIZE_T
+yystrlen (yystr)
+    const char *yystr;
+#endif
+{
+  YYSIZE_T yylen;
+  for (yylen = 0; yystr[yylen]; yylen++)
+    continue;
+  return yylen;
+}
+#  endif
+# endif
+
+# ifndef yystpcpy
+#  if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE
+#   define yystpcpy stpcpy
+#  else
+/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in
+   YYDEST.  */
+#if (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+static char *
+yystpcpy (char *yydest, const char *yysrc)
+#else
+static char *
+yystpcpy (yydest, yysrc)
+    char *yydest;
+    const char *yysrc;
+#endif
+{
+  char *yyd = yydest;
+  const char *yys = yysrc;
+
+  while ((*yyd++ = *yys++) != '\0')
+    continue;
+
+  return yyd - 1;
+}
+#  endif
+# endif
+
+# ifndef yytnamerr
+/* Copy to YYRES the contents of YYSTR after stripping away unnecessary
+   quotes and backslashes, so that it's suitable for yyerror.  The
+   heuristic is that double-quoting is unnecessary unless the string
+   contains an apostrophe, a comma, or backslash (other than
+   backslash-backslash).  YYSTR is taken from yytname.  If YYRES is
+   null, do not copy; instead, return the length of what the result
+   would have been.  */
+static YYSIZE_T
+yytnamerr (char *yyres, const char *yystr)
+{
+  if (*yystr == '"')
+    {
+      YYSIZE_T yyn = 0;
+      char const *yyp = yystr;
+
+      for (;;)
+	switch (*++yyp)
+	  {
+	  case '\'':
+	  case ',':
+	    goto do_not_strip_quotes;
+
+	  case '\\':
+	    if (*++yyp != '\\')
+	      goto do_not_strip_quotes;
+	    /* Fall through.  */
+	  default:
+	    if (yyres)
+	      yyres[yyn] = *yyp;
+	    yyn++;
+	    break;
+
+	  case '"':
+	    if (yyres)
+	      yyres[yyn] = '\0';
+	    return yyn;
+	  }
+    do_not_strip_quotes: ;
+    }
+
+  if (! yyres)
+    return yystrlen (yystr);
+
+  return yystpcpy (yyres, yystr) - yyres;
+}
+# endif
+
+/* Copy into YYRESULT an error message about the unexpected token
+   YYCHAR while in state YYSTATE.  Return the number of bytes copied,
+   including the terminating null byte.  If YYRESULT is null, do not
+   copy anything; just return the number of bytes that would be
+   copied.  As a special case, return 0 if an ordinary "syntax error"
+   message will do.  Return YYSIZE_MAXIMUM if overflow occurs during
+   size calculation.  */
+static YYSIZE_T
+yysyntax_error (char *yyresult, int yystate, int yychar)
+{
+  int yyn = yypact[yystate];
+
+  if (! (YYPACT_NINF < yyn && yyn <= YYLAST))
+    return 0;
+  else
+    {
+      int yytype = YYTRANSLATE (yychar);
+      YYSIZE_T yysize0 = yytnamerr (0, yytname[yytype]);
+      YYSIZE_T yysize = yysize0;
+      YYSIZE_T yysize1;
+      int yysize_overflow = 0;
+      enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 };
+      char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM];
+      int yyx;
+
+# if 0
+      /* This is so xgettext sees the translatable formats that are
+	 constructed on the fly.  */
+      YY_("syntax error, unexpected %s");
+      YY_("syntax error, unexpected %s, expecting %s");
+      YY_("syntax error, unexpected %s, expecting %s or %s");
+      YY_("syntax error, unexpected %s, expecting %s or %s or %s");
+      YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s");
+# endif
+      char *yyfmt;
+      char const *yyf;
+      static char const yyunexpected[] = "syntax error, unexpected %s";
+      static char const yyexpecting[] = ", expecting %s";
+      static char const yyor[] = " or %s";
+      char yyformat[sizeof yyunexpected
+		    + sizeof yyexpecting - 1
+		    + ((YYERROR_VERBOSE_ARGS_MAXIMUM - 2)
+		       * (sizeof yyor - 1))];
+      char const *yyprefix = yyexpecting;
+
+      /* Start YYX at -YYN if negative to avoid negative indexes in
+	 YYCHECK.  */
+      int yyxbegin = yyn < 0 ? -yyn : 0;
+
+      /* Stay within bounds of both yycheck and yytname.  */
+      int yychecklim = YYLAST - yyn + 1;
+      int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
+      int yycount = 1;
+
+      yyarg[0] = yytname[yytype];
+      yyfmt = yystpcpy (yyformat, yyunexpected);
+
+      for (yyx = yyxbegin; yyx < yyxend; ++yyx)
+	if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR)
+	  {
+	    if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM)
+	      {
+		yycount = 1;
+		yysize = yysize0;
+		yyformat[sizeof yyunexpected - 1] = '\0';
+		break;
+	      }
+	    yyarg[yycount++] = yytname[yyx];
+	    yysize1 = yysize + yytnamerr (0, yytname[yyx]);
+	    yysize_overflow |= (yysize1 < yysize);
+	    yysize = yysize1;
+	    yyfmt = yystpcpy (yyfmt, yyprefix);
+	    yyprefix = yyor;
+	  }
+
+      yyf = YY_(yyformat);
+      yysize1 = yysize + yystrlen (yyf);
+      yysize_overflow |= (yysize1 < yysize);
+      yysize = yysize1;
+
+      if (yysize_overflow)
+	return YYSIZE_MAXIMUM;
+
+      if (yyresult)
+	{
+	  /* Avoid sprintf, as that infringes on the user's name space.
+	     Don't have undefined behavior even if the translation
+	     produced a string with the wrong number of "%s"s.  */
+	  char *yyp = yyresult;
+	  int yyi = 0;
+	  while ((*yyp = *yyf) != '\0')
+	    {
+	      if (*yyp == '%' && yyf[1] == 's' && yyi < yycount)
+		{
+		  yyp += yytnamerr (yyp, yyarg[yyi++]);
+		  yyf += 2;
+		}
+	      else
+		{
+		  yyp++;
+		  yyf++;
+		}
+	    }
+	}
+      return yysize;
+    }
+}
+#endif /* YYERROR_VERBOSE */
+
+
+/*-----------------------------------------------.
+| Release the memory associated to this symbol.  |
+`-----------------------------------------------*/
+
+/*ARGSUSED*/
+#if (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+static void
+yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep)
+#else
+static void
+yydestruct (yymsg, yytype, yyvaluep)
+    const char *yymsg;
+    int yytype;
+    YYSTYPE *yyvaluep;
+#endif
+{
+  YYUSE (yyvaluep);
+
+  if (!yymsg)
+    yymsg = "Deleting";
+  YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp);
+
+  switch (yytype)
+    {
+
+      default:
+	break;
+    }
+}
+
+
+/* Prevent warnings from -Wmissing-prototypes.  */
+
+#ifdef YYPARSE_PARAM
+#if defined __STDC__ || defined __cplusplus
+int yyparse (void *YYPARSE_PARAM);
+#else
+int yyparse ();
+#endif
+#else /* ! YYPARSE_PARAM */
+#if defined __STDC__ || defined __cplusplus
+int yyparse (void);
+#else
+int yyparse ();
+#endif
+#endif /* ! YYPARSE_PARAM */
+
+
+
+/* The look-ahead symbol.  */
+int yychar;
+
+/* The semantic value of the look-ahead symbol.  */
+YYSTYPE yylval;
+
+/* Number of syntax errors so far.  */
+int yynerrs;
+
+
+
+/*----------.
+| yyparse.  |
+`----------*/
+
+#ifdef YYPARSE_PARAM
+#if (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+int
+yyparse (void *YYPARSE_PARAM)
+#else
+int
+yyparse (YYPARSE_PARAM)
+    void *YYPARSE_PARAM;
+#endif
+#else /* ! YYPARSE_PARAM */
+#if (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+int
+yyparse (void)
+#else
+int
+yyparse ()
+
+#endif
+#endif
+{
+  
+  int yystate;
+  int yyn;
+  int yyresult;
+  /* Number of tokens to shift before error messages enabled.  */
+  int yyerrstatus;
+  /* Look-ahead token as an internal (translated) token number.  */
+  int yytoken = 0;
+#if YYERROR_VERBOSE
+  /* Buffer for error messages, and its allocated size.  */
+  char yymsgbuf[128];
+  char *yymsg = yymsgbuf;
+  YYSIZE_T yymsg_alloc = sizeof yymsgbuf;
+#endif
+
+  /* Three stacks and their tools:
+     `yyss': related to states,
+     `yyvs': related to semantic values,
+     `yyls': related to locations.
+
+     Refer to the stacks thru separate pointers, to allow yyoverflow
+     to reallocate them elsewhere.  */
+
+  /* The state stack.  */
+  yytype_int16 yyssa[YYINITDEPTH];
+  yytype_int16 *yyss = yyssa;
+  yytype_int16 *yyssp;
+
+  /* The semantic value stack.  */
+  YYSTYPE yyvsa[YYINITDEPTH];
+  YYSTYPE *yyvs = yyvsa;
+  YYSTYPE *yyvsp;
+
+
+
+#define YYPOPSTACK(N)   (yyvsp -= (N), yyssp -= (N))
+
+  YYSIZE_T yystacksize = YYINITDEPTH;
+
+  /* The variables used to return semantic value and location from the
+     action routines.  */
+  YYSTYPE yyval;
+
+
+  /* The number of symbols on the RHS of the reduced rule.
+     Keep to zero when no symbol should be popped.  */
+  int yylen = 0;
+
+  YYDPRINTF ((stderr, "Starting parse\n"));
+
+  yystate = 0;
+  yyerrstatus = 0;
+  yynerrs = 0;
+  yychar = YYEMPTY;		/* Cause a token to be read.  */
+
+  /* Initialize stack pointers.
+     Waste one element of value and location stack
+     so that they stay on the same level as the state stack.
+     The wasted elements are never initialized.  */
+
+  yyssp = yyss;
+  yyvsp = yyvs;
+
+  goto yysetstate;
+
+/*------------------------------------------------------------.
+| yynewstate -- Push a new state, which is found in yystate.  |
+`------------------------------------------------------------*/
+ yynewstate:
+  /* In all cases, when you get here, the value and location stacks
+     have just been pushed.  So pushing a state here evens the stacks.  */
+  yyssp++;
+
+ yysetstate:
+  *yyssp = yystate;
+
+  if (yyss + yystacksize - 1 <= yyssp)
+    {
+      /* Get the current used size of the three stacks, in elements.  */
+      YYSIZE_T yysize = yyssp - yyss + 1;
+
+#ifdef yyoverflow
+      {
+	/* Give user a chance to reallocate the stack.  Use copies of
+	   these so that the &'s don't force the real ones into
+	   memory.  */
+	YYSTYPE *yyvs1 = yyvs;
+	yytype_int16 *yyss1 = yyss;
+
+
+	/* Each stack pointer address is followed by the size of the
+	   data in use in that stack, in bytes.  This used to be a
+	   conditional around just the two extra args, but that might
+	   be undefined if yyoverflow is a macro.  */
+	yyoverflow (YY_("memory exhausted"),
+		    &yyss1, yysize * sizeof (*yyssp),
+		    &yyvs1, yysize * sizeof (*yyvsp),
+
+		    &yystacksize);
+
+	yyss = yyss1;
+	yyvs = yyvs1;
+      }
+#else /* no yyoverflow */
+# ifndef YYSTACK_RELOCATE
+      goto yyexhaustedlab;
+# else
+      /* Extend the stack our own way.  */
+      if (YYMAXDEPTH <= yystacksize)
+	goto yyexhaustedlab;
+      yystacksize *= 2;
+      if (YYMAXDEPTH < yystacksize)
+	yystacksize = YYMAXDEPTH;
+
+      {
+	yytype_int16 *yyss1 = yyss;
+	union yyalloc *yyptr =
+	  (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
+	if (! yyptr)
+	  goto yyexhaustedlab;
+	YYSTACK_RELOCATE (yyss);
+	YYSTACK_RELOCATE (yyvs);
+
+#  undef YYSTACK_RELOCATE
+	if (yyss1 != yyssa)
+	  YYSTACK_FREE (yyss1);
+      }
+# endif
+#endif /* no yyoverflow */
+
+      yyssp = yyss + yysize - 1;
+      yyvsp = yyvs + yysize - 1;
+
+
+      YYDPRINTF ((stderr, "Stack size increased to %lu\n",
+		  (unsigned long int) yystacksize));
+
+      if (yyss + yystacksize - 1 <= yyssp)
+	YYABORT;
+    }
+
+  YYDPRINTF ((stderr, "Entering state %d\n", yystate));
+
+  goto yybackup;
+
+/*-----------.
+| yybackup.  |
+`-----------*/
+yybackup:
+
+  /* Do appropriate processing given the current state.  Read a
+     look-ahead token if we need one and don't already have one.  */
+
+  /* First try to decide what to do without reference to look-ahead token.  */
+  yyn = yypact[yystate];
+  if (yyn == YYPACT_NINF)
+    goto yydefault;
+
+  /* Not known => get a look-ahead token if don't already have one.  */
+
+  /* YYCHAR is either YYEMPTY or YYEOF or a valid look-ahead symbol.  */
+  if (yychar == YYEMPTY)
+    {
+      YYDPRINTF ((stderr, "Reading a token: "));
+      yychar = YYLEX;
+    }
+
+  if (yychar <= YYEOF)
+    {
+      yychar = yytoken = YYEOF;
+      YYDPRINTF ((stderr, "Now at end of input.\n"));
+    }
+  else
+    {
+      yytoken = YYTRANSLATE (yychar);
+      YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc);
+    }
+
+  /* If the proper action on seeing token YYTOKEN is to reduce or to
+     detect an error, take that action.  */
+  yyn += yytoken;
+  if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken)
+    goto yydefault;
+  yyn = yytable[yyn];
+  if (yyn <= 0)
+    {
+      if (yyn == 0 || yyn == YYTABLE_NINF)
+	goto yyerrlab;
+      yyn = -yyn;
+      goto yyreduce;
+    }
+
+  if (yyn == YYFINAL)
+    YYACCEPT;
+
+  /* Count tokens shifted since error; after three, turn off error
+     status.  */
+  if (yyerrstatus)
+    yyerrstatus--;
+
+  /* Shift the look-ahead token.  */
+  YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc);
+
+  /* Discard the shifted token unless it is eof.  */
+  if (yychar != YYEOF)
+    yychar = YYEMPTY;
+
+  yystate = yyn;
+  *++yyvsp = yylval;
+
+  goto yynewstate;
+
+
+/*-----------------------------------------------------------.
+| yydefault -- do the default action for the current state.  |
+`-----------------------------------------------------------*/
+yydefault:
+  yyn = yydefact[yystate];
+  if (yyn == 0)
+    goto yyerrlab;
+  goto yyreduce;
+
+
+/*-----------------------------.
+| yyreduce -- Do a reduction.  |
+`-----------------------------*/
+yyreduce:
+  /* yyn is the number of a rule to reduce with.  */
+  yylen = yyr2[yyn];
+
+  /* If YYLEN is nonzero, implement the default value of the action:
+     `$$ = $1'.
+
+     Otherwise, the following line sets YYVAL to garbage.
+     This behavior is undocumented and Bison
+     users should not rely upon it.  Assigning to YYVAL
+     unconditionally makes the parser a bit smaller, and it avoids a
+     GCC warning that YYVAL may be used uninitialized.  */
+  yyval = yyvsp[1-yylen];
+
+
+  YY_REDUCE_PRINT (yyn);
+  switch (yyn)
+    {
+        case 21:
+#line 291 "cfparse.y"
+    {
+			struct passwd *pw;
+
+			if ((pw = getpwnam((yyvsp[(2) - (2)].val)->v)) == NULL) {
+				yyerror("unknown user \"%s\"", (yyvsp[(2) - (2)].val)->v);
+				return -1;
+			}
+			lcconf->uid = pw->pw_uid;
+		}
+    break;
+
+  case 23:
+#line 301 "cfparse.y"
+    { lcconf->uid = (yyvsp[(2) - (2)].num); }
+    break;
+
+  case 25:
+#line 303 "cfparse.y"
+    {
+			struct group *gr;
+
+			if ((gr = getgrnam((yyvsp[(2) - (2)].val)->v)) == NULL) {
+				yyerror("unknown group \"%s\"", (yyvsp[(2) - (2)].val)->v);
+				return -1;
+			}
+			lcconf->gid = gr->gr_gid;
+		}
+    break;
+
+  case 27:
+#line 313 "cfparse.y"
+    { lcconf->gid = (yyvsp[(2) - (2)].num); }
+    break;
+
+  case 29:
+#line 314 "cfparse.y"
+    { lcconf->chroot = (yyvsp[(2) - (2)].val)->v; }
+    break;
+
+  case 31:
+#line 320 "cfparse.y"
+    {
+			if ((yyvsp[(2) - (3)].num) >= LC_PATHTYPE_MAX) {
+				yyerror("invalid path type %d", (yyvsp[(2) - (3)].num));
+				return -1;
+			}
+
+			/* free old pathinfo */
+			if (lcconf->pathinfo[(yyvsp[(2) - (3)].num)])
+				racoon_free(lcconf->pathinfo[(yyvsp[(2) - (3)].num)]);
+
+			/* set new pathinfo */
+			lcconf->pathinfo[(yyvsp[(2) - (3)].num)] = racoon_strdup((yyvsp[(3) - (3)].val)->v);
+			STRDUP_FATAL(lcconf->pathinfo[(yyvsp[(2) - (3)].num)]);
+			vfree((yyvsp[(3) - (3)].val));
+		}
+    break;
+
+  case 33:
+#line 340 "cfparse.y"
+    { lcconf->complex_bundle = (yyvsp[(2) - (2)].num); }
+    break;
+
+  case 35:
+#line 346 "cfparse.y"
+    {
+			char path[MAXPATHLEN];
+
+			getpathname(path, sizeof(path),
+				LC_PATHTYPE_INCLUDE, (yyvsp[(2) - (3)].val)->v);
+			vfree((yyvsp[(2) - (3)].val));
+			if (yycf_switch_buffer(path) != 0)
+				return -1;
+		}
+    break;
+
+  case 36:
+#line 360 "cfparse.y"
+    {
+			if ((yyvsp[(2) - (3)].num) >= LC_GSSENC_MAX) {
+				yyerror("invalid GSS ID encoding %d", (yyvsp[(2) - (3)].num));
+				return -1;
+			}
+			lcconf->gss_id_enc = (yyvsp[(2) - (3)].num);
+		}
+    break;
+
+  case 38:
+#line 375 "cfparse.y"
+    {
+			/*XXX to be deleted */
+		}
+    break;
+
+  case 40:
+#line 380 "cfparse.y"
+    {
+			/*XXX to be deleted */
+			(yyvsp[(2) - (2)].val)->l--;	/* nuke '\0' */
+			lcconf->ident[(yyvsp[(1) - (2)].num)] = (yyvsp[(2) - (2)].val);
+			if (lcconf->ident[(yyvsp[(1) - (2)].num)] == NULL) {
+				yyerror("failed to set my ident: %s",
+					strerror(errno));
+				return -1;
+			}
+		}
+    break;
+
+  case 43:
+#line 399 "cfparse.y"
+    {
+			/*
+			 * XXX ignore it because this specification
+			 * will be obsoleted.
+			 */
+			yywarn("see racoon.conf(5), such a log specification will be obsoleted.");
+			vfree((yyvsp[(1) - (1)].val));
+		}
+    break;
+
+  case 44:
+#line 408 "cfparse.y"
+    {
+			/*
+			 * set the loglevel to the value specified
+			 * in the configuration file plus the number
+			 * of -d options specified on the command line
+			 */
+			loglevel += (yyvsp[(1) - (1)].num) - oldloglevel;
+			oldloglevel = (yyvsp[(1) - (1)].num);
+		}
+    break;
+
+  case 48:
+#line 428 "cfparse.y"
+    { lcconf->pad_random = (yyvsp[(2) - (2)].num); }
+    break;
+
+  case 50:
+#line 429 "cfparse.y"
+    { lcconf->pad_randomlen = (yyvsp[(2) - (2)].num); }
+    break;
+
+  case 52:
+#line 430 "cfparse.y"
+    { lcconf->pad_maxsize = (yyvsp[(2) - (2)].num); }
+    break;
+
+  case 54:
+#line 431 "cfparse.y"
+    { lcconf->pad_strict = (yyvsp[(2) - (2)].num); }
+    break;
+
+  case 56:
+#line 432 "cfparse.y"
+    { lcconf->pad_excltail = (yyvsp[(2) - (2)].num); }
+    break;
+
+  case 61:
+#line 445 "cfparse.y"
+    {
+			listen_addr ((yyvsp[(2) - (2)].saddr), 0);
+		}
+    break;
+
+  case 63:
+#line 450 "cfparse.y"
+    {
+#ifdef ENABLE_NATT
+			listen_addr ((yyvsp[(2) - (2)].saddr), 1);
+#else
+			yyerror("NAT-T support not compiled in.");
+#endif
+		}
+    break;
+
+  case 65:
+#line 459 "cfparse.y"
+    {
+			yyerror("admin directive is obsoleted.");
+		}
+    break;
+
+  case 67:
+#line 464 "cfparse.y"
+    {
+#ifdef ENABLE_ADMINPORT
+			adminsock_conf((yyvsp[(2) - (5)].val), (yyvsp[(3) - (5)].val), (yyvsp[(4) - (5)].val), (yyvsp[(5) - (5)].num));
+#else
+			yywarn("admin port support not compiled in");
+#endif
+		}
+    break;
+
+  case 69:
+#line 473 "cfparse.y"
+    {
+#ifdef ENABLE_ADMINPORT
+			adminsock_conf((yyvsp[(2) - (2)].val), NULL, NULL, -1);
+#else
+			yywarn("admin port support not compiled in");
+#endif
+		}
+    break;
+
+  case 71:
+#line 482 "cfparse.y"
+    {
+#ifdef ENABLE_ADMINPORT
+			adminsock_path = NULL;
+#else
+			yywarn("admin port support not compiled in");
+#endif
+		}
+    break;
+
+  case 73:
+#line 490 "cfparse.y"
+    { lcconf->strict_address = TRUE; }
+    break;
+
+  case 75:
+#line 494 "cfparse.y"
+    {
+			char portbuf[10];
+
+			snprintf(portbuf, sizeof(portbuf), "%ld", (yyvsp[(2) - (2)].num));
+			(yyval.saddr) = str2saddr((yyvsp[(1) - (2)].val)->v, portbuf);
+			vfree((yyvsp[(1) - (2)].val));
+			if (!(yyval.saddr))
+				return -1;
+		}
+    break;
+
+  case 76:
+#line 505 "cfparse.y"
+    { (yyval.num) = PORT_ISAKMP; }
+    break;
+
+  case 77:
+#line 506 "cfparse.y"
+    { (yyval.num) = (yyvsp[(1) - (1)].num); }
+    break;
+
+  case 78:
+#line 511 "cfparse.y"
+    {
+#ifndef ENABLE_HYBRID
+			yyerror("racoon not configured with --enable-hybrid");
+			return -1;
+#endif
+#ifndef HAVE_LIBLDAP
+			yyerror("racoon not configured with --with-libldap");
+			return -1;
+#endif
+		}
+    break;
+
+  case 82:
+#line 528 "cfparse.y"
+    {
+#ifdef ENABLE_HYBRID
+#ifdef HAVE_LIBLDAP
+			if (((yyvsp[(2) - (2)].num)<2)||((yyvsp[(2) - (2)].num)>3))
+				yyerror("invalid ldap protocol version (2|3)");
+			xauth_ldap_config.pver = (yyvsp[(2) - (2)].num);
+#endif
+#endif
+		}
+    break;
+
+  case 84:
+#line 539 "cfparse.y"
+    {
+#ifdef ENABLE_HYBRID
+#ifdef HAVE_LIBLDAP
+			if (xauth_ldap_config.host != NULL)
+				vfree(xauth_ldap_config.host);
+			xauth_ldap_config.host = vdup((yyvsp[(2) - (2)].val));
+#endif
+#endif
+		}
+    break;
+
+  case 86:
+#line 550 "cfparse.y"
+    {
+#ifdef ENABLE_HYBRID
+#ifdef HAVE_LIBLDAP
+			xauth_ldap_config.port = (yyvsp[(2) - (2)].num);
+#endif
+#endif
+		}
+    break;
+
+  case 88:
+#line 559 "cfparse.y"
+    {
+#ifdef ENABLE_HYBRID
+#ifdef HAVE_LIBLDAP
+			if (xauth_ldap_config.base != NULL)
+				vfree(xauth_ldap_config.base);
+			xauth_ldap_config.base = vdup((yyvsp[(2) - (2)].val));
+#endif
+#endif
+		}
+    break;
+
+  case 90:
+#line 570 "cfparse.y"
+    {
+#ifdef ENABLE_HYBRID
+#ifdef HAVE_LIBLDAP
+			xauth_ldap_config.subtree = (yyvsp[(2) - (2)].num);
+#endif
+#endif
+		}
+    break;
+
+  case 92:
+#line 579 "cfparse.y"
+    {
+#ifdef ENABLE_HYBRID
+#ifdef HAVE_LIBLDAP
+			if (xauth_ldap_config.bind_dn != NULL)
+				vfree(xauth_ldap_config.bind_dn);
+			xauth_ldap_config.bind_dn = vdup((yyvsp[(2) - (2)].val));
+#endif
+#endif
+		}
+    break;
+
+  case 94:
+#line 590 "cfparse.y"
+    {
+#ifdef ENABLE_HYBRID
+#ifdef HAVE_LIBLDAP
+			if (xauth_ldap_config.bind_pw != NULL)
+				vfree(xauth_ldap_config.bind_pw);
+			xauth_ldap_config.bind_pw = vdup((yyvsp[(2) - (2)].val));
+#endif
+#endif
+		}
+    break;
+
+  case 96:
+#line 601 "cfparse.y"
+    {
+#ifdef ENABLE_HYBRID
+#ifdef HAVE_LIBLDAP
+			if (xauth_ldap_config.attr_user != NULL)
+				vfree(xauth_ldap_config.attr_user);
+			xauth_ldap_config.attr_user = vdup((yyvsp[(2) - (2)].val));
+#endif
+#endif
+		}
+    break;
+
+  case 98:
+#line 612 "cfparse.y"
+    {
+#ifdef ENABLE_HYBRID
+#ifdef HAVE_LIBLDAP
+			if (xauth_ldap_config.attr_addr != NULL)
+				vfree(xauth_ldap_config.attr_addr);
+			xauth_ldap_config.attr_addr = vdup((yyvsp[(2) - (2)].val));
+#endif
+#endif
+		}
+    break;
+
+  case 100:
+#line 623 "cfparse.y"
+    {
+#ifdef ENABLE_HYBRID
+#ifdef HAVE_LIBLDAP
+			if (xauth_ldap_config.attr_mask != NULL)
+				vfree(xauth_ldap_config.attr_mask);
+			xauth_ldap_config.attr_mask = vdup((yyvsp[(2) - (2)].val));
+#endif
+#endif
+		}
+    break;
+
+  case 102:
+#line 634 "cfparse.y"
+    {
+#ifdef ENABLE_HYBRID
+#ifdef HAVE_LIBLDAP
+			if (xauth_ldap_config.attr_group != NULL)
+				vfree(xauth_ldap_config.attr_group);
+			xauth_ldap_config.attr_group = vdup((yyvsp[(2) - (2)].val));
+#endif
+#endif
+		}
+    break;
+
+  case 104:
+#line 645 "cfparse.y"
+    {
+#ifdef ENABLE_HYBRID
+#ifdef HAVE_LIBLDAP
+			if (xauth_ldap_config.attr_member != NULL)
+				vfree(xauth_ldap_config.attr_member);
+			xauth_ldap_config.attr_member = vdup((yyvsp[(2) - (2)].val));
+#endif
+#endif
+		}
+    break;
+
+  case 109:
+#line 667 "cfparse.y"
+    {
+#ifdef ENABLE_HYBRID
+			if (inet_pton(AF_INET, (yyvsp[(2) - (2)].val)->v,
+			     &isakmp_cfg_config.network4) != 1)
+				yyerror("bad IPv4 network address.");
+#else
+			yyerror("racoon not configured with --enable-hybrid");
+#endif
+		}
+    break;
+
+  case 111:
+#line 678 "cfparse.y"
+    {
+#ifdef ENABLE_HYBRID
+			if (inet_pton(AF_INET, (yyvsp[(2) - (2)].val)->v,
+			    &isakmp_cfg_config.netmask4) != 1)
+				yyerror("bad IPv4 netmask address.");
+#else
+			yyerror("racoon not configured with --enable-hybrid");
+#endif
+		}
+    break;
+
+  case 115:
+#line 693 "cfparse.y"
+    {
+#ifdef ENABLE_HYBRID
+			isakmp_cfg_config.splitnet_type = UNITY_LOCAL_LAN;
+#else
+			yyerror("racoon not configured with --enable-hybrid");
+#endif
+		}
+    break;
+
+  case 117:
+#line 702 "cfparse.y"
+    {
+#ifdef ENABLE_HYBRID
+			isakmp_cfg_config.splitnet_type = UNITY_SPLIT_INCLUDE;
+#else
+			yyerror("racoon not configured with --enable-hybrid");
+#endif
+		}
+    break;
+
+  case 119:
+#line 711 "cfparse.y"
+    {
+#ifndef ENABLE_HYBRID
+			yyerror("racoon not configured with --enable-hybrid");
+#endif
+		}
+    break;
+
+  case 121:
+#line 718 "cfparse.y"
+    {
+#ifdef ENABLE_HYBRID
+			strncpy(&isakmp_cfg_config.default_domain[0], 
+			    (yyvsp[(2) - (2)].val)->v, MAXPATHLEN);
+			isakmp_cfg_config.default_domain[MAXPATHLEN] = '\0';
+			vfree((yyvsp[(2) - (2)].val));
+#else
+			yyerror("racoon not configured with --enable-hybrid");
+#endif
+		}
+    break;
+
+  case 123:
+#line 730 "cfparse.y"
+    {
+#ifdef ENABLE_HYBRID
+			isakmp_cfg_config.authsource = ISAKMP_CFG_AUTH_SYSTEM;
+#else
+			yyerror("racoon not configured with --enable-hybrid");
+#endif
+		}
+    break;
+
+  case 125:
+#line 739 "cfparse.y"
+    {
+#ifdef ENABLE_HYBRID
+#ifdef HAVE_LIBRADIUS
+			isakmp_cfg_config.authsource = ISAKMP_CFG_AUTH_RADIUS;
+#else /* HAVE_LIBRADIUS */
+			yyerror("racoon not configured with --with-libradius");
+#endif /* HAVE_LIBRADIUS */
+#else /* ENABLE_HYBRID */
+			yyerror("racoon not configured with --enable-hybrid");
+#endif /* ENABLE_HYBRID */
+		}
+    break;
+
+  case 127:
+#line 752 "cfparse.y"
+    {
+#ifdef ENABLE_HYBRID
+#ifdef HAVE_LIBPAM
+			isakmp_cfg_config.authsource = ISAKMP_CFG_AUTH_PAM;
+#else /* HAVE_LIBPAM */
+			yyerror("racoon not configured with --with-libpam");
+#endif /* HAVE_LIBPAM */
+#else /* ENABLE_HYBRID */
+			yyerror("racoon not configured with --enable-hybrid");
+#endif /* ENABLE_HYBRID */
+		}
+    break;
+
+  case 129:
+#line 765 "cfparse.y"
+    {
+#ifdef ENABLE_HYBRID
+#ifdef HAVE_LIBLDAP
+			isakmp_cfg_config.authsource = ISAKMP_CFG_AUTH_LDAP;
+#else /* HAVE_LIBLDAP */
+			yyerror("racoon not configured with --with-libldap");
+#endif /* HAVE_LIBLDAP */
+#else /* ENABLE_HYBRID */
+			yyerror("racoon not configured with --enable-hybrid");
+#endif /* ENABLE_HYBRID */
+		}
+    break;
+
+  case 131:
+#line 778 "cfparse.y"
+    {
+#ifndef ENABLE_HYBRID
+			yyerror("racoon not configured with --enable-hybrid");
+#endif
+		}
+    break;
+
+  case 133:
+#line 785 "cfparse.y"
+    {
+#ifdef ENABLE_HYBRID
+			isakmp_cfg_config.groupsource = ISAKMP_CFG_GROUP_SYSTEM;
+#else
+			yyerror("racoon not configured with --enable-hybrid");
+#endif
+		}
+    break;
+
+  case 135:
+#line 794 "cfparse.y"
+    {
+#ifdef ENABLE_HYBRID
+#ifdef HAVE_LIBLDAP
+			isakmp_cfg_config.groupsource = ISAKMP_CFG_GROUP_LDAP;
+#else /* HAVE_LIBLDAP */
+			yyerror("racoon not configured with --with-libldap");
+#endif /* HAVE_LIBLDAP */
+#else /* ENABLE_HYBRID */
+			yyerror("racoon not configured with --enable-hybrid");
+#endif /* ENABLE_HYBRID */
+		}
+    break;
+
+  case 137:
+#line 807 "cfparse.y"
+    {
+#ifdef ENABLE_HYBRID
+			isakmp_cfg_config.accounting = ISAKMP_CFG_ACCT_NONE;
+#else
+			yyerror("racoon not configured with --enable-hybrid");
+#endif
+		}
+    break;
+
+  case 139:
+#line 816 "cfparse.y"
+    {
+#ifdef ENABLE_HYBRID
+			isakmp_cfg_config.accounting = ISAKMP_CFG_ACCT_SYSTEM;
+#else
+			yyerror("racoon not configured with --enable-hybrid");
+#endif
+		}
+    break;
+
+  case 141:
+#line 825 "cfparse.y"
+    {
+#ifdef ENABLE_HYBRID
+#ifdef HAVE_LIBRADIUS
+			isakmp_cfg_config.accounting = ISAKMP_CFG_ACCT_RADIUS;
+#else /* HAVE_LIBRADIUS */
+			yyerror("racoon not configured with --with-libradius");
+#endif /* HAVE_LIBRADIUS */
+#else /* ENABLE_HYBRID */
+			yyerror("racoon not configured with --enable-hybrid");
+#endif /* ENABLE_HYBRID */
+		}
+    break;
+
+  case 143:
+#line 838 "cfparse.y"
+    {
+#ifdef ENABLE_HYBRID
+#ifdef HAVE_LIBPAM
+			isakmp_cfg_config.accounting = ISAKMP_CFG_ACCT_PAM;
+#else /* HAVE_LIBPAM */
+			yyerror("racoon not configured with --with-libpam");
+#endif /* HAVE_LIBPAM */
+#else /* ENABLE_HYBRID */
+			yyerror("racoon not configured with --enable-hybrid");
+#endif /* ENABLE_HYBRID */
+		}
+    break;
+
+  case 145:
+#line 851 "cfparse.y"
+    {
+#ifdef ENABLE_HYBRID
+			if (isakmp_cfg_resize_pool((yyvsp[(2) - (2)].num)) != 0)
+				yyerror("cannot allocate memory for pool");
+#else /* ENABLE_HYBRID */
+			yyerror("racoon not configured with --enable-hybrid");
+#endif /* ENABLE_HYBRID */
+		}
+    break;
+
+  case 147:
+#line 861 "cfparse.y"
+    {
+#ifdef ENABLE_HYBRID
+			isakmp_cfg_config.pfs_group = (yyvsp[(2) - (2)].num);
+#else /* ENABLE_HYBRID */
+			yyerror("racoon not configured with --enable-hybrid");
+#endif /* ENABLE_HYBRID */
+		}
+    break;
+
+  case 149:
+#line 870 "cfparse.y"
+    {
+#ifdef ENABLE_HYBRID
+			isakmp_cfg_config.save_passwd = (yyvsp[(2) - (2)].num);
+#else /* ENABLE_HYBRID */
+			yyerror("racoon not configured with --enable-hybrid");
+#endif /* ENABLE_HYBRID */
+		}
+    break;
+
+  case 151:
+#line 879 "cfparse.y"
+    {
+#ifdef ENABLE_HYBRID
+			isakmp_cfg_config.auth_throttle = (yyvsp[(2) - (2)].num);
+#else /* ENABLE_HYBRID */
+			yyerror("racoon not configured with --enable-hybrid");
+#endif /* ENABLE_HYBRID */
+		}
+    break;
+
+  case 153:
+#line 888 "cfparse.y"
+    {
+#ifdef ENABLE_HYBRID
+			isakmp_cfg_config.confsource = ISAKMP_CFG_CONF_LOCAL;
+#else /* ENABLE_HYBRID */
+			yyerror("racoon not configured with --enable-hybrid");
+#endif /* ENABLE_HYBRID */
+		}
+    break;
+
+  case 155:
+#line 897 "cfparse.y"
+    {
+#ifdef ENABLE_HYBRID
+#ifdef HAVE_LIBRADIUS
+			isakmp_cfg_config.confsource = ISAKMP_CFG_CONF_RADIUS;
+#else /* HAVE_LIBRADIUS */
+			yyerror("racoon not configured with --with-libradius");
+#endif /* HAVE_LIBRADIUS */
+#else /* ENABLE_HYBRID */
+			yyerror("racoon not configured with --enable-hybrid");
+#endif /* ENABLE_HYBRID */
+		}
+    break;
+
+  case 157:
+#line 910 "cfparse.y"
+    {
+#ifdef ENABLE_HYBRID
+#ifdef HAVE_LIBLDAP
+			isakmp_cfg_config.confsource = ISAKMP_CFG_CONF_LDAP;
+#else /* HAVE_LIBLDAP */
+			yyerror("racoon not configured with --with-libldap");
+#endif /* HAVE_LIBLDAP */
+#else /* ENABLE_HYBRID */
+			yyerror("racoon not configured with --enable-hybrid");
+#endif /* ENABLE_HYBRID */
+		}
+    break;
+
+  case 159:
+#line 923 "cfparse.y"
+    {
+#ifdef ENABLE_HYBRID
+			strncpy(&isakmp_cfg_config.motd[0], (yyvsp[(2) - (2)].val)->v, MAXPATHLEN);
+			isakmp_cfg_config.motd[MAXPATHLEN] = '\0';
+			vfree((yyvsp[(2) - (2)].val));
+#else
+			yyerror("racoon not configured with --enable-hybrid");
+#endif
+		}
+    break;
+
+  case 163:
+#line 941 "cfparse.y"
+    {
+#ifdef ENABLE_HYBRID
+			struct isakmp_cfg_config *icc = &isakmp_cfg_config;
+
+			if (icc->dns4_index > MAXNS)
+				yyerror("No more than %d DNS", MAXNS);
+			if (inet_pton(AF_INET, (yyvsp[(1) - (1)].val)->v,
+			    &icc->dns4[icc->dns4_index++]) != 1)
+				yyerror("bad IPv4 DNS address.");
+#else
+			yyerror("racoon not configured with --enable-hybrid");
+#endif
+		}
+    break;
+
+  case 166:
+#line 962 "cfparse.y"
+    {
+#ifdef ENABLE_HYBRID
+			struct isakmp_cfg_config *icc = &isakmp_cfg_config;
+
+			if (icc->nbns4_index > MAXWINS)
+				yyerror("No more than %d WINS", MAXWINS);
+			if (inet_pton(AF_INET, (yyvsp[(1) - (1)].val)->v,
+			    &icc->nbns4[icc->nbns4_index++]) != 1)
+				yyerror("bad IPv4 WINS address.");
+#else
+			yyerror("racoon not configured with --enable-hybrid");
+#endif
+		}
+    break;
+
+  case 169:
+#line 983 "cfparse.y"
+    {
+#ifdef ENABLE_HYBRID
+			struct isakmp_cfg_config *icc = &isakmp_cfg_config;
+			struct unity_network network;
+			memset(&network,0,sizeof(network));
+
+			if (inet_pton(AF_INET, (yyvsp[(1) - (2)].val)->v, &network.addr4) != 1)
+				yyerror("bad IPv4 SPLIT address.");
+
+			/* Turn $2 (the prefix) into a subnet mask */
+			network.mask4.s_addr = ((yyvsp[(2) - (2)].num)) ? htonl(~((1 << (32 - (yyvsp[(2) - (2)].num))) - 1)) : 0;
+
+			/* add the network to our list */ 
+			if (splitnet_list_add(&icc->splitnet_list, &network,&icc->splitnet_count))
+				yyerror("Unable to allocate split network");
+#else
+			yyerror("racoon not configured with --enable-hybrid");
+#endif
+		}
+    break;
+
+  case 172:
+#line 1010 "cfparse.y"
+    {
+#ifdef ENABLE_HYBRID
+			char * groupname = NULL;
+			char ** grouplist = NULL;
+			struct isakmp_cfg_config *icc = &isakmp_cfg_config;
+
+			grouplist = racoon_realloc(icc->grouplist,
+					sizeof(char**)*(icc->groupcount+1));
+			if (grouplist == NULL)
+				yyerror("unable to allocate auth group list");
+
+			groupname = racoon_malloc((yyvsp[(1) - (1)].val)->l+1);
+			if (groupname == NULL)
+				yyerror("unable to allocate auth group name");
+
+			memcpy(groupname,(yyvsp[(1) - (1)].val)->v,(yyvsp[(1) - (1)].val)->l);
+			groupname[(yyvsp[(1) - (1)].val)->l]=0;
+			grouplist[icc->groupcount]=groupname;
+			icc->grouplist = grouplist;
+			icc->groupcount++;
+
+			vfree((yyvsp[(1) - (1)].val));
+#else
+			yyerror("racoon not configured with --enable-hybrid");
+#endif
+		}
+    break;
+
+  case 175:
+#line 1044 "cfparse.y"
+    {
+#ifdef ENABLE_HYBRID
+			struct isakmp_cfg_config *icc = &isakmp_cfg_config;
+
+			if (!icc->splitdns_len)
+			{
+				icc->splitdns_list = racoon_malloc((yyvsp[(1) - (1)].val)->l);
+				if(icc->splitdns_list == NULL)
+					yyerror("error allocating splitdns list buffer");
+				memcpy(icc->splitdns_list,(yyvsp[(1) - (1)].val)->v,(yyvsp[(1) - (1)].val)->l);
+				icc->splitdns_len = (yyvsp[(1) - (1)].val)->l;
+			}
+			else
+			{
+				int len = icc->splitdns_len + (yyvsp[(1) - (1)].val)->l + 1;
+				icc->splitdns_list = racoon_realloc(icc->splitdns_list,len);
+				if(icc->splitdns_list == NULL)
+					yyerror("error allocating splitdns list buffer");
+				icc->splitdns_list[icc->splitdns_len] = ',';
+				memcpy(icc->splitdns_list + icc->splitdns_len + 1, (yyvsp[(1) - (1)].val)->v, (yyvsp[(1) - (1)].val)->l);
+				icc->splitdns_len = len;
+			}
+			vfree((yyvsp[(1) - (1)].val));
+#else
+			yyerror("racoon not configured with --enable-hybrid");
+#endif
+		}
+    break;
+
+  case 179:
+#line 1084 "cfparse.y"
+    {
+			lcconf->retry_counter = (yyvsp[(2) - (2)].num);
+		}
+    break;
+
+  case 181:
+#line 1089 "cfparse.y"
+    {
+			lcconf->retry_interval = (yyvsp[(2) - (3)].num) * (yyvsp[(3) - (3)].num);
+		}
+    break;
+
+  case 183:
+#line 1094 "cfparse.y"
+    {
+			lcconf->count_persend = (yyvsp[(2) - (2)].num);
+		}
+    break;
+
+  case 185:
+#line 1099 "cfparse.y"
+    {
+			lcconf->retry_checkph1 = (yyvsp[(2) - (3)].num) * (yyvsp[(3) - (3)].num);
+		}
+    break;
+
+  case 187:
+#line 1104 "cfparse.y"
+    {
+			lcconf->wait_ph2complete = (yyvsp[(2) - (3)].num) * (yyvsp[(3) - (3)].num);
+		}
+    break;
+
+  case 189:
+#line 1109 "cfparse.y"
+    {
+#ifdef ENABLE_NATT
+        		if (libipsec_opt & LIBIPSEC_OPT_NATT)
+				lcconf->natt_ka_interval = (yyvsp[(2) - (3)].num) * (yyvsp[(3) - (3)].num);
+			else
+                		yyerror("libipsec lacks NAT-T support");
+#else
+			yyerror("NAT-T support not compiled in.");
+#endif
+		}
+    break;
+
+  case 191:
+#line 1125 "cfparse.y"
+    {
+			cur_sainfo = newsainfo();
+			if (cur_sainfo == NULL) {
+				yyerror("failed to allocate sainfo");
+				return -1;
+			}
+		}
+    break;
+
+  case 192:
+#line 1133 "cfparse.y"
+    {
+			struct sainfo *check;
+
+			/* default */
+			if (cur_sainfo->algs[algclass_ipsec_enc] == 0) {
+				yyerror("no encryption algorithm at %s",
+					sainfo2str(cur_sainfo));
+				return -1;
+			}
+			if (cur_sainfo->algs[algclass_ipsec_auth] == 0) {
+				yyerror("no authentication algorithm at %s",
+					sainfo2str(cur_sainfo));
+				return -1;
+			}
+			if (cur_sainfo->algs[algclass_ipsec_comp] == 0) {
+				yyerror("no compression algorithm at %s",
+					sainfo2str(cur_sainfo));
+				return -1;
+			}
+
+			/* duplicate check */
+			check = getsainfo(cur_sainfo->idsrc,
+					  cur_sainfo->iddst,
+					  cur_sainfo->id_i,
+					  cur_sainfo->remoteid);
+			if (check && (!check->idsrc && !cur_sainfo->idsrc)) {
+				yyerror("duplicated sainfo: %s",
+					sainfo2str(cur_sainfo));
+				return -1;
+			}
+			inssainfo(cur_sainfo);
+		}
+    break;
+
+  case 194:
+#line 1169 "cfparse.y"
+    {
+			cur_sainfo->idsrc = NULL;
+			cur_sainfo->iddst = NULL;
+		}
+    break;
+
+  case 195:
+#line 1174 "cfparse.y"
+    {
+			cur_sainfo->idsrc = NULL;
+			cur_sainfo->iddst = (yyvsp[(2) - (2)].val);
+		}
+    break;
+
+  case 196:
+#line 1179 "cfparse.y"
+    {
+			cur_sainfo->idsrc = (yyvsp[(1) - (2)].val);
+			cur_sainfo->iddst = NULL;
+		}
+    break;
+
+  case 197:
+#line 1184 "cfparse.y"
+    {
+			cur_sainfo->idsrc = (yyvsp[(1) - (2)].val);
+			cur_sainfo->iddst = (yyvsp[(2) - (2)].val);
+		}
+    break;
+
+  case 198:
+#line 1191 "cfparse.y"
+    {
+			char portbuf[10];
+			struct sockaddr *saddr;
+
+			if (((yyvsp[(5) - (5)].num) == IPPROTO_ICMP || (yyvsp[(5) - (5)].num) == IPPROTO_ICMPV6)
+			 && ((yyvsp[(4) - (5)].num) != IPSEC_PORT_ANY || (yyvsp[(4) - (5)].num) != IPSEC_PORT_ANY)) {
+				yyerror("port number must be \"any\".");
+				return -1;
+			}
+
+			snprintf(portbuf, sizeof(portbuf), "%lu", (yyvsp[(4) - (5)].num));
+			saddr = str2saddr((yyvsp[(2) - (5)].val)->v, portbuf);
+			vfree((yyvsp[(2) - (5)].val));
+			if (saddr == NULL)
+				return -1;
+
+			switch (saddr->sa_family) {
+			case AF_INET:
+				if ((yyvsp[(5) - (5)].num) == IPPROTO_ICMPV6) {
+					yyerror("upper layer protocol mismatched.\n");
+					racoon_free(saddr);
+					return -1;
+				}
+				(yyval.val) = ipsecdoi_sockaddr2id(saddr,
+										  (yyvsp[(3) - (5)].num) == ~0 ? (sizeof(struct in_addr) << 3): (yyvsp[(3) - (5)].num),
+										  (yyvsp[(5) - (5)].num));
+				break;
+#ifdef INET6
+			case AF_INET6:
+				if ((yyvsp[(5) - (5)].num) == IPPROTO_ICMP) {
+					yyerror("upper layer protocol mismatched.\n");
+					racoon_free(saddr);
+					return -1;
+				}
+				(yyval.val) = ipsecdoi_sockaddr2id(saddr, 
+										  (yyvsp[(3) - (5)].num) == ~0 ? (sizeof(struct in6_addr) << 3): (yyvsp[(3) - (5)].num),
+										  (yyvsp[(5) - (5)].num));
+				break;
+#endif
+			default:
+				yyerror("invalid family: %d", saddr->sa_family);
+				(yyval.val) = NULL;
+				break;
+			}
+			racoon_free(saddr);
+			if ((yyval.val) == NULL)
+				return -1;
+		}
+    break;
+
+  case 199:
+#line 1240 "cfparse.y"
+    {
+			char portbuf[10];
+			struct sockaddr *laddr = NULL, *haddr = NULL;
+			char *cur = NULL;
+
+			if (((yyvsp[(6) - (6)].num) == IPPROTO_ICMP || (yyvsp[(6) - (6)].num) == IPPROTO_ICMPV6)
+			 && ((yyvsp[(5) - (6)].num) != IPSEC_PORT_ANY || (yyvsp[(5) - (6)].num) != IPSEC_PORT_ANY)) {
+				yyerror("port number must be \"any\".");
+				return -1;
+			}
+
+			snprintf(portbuf, sizeof(portbuf), "%lu", (yyvsp[(5) - (6)].num));
+			
+			laddr = str2saddr((yyvsp[(2) - (6)].val)->v, portbuf);
+			if (laddr == NULL) {
+			    return -1;
+			}
+			vfree((yyvsp[(2) - (6)].val));
+			haddr = str2saddr((yyvsp[(3) - (6)].val)->v, portbuf);
+			if (haddr == NULL) {
+			    racoon_free(laddr);
+			    return -1;
+			}
+			vfree((yyvsp[(3) - (6)].val));
+
+			switch (laddr->sa_family) {
+			case AF_INET:
+				if ((yyvsp[(6) - (6)].num) == IPPROTO_ICMPV6) {
+				    yyerror("upper layer protocol mismatched.\n");
+				    if (laddr)
+					racoon_free(laddr);
+				    if (haddr)
+					racoon_free(haddr);
+				    return -1;
+				}
+                                (yyval.val) = ipsecdoi_sockrange2id(laddr, haddr, 
+							   (yyvsp[(6) - (6)].num));
+				break;
+#ifdef INET6
+			case AF_INET6:
+				if ((yyvsp[(6) - (6)].num) == IPPROTO_ICMP) {
+					yyerror("upper layer protocol mismatched.\n");
+					if (laddr)
+					    racoon_free(laddr);
+					if (haddr)
+					    racoon_free(haddr);
+					return -1;
+				}
+				(yyval.val) = ipsecdoi_sockrange2id(laddr, haddr, 
+							       (yyvsp[(6) - (6)].num));
+				break;
+#endif
+			default:
+				yyerror("invalid family: %d", laddr->sa_family);
+				(yyval.val) = NULL;
+				break;
+			}
+			if (laddr)
+			    racoon_free(laddr);
+			if (haddr)
+			    racoon_free(haddr);
+			if ((yyval.val) == NULL)
+				return -1;
+		}
+    break;
+
+  case 200:
+#line 1305 "cfparse.y"
+    {
+			struct ipsecdoi_id_b *id_b;
+
+			if ((yyvsp[(1) - (2)].num) == IDTYPE_ASN1DN) {
+				yyerror("id type forbidden: %d", (yyvsp[(1) - (2)].num));
+				(yyval.val) = NULL;
+				return -1;
+			}
+
+			(yyvsp[(2) - (2)].val)->l--;
+
+			(yyval.val) = vmalloc(sizeof(*id_b) + (yyvsp[(2) - (2)].val)->l);
+			if ((yyval.val) == NULL) {
+				yyerror("failed to allocate identifier");
+				return -1;
+			}
+
+			id_b = (struct ipsecdoi_id_b *)(yyval.val)->v;
+			id_b->type = idtype2doi((yyvsp[(1) - (2)].num));
+
+			id_b->proto_id = 0;
+			id_b->port = 0;
+
+			memcpy((yyval.val)->v + sizeof(*id_b), (yyvsp[(2) - (2)].val)->v, (yyvsp[(2) - (2)].val)->l);
+		}
+    break;
+
+  case 201:
+#line 1333 "cfparse.y"
+    {
+			cur_sainfo->id_i = NULL;
+		}
+    break;
+
+  case 202:
+#line 1337 "cfparse.y"
+    {
+			struct ipsecdoi_id_b *id_b;
+			vchar_t *idv;
+
+			if (set_identifier(&idv, (yyvsp[(2) - (3)].num), (yyvsp[(3) - (3)].val)) != 0) {
+				yyerror("failed to set identifer.\n");
+				return -1;
+			}
+			cur_sainfo->id_i = vmalloc(sizeof(*id_b) + idv->l);
+			if (cur_sainfo->id_i == NULL) {
+				yyerror("failed to allocate identifier");
+				return -1;
+			}
+
+			id_b = (struct ipsecdoi_id_b *)cur_sainfo->id_i->v;
+			id_b->type = idtype2doi((yyvsp[(2) - (3)].num));
+
+			id_b->proto_id = 0;
+			id_b->port = 0;
+
+			memcpy(cur_sainfo->id_i->v + sizeof(*id_b),
+			       idv->v, idv->l);
+			vfree(idv);
+		}
+    break;
+
+  case 203:
+#line 1362 "cfparse.y"
+    {
+#ifdef ENABLE_HYBRID
+			if ((cur_sainfo->group = vdup((yyvsp[(2) - (2)].val))) == NULL) {
+				yyerror("failed to set sainfo xauth group.\n");
+				return -1;
+			}
+#else
+			yyerror("racoon not configured with --enable-hybrid");
+			return -1;
+#endif
+ 		}
+    break;
+
+  case 206:
+#line 1380 "cfparse.y"
+    {
+			cur_sainfo->pfs_group = (yyvsp[(2) - (2)].num);
+		}
+    break;
+
+  case 208:
+#line 1385 "cfparse.y"
+    {
+			cur_sainfo->remoteid = (yyvsp[(2) - (2)].num);
+		}
+    break;
+
+  case 210:
+#line 1390 "cfparse.y"
+    {
+			cur_sainfo->lifetime = (yyvsp[(3) - (4)].num) * (yyvsp[(4) - (4)].num);
+		}
+    break;
+
+  case 212:
+#line 1395 "cfparse.y"
+    {
+#if 1
+			yyerror("byte lifetime support is deprecated");
+			return -1;
+#else
+			cur_sainfo->lifebyte = fix_lifebyte((yyvsp[(3) - (4)].num) * (yyvsp[(4) - (4)].num));
+			if (cur_sainfo->lifebyte == 0)
+				return -1;
+#endif
+		}
+    break;
+
+  case 214:
+#line 1406 "cfparse.y"
+    {
+			cur_algclass = (yyvsp[(1) - (1)].num);
+		}
+    break;
+
+  case 216:
+#line 1411 "cfparse.y"
+    {
+			yyerror("it's deprecated to specify a identifier in phase 2");
+		}
+    break;
+
+  case 218:
+#line 1416 "cfparse.y"
+    {
+			yyerror("it's deprecated to specify a identifier in phase 2");
+		}
+    break;
+
+  case 220:
+#line 1424 "cfparse.y"
+    {
+			inssainfoalg(&cur_sainfo->algs[cur_algclass], (yyvsp[(1) - (1)].alg));
+		}
+    break;
+
+  case 221:
+#line 1428 "cfparse.y"
+    {
+			inssainfoalg(&cur_sainfo->algs[cur_algclass], (yyvsp[(1) - (1)].alg));
+		}
+    break;
+
+  case 223:
+#line 1435 "cfparse.y"
+    {
+			int defklen;
+
+			(yyval.alg) = newsainfoalg();
+			if ((yyval.alg) == NULL) {
+				yyerror("failed to get algorithm allocation");
+				return -1;
+			}
+
+			(yyval.alg)->alg = algtype2doi(cur_algclass, (yyvsp[(1) - (2)].num));
+			if ((yyval.alg)->alg == -1) {
+				yyerror("algorithm mismatched");
+				racoon_free((yyval.alg));
+				(yyval.alg) = NULL;
+				return -1;
+			}
+
+			defklen = default_keylen(cur_algclass, (yyvsp[(1) - (2)].num));
+			if (defklen == 0) {
+				if ((yyvsp[(2) - (2)].num)) {
+					yyerror("keylen not allowed");
+					racoon_free((yyval.alg));
+					(yyval.alg) = NULL;
+					return -1;
+				}
+			} else {
+				if ((yyvsp[(2) - (2)].num) && check_keylen(cur_algclass, (yyvsp[(1) - (2)].num), (yyvsp[(2) - (2)].num)) < 0) {
+					yyerror("invalid keylen %d", (yyvsp[(2) - (2)].num));
+					racoon_free((yyval.alg));
+					(yyval.alg) = NULL;
+					return -1;
+				}
+			}
+
+			if ((yyvsp[(2) - (2)].num))
+				(yyval.alg)->encklen = (yyvsp[(2) - (2)].num);
+			else
+				(yyval.alg)->encklen = defklen;
+
+			/* check if it's supported algorithm by kernel */
+			if (!(cur_algclass == algclass_ipsec_auth && (yyvsp[(1) - (2)].num) == algtype_non_auth)
+			 && pk_checkalg(cur_algclass, (yyvsp[(1) - (2)].num), (yyval.alg)->encklen)) {
+				int a = algclass2doi(cur_algclass);
+				int b = algtype2doi(cur_algclass, (yyvsp[(1) - (2)].num));
+				if (a == IPSECDOI_ATTR_AUTH)
+					a = IPSECDOI_PROTO_IPSEC_AH;
+				yyerror("algorithm %s not supported by the kernel (missing module?)",
+					s_ipsecdoi_trns(a, b));
+				racoon_free((yyval.alg));
+				(yyval.alg) = NULL;
+				return -1;
+			}
+		}
+    break;
+
+  case 224:
+#line 1490 "cfparse.y"
+    { (yyval.num) = ~0; }
+    break;
+
+  case 225:
+#line 1491 "cfparse.y"
+    { (yyval.num) = (yyvsp[(1) - (1)].num); }
+    break;
+
+  case 226:
+#line 1494 "cfparse.y"
+    { (yyval.num) = IPSEC_PORT_ANY; }
+    break;
+
+  case 227:
+#line 1495 "cfparse.y"
+    { (yyval.num) = (yyvsp[(1) - (1)].num); }
+    break;
+
+  case 228:
+#line 1496 "cfparse.y"
+    { (yyval.num) = IPSEC_PORT_ANY; }
+    break;
+
+  case 229:
+#line 1499 "cfparse.y"
+    { (yyval.num) = (yyvsp[(1) - (1)].num); }
+    break;
+
+  case 230:
+#line 1500 "cfparse.y"
+    { (yyval.num) = (yyvsp[(1) - (1)].num); }
+    break;
+
+  case 231:
+#line 1501 "cfparse.y"
+    { (yyval.num) = IPSEC_ULPROTO_ANY; }
+    break;
+
+  case 232:
+#line 1504 "cfparse.y"
+    { (yyval.num) = 0; }
+    break;
+
+  case 233:
+#line 1505 "cfparse.y"
+    { (yyval.num) = (yyvsp[(1) - (1)].num); }
+    break;
+
+  case 234:
+#line 1511 "cfparse.y"
+    {
+			struct remoteconf *new;
+			struct proposalspec *prspec;
+
+			new = copyrmconf((yyvsp[(4) - (4)].saddr));
+			if (new == NULL) {
+				yyerror("failed to get remoteconf for %s.", saddr2str ((yyvsp[(4) - (4)].saddr)));
+				return -1;
+			}
+
+			new->remote = (yyvsp[(2) - (4)].saddr);
+			new->inherited_from = getrmconf_strict((yyvsp[(4) - (4)].saddr), 1);
+			new->proposal = NULL;
+			new->prhead = NULL;
+			cur_rmconf = new;
+
+			prspec = newprspec();
+			if (prspec == NULL || !cur_rmconf->inherited_from 
+				|| !cur_rmconf->inherited_from->proposal)
+				return -1;
+			prspec->lifetime = cur_rmconf->inherited_from->proposal->lifetime;
+			prspec->lifebyte = cur_rmconf->inherited_from->proposal->lifebyte;
+			insprspec(prspec, &cur_rmconf->prhead);
+		}
+    break;
+
+  case 236:
+#line 1537 "cfparse.y"
+    {
+			struct remoteconf *new;
+			struct proposalspec *prspec;
+
+			new = newrmconf();
+			if (new == NULL) {
+				yyerror("failed to get new remoteconf.");
+				return -1;
+			}
+
+			new->remote = (yyvsp[(2) - (2)].saddr);
+			cur_rmconf = new;
+
+			prspec = newprspec();
+			if (prspec == NULL)
+				return -1;
+			prspec->lifetime = oakley_get_defaultlifetime();
+			insprspec(prspec, &cur_rmconf->prhead);
+		}
+    break;
+
+  case 238:
+#line 1561 "cfparse.y"
+    {
+			/* check a exchange mode */
+			if (cur_rmconf->etypes == NULL) {
+				yyerror("no exchange mode specified.\n");
+				return -1;
+			}
+
+			if (cur_rmconf->idvtype == IDTYPE_UNDEFINED)
+				cur_rmconf->idvtype = IDTYPE_ADDRESS;
+
+
+			if (cur_rmconf->idvtype == IDTYPE_ASN1DN) {
+				if (cur_rmconf->mycertfile) {
+					if (cur_rmconf->idv)
+						yywarn("Both CERT and ASN1 ID "
+						       "are set. Hope this is OK.\n");
+					/* TODO: Preparse the DN here */
+				} else if (cur_rmconf->idv) {
+					/* OK, using asn1dn without X.509. */
+				} else {
+					yyerror("ASN1 ID not specified "
+						"and no CERT defined!\n");
+					return -1;
+				}
+			}
+			
+			if (cur_rmconf->prhead->spspec == NULL
+				&& cur_rmconf->inherited_from
+				&& cur_rmconf->inherited_from->prhead) {
+				cur_rmconf->prhead->spspec = cur_rmconf->inherited_from->prhead->spspec;
+			}
+			if (set_isakmp_proposal(cur_rmconf, cur_rmconf->prhead) != 0)
+				return -1;
+
+			/* DH group settting if aggressive mode is there. */
+			if (check_etypeok(cur_rmconf, ISAKMP_ETYPE_AGG) != NULL) {
+				struct isakmpsa *p;
+				int b = 0;
+
+				/* DH group */
+				for (p = cur_rmconf->proposal; p; p = p->next) {
+					if (b == 0 || (b && b == p->dh_group)) {
+						b = p->dh_group;
+						continue;
+					}
+					yyerror("DH group must be equal "
+						"in all proposals "
+						"when aggressive mode is "
+						"used.\n");
+					return -1;
+				}
+				cur_rmconf->dh_group = b;
+
+				if (cur_rmconf->dh_group == 0) {
+					yyerror("DH group must be set in the proposal.\n");
+					return -1;
+				}
+
+				/* DH group settting if PFS is required. */
+				if (oakley_setdhgroup(cur_rmconf->dh_group,
+						&cur_rmconf->dhgrp) < 0) {
+					yyerror("failed to set DH value.\n");
+					return -1;
+				}
+			}
+
+			insrmconf(cur_rmconf);
+		}
+    break;
+
+  case 239:
+#line 1632 "cfparse.y"
+    {
+			(yyval.saddr) = newsaddr(sizeof(struct sockaddr));
+			(yyval.saddr)->sa_family = AF_UNSPEC;
+			((struct sockaddr_in *)(yyval.saddr))->sin_port = htons((yyvsp[(2) - (2)].num));
+		}
+    break;
+
+  case 240:
+#line 1638 "cfparse.y"
+    {
+			(yyval.saddr) = (yyvsp[(1) - (1)].saddr);
+			if ((yyval.saddr) == NULL) {
+				yyerror("failed to allocate sockaddr");
+				return -1;
+			}
+		}
+    break;
+
+  case 243:
+#line 1652 "cfparse.y"
+    {
+			cur_rmconf->etypes = NULL;
+		}
+    break;
+
+  case 245:
+#line 1656 "cfparse.y"
+    { cur_rmconf->doitype = (yyvsp[(2) - (2)].num); }
+    break;
+
+  case 247:
+#line 1657 "cfparse.y"
+    { cur_rmconf->sittype = (yyvsp[(2) - (2)].num); }
+    break;
+
+  case 250:
+#line 1660 "cfparse.y"
+    {
+			yywarn("This directive without certtype will be removed!\n");
+			yywarn("Please use 'peers_certfile x509 \"%s\";' instead\n", (yyvsp[(2) - (2)].val)->v);
+			cur_rmconf->getcert_method = ISAKMP_GETCERT_LOCALFILE;
+
+			if (cur_rmconf->peerscertfile != NULL)
+				racoon_free(cur_rmconf->peerscertfile);
+			cur_rmconf->peerscertfile = racoon_strdup((yyvsp[(2) - (2)].val)->v);
+			STRDUP_FATAL(cur_rmconf->peerscertfile);
+			vfree((yyvsp[(2) - (2)].val));
+		}
+    break;
+
+  case 252:
+#line 1673 "cfparse.y"
+    {
+			cur_rmconf->cacerttype = (yyvsp[(2) - (3)].num);
+			cur_rmconf->getcacert_method = ISAKMP_GETCERT_LOCALFILE;
+			if (cur_rmconf->cacertfile != NULL)
+				racoon_free(cur_rmconf->cacertfile);
+			cur_rmconf->cacertfile = racoon_strdup((yyvsp[(3) - (3)].val)->v);
+			STRDUP_FATAL(cur_rmconf->cacertfile);
+			vfree((yyvsp[(3) - (3)].val));
+		}
+    break;
+
+  case 254:
+#line 1684 "cfparse.y"
+    {
+			cur_rmconf->getcert_method = ISAKMP_GETCERT_LOCALFILE;
+			if (cur_rmconf->peerscertfile != NULL)
+				racoon_free(cur_rmconf->peerscertfile);
+			cur_rmconf->peerscertfile = racoon_strdup((yyvsp[(3) - (3)].val)->v);
+			STRDUP_FATAL(cur_rmconf->peerscertfile);
+			vfree((yyvsp[(3) - (3)].val));
+		}
+    break;
+
+  case 256:
+#line 1694 "cfparse.y"
+    {
+			char path[MAXPATHLEN];
+			int ret = 0;
+
+			getpathname(path, sizeof(path),
+				LC_PATHTYPE_CERT, (yyvsp[(3) - (3)].val)->v);
+			vfree((yyvsp[(3) - (3)].val));
+
+			if (cur_rmconf->getcert_method == ISAKMP_GETCERT_DNS) {
+				yyerror("Different peers_certfile method "
+					"already defined: %d!\n",
+					cur_rmconf->getcert_method);
+				return -1;
+			}
+			cur_rmconf->getcert_method = ISAKMP_GETCERT_LOCALFILE;
+			if (rsa_parse_file(cur_rmconf->rsa_public, path, RSA_TYPE_PUBLIC)) {
+				yyerror("Couldn't parse keyfile.\n", path);
+				return -1;
+			}
+			plog(LLV_DEBUG, LOCATION, NULL, "Public PlainRSA keyfile parsed: %s\n", path);
+		}
+    break;
+
+  case 258:
+#line 1717 "cfparse.y"
+    {
+			if (cur_rmconf->getcert_method) {
+				yyerror("Different peers_certfile method already defined!\n");
+				return -1;
+			}
+			cur_rmconf->getcert_method = ISAKMP_GETCERT_DNS;
+			cur_rmconf->peerscertfile = NULL;
+		}
+    break;
+
+  case 260:
+#line 1726 "cfparse.y"
+    { cur_rmconf->verify_cert = (yyvsp[(2) - (2)].num); }
+    break;
+
+  case 262:
+#line 1727 "cfparse.y"
+    { cur_rmconf->send_cert = (yyvsp[(2) - (2)].num); }
+    break;
+
+  case 264:
+#line 1728 "cfparse.y"
+    { cur_rmconf->send_cr = (yyvsp[(2) - (2)].num); }
+    break;
+
+  case 266:
+#line 1730 "cfparse.y"
+    {
+			if (set_identifier(&cur_rmconf->idv, (yyvsp[(2) - (3)].num), (yyvsp[(3) - (3)].val)) != 0) {
+				yyerror("failed to set identifer.\n");
+				return -1;
+			}
+			cur_rmconf->idvtype = (yyvsp[(2) - (3)].num);
+		}
+    break;
+
+  case 268:
+#line 1739 "cfparse.y"
+    {
+			if (set_identifier_qual(&cur_rmconf->idv, (yyvsp[(2) - (4)].num), (yyvsp[(4) - (4)].val), (yyvsp[(3) - (4)].num)) != 0) {
+				yyerror("failed to set identifer.\n");
+				return -1;
+			}
+			cur_rmconf->idvtype = (yyvsp[(2) - (4)].num);
+		}
+    break;
+
+  case 270:
+#line 1748 "cfparse.y"
+    {
+#ifdef ENABLE_HYBRID
+			/* formerly identifier type login */
+			if (xauth_rmconf_used(&cur_rmconf->xauth) == -1) {
+				yyerror("failed to allocate xauth state\n");
+				return -1;
+			}
+			if ((cur_rmconf->xauth->login = vdup((yyvsp[(2) - (2)].val))) == NULL) {
+				yyerror("failed to set identifer.\n");
+				return -1;
+			}
+#else
+			yyerror("racoon not configured with --enable-hybrid");
+#endif
+		}
+    break;
+
+  case 272:
+#line 1765 "cfparse.y"
+    {
+			struct idspec  *id;
+			id = newidspec();
+			if (id == NULL) {
+				yyerror("failed to allocate idspec");
+				return -1;
+			}
+			if (set_identifier(&id->id, (yyvsp[(2) - (3)].num), (yyvsp[(3) - (3)].val)) != 0) {
+				yyerror("failed to set identifer.\n");
+				racoon_free(id);
+				return -1;
+			}
+			id->idtype = (yyvsp[(2) - (3)].num);
+			genlist_append (cur_rmconf->idvl_p, id);
+		}
+    break;
+
+  case 274:
+#line 1782 "cfparse.y"
+    {
+			struct idspec  *id;
+			id = newidspec();
+			if (id == NULL) {
+				yyerror("failed to allocate idspec");
+				return -1;
+			}
+			if (set_identifier_qual(&id->id, (yyvsp[(2) - (4)].num), (yyvsp[(4) - (4)].val), (yyvsp[(3) - (4)].num)) != 0) {
+				yyerror("failed to set identifer.\n");
+				racoon_free(id);
+				return -1;
+			}
+			id->idtype = (yyvsp[(2) - (4)].num);
+			genlist_append (cur_rmconf->idvl_p, id);
+		}
+    break;
+
+  case 276:
+#line 1798 "cfparse.y"
+    { cur_rmconf->verify_identifier = (yyvsp[(2) - (2)].num); }
+    break;
+
+  case 278:
+#line 1799 "cfparse.y"
+    { cur_rmconf->nonce_size = (yyvsp[(2) - (2)].num); }
+    break;
+
+  case 280:
+#line 1801 "cfparse.y"
+    {
+			yyerror("dh_group cannot be defined here.");
+			return -1;
+		}
+    break;
+
+  case 282:
+#line 1806 "cfparse.y"
+    { cur_rmconf->passive = (yyvsp[(2) - (2)].num); }
+    break;
+
+  case 284:
+#line 1807 "cfparse.y"
+    { cur_rmconf->ike_frag = (yyvsp[(2) - (2)].num); }
+    break;
+
+  case 286:
+#line 1808 "cfparse.y"
+    { cur_rmconf->ike_frag = ISAKMP_FRAG_FORCE; }
+    break;
+
+  case 288:
+#line 1809 "cfparse.y"
+    { 
+#ifdef SADB_X_EXT_NAT_T_FRAG
+        		if (libipsec_opt & LIBIPSEC_OPT_FRAG)
+				cur_rmconf->esp_frag = (yyvsp[(2) - (2)].num); 
+			else
+                		yywarn("libipsec lacks IKE frag support");
+#else
+			yywarn("Your kernel does not support esp_frag");
+#endif
+		}
+    break;
+
+  case 290:
+#line 1819 "cfparse.y"
+    { 
+			if (cur_rmconf->script[SCRIPT_PHASE1_UP] != NULL)
+				vfree(cur_rmconf->script[SCRIPT_PHASE1_UP]);
+
+			cur_rmconf->script[SCRIPT_PHASE1_UP] = 
+			    script_path_add(vdup((yyvsp[(2) - (3)].val)));
+		}
+    break;
+
+  case 292:
+#line 1826 "cfparse.y"
+    { 
+			if (cur_rmconf->script[SCRIPT_PHASE1_DOWN] != NULL)
+				vfree(cur_rmconf->script[SCRIPT_PHASE1_DOWN]);
+
+			cur_rmconf->script[SCRIPT_PHASE1_DOWN] = 
+			    script_path_add(vdup((yyvsp[(2) - (3)].val)));
+		}
+    break;
+
+  case 294:
+#line 1833 "cfparse.y"
+    { cur_rmconf->mode_cfg = (yyvsp[(2) - (2)].num); }
+    break;
+
+  case 296:
+#line 1834 "cfparse.y"
+    {
+			cur_rmconf->weak_phase1_check = (yyvsp[(2) - (2)].num);
+		}
+    break;
+
+  case 298:
+#line 1837 "cfparse.y"
+    { cur_rmconf->gen_policy = (yyvsp[(2) - (2)].num); }
+    break;
+
+  case 300:
+#line 1838 "cfparse.y"
+    { cur_rmconf->gen_policy = (yyvsp[(2) - (2)].num); }
+    break;
+
+  case 302:
+#line 1839 "cfparse.y"
+    { cur_rmconf->support_proxy = (yyvsp[(2) - (2)].num); }
+    break;
+
+  case 304:
+#line 1840 "cfparse.y"
+    { cur_rmconf->ini_contact = (yyvsp[(2) - (2)].num); }
+    break;
+
+  case 306:
+#line 1842 "cfparse.y"
+    {
+#ifdef ENABLE_NATT
+        		if (libipsec_opt & LIBIPSEC_OPT_NATT)
+				cur_rmconf->nat_traversal = (yyvsp[(2) - (2)].num);
+			else
+                		yyerror("libipsec lacks NAT-T support");
+#else
+			yyerror("NAT-T support not compiled in.");
+#endif
+		}
+    break;
+
+  case 308:
+#line 1853 "cfparse.y"
+    {
+#ifdef ENABLE_NATT
+			if (libipsec_opt & LIBIPSEC_OPT_NATT)
+				cur_rmconf->nat_traversal = NATT_FORCE;
+			else
+                		yyerror("libipsec lacks NAT-T support");
+#else
+			yyerror("NAT-T support not compiled in.");
+#endif
+		}
+    break;
+
+  case 310:
+#line 1864 "cfparse.y"
+    {
+#ifdef ENABLE_DPD
+			cur_rmconf->dpd = (yyvsp[(2) - (2)].num);
+#else
+			yyerror("DPD support not compiled in.");
+#endif
+		}
+    break;
+
+  case 312:
+#line 1872 "cfparse.y"
+    {
+#ifdef ENABLE_DPD
+			cur_rmconf->dpd_interval = (yyvsp[(2) - (2)].num);
+#else
+			yyerror("DPD support not compiled in.");
+#endif
+		}
+    break;
+
+  case 314:
+#line 1881 "cfparse.y"
+    {
+#ifdef ENABLE_DPD
+			cur_rmconf->dpd_retry = (yyvsp[(2) - (2)].num);
+#else
+			yyerror("DPD support not compiled in.");
+#endif
+		}
+    break;
+
+  case 316:
+#line 1890 "cfparse.y"
+    {
+#ifdef ENABLE_DPD
+			cur_rmconf->dpd_maxfails = (yyvsp[(2) - (2)].num);
+#else
+			yyerror("DPD support not compiled in.");
+#endif
+		}
+    break;
+
+  case 318:
+#line 1899 "cfparse.y"
+    {
+			cur_rmconf->ph1id = (yyvsp[(2) - (2)].num);
+		}
+    break;
+
+  case 320:
+#line 1904 "cfparse.y"
+    {
+			cur_rmconf->prhead->lifetime = (yyvsp[(3) - (4)].num) * (yyvsp[(4) - (4)].num);
+		}
+    break;
+
+  case 322:
+#line 1908 "cfparse.y"
+    { cur_rmconf->pcheck_level = (yyvsp[(2) - (2)].num); }
+    break;
+
+  case 324:
+#line 1910 "cfparse.y"
+    {
+#if 1
+			yyerror("byte lifetime support is deprecated in Phase1");
+			return -1;
+#else
+			yywarn("the lifetime of bytes in phase 1 "
+				"will be ignored at the moment.");
+			cur_rmconf->prhead->lifebyte = fix_lifebyte((yyvsp[(3) - (4)].num) * (yyvsp[(4) - (4)].num));
+			if (cur_rmconf->prhead->lifebyte == 0)
+				return -1;
+#endif
+		}
+    break;
+
+  case 326:
+#line 1924 "cfparse.y"
+    {
+			struct secprotospec *spspec;
+
+			spspec = newspspec();
+			if (spspec == NULL)
+				return -1;
+			insspspec(spspec, &cur_rmconf->prhead);
+		}
+    break;
+
+  case 329:
+#line 1937 "cfparse.y"
+    {
+			struct etypes *new;
+			new = racoon_malloc(sizeof(struct etypes));
+			if (new == NULL) {
+				yyerror("failed to allocate etypes");
+				return -1;
+			}
+			new->type = (yyvsp[(2) - (2)].num);
+			new->next = NULL;
+			if (cur_rmconf->etypes == NULL)
+				cur_rmconf->etypes = new;
+			else {
+				struct etypes *p;
+				for (p = cur_rmconf->etypes;
+				     p->next != NULL;
+				     p = p->next)
+					;
+				p->next = new;
+			}
+		}
+    break;
+
+  case 330:
+#line 1960 "cfparse.y"
+    {
+			cur_rmconf->certtype = (yyvsp[(1) - (3)].num);
+			if (cur_rmconf->mycertfile != NULL)
+				racoon_free(cur_rmconf->mycertfile);
+			cur_rmconf->mycertfile = racoon_strdup((yyvsp[(2) - (3)].val)->v);
+			STRDUP_FATAL(cur_rmconf->mycertfile);
+			vfree((yyvsp[(2) - (3)].val));
+			if (cur_rmconf->myprivfile != NULL)
+				racoon_free(cur_rmconf->myprivfile);
+			cur_rmconf->myprivfile = racoon_strdup((yyvsp[(3) - (3)].val)->v);
+			STRDUP_FATAL(cur_rmconf->myprivfile);
+			vfree((yyvsp[(3) - (3)].val));
+		}
+    break;
+
+  case 332:
+#line 1975 "cfparse.y"
+    {
+			char path[MAXPATHLEN];
+			int ret = 0;
+
+			getpathname(path, sizeof(path),
+				LC_PATHTYPE_CERT, (yyvsp[(2) - (2)].val)->v);
+			vfree((yyvsp[(2) - (2)].val));
+
+			cur_rmconf->certtype = (yyvsp[(1) - (2)].num);
+			cur_rmconf->send_cr = FALSE;
+			cur_rmconf->send_cert = FALSE;
+			cur_rmconf->verify_cert = FALSE;
+			if (rsa_parse_file(cur_rmconf->rsa_private, path, RSA_TYPE_PRIVATE)) {
+				yyerror("Couldn't parse keyfile.\n", path);
+				return -1;
+			}
+			plog(LLV_DEBUG, LOCATION, NULL, "Private PlainRSA keyfile parsed: %s\n", path);
+		}
+    break;
+
+  case 334:
+#line 1997 "cfparse.y"
+    {
+			(yyval.num) = algtype2doi(algclass_isakmp_dh, (yyvsp[(1) - (1)].num));
+			if ((yyval.num) == -1) {
+				yyerror("must be DH group");
+				return -1;
+			}
+		}
+    break;
+
+  case 335:
+#line 2005 "cfparse.y"
+    {
+			if (ARRAYLEN(num2dhgroup) > (yyvsp[(1) - (1)].num) && num2dhgroup[(yyvsp[(1) - (1)].num)] != 0) {
+				(yyval.num) = num2dhgroup[(yyvsp[(1) - (1)].num)];
+			} else {
+				yyerror("must be DH group");
+				(yyval.num) = 0;
+				return -1;
+			}
+		}
+    break;
+
+  case 336:
+#line 2016 "cfparse.y"
+    { (yyval.val) = NULL; }
+    break;
+
+  case 337:
+#line 2017 "cfparse.y"
+    { (yyval.val) = (yyvsp[(1) - (1)].val); }
+    break;
+
+  case 338:
+#line 2018 "cfparse.y"
+    { (yyval.val) = (yyvsp[(1) - (1)].val); }
+    break;
+
+  case 341:
+#line 2026 "cfparse.y"
+    {
+			yyerror("strength directive is obsoleted.");
+		}
+    break;
+
+  case 343:
+#line 2030 "cfparse.y"
+    {
+			cur_rmconf->prhead->spspec->lifetime = (yyvsp[(3) - (4)].num) * (yyvsp[(4) - (4)].num);
+		}
+    break;
+
+  case 345:
+#line 2035 "cfparse.y"
+    {
+#if 1
+			yyerror("byte lifetime support is deprecated");
+			return -1;
+#else
+			cur_rmconf->prhead->spspec->lifebyte = fix_lifebyte((yyvsp[(3) - (4)].num) * (yyvsp[(4) - (4)].num));
+			if (cur_rmconf->prhead->spspec->lifebyte == 0)
+				return -1;
+#endif
+		}
+    break;
+
+  case 347:
+#line 2047 "cfparse.y"
+    {
+			cur_rmconf->prhead->spspec->algclass[algclass_isakmp_dh] = (yyvsp[(2) - (2)].num);
+		}
+    break;
+
+  case 349:
+#line 2052 "cfparse.y"
+    {
+			if (cur_rmconf->prhead->spspec->vendorid != VENDORID_GSSAPI) {
+				yyerror("wrong Vendor ID for gssapi_id");
+				return -1;
+			}
+			if (cur_rmconf->prhead->spspec->gssid != NULL)
+				racoon_free(cur_rmconf->prhead->spspec->gssid);
+			cur_rmconf->prhead->spspec->gssid = 
+			    racoon_strdup((yyvsp[(2) - (2)].val)->v);
+			STRDUP_FATAL(cur_rmconf->prhead->spspec->gssid);
+		}
+    break;
+
+  case 351:
+#line 2065 "cfparse.y"
+    {
+			int doi;
+			int defklen;
+
+			doi = algtype2doi((yyvsp[(1) - (3)].num), (yyvsp[(2) - (3)].num));
+			if (doi == -1) {
+				yyerror("algorithm mismatched 1");
+				return -1;
+			}
+
+			switch ((yyvsp[(1) - (3)].num)) {
+			case algclass_isakmp_enc:
+			/* reject suppressed algorithms */
+#ifndef HAVE_OPENSSL_RC5_H
+				if ((yyvsp[(2) - (3)].num) == algtype_rc5) {
+					yyerror("algorithm %s not supported",
+					    s_attr_isakmp_enc(doi));
+					return -1;
+				}
+#endif
+#ifndef HAVE_OPENSSL_IDEA_H
+				if ((yyvsp[(2) - (3)].num) == algtype_idea) {
+					yyerror("algorithm %s not supported",
+					    s_attr_isakmp_enc(doi));
+					return -1;
+				}
+#endif
+
+				cur_rmconf->prhead->spspec->algclass[algclass_isakmp_enc] = doi;
+				defklen = default_keylen((yyvsp[(1) - (3)].num), (yyvsp[(2) - (3)].num));
+				if (defklen == 0) {
+					if ((yyvsp[(3) - (3)].num)) {
+						yyerror("keylen not allowed");
+						return -1;
+					}
+				} else {
+					if ((yyvsp[(3) - (3)].num) && check_keylen((yyvsp[(1) - (3)].num), (yyvsp[(2) - (3)].num), (yyvsp[(3) - (3)].num)) < 0) {
+						yyerror("invalid keylen %d", (yyvsp[(3) - (3)].num));
+						return -1;
+					}
+				}
+				if ((yyvsp[(3) - (3)].num))
+					cur_rmconf->prhead->spspec->encklen = (yyvsp[(3) - (3)].num);
+				else
+					cur_rmconf->prhead->spspec->encklen = defklen;
+				break;
+			case algclass_isakmp_hash:
+				cur_rmconf->prhead->spspec->algclass[algclass_isakmp_hash] = doi;
+				break;
+			case algclass_isakmp_ameth:
+				cur_rmconf->prhead->spspec->algclass[algclass_isakmp_ameth] = doi;
+				/*
+				 * We may have to set the Vendor ID for the
+				 * authentication method we're using.
+				 */
+				switch ((yyvsp[(2) - (3)].num)) {
+				case algtype_gssapikrb:
+					if (cur_rmconf->prhead->spspec->vendorid !=
+					    VENDORID_UNKNOWN) {
+						yyerror("Vendor ID mismatch "
+						    "for auth method");
+						return -1;
+					}
+					/*
+					 * For interoperability with Win2k,
+					 * we set the Vendor ID to "GSSAPI".
+					 */
+					cur_rmconf->prhead->spspec->vendorid =
+					    VENDORID_GSSAPI;
+					break;
+				case algtype_rsasig:
+					if (cur_rmconf->certtype == ISAKMP_CERT_PLAINRSA) {
+						if (rsa_list_count(cur_rmconf->rsa_private) == 0) {
+							yyerror ("Private PlainRSA key not set. "
+								"Use directive 'certificate_type plainrsa ...'\n");
+							return -1;
+						}
+						if (rsa_list_count(cur_rmconf->rsa_public) == 0) {
+							yyerror ("Public PlainRSA keys not set. "
+								"Use directive 'peers_certfile plainrsa ...'\n");
+							return -1;
+						}
+					}
+					break;
+				default:
+					break;
+				}
+				break;
+			default:
+				yyerror("algorithm mismatched 2");
+				return -1;
+			}
+		}
+    break;
+
+  case 353:
+#line 2162 "cfparse.y"
+    { (yyval.num) = 1; }
+    break;
+
+  case 354:
+#line 2163 "cfparse.y"
+    { (yyval.num) = 60; }
+    break;
+
+  case 355:
+#line 2164 "cfparse.y"
+    { (yyval.num) = (60 * 60); }
+    break;
+
+  case 356:
+#line 2167 "cfparse.y"
+    { (yyval.num) = 1; }
+    break;
+
+  case 357:
+#line 2168 "cfparse.y"
+    { (yyval.num) = 1024; }
+    break;
+
+  case 358:
+#line 2169 "cfparse.y"
+    { (yyval.num) = (1024 * 1024); }
+    break;
+
+  case 359:
+#line 2170 "cfparse.y"
+    { (yyval.num) = (1024 * 1024 * 1024); }
+    break;
+
+
+/* Line 1267 of yacc.c.  */
+#line 4644 "cfparse.c"
+      default: break;
+    }
+  YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
+
+  YYPOPSTACK (yylen);
+  yylen = 0;
+  YY_STACK_PRINT (yyss, yyssp);
+
+  *++yyvsp = yyval;
+
+
+  /* Now `shift' the result of the reduction.  Determine what state
+     that goes to, based on the state we popped back to and the rule
+     number reduced by.  */
+
+  yyn = yyr1[yyn];
+
+  yystate = yypgoto[yyn - YYNTOKENS] + *yyssp;
+  if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp)
+    yystate = yytable[yystate];
+  else
+    yystate = yydefgoto[yyn - YYNTOKENS];
+
+  goto yynewstate;
+
+
+/*------------------------------------.
+| yyerrlab -- here on detecting error |
+`------------------------------------*/
+yyerrlab:
+  /* If not already recovering from an error, report this error.  */
+  if (!yyerrstatus)
+    {
+      ++yynerrs;
+#if ! YYERROR_VERBOSE
+      yyerror (YY_("syntax error"));
+#else
+      {
+	YYSIZE_T yysize = yysyntax_error (0, yystate, yychar);
+	if (yymsg_alloc < yysize && yymsg_alloc < YYSTACK_ALLOC_MAXIMUM)
+	  {
+	    YYSIZE_T yyalloc = 2 * yysize;
+	    if (! (yysize <= yyalloc && yyalloc <= YYSTACK_ALLOC_MAXIMUM))
+	      yyalloc = YYSTACK_ALLOC_MAXIMUM;
+	    if (yymsg != yymsgbuf)
+	      YYSTACK_FREE (yymsg);
+	    yymsg = (char *) YYSTACK_ALLOC (yyalloc);
+	    if (yymsg)
+	      yymsg_alloc = yyalloc;
+	    else
+	      {
+		yymsg = yymsgbuf;
+		yymsg_alloc = sizeof yymsgbuf;
+	      }
+	  }
+
+	if (0 < yysize && yysize <= yymsg_alloc)
+	  {
+	    (void) yysyntax_error (yymsg, yystate, yychar);
+	    yyerror (yymsg);
+	  }
+	else
+	  {
+	    yyerror (YY_("syntax error"));
+	    if (yysize != 0)
+	      goto yyexhaustedlab;
+	  }
+      }
+#endif
+    }
+
+
+
+  if (yyerrstatus == 3)
+    {
+      /* If just tried and failed to reuse look-ahead token after an
+	 error, discard it.  */
+
+      if (yychar <= YYEOF)
+	{
+	  /* Return failure if at end of input.  */
+	  if (yychar == YYEOF)
+	    YYABORT;
+	}
+      else
+	{
+	  yydestruct ("Error: discarding",
+		      yytoken, &yylval);
+	  yychar = YYEMPTY;
+	}
+    }
+
+  /* Else will try to reuse look-ahead token after shifting the error
+     token.  */
+  goto yyerrlab1;
+
+
+/*---------------------------------------------------.
+| yyerrorlab -- error raised explicitly by YYERROR.  |
+`---------------------------------------------------*/
+yyerrorlab:
+
+  /* Pacify compilers like GCC when the user code never invokes
+     YYERROR and the label yyerrorlab therefore never appears in user
+     code.  */
+  if (/*CONSTCOND*/ 0)
+     goto yyerrorlab;
+
+  /* Do not reclaim the symbols of the rule which action triggered
+     this YYERROR.  */
+  YYPOPSTACK (yylen);
+  yylen = 0;
+  YY_STACK_PRINT (yyss, yyssp);
+  yystate = *yyssp;
+  goto yyerrlab1;
+
+
+/*-------------------------------------------------------------.
+| yyerrlab1 -- common code for both syntax error and YYERROR.  |
+`-------------------------------------------------------------*/
+yyerrlab1:
+  yyerrstatus = 3;	/* Each real token shifted decrements this.  */
+
+  for (;;)
+    {
+      yyn = yypact[yystate];
+      if (yyn != YYPACT_NINF)
+	{
+	  yyn += YYTERROR;
+	  if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR)
+	    {
+	      yyn = yytable[yyn];
+	      if (0 < yyn)
+		break;
+	    }
+	}
+
+      /* Pop the current state because it cannot handle the error token.  */
+      if (yyssp == yyss)
+	YYABORT;
+
+
+      yydestruct ("Error: popping",
+		  yystos[yystate], yyvsp);
+      YYPOPSTACK (1);
+      yystate = *yyssp;
+      YY_STACK_PRINT (yyss, yyssp);
+    }
+
+  if (yyn == YYFINAL)
+    YYACCEPT;
+
+  *++yyvsp = yylval;
+
+
+  /* Shift the error token.  */
+  YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp);
+
+  yystate = yyn;
+  goto yynewstate;
+
+
+/*-------------------------------------.
+| yyacceptlab -- YYACCEPT comes here.  |
+`-------------------------------------*/
+yyacceptlab:
+  yyresult = 0;
+  goto yyreturn;
+
+/*-----------------------------------.
+| yyabortlab -- YYABORT comes here.  |
+`-----------------------------------*/
+yyabortlab:
+  yyresult = 1;
+  goto yyreturn;
+
+#ifndef yyoverflow
+/*-------------------------------------------------.
+| yyexhaustedlab -- memory exhaustion comes here.  |
+`-------------------------------------------------*/
+yyexhaustedlab:
+  yyerror (YY_("memory exhausted"));
+  yyresult = 2;
+  /* Fall through.  */
+#endif
+
+yyreturn:
+  if (yychar != YYEOF && yychar != YYEMPTY)
+     yydestruct ("Cleanup: discarding lookahead",
+		 yytoken, &yylval);
+  /* Do not reclaim the symbols of the rule which action triggered
+     this YYABORT or YYACCEPT.  */
+  YYPOPSTACK (yylen);
+  YY_STACK_PRINT (yyss, yyssp);
+  while (yyssp != yyss)
+    {
+      yydestruct ("Cleanup: popping",
+		  yystos[*yyssp], yyvsp);
+      YYPOPSTACK (1);
+    }
+#ifndef yyoverflow
+  if (yyss != yyssa)
+    YYSTACK_FREE (yyss);
+#endif
+#if YYERROR_VERBOSE
+  if (yymsg != yymsgbuf)
+    YYSTACK_FREE (yymsg);
+#endif
+  /* Make sure YYID is used.  */
+  return YYID (yyresult);
+}
+
+
+#line 2172 "cfparse.y"
+
+
+static struct proposalspec *
+newprspec()
+{
+	struct proposalspec *new;
+
+	new = racoon_calloc(1, sizeof(*new));
+	if (new == NULL)
+		yyerror("failed to allocate proposal");
+
+	return new;
+}
+
+/*
+ * insert into head of list.
+ */
+static void
+insprspec(prspec, head)
+	struct proposalspec *prspec;
+	struct proposalspec **head;
+{
+	if (*head != NULL)
+		(*head)->prev = prspec;
+	prspec->next = *head;
+	*head = prspec;
+}
+
+static struct secprotospec *
+newspspec()
+{
+	struct secprotospec *new;
+
+	new = racoon_calloc(1, sizeof(*new));
+	if (new == NULL) {
+		yyerror("failed to allocate spproto");
+		return NULL;
+	}
+
+	new->encklen = 0;	/*XXX*/
+
+	/*
+	 * Default to "uknown" vendor -- we will override this
+	 * as necessary.  When we send a Vendor ID payload, an
+	 * "unknown" will be translated to a KAME/racoon ID.
+	 */
+	new->vendorid = VENDORID_UNKNOWN;
+
+	return new;
+}
+
+/*
+ * insert into head of list.
+ */
+static void
+insspspec(spspec, head)
+	struct secprotospec *spspec;
+	struct proposalspec **head;
+{
+	spspec->back = *head;
+
+	if ((*head)->spspec != NULL)
+		(*head)->spspec->prev = spspec;
+	spspec->next = (*head)->spspec;
+	(*head)->spspec = spspec;
+}
+
+/* set final acceptable proposal */
+static int
+set_isakmp_proposal(rmconf, prspec)
+	struct remoteconf *rmconf;
+	struct proposalspec *prspec;
+{
+	struct proposalspec *p;
+	struct secprotospec *s;
+	int prop_no = 1; 
+	int trns_no = 1;
+	int32_t types[MAXALGCLASS];
+
+	p = prspec;
+	if (p->next != 0) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"multiple proposal definition.\n");
+		return -1;
+	}
+
+	/* mandatory check */
+	if (p->spspec == NULL) {
+		yyerror("no remote specification found: %s.\n",
+			saddr2str(rmconf->remote));
+		return -1;
+	}
+	for (s = p->spspec; s != NULL; s = s->next) {
+		/* XXX need more to check */
+		if (s->algclass[algclass_isakmp_enc] == 0) {
+			yyerror("encryption algorithm required.");
+			return -1;
+		}
+		if (s->algclass[algclass_isakmp_hash] == 0) {
+			yyerror("hash algorithm required.");
+			return -1;
+		}
+		if (s->algclass[algclass_isakmp_dh] == 0) {
+			yyerror("DH group required.");
+			return -1;
+		}
+		if (s->algclass[algclass_isakmp_ameth] == 0) {
+			yyerror("authentication method required.");
+			return -1;
+		}
+	}
+
+	/* skip to last part */
+	for (s = p->spspec; s->next != NULL; s = s->next)
+		;
+
+	while (s != NULL) {
+		plog(LLV_DEBUG2, LOCATION, NULL,
+			"lifetime = %ld\n", (long)
+			(s->lifetime ? s->lifetime : p->lifetime));
+		plog(LLV_DEBUG2, LOCATION, NULL,
+			"lifebyte = %d\n",
+			s->lifebyte ? s->lifebyte : p->lifebyte);
+		plog(LLV_DEBUG2, LOCATION, NULL,
+			"encklen=%d\n", s->encklen);
+
+		memset(types, 0, ARRAYLEN(types));
+		types[algclass_isakmp_enc] = s->algclass[algclass_isakmp_enc];
+		types[algclass_isakmp_hash] = s->algclass[algclass_isakmp_hash];
+		types[algclass_isakmp_dh] = s->algclass[algclass_isakmp_dh];
+		types[algclass_isakmp_ameth] =
+		    s->algclass[algclass_isakmp_ameth];
+
+		/* expanding spspec */
+		clean_tmpalgtype();
+		trns_no = expand_isakmpspec(prop_no, trns_no, types,
+				algclass_isakmp_enc, algclass_isakmp_ameth + 1,
+				s->lifetime ? s->lifetime : p->lifetime,
+				s->lifebyte ? s->lifebyte : p->lifebyte,
+				s->encklen, s->vendorid, s->gssid,
+				rmconf);
+		if (trns_no == -1) {
+			plog(LLV_ERROR, LOCATION, NULL,
+				"failed to expand isakmp proposal.\n");
+			return -1;
+		}
+
+		s = s->prev;
+	}
+
+	if (rmconf->proposal == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"no proposal found.\n");
+		return -1;
+	}
+
+	return 0;
+}
+
+static void
+clean_tmpalgtype()
+{
+	int i;
+	for (i = 0; i < MAXALGCLASS; i++)
+		tmpalgtype[i] = 0;	/* means algorithm undefined. */
+}
+
+static int
+expand_isakmpspec(prop_no, trns_no, types,
+		class, last, lifetime, lifebyte, encklen, vendorid, gssid,
+		rmconf)
+	int prop_no, trns_no;
+	int *types, class, last;
+	time_t lifetime;
+	int lifebyte;
+	int encklen;
+	int vendorid;
+	char *gssid;
+	struct remoteconf *rmconf;
+{
+	struct isakmpsa *new;
+
+	/* debugging */
+    {
+	int j;
+	char tb[10];
+	plog(LLV_DEBUG2, LOCATION, NULL,
+		"p:%d t:%d\n", prop_no, trns_no);
+	for (j = class; j < MAXALGCLASS; j++) {
+		snprintf(tb, sizeof(tb), "%d", types[j]);
+		plog(LLV_DEBUG2, LOCATION, NULL,
+			"%s%s%s%s\n",
+			s_algtype(j, types[j]),
+			types[j] ? "(" : "",
+			tb[0] == '0' ? "" : tb,
+			types[j] ? ")" : "");
+	}
+	plog(LLV_DEBUG2, LOCATION, NULL, "\n");
+    }
+
+#define TMPALGTYPE2STR(n) \
+	s_algtype(algclass_isakmp_##n, types[algclass_isakmp_##n])
+		/* check mandatory values */
+		if (types[algclass_isakmp_enc] == 0
+		 || types[algclass_isakmp_ameth] == 0
+		 || types[algclass_isakmp_hash] == 0
+		 || types[algclass_isakmp_dh] == 0) {
+			yyerror("few definition of algorithm "
+				"enc=%s ameth=%s hash=%s dhgroup=%s.\n",
+				TMPALGTYPE2STR(enc),
+				TMPALGTYPE2STR(ameth),
+				TMPALGTYPE2STR(hash),
+				TMPALGTYPE2STR(dh));
+			return -1;
+		}
+#undef TMPALGTYPE2STR
+
+	/* set new sa */
+	new = newisakmpsa();
+	if (new == NULL) {
+		yyerror("failed to allocate isakmp sa");
+		return -1;
+	}
+	new->prop_no = prop_no;
+	new->trns_no = trns_no++;
+	new->lifetime = lifetime;
+	new->lifebyte = lifebyte;
+	new->enctype = types[algclass_isakmp_enc];
+	new->encklen = encklen;
+	new->authmethod = types[algclass_isakmp_ameth];
+	new->hashtype = types[algclass_isakmp_hash];
+	new->dh_group = types[algclass_isakmp_dh];
+	new->vendorid = vendorid;
+#ifdef HAVE_GSSAPI
+	if (new->authmethod == OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB) {
+		if (gssid != NULL) {
+			if ((new->gssid = vmalloc(strlen(gssid))) == NULL) {
+				racoon_free(new);
+				yyerror("failed to allocate gssid");
+				return -1;
+			}
+			memcpy(new->gssid->v, gssid, new->gssid->l);
+			racoon_free(gssid);
+#ifdef ENABLE_HYBRID
+		} else if (rmconf->xauth == NULL) {
+#else
+		} else {
+#endif
+			/*
+			 * Allocate the default ID so that it gets put
+			 * into a GSS ID attribute during the Phase 1
+			 * exchange.
+			 */
+			new->gssid = gssapi_get_default_gss_id();
+		}
+	}
+#endif
+	insisakmpsa(new, rmconf);
+
+	return trns_no;
+}
+
+static int
+listen_addr (struct sockaddr *addr, int udp_encap)
+{
+	struct myaddrs *p;
+
+	p = newmyaddr();
+	if (p == NULL) {
+		yyerror("failed to allocate myaddrs");
+		return -1;
+	}
+	p->addr = addr;
+	if (p->addr == NULL) {
+		yyerror("failed to copy sockaddr ");
+		delmyaddr(p);
+		return -1;
+	}
+	p->udp_encap = udp_encap;
+
+	insmyaddr(p, &lcconf->myaddrs);
+
+	lcconf->autograbaddr = 0;
+	return 0;
+}
+
+#if 0
+/*
+ * fix lifebyte.
+ * Must be more than 1024B because its unit is kilobytes.
+ * That is defined RFC2407.
+ */
+static int
+fix_lifebyte(t)
+	unsigned long t;
+{
+	if (t < 1024) {
+		yyerror("byte size should be more than 1024B.");
+		return 0;
+	}
+
+	return(t / 1024);
+}
+#endif
+
+int
+cfparse()
+{
+	int error;
+
+	yycf_init_buffer();
+
+	if (yycf_switch_buffer(lcconf->racoon_conf) != 0) {
+		plog(LLV_ERROR, LOCATION, NULL, 
+		    "could not read configuration file \"%s\"\n", 
+		    lcconf->racoon_conf);
+		return -1;
+	}
+
+	error = yyparse();
+	if (error != 0) {
+		if (yyerrorcount) {
+			plog(LLV_ERROR, LOCATION, NULL,
+				"fatal parse failure (%d errors)\n",
+				yyerrorcount);
+		} else {
+			plog(LLV_ERROR, LOCATION, NULL,
+				"fatal parse failure.\n");
+		}
+		return -1;
+	}
+
+	if (error == 0 && yyerrorcount) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"parse error is nothing, but yyerrorcount is %d.\n",
+				yyerrorcount);
+		exit(1);
+	}
+
+	yycf_clean_buffer();
+
+	plog(LLV_DEBUG2, LOCATION, NULL, "parse successed.\n");
+
+	return 0;
+}
+
+int
+cfreparse()
+{
+	flushph2();
+	flushph1();
+	flushrmconf();
+	flushsainfo();
+	clean_tmpalgtype();
+	return(cfparse());
+}
+
+#ifdef ENABLE_ADMINPORT
+static void
+adminsock_conf(path, owner, group, mode_dec)
+	vchar_t *path;
+	vchar_t *owner;
+	vchar_t *group;
+	int mode_dec;
+{
+	struct passwd *pw = NULL;
+	struct group *gr = NULL;
+	mode_t mode = 0;
+	uid_t uid;
+	gid_t gid;
+	int isnum;
+
+	adminsock_path = path->v;
+
+	if (owner == NULL)
+		return;
+
+	errno = 0;
+	uid = atoi(owner->v);
+	isnum = !errno;
+	if (((pw = getpwnam(owner->v)) == NULL) && !isnum)
+		yyerror("User \"%s\" does not exist", owner->v);
+
+	if (pw)
+		adminsock_owner = pw->pw_uid;
+	else
+		adminsock_owner = uid;
+
+	if (group == NULL)
+		return;
+
+	errno = 0;
+	gid = atoi(group->v);
+	isnum = !errno;
+	if (((gr = getgrnam(group->v)) == NULL) && !isnum)
+		yyerror("Group \"%s\" does not exist", group->v);
+
+	if (gr)
+		adminsock_group = gr->gr_gid;
+	else
+		adminsock_group = gid;
+
+	if (mode_dec == -1)
+		return;
+
+	if (mode_dec > 777)
+		yyerror("Mode 0%03o is invalid", mode_dec);
+	if (mode_dec >= 400) { mode += 0400; mode_dec -= 400; }
+	if (mode_dec >= 200) { mode += 0200; mode_dec -= 200; }
+	if (mode_dec >= 100) { mode += 0200; mode_dec -= 100; }
+
+	if (mode_dec > 77)
+		yyerror("Mode 0%03o is invalid", mode_dec);
+	if (mode_dec >= 40) { mode += 040; mode_dec -= 40; }
+	if (mode_dec >= 20) { mode += 020; mode_dec -= 20; }
+	if (mode_dec >= 10) { mode += 020; mode_dec -= 10; }
+
+	if (mode_dec > 7)
+		yyerror("Mode 0%03o is invalid", mode_dec);
+	if (mode_dec >= 4) { mode += 04; mode_dec -= 4; }
+	if (mode_dec >= 2) { mode += 02; mode_dec -= 2; }
+	if (mode_dec >= 1) { mode += 02; mode_dec -= 1; }
+	
+	adminsock_mode = mode;
+
+	return;
+}
+#endif
+
diff --git a/src/racoon/cfparse.h b/src/racoon/cfparse.h
new file mode 100644
index 0000000..2946b3e
--- /dev/null
+++ b/src/racoon/cfparse.h
@@ -0,0 +1,392 @@
+/* A Bison parser, made by GNU Bison 2.3.  */
+
+/* Skeleton interface for Bison's Yacc-like parsers in C
+
+   Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
+   Free Software Foundation, Inc.
+
+   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, or (at your option)
+   any later version.
+
+   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.
+
+   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., 51 Franklin Street, Fifth Floor,
+   Boston, MA 02110-1301, USA.  */
+
+/* As a special exception, you may create a larger work that contains
+   part or all of the Bison parser skeleton and distribute that work
+   under terms of your choice, so long as that work isn't itself a
+   parser generator using the skeleton or a modified version thereof
+   as a parser skeleton.  Alternatively, if you modify or redistribute
+   the parser skeleton itself, you may (at your option) remove this
+   special exception, which will cause the skeleton and the resulting
+   Bison output files to be licensed under the GNU General Public
+   License without this special exception.
+
+   This special exception was added by the Free Software Foundation in
+   version 2.2 of Bison.  */
+
+/* Tokens.  */
+#ifndef YYTOKENTYPE
+# define YYTOKENTYPE
+   /* Put the tokens into the symbol table, so that GDB and other debuggers
+      know about them.  */
+   enum yytokentype {
+     PRIVSEP = 258,
+     USER = 259,
+     GROUP = 260,
+     CHROOT = 261,
+     PATH = 262,
+     PATHTYPE = 263,
+     INCLUDE = 264,
+     IDENTIFIER = 265,
+     VENDORID = 266,
+     LOGGING = 267,
+     LOGLEV = 268,
+     PADDING = 269,
+     PAD_RANDOMIZE = 270,
+     PAD_RANDOMIZELEN = 271,
+     PAD_MAXLEN = 272,
+     PAD_STRICT = 273,
+     PAD_EXCLTAIL = 274,
+     LISTEN = 275,
+     X_ISAKMP = 276,
+     X_ISAKMP_NATT = 277,
+     X_ADMIN = 278,
+     STRICT_ADDRESS = 279,
+     ADMINSOCK = 280,
+     DISABLED = 281,
+     LDAPCFG = 282,
+     LDAP_HOST = 283,
+     LDAP_PORT = 284,
+     LDAP_PVER = 285,
+     LDAP_BASE = 286,
+     LDAP_BIND_DN = 287,
+     LDAP_BIND_PW = 288,
+     LDAP_SUBTREE = 289,
+     LDAP_ATTR_USER = 290,
+     LDAP_ATTR_ADDR = 291,
+     LDAP_ATTR_MASK = 292,
+     LDAP_ATTR_GROUP = 293,
+     LDAP_ATTR_MEMBER = 294,
+     MODECFG = 295,
+     CFG_NET4 = 296,
+     CFG_MASK4 = 297,
+     CFG_DNS4 = 298,
+     CFG_NBNS4 = 299,
+     CFG_DEFAULT_DOMAIN = 300,
+     CFG_AUTH_SOURCE = 301,
+     CFG_AUTH_GROUPS = 302,
+     CFG_SYSTEM = 303,
+     CFG_RADIUS = 304,
+     CFG_PAM = 305,
+     CFG_LDAP = 306,
+     CFG_LOCAL = 307,
+     CFG_NONE = 308,
+     CFG_GROUP_SOURCE = 309,
+     CFG_ACCOUNTING = 310,
+     CFG_CONF_SOURCE = 311,
+     CFG_MOTD = 312,
+     CFG_POOL_SIZE = 313,
+     CFG_AUTH_THROTTLE = 314,
+     CFG_SPLIT_NETWORK = 315,
+     CFG_SPLIT_LOCAL = 316,
+     CFG_SPLIT_INCLUDE = 317,
+     CFG_SPLIT_DNS = 318,
+     CFG_PFS_GROUP = 319,
+     CFG_SAVE_PASSWD = 320,
+     RETRY = 321,
+     RETRY_COUNTER = 322,
+     RETRY_INTERVAL = 323,
+     RETRY_PERSEND = 324,
+     RETRY_PHASE1 = 325,
+     RETRY_PHASE2 = 326,
+     NATT_KA = 327,
+     ALGORITHM_CLASS = 328,
+     ALGORITHMTYPE = 329,
+     STRENGTHTYPE = 330,
+     SAINFO = 331,
+     FROM = 332,
+     REMOTE = 333,
+     ANONYMOUS = 334,
+     INHERIT = 335,
+     EXCHANGE_MODE = 336,
+     EXCHANGETYPE = 337,
+     DOI = 338,
+     DOITYPE = 339,
+     SITUATION = 340,
+     SITUATIONTYPE = 341,
+     CERTIFICATE_TYPE = 342,
+     CERTTYPE = 343,
+     PEERS_CERTFILE = 344,
+     CA_TYPE = 345,
+     VERIFY_CERT = 346,
+     SEND_CERT = 347,
+     SEND_CR = 348,
+     IDENTIFIERTYPE = 349,
+     IDENTIFIERQUAL = 350,
+     MY_IDENTIFIER = 351,
+     PEERS_IDENTIFIER = 352,
+     VERIFY_IDENTIFIER = 353,
+     DNSSEC = 354,
+     CERT_X509 = 355,
+     CERT_PLAINRSA = 356,
+     NONCE_SIZE = 357,
+     DH_GROUP = 358,
+     KEEPALIVE = 359,
+     PASSIVE = 360,
+     INITIAL_CONTACT = 361,
+     NAT_TRAVERSAL = 362,
+     REMOTE_FORCE_LEVEL = 363,
+     PROPOSAL_CHECK = 364,
+     PROPOSAL_CHECK_LEVEL = 365,
+     GENERATE_POLICY = 366,
+     GENERATE_LEVEL = 367,
+     SUPPORT_PROXY = 368,
+     PROPOSAL = 369,
+     EXEC_PATH = 370,
+     EXEC_COMMAND = 371,
+     EXEC_SUCCESS = 372,
+     EXEC_FAILURE = 373,
+     GSS_ID = 374,
+     GSS_ID_ENC = 375,
+     GSS_ID_ENCTYPE = 376,
+     COMPLEX_BUNDLE = 377,
+     DPD = 378,
+     DPD_DELAY = 379,
+     DPD_RETRY = 380,
+     DPD_MAXFAIL = 381,
+     PH1ID = 382,
+     XAUTH_LOGIN = 383,
+     WEAK_PHASE1_CHECK = 384,
+     PREFIX = 385,
+     PORT = 386,
+     PORTANY = 387,
+     UL_PROTO = 388,
+     ANY = 389,
+     IKE_FRAG = 390,
+     ESP_FRAG = 391,
+     MODE_CFG = 392,
+     PFS_GROUP = 393,
+     LIFETIME = 394,
+     LIFETYPE_TIME = 395,
+     LIFETYPE_BYTE = 396,
+     STRENGTH = 397,
+     REMOTEID = 398,
+     SCRIPT = 399,
+     PHASE1_UP = 400,
+     PHASE1_DOWN = 401,
+     NUMBER = 402,
+     SWITCH = 403,
+     BOOLEAN = 404,
+     HEXSTRING = 405,
+     QUOTEDSTRING = 406,
+     ADDRSTRING = 407,
+     ADDRRANGE = 408,
+     UNITTYPE_BYTE = 409,
+     UNITTYPE_KBYTES = 410,
+     UNITTYPE_MBYTES = 411,
+     UNITTYPE_TBYTES = 412,
+     UNITTYPE_SEC = 413,
+     UNITTYPE_MIN = 414,
+     UNITTYPE_HOUR = 415,
+     EOS = 416,
+     BOC = 417,
+     EOC = 418,
+     COMMA = 419
+   };
+#endif
+/* Tokens.  */
+#define PRIVSEP 258
+#define USER 259
+#define GROUP 260
+#define CHROOT 261
+#define PATH 262
+#define PATHTYPE 263
+#define INCLUDE 264
+#define IDENTIFIER 265
+#define VENDORID 266
+#define LOGGING 267
+#define LOGLEV 268
+#define PADDING 269
+#define PAD_RANDOMIZE 270
+#define PAD_RANDOMIZELEN 271
+#define PAD_MAXLEN 272
+#define PAD_STRICT 273
+#define PAD_EXCLTAIL 274
+#define LISTEN 275
+#define X_ISAKMP 276
+#define X_ISAKMP_NATT 277
+#define X_ADMIN 278
+#define STRICT_ADDRESS 279
+#define ADMINSOCK 280
+#define DISABLED 281
+#define LDAPCFG 282
+#define LDAP_HOST 283
+#define LDAP_PORT 284
+#define LDAP_PVER 285
+#define LDAP_BASE 286
+#define LDAP_BIND_DN 287
+#define LDAP_BIND_PW 288
+#define LDAP_SUBTREE 289
+#define LDAP_ATTR_USER 290
+#define LDAP_ATTR_ADDR 291
+#define LDAP_ATTR_MASK 292
+#define LDAP_ATTR_GROUP 293
+#define LDAP_ATTR_MEMBER 294
+#define MODECFG 295
+#define CFG_NET4 296
+#define CFG_MASK4 297
+#define CFG_DNS4 298
+#define CFG_NBNS4 299
+#define CFG_DEFAULT_DOMAIN 300
+#define CFG_AUTH_SOURCE 301
+#define CFG_AUTH_GROUPS 302
+#define CFG_SYSTEM 303
+#define CFG_RADIUS 304
+#define CFG_PAM 305
+#define CFG_LDAP 306
+#define CFG_LOCAL 307
+#define CFG_NONE 308
+#define CFG_GROUP_SOURCE 309
+#define CFG_ACCOUNTING 310
+#define CFG_CONF_SOURCE 311
+#define CFG_MOTD 312
+#define CFG_POOL_SIZE 313
+#define CFG_AUTH_THROTTLE 314
+#define CFG_SPLIT_NETWORK 315
+#define CFG_SPLIT_LOCAL 316
+#define CFG_SPLIT_INCLUDE 317
+#define CFG_SPLIT_DNS 318
+#define CFG_PFS_GROUP 319
+#define CFG_SAVE_PASSWD 320
+#define RETRY 321
+#define RETRY_COUNTER 322
+#define RETRY_INTERVAL 323
+#define RETRY_PERSEND 324
+#define RETRY_PHASE1 325
+#define RETRY_PHASE2 326
+#define NATT_KA 327
+#define ALGORITHM_CLASS 328
+#define ALGORITHMTYPE 329
+#define STRENGTHTYPE 330
+#define SAINFO 331
+#define FROM 332
+#define REMOTE 333
+#define ANONYMOUS 334
+#define INHERIT 335
+#define EXCHANGE_MODE 336
+#define EXCHANGETYPE 337
+#define DOI 338
+#define DOITYPE 339
+#define SITUATION 340
+#define SITUATIONTYPE 341
+#define CERTIFICATE_TYPE 342
+#define CERTTYPE 343
+#define PEERS_CERTFILE 344
+#define CA_TYPE 345
+#define VERIFY_CERT 346
+#define SEND_CERT 347
+#define SEND_CR 348
+#define IDENTIFIERTYPE 349
+#define IDENTIFIERQUAL 350
+#define MY_IDENTIFIER 351
+#define PEERS_IDENTIFIER 352
+#define VERIFY_IDENTIFIER 353
+#define DNSSEC 354
+#define CERT_X509 355
+#define CERT_PLAINRSA 356
+#define NONCE_SIZE 357
+#define DH_GROUP 358
+#define KEEPALIVE 359
+#define PASSIVE 360
+#define INITIAL_CONTACT 361
+#define NAT_TRAVERSAL 362
+#define REMOTE_FORCE_LEVEL 363
+#define PROPOSAL_CHECK 364
+#define PROPOSAL_CHECK_LEVEL 365
+#define GENERATE_POLICY 366
+#define GENERATE_LEVEL 367
+#define SUPPORT_PROXY 368
+#define PROPOSAL 369
+#define EXEC_PATH 370
+#define EXEC_COMMAND 371
+#define EXEC_SUCCESS 372
+#define EXEC_FAILURE 373
+#define GSS_ID 374
+#define GSS_ID_ENC 375
+#define GSS_ID_ENCTYPE 376
+#define COMPLEX_BUNDLE 377
+#define DPD 378
+#define DPD_DELAY 379
+#define DPD_RETRY 380
+#define DPD_MAXFAIL 381
+#define PH1ID 382
+#define XAUTH_LOGIN 383
+#define WEAK_PHASE1_CHECK 384
+#define PREFIX 385
+#define PORT 386
+#define PORTANY 387
+#define UL_PROTO 388
+#define ANY 389
+#define IKE_FRAG 390
+#define ESP_FRAG 391
+#define MODE_CFG 392
+#define PFS_GROUP 393
+#define LIFETIME 394
+#define LIFETYPE_TIME 395
+#define LIFETYPE_BYTE 396
+#define STRENGTH 397
+#define REMOTEID 398
+#define SCRIPT 399
+#define PHASE1_UP 400
+#define PHASE1_DOWN 401
+#define NUMBER 402
+#define SWITCH 403
+#define BOOLEAN 404
+#define HEXSTRING 405
+#define QUOTEDSTRING 406
+#define ADDRSTRING 407
+#define ADDRRANGE 408
+#define UNITTYPE_BYTE 409
+#define UNITTYPE_KBYTES 410
+#define UNITTYPE_MBYTES 411
+#define UNITTYPE_TBYTES 412
+#define UNITTYPE_SEC 413
+#define UNITTYPE_MIN 414
+#define UNITTYPE_HOUR 415
+#define EOS 416
+#define BOC 417
+#define EOC 418
+#define COMMA 419
+
+
+
+
+#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
+typedef union YYSTYPE
+#line 174 "cfparse.y"
+{
+	unsigned long num;
+	vchar_t *val;
+	struct remoteconf *rmconf;
+	struct sockaddr *saddr;
+	struct sainfoalg *alg;
+}
+/* Line 1489 of yacc.c.  */
+#line 385 "cfparse.h"
+	YYSTYPE;
+# define yystype YYSTYPE /* obsolescent; will be withdrawn */
+# define YYSTYPE_IS_DECLARED 1
+# define YYSTYPE_IS_TRIVIAL 1
+#endif
+
+extern YYSTYPE yylval;
+
diff --git a/src/racoon/cfparse.y b/src/racoon/cfparse.y
new file mode 100644
index 0000000..540c400
--- /dev/null
+++ b/src/racoon/cfparse.y
@@ -0,0 +1,2599 @@
+/*	$NetBSD: cfparse.y,v 1.18.4.7 2008/07/21 20:45:32 tteras Exp $	*/
+
+/* Id: cfparse.y,v 1.66 2006/08/22 18:17:17 manubsd Exp */
+
+%{
+/*
+ * Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002 and 2003 WIDE Project.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/queue.h>
+#include <sys/socket.h>
+
+#include <netinet/in.h>
+#include PATH_IPSEC_H
+
+#ifdef ENABLE_HYBRID
+#include <arpa/inet.h>
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <netdb.h>
+#include <pwd.h>
+#include <grp.h>
+
+#include "var.h"
+#include "misc.h"
+#include "vmbuf.h"
+#include "plog.h"
+#include "sockmisc.h"
+#include "str2val.h"
+#include "genlist.h"
+#include "debug.h"
+
+#include "admin.h"
+#include "privsep.h"
+#include "cfparse_proto.h"
+#include "cftoken_proto.h"
+#include "algorithm.h"
+#include "localconf.h"
+#include "policy.h"
+#include "sainfo.h"
+#include "oakley.h"
+#include "pfkey.h"
+#include "remoteconf.h"
+#include "grabmyaddr.h"
+#include "isakmp_var.h"
+#include "handler.h"
+#include "isakmp.h"
+#include "nattraversal.h"
+#include "isakmp_frag.h"
+#ifdef ENABLE_HYBRID
+#include "resolv.h"
+#include "isakmp_unity.h"
+#include "isakmp_xauth.h"
+#include "isakmp_cfg.h"
+#endif
+#include "ipsec_doi.h"
+#include "strnames.h"
+#include "gcmalloc.h"
+#ifdef HAVE_GSSAPI
+#include "gssapi.h"
+#endif
+#include "vendorid.h"
+#include "rsalist.h"
+
+struct proposalspec {
+	time_t lifetime;		/* for isakmp/ipsec */
+	int lifebyte;			/* for isakmp/ipsec */
+	struct secprotospec *spspec;	/* the head is always current spec. */
+	struct proposalspec *next;	/* the tail is the most prefered. */
+	struct proposalspec *prev;
+};
+
+struct secprotospec {
+	int prop_no;
+	int trns_no;
+	int strength;		/* for isakmp/ipsec */
+	int encklen;		/* for isakmp/ipsec */
+	time_t lifetime;	/* for isakmp */
+	int lifebyte;		/* for isakmp */
+	int proto_id;		/* for ipsec (isakmp?) */
+	int ipsec_level;	/* for ipsec */
+	int encmode;		/* for ipsec */
+	int vendorid;		/* for isakmp */
+	char *gssid;
+	struct sockaddr *remote;
+	int algclass[MAXALGCLASS];
+
+	struct secprotospec *next;	/* the tail is the most prefiered. */
+	struct secprotospec *prev;
+	struct proposalspec *back;
+};
+
+static int num2dhgroup[] = {
+	0,
+	OAKLEY_ATTR_GRP_DESC_MODP768,
+	OAKLEY_ATTR_GRP_DESC_MODP1024,
+	OAKLEY_ATTR_GRP_DESC_EC2N155,
+	OAKLEY_ATTR_GRP_DESC_EC2N185,
+	OAKLEY_ATTR_GRP_DESC_MODP1536,
+	0,
+	0,
+	0,
+	0,
+	0,
+	0,
+	0,
+	0,
+	OAKLEY_ATTR_GRP_DESC_MODP2048,
+	OAKLEY_ATTR_GRP_DESC_MODP3072,
+	OAKLEY_ATTR_GRP_DESC_MODP4096,
+	OAKLEY_ATTR_GRP_DESC_MODP6144,
+	OAKLEY_ATTR_GRP_DESC_MODP8192
+};
+
+static struct remoteconf *cur_rmconf;
+static int tmpalgtype[MAXALGCLASS];
+static struct sainfo *cur_sainfo;
+static int cur_algclass;
+static int oldloglevel = LLV_BASE;
+
+static struct proposalspec *newprspec __P((void));
+static void insprspec __P((struct proposalspec *, struct proposalspec **));
+static struct secprotospec *newspspec __P((void));
+static void insspspec __P((struct secprotospec *, struct proposalspec **));
+static void adminsock_conf __P((vchar_t *, vchar_t *, vchar_t *, int));
+
+static int set_isakmp_proposal
+	__P((struct remoteconf *, struct proposalspec *));
+static void clean_tmpalgtype __P((void));
+static int expand_isakmpspec __P((int, int, int *,
+	int, int, time_t, int, int, int, char *, struct remoteconf *));
+static int listen_addr __P((struct sockaddr *addr, int udp_encap));
+
+void freeetypes (struct etypes **etypes);
+
+#if 0
+static int fix_lifebyte __P((u_long));
+#endif
+%}
+
+%union {
+	unsigned long num;
+	vchar_t *val;
+	struct remoteconf *rmconf;
+	struct sockaddr *saddr;
+	struct sainfoalg *alg;
+}
+
+	/* privsep */
+%token PRIVSEP USER GROUP CHROOT
+	/* path */
+%token PATH PATHTYPE
+	/* include */
+%token INCLUDE
+	/* self information */
+%token IDENTIFIER VENDORID
+	/* logging */
+%token LOGGING LOGLEV
+	/* padding */
+%token PADDING PAD_RANDOMIZE PAD_RANDOMIZELEN PAD_MAXLEN PAD_STRICT PAD_EXCLTAIL
+	/* listen */
+%token LISTEN X_ISAKMP X_ISAKMP_NATT X_ADMIN STRICT_ADDRESS ADMINSOCK DISABLED
+	/* ldap config */
+%token LDAPCFG LDAP_HOST LDAP_PORT LDAP_PVER LDAP_BASE LDAP_BIND_DN LDAP_BIND_PW LDAP_SUBTREE
+%token LDAP_ATTR_USER LDAP_ATTR_ADDR LDAP_ATTR_MASK LDAP_ATTR_GROUP LDAP_ATTR_MEMBER
+	/* modecfg */
+%token MODECFG CFG_NET4 CFG_MASK4 CFG_DNS4 CFG_NBNS4 CFG_DEFAULT_DOMAIN
+%token CFG_AUTH_SOURCE CFG_AUTH_GROUPS CFG_SYSTEM CFG_RADIUS CFG_PAM CFG_LDAP CFG_LOCAL CFG_NONE
+%token CFG_GROUP_SOURCE CFG_ACCOUNTING CFG_CONF_SOURCE CFG_MOTD CFG_POOL_SIZE CFG_AUTH_THROTTLE
+%token CFG_SPLIT_NETWORK CFG_SPLIT_LOCAL CFG_SPLIT_INCLUDE CFG_SPLIT_DNS
+%token CFG_PFS_GROUP CFG_SAVE_PASSWD
+
+	/* timer */
+%token RETRY RETRY_COUNTER RETRY_INTERVAL RETRY_PERSEND
+%token RETRY_PHASE1 RETRY_PHASE2 NATT_KA
+	/* algorithm */
+%token ALGORITHM_CLASS ALGORITHMTYPE STRENGTHTYPE
+	/* sainfo */
+%token SAINFO FROM
+	/* remote */
+%token REMOTE ANONYMOUS INHERIT
+%token EXCHANGE_MODE EXCHANGETYPE DOI DOITYPE SITUATION SITUATIONTYPE
+%token CERTIFICATE_TYPE CERTTYPE PEERS_CERTFILE CA_TYPE
+%token VERIFY_CERT SEND_CERT SEND_CR
+%token IDENTIFIERTYPE IDENTIFIERQUAL MY_IDENTIFIER 
+%token PEERS_IDENTIFIER VERIFY_IDENTIFIER
+%token DNSSEC CERT_X509 CERT_PLAINRSA
+%token NONCE_SIZE DH_GROUP KEEPALIVE PASSIVE INITIAL_CONTACT
+%token NAT_TRAVERSAL REMOTE_FORCE_LEVEL
+%token PROPOSAL_CHECK PROPOSAL_CHECK_LEVEL
+%token GENERATE_POLICY GENERATE_LEVEL SUPPORT_PROXY
+%token PROPOSAL
+%token EXEC_PATH EXEC_COMMAND EXEC_SUCCESS EXEC_FAILURE
+%token GSS_ID GSS_ID_ENC GSS_ID_ENCTYPE
+%token COMPLEX_BUNDLE
+%token DPD DPD_DELAY DPD_RETRY DPD_MAXFAIL
+%token PH1ID
+%token XAUTH_LOGIN WEAK_PHASE1_CHECK
+
+%token PREFIX PORT PORTANY UL_PROTO ANY IKE_FRAG ESP_FRAG MODE_CFG
+%token PFS_GROUP LIFETIME LIFETYPE_TIME LIFETYPE_BYTE STRENGTH REMOTEID
+
+%token SCRIPT PHASE1_UP PHASE1_DOWN
+
+%token NUMBER SWITCH BOOLEAN
+%token HEXSTRING QUOTEDSTRING ADDRSTRING ADDRRANGE
+%token UNITTYPE_BYTE UNITTYPE_KBYTES UNITTYPE_MBYTES UNITTYPE_TBYTES
+%token UNITTYPE_SEC UNITTYPE_MIN UNITTYPE_HOUR
+%token EOS BOC EOC COMMA
+
+%type <num> NUMBER BOOLEAN SWITCH keylength
+%type <num> PATHTYPE IDENTIFIERTYPE IDENTIFIERQUAL LOGLEV GSS_ID_ENCTYPE 
+%type <num> ALGORITHM_CLASS dh_group_num
+%type <num> ALGORITHMTYPE STRENGTHTYPE
+%type <num> PREFIX prefix PORT port ike_port
+%type <num> ul_proto UL_PROTO
+%type <num> EXCHANGETYPE DOITYPE SITUATIONTYPE
+%type <num> CERTTYPE CERT_X509 CERT_PLAINRSA PROPOSAL_CHECK_LEVEL REMOTE_FORCE_LEVEL GENERATE_LEVEL
+%type <num> unittype_time unittype_byte
+%type <val> QUOTEDSTRING HEXSTRING ADDRSTRING ADDRRANGE sainfo_id
+%type <val> identifierstring
+%type <saddr> remote_index ike_addrinfo_port
+%type <alg> algorithm
+
+%%
+
+statements
+	:	/* nothing */
+	|	statements statement
+	;
+statement
+	:	privsep_statement
+	|	path_statement
+	|	include_statement
+	|	gssenc_statement
+	|	identifier_statement
+	|	logging_statement
+	|	padding_statement
+	|	listen_statement
+	|	ldapcfg_statement
+	|	modecfg_statement
+	|	timer_statement
+	|	sainfo_statement
+	|	remote_statement
+	|	special_statement
+	;
+
+	/* privsep */
+privsep_statement
+	:	PRIVSEP BOC privsep_stmts EOC
+	;
+privsep_stmts
+	:	/* nothing */
+	|	privsep_stmts privsep_stmt
+	;
+privsep_stmt
+	:	USER QUOTEDSTRING
+		{
+			struct passwd *pw;
+
+			if ((pw = getpwnam($2->v)) == NULL) {
+				yyerror("unknown user \"%s\"", $2->v);
+				return -1;
+			}
+			lcconf->uid = pw->pw_uid;
+		} 
+		EOS
+	|	USER NUMBER { lcconf->uid = $2; } EOS
+	|	GROUP QUOTEDSTRING
+		{
+			struct group *gr;
+
+			if ((gr = getgrnam($2->v)) == NULL) {
+				yyerror("unknown group \"%s\"", $2->v);
+				return -1;
+			}
+			lcconf->gid = gr->gr_gid;
+		}
+		EOS
+	|	GROUP NUMBER { lcconf->gid = $2; } EOS
+	|	CHROOT QUOTEDSTRING { lcconf->chroot = $2->v; } EOS
+	;
+
+	/* path */
+path_statement
+	:	PATH PATHTYPE QUOTEDSTRING
+		{
+			if ($2 >= LC_PATHTYPE_MAX) {
+				yyerror("invalid path type %d", $2);
+				return -1;
+			}
+
+			/* free old pathinfo */
+			if (lcconf->pathinfo[$2])
+				racoon_free(lcconf->pathinfo[$2]);
+
+			/* set new pathinfo */
+			lcconf->pathinfo[$2] = racoon_strdup($3->v);
+			STRDUP_FATAL(lcconf->pathinfo[$2]);
+			vfree($3);
+		}
+		EOS
+	;
+
+	/* special */
+special_statement
+	:	COMPLEX_BUNDLE SWITCH { lcconf->complex_bundle = $2; } EOS
+	;
+
+	/* include */
+include_statement
+	:	INCLUDE QUOTEDSTRING EOS
+		{
+			char path[MAXPATHLEN];
+
+			getpathname(path, sizeof(path),
+				LC_PATHTYPE_INCLUDE, $2->v);
+			vfree($2);
+			if (yycf_switch_buffer(path) != 0)
+				return -1;
+		}
+	;
+
+	/* gss_id_enc */
+gssenc_statement
+	:	GSS_ID_ENC GSS_ID_ENCTYPE EOS
+		{
+			if ($2 >= LC_GSSENC_MAX) {
+				yyerror("invalid GSS ID encoding %d", $2);
+				return -1;
+			}
+			lcconf->gss_id_enc = $2;
+		}
+	;
+
+	/* self information */
+identifier_statement
+	:	IDENTIFIER identifier_stmt
+	;
+identifier_stmt
+	:	VENDORID
+		{
+			/*XXX to be deleted */
+		}
+		QUOTEDSTRING EOS
+	|	IDENTIFIERTYPE QUOTEDSTRING
+		{
+			/*XXX to be deleted */
+			$2->l--;	/* nuke '\0' */
+			lcconf->ident[$1] = $2;
+			if (lcconf->ident[$1] == NULL) {
+				yyerror("failed to set my ident: %s",
+					strerror(errno));
+				return -1;
+			}
+		}
+		EOS
+	;
+
+	/* logging */
+logging_statement
+	:	LOGGING log_level EOS
+	;
+log_level
+	:	HEXSTRING
+		{
+			/*
+			 * XXX ignore it because this specification
+			 * will be obsoleted.
+			 */
+			yywarn("see racoon.conf(5), such a log specification will be obsoleted.");
+			vfree($1);
+		}
+	|	LOGLEV
+		{
+			/*
+			 * set the loglevel to the value specified
+			 * in the configuration file plus the number
+			 * of -d options specified on the command line
+			 */
+			loglevel += $1 - oldloglevel;
+			oldloglevel = $1;
+		}
+	;
+
+	/* padding */
+padding_statement
+	:	PADDING BOC padding_stmts EOC
+	;
+padding_stmts
+	:	/* nothing */
+	|	padding_stmts padding_stmt
+	;
+padding_stmt
+	:	PAD_RANDOMIZE SWITCH { lcconf->pad_random = $2; } EOS
+	|	PAD_RANDOMIZELEN SWITCH { lcconf->pad_randomlen = $2; } EOS
+	|	PAD_MAXLEN NUMBER { lcconf->pad_maxsize = $2; } EOS
+	|	PAD_STRICT SWITCH { lcconf->pad_strict = $2; } EOS
+	|	PAD_EXCLTAIL SWITCH { lcconf->pad_excltail = $2; } EOS
+	;
+
+	/* listen */
+listen_statement
+	:	LISTEN BOC listen_stmts EOC
+	;
+listen_stmts
+	:	/* nothing */
+	|	listen_stmts listen_stmt
+	;
+listen_stmt
+	:	X_ISAKMP ike_addrinfo_port
+		{
+			listen_addr ($2, 0);
+		}
+		EOS
+	|	X_ISAKMP_NATT ike_addrinfo_port
+		{
+#ifdef ENABLE_NATT
+			listen_addr ($2, 1);
+#else
+			yyerror("NAT-T support not compiled in.");
+#endif
+		}
+		EOS
+	|	X_ADMIN
+		{
+			yyerror("admin directive is obsoleted.");
+		}
+		PORT EOS
+	|	ADMINSOCK QUOTEDSTRING QUOTEDSTRING QUOTEDSTRING NUMBER 
+		{
+#ifdef ENABLE_ADMINPORT
+			adminsock_conf($2, $3, $4, $5);
+#else
+			yywarn("admin port support not compiled in");
+#endif
+		}
+		EOS
+	|	ADMINSOCK QUOTEDSTRING
+		{
+#ifdef ENABLE_ADMINPORT
+			adminsock_conf($2, NULL, NULL, -1);
+#else
+			yywarn("admin port support not compiled in");
+#endif
+		}
+		EOS
+	|	ADMINSOCK DISABLED
+		{
+#ifdef ENABLE_ADMINPORT
+			adminsock_path = NULL;
+#else
+			yywarn("admin port support not compiled in");
+#endif
+		}
+		EOS
+	|	STRICT_ADDRESS { lcconf->strict_address = TRUE; } EOS
+	;
+ike_addrinfo_port
+	:	ADDRSTRING ike_port
+		{
+			char portbuf[10];
+
+			snprintf(portbuf, sizeof(portbuf), "%ld", $2);
+			$$ = str2saddr($1->v, portbuf);
+			vfree($1);
+			if (!$$)
+				return -1;
+		}
+	;
+ike_port
+	:	/* nothing */	{ $$ = PORT_ISAKMP; }
+	|	PORT		{ $$ = $1; }
+	;
+
+	/* ldap configuration */
+ldapcfg_statement
+	:	LDAPCFG {
+#ifndef ENABLE_HYBRID
+			yyerror("racoon not configured with --enable-hybrid");
+			return -1;
+#endif
+#ifndef HAVE_LIBLDAP
+			yyerror("racoon not configured with --with-libldap");
+			return -1;
+#endif
+		} BOC ldapcfg_stmts EOC
+	;
+ldapcfg_stmts
+	:	/* nothing */
+	|	ldapcfg_stmts ldapcfg_stmt
+	;
+ldapcfg_stmt
+	:	LDAP_PVER NUMBER
+		{
+#ifdef ENABLE_HYBRID
+#ifdef HAVE_LIBLDAP
+			if (($2<2)||($2>3))
+				yyerror("invalid ldap protocol version (2|3)");
+			xauth_ldap_config.pver = $2;
+#endif
+#endif
+		}
+		EOS
+	|	LDAP_HOST QUOTEDSTRING
+		{
+#ifdef ENABLE_HYBRID
+#ifdef HAVE_LIBLDAP
+			if (xauth_ldap_config.host != NULL)
+				vfree(xauth_ldap_config.host);
+			xauth_ldap_config.host = vdup($2);
+#endif
+#endif
+		}
+		EOS
+	|	LDAP_PORT NUMBER
+		{
+#ifdef ENABLE_HYBRID
+#ifdef HAVE_LIBLDAP
+			xauth_ldap_config.port = $2;
+#endif
+#endif
+		}
+		EOS
+	|	LDAP_BASE QUOTEDSTRING
+		{
+#ifdef ENABLE_HYBRID
+#ifdef HAVE_LIBLDAP
+			if (xauth_ldap_config.base != NULL)
+				vfree(xauth_ldap_config.base);
+			xauth_ldap_config.base = vdup($2);
+#endif
+#endif
+		}
+		EOS
+	|	LDAP_SUBTREE SWITCH
+		{
+#ifdef ENABLE_HYBRID
+#ifdef HAVE_LIBLDAP
+			xauth_ldap_config.subtree = $2;
+#endif
+#endif
+		}
+		EOS
+	|	LDAP_BIND_DN QUOTEDSTRING
+		{
+#ifdef ENABLE_HYBRID
+#ifdef HAVE_LIBLDAP
+			if (xauth_ldap_config.bind_dn != NULL)
+				vfree(xauth_ldap_config.bind_dn);
+			xauth_ldap_config.bind_dn = vdup($2);
+#endif
+#endif
+		}
+		EOS
+	|	LDAP_BIND_PW QUOTEDSTRING
+		{
+#ifdef ENABLE_HYBRID
+#ifdef HAVE_LIBLDAP
+			if (xauth_ldap_config.bind_pw != NULL)
+				vfree(xauth_ldap_config.bind_pw);
+			xauth_ldap_config.bind_pw = vdup($2);
+#endif
+#endif
+		}
+		EOS
+	|	LDAP_ATTR_USER QUOTEDSTRING
+		{
+#ifdef ENABLE_HYBRID
+#ifdef HAVE_LIBLDAP
+			if (xauth_ldap_config.attr_user != NULL)
+				vfree(xauth_ldap_config.attr_user);
+			xauth_ldap_config.attr_user = vdup($2);
+#endif
+#endif
+		}
+		EOS
+	|	LDAP_ATTR_ADDR QUOTEDSTRING
+		{
+#ifdef ENABLE_HYBRID
+#ifdef HAVE_LIBLDAP
+			if (xauth_ldap_config.attr_addr != NULL)
+				vfree(xauth_ldap_config.attr_addr);
+			xauth_ldap_config.attr_addr = vdup($2);
+#endif
+#endif
+		}
+		EOS
+	|	LDAP_ATTR_MASK QUOTEDSTRING
+		{
+#ifdef ENABLE_HYBRID
+#ifdef HAVE_LIBLDAP
+			if (xauth_ldap_config.attr_mask != NULL)
+				vfree(xauth_ldap_config.attr_mask);
+			xauth_ldap_config.attr_mask = vdup($2);
+#endif
+#endif
+		}
+		EOS
+	|	LDAP_ATTR_GROUP QUOTEDSTRING
+		{
+#ifdef ENABLE_HYBRID
+#ifdef HAVE_LIBLDAP
+			if (xauth_ldap_config.attr_group != NULL)
+				vfree(xauth_ldap_config.attr_group);
+			xauth_ldap_config.attr_group = vdup($2);
+#endif
+#endif
+		}
+		EOS
+	|	LDAP_ATTR_MEMBER QUOTEDSTRING
+		{
+#ifdef ENABLE_HYBRID
+#ifdef HAVE_LIBLDAP
+			if (xauth_ldap_config.attr_member != NULL)
+				vfree(xauth_ldap_config.attr_member);
+			xauth_ldap_config.attr_member = vdup($2);
+#endif
+#endif
+		}
+		EOS
+	;
+
+	/* modecfg */
+modecfg_statement
+	:	MODECFG BOC modecfg_stmts EOC
+	;
+modecfg_stmts
+	:	/* nothing */
+	|	modecfg_stmts modecfg_stmt
+	;
+modecfg_stmt
+	:	CFG_NET4 ADDRSTRING
+		{
+#ifdef ENABLE_HYBRID
+			if (inet_pton(AF_INET, $2->v,
+			     &isakmp_cfg_config.network4) != 1)
+				yyerror("bad IPv4 network address.");
+#else
+			yyerror("racoon not configured with --enable-hybrid");
+#endif
+		}
+		EOS
+	|	CFG_MASK4 ADDRSTRING
+		{
+#ifdef ENABLE_HYBRID
+			if (inet_pton(AF_INET, $2->v,
+			    &isakmp_cfg_config.netmask4) != 1)
+				yyerror("bad IPv4 netmask address.");
+#else
+			yyerror("racoon not configured with --enable-hybrid");
+#endif
+		}
+		EOS
+	|	CFG_DNS4 addrdnslist
+		EOS
+	|	CFG_NBNS4 addrwinslist
+		EOS
+	|	CFG_SPLIT_NETWORK CFG_SPLIT_LOCAL splitnetlist
+		{
+#ifdef ENABLE_HYBRID
+			isakmp_cfg_config.splitnet_type = UNITY_LOCAL_LAN;
+#else
+			yyerror("racoon not configured with --enable-hybrid");
+#endif
+		}
+		EOS
+	|	CFG_SPLIT_NETWORK CFG_SPLIT_INCLUDE splitnetlist
+		{
+#ifdef ENABLE_HYBRID
+			isakmp_cfg_config.splitnet_type = UNITY_SPLIT_INCLUDE;
+#else
+			yyerror("racoon not configured with --enable-hybrid");
+#endif
+		}
+		EOS
+	|	CFG_SPLIT_DNS splitdnslist
+		{
+#ifndef ENABLE_HYBRID
+			yyerror("racoon not configured with --enable-hybrid");
+#endif
+		}
+		EOS
+	|	CFG_DEFAULT_DOMAIN QUOTEDSTRING
+		{
+#ifdef ENABLE_HYBRID
+			strncpy(&isakmp_cfg_config.default_domain[0], 
+			    $2->v, MAXPATHLEN);
+			isakmp_cfg_config.default_domain[MAXPATHLEN] = '\0';
+			vfree($2);
+#else
+			yyerror("racoon not configured with --enable-hybrid");
+#endif
+		}
+		EOS
+	|	CFG_AUTH_SOURCE CFG_SYSTEM
+		{
+#ifdef ENABLE_HYBRID
+			isakmp_cfg_config.authsource = ISAKMP_CFG_AUTH_SYSTEM;
+#else
+			yyerror("racoon not configured with --enable-hybrid");
+#endif
+		}
+		EOS
+	|	CFG_AUTH_SOURCE CFG_RADIUS
+		{
+#ifdef ENABLE_HYBRID
+#ifdef HAVE_LIBRADIUS
+			isakmp_cfg_config.authsource = ISAKMP_CFG_AUTH_RADIUS;
+#else /* HAVE_LIBRADIUS */
+			yyerror("racoon not configured with --with-libradius");
+#endif /* HAVE_LIBRADIUS */
+#else /* ENABLE_HYBRID */
+			yyerror("racoon not configured with --enable-hybrid");
+#endif /* ENABLE_HYBRID */
+		}
+		EOS
+	|	CFG_AUTH_SOURCE CFG_PAM
+		{
+#ifdef ENABLE_HYBRID
+#ifdef HAVE_LIBPAM
+			isakmp_cfg_config.authsource = ISAKMP_CFG_AUTH_PAM;
+#else /* HAVE_LIBPAM */
+			yyerror("racoon not configured with --with-libpam");
+#endif /* HAVE_LIBPAM */
+#else /* ENABLE_HYBRID */
+			yyerror("racoon not configured with --enable-hybrid");
+#endif /* ENABLE_HYBRID */
+		}
+		EOS
+	|	CFG_AUTH_SOURCE CFG_LDAP
+		{
+#ifdef ENABLE_HYBRID
+#ifdef HAVE_LIBLDAP
+			isakmp_cfg_config.authsource = ISAKMP_CFG_AUTH_LDAP;
+#else /* HAVE_LIBLDAP */
+			yyerror("racoon not configured with --with-libldap");
+#endif /* HAVE_LIBLDAP */
+#else /* ENABLE_HYBRID */
+			yyerror("racoon not configured with --enable-hybrid");
+#endif /* ENABLE_HYBRID */
+		}
+		EOS
+	|	CFG_AUTH_GROUPS authgrouplist
+		{
+#ifndef ENABLE_HYBRID
+			yyerror("racoon not configured with --enable-hybrid");
+#endif
+		}
+		EOS
+	|	CFG_GROUP_SOURCE CFG_SYSTEM
+		{
+#ifdef ENABLE_HYBRID
+			isakmp_cfg_config.groupsource = ISAKMP_CFG_GROUP_SYSTEM;
+#else
+			yyerror("racoon not configured with --enable-hybrid");
+#endif
+		}
+		EOS
+	|	CFG_GROUP_SOURCE CFG_LDAP
+		{
+#ifdef ENABLE_HYBRID
+#ifdef HAVE_LIBLDAP
+			isakmp_cfg_config.groupsource = ISAKMP_CFG_GROUP_LDAP;
+#else /* HAVE_LIBLDAP */
+			yyerror("racoon not configured with --with-libldap");
+#endif /* HAVE_LIBLDAP */
+#else /* ENABLE_HYBRID */
+			yyerror("racoon not configured with --enable-hybrid");
+#endif /* ENABLE_HYBRID */
+		}
+		EOS
+	|	CFG_ACCOUNTING CFG_NONE
+		{
+#ifdef ENABLE_HYBRID
+			isakmp_cfg_config.accounting = ISAKMP_CFG_ACCT_NONE;
+#else
+			yyerror("racoon not configured with --enable-hybrid");
+#endif
+		}
+		EOS
+	|	CFG_ACCOUNTING CFG_SYSTEM
+		{
+#ifdef ENABLE_HYBRID
+			isakmp_cfg_config.accounting = ISAKMP_CFG_ACCT_SYSTEM;
+#else
+			yyerror("racoon not configured with --enable-hybrid");
+#endif
+		}
+		EOS
+	|	CFG_ACCOUNTING CFG_RADIUS
+		{
+#ifdef ENABLE_HYBRID
+#ifdef HAVE_LIBRADIUS
+			isakmp_cfg_config.accounting = ISAKMP_CFG_ACCT_RADIUS;
+#else /* HAVE_LIBRADIUS */
+			yyerror("racoon not configured with --with-libradius");
+#endif /* HAVE_LIBRADIUS */
+#else /* ENABLE_HYBRID */
+			yyerror("racoon not configured with --enable-hybrid");
+#endif /* ENABLE_HYBRID */
+		}
+		EOS
+	|	CFG_ACCOUNTING CFG_PAM
+		{
+#ifdef ENABLE_HYBRID
+#ifdef HAVE_LIBPAM
+			isakmp_cfg_config.accounting = ISAKMP_CFG_ACCT_PAM;
+#else /* HAVE_LIBPAM */
+			yyerror("racoon not configured with --with-libpam");
+#endif /* HAVE_LIBPAM */
+#else /* ENABLE_HYBRID */
+			yyerror("racoon not configured with --enable-hybrid");
+#endif /* ENABLE_HYBRID */
+		}
+		EOS
+	|	CFG_POOL_SIZE NUMBER
+		{
+#ifdef ENABLE_HYBRID
+			if (isakmp_cfg_resize_pool($2) != 0)
+				yyerror("cannot allocate memory for pool");
+#else /* ENABLE_HYBRID */
+			yyerror("racoon not configured with --enable-hybrid");
+#endif /* ENABLE_HYBRID */
+		}
+		EOS
+	|	CFG_PFS_GROUP NUMBER
+		{
+#ifdef ENABLE_HYBRID
+			isakmp_cfg_config.pfs_group = $2;
+#else /* ENABLE_HYBRID */
+			yyerror("racoon not configured with --enable-hybrid");
+#endif /* ENABLE_HYBRID */
+		}
+		EOS
+	|	CFG_SAVE_PASSWD SWITCH
+		{
+#ifdef ENABLE_HYBRID
+			isakmp_cfg_config.save_passwd = $2;
+#else /* ENABLE_HYBRID */
+			yyerror("racoon not configured with --enable-hybrid");
+#endif /* ENABLE_HYBRID */
+		}
+		EOS
+	|	CFG_AUTH_THROTTLE NUMBER
+		{
+#ifdef ENABLE_HYBRID
+			isakmp_cfg_config.auth_throttle = $2;
+#else /* ENABLE_HYBRID */
+			yyerror("racoon not configured with --enable-hybrid");
+#endif /* ENABLE_HYBRID */
+		}
+		EOS
+	|	CFG_CONF_SOURCE CFG_LOCAL
+		{
+#ifdef ENABLE_HYBRID
+			isakmp_cfg_config.confsource = ISAKMP_CFG_CONF_LOCAL;
+#else /* ENABLE_HYBRID */
+			yyerror("racoon not configured with --enable-hybrid");
+#endif /* ENABLE_HYBRID */
+		}
+		EOS
+	|	CFG_CONF_SOURCE CFG_RADIUS
+		{
+#ifdef ENABLE_HYBRID
+#ifdef HAVE_LIBRADIUS
+			isakmp_cfg_config.confsource = ISAKMP_CFG_CONF_RADIUS;
+#else /* HAVE_LIBRADIUS */
+			yyerror("racoon not configured with --with-libradius");
+#endif /* HAVE_LIBRADIUS */
+#else /* ENABLE_HYBRID */
+			yyerror("racoon not configured with --enable-hybrid");
+#endif /* ENABLE_HYBRID */
+		}
+		EOS
+	|	CFG_CONF_SOURCE CFG_LDAP
+		{
+#ifdef ENABLE_HYBRID
+#ifdef HAVE_LIBLDAP
+			isakmp_cfg_config.confsource = ISAKMP_CFG_CONF_LDAP;
+#else /* HAVE_LIBLDAP */
+			yyerror("racoon not configured with --with-libldap");
+#endif /* HAVE_LIBLDAP */
+#else /* ENABLE_HYBRID */
+			yyerror("racoon not configured with --enable-hybrid");
+#endif /* ENABLE_HYBRID */
+		}
+		EOS
+	|	CFG_MOTD QUOTEDSTRING
+		{
+#ifdef ENABLE_HYBRID
+			strncpy(&isakmp_cfg_config.motd[0], $2->v, MAXPATHLEN);
+			isakmp_cfg_config.motd[MAXPATHLEN] = '\0';
+			vfree($2);
+#else
+			yyerror("racoon not configured with --enable-hybrid");
+#endif
+		}
+		EOS
+	;
+
+addrdnslist
+	:	addrdns
+	|	addrdns COMMA addrdnslist
+	;
+addrdns
+	:	ADDRSTRING
+		{
+#ifdef ENABLE_HYBRID
+			struct isakmp_cfg_config *icc = &isakmp_cfg_config;
+
+			if (icc->dns4_index > MAXNS)
+				yyerror("No more than %d DNS", MAXNS);
+			if (inet_pton(AF_INET, $1->v,
+			    &icc->dns4[icc->dns4_index++]) != 1)
+				yyerror("bad IPv4 DNS address.");
+#else
+			yyerror("racoon not configured with --enable-hybrid");
+#endif
+		}
+	;
+
+addrwinslist
+	:	addrwins
+	|	addrwins COMMA addrwinslist
+	;
+addrwins
+	:	ADDRSTRING
+		{
+#ifdef ENABLE_HYBRID
+			struct isakmp_cfg_config *icc = &isakmp_cfg_config;
+
+			if (icc->nbns4_index > MAXWINS)
+				yyerror("No more than %d WINS", MAXWINS);
+			if (inet_pton(AF_INET, $1->v,
+			    &icc->nbns4[icc->nbns4_index++]) != 1)
+				yyerror("bad IPv4 WINS address.");
+#else
+			yyerror("racoon not configured with --enable-hybrid");
+#endif
+		}
+	;
+
+splitnetlist
+	:	splitnet
+	|	splitnetlist COMMA splitnet
+	;
+splitnet
+	:	ADDRSTRING PREFIX
+		{
+#ifdef ENABLE_HYBRID
+			struct isakmp_cfg_config *icc = &isakmp_cfg_config;
+			struct unity_network network;
+			memset(&network,0,sizeof(network));
+
+			if (inet_pton(AF_INET, $1->v, &network.addr4) != 1)
+				yyerror("bad IPv4 SPLIT address.");
+
+			/* Turn $2 (the prefix) into a subnet mask */
+			network.mask4.s_addr = ($2) ? htonl(~((1 << (32 - $2)) - 1)) : 0;
+
+			/* add the network to our list */ 
+			if (splitnet_list_add(&icc->splitnet_list, &network,&icc->splitnet_count))
+				yyerror("Unable to allocate split network");
+#else
+			yyerror("racoon not configured with --enable-hybrid");
+#endif
+		}
+	;
+
+authgrouplist
+	:	authgroup
+	|	authgroup COMMA authgrouplist
+	;
+authgroup
+	:	QUOTEDSTRING
+		{
+#ifdef ENABLE_HYBRID
+			char * groupname = NULL;
+			char ** grouplist = NULL;
+			struct isakmp_cfg_config *icc = &isakmp_cfg_config;
+
+			grouplist = racoon_realloc(icc->grouplist,
+					sizeof(char**)*(icc->groupcount+1));
+			if (grouplist == NULL)
+				yyerror("unable to allocate auth group list");
+
+			groupname = racoon_malloc($1->l+1);
+			if (groupname == NULL)
+				yyerror("unable to allocate auth group name");
+
+			memcpy(groupname,$1->v,$1->l);
+			groupname[$1->l]=0;
+			grouplist[icc->groupcount]=groupname;
+			icc->grouplist = grouplist;
+			icc->groupcount++;
+
+			vfree($1);
+#else
+			yyerror("racoon not configured with --enable-hybrid");
+#endif
+		}
+	;
+
+splitdnslist
+	:	splitdns
+	|	splitdns COMMA splitdnslist
+	;
+splitdns
+	:	QUOTEDSTRING
+		{
+#ifdef ENABLE_HYBRID
+			struct isakmp_cfg_config *icc = &isakmp_cfg_config;
+
+			if (!icc->splitdns_len)
+			{
+				icc->splitdns_list = racoon_malloc($1->l);
+				if(icc->splitdns_list == NULL)
+					yyerror("error allocating splitdns list buffer");
+				memcpy(icc->splitdns_list,$1->v,$1->l);
+				icc->splitdns_len = $1->l;
+			}
+			else
+			{
+				int len = icc->splitdns_len + $1->l + 1;
+				icc->splitdns_list = racoon_realloc(icc->splitdns_list,len);
+				if(icc->splitdns_list == NULL)
+					yyerror("error allocating splitdns list buffer");
+				icc->splitdns_list[icc->splitdns_len] = ',';
+				memcpy(icc->splitdns_list + icc->splitdns_len + 1, $1->v, $1->l);
+				icc->splitdns_len = len;
+			}
+			vfree($1);
+#else
+			yyerror("racoon not configured with --enable-hybrid");
+#endif
+		}
+	;
+
+
+	/* timer */
+timer_statement
+	:	RETRY BOC timer_stmts EOC
+	;
+timer_stmts
+	:	/* nothing */
+	|	timer_stmts timer_stmt
+	;
+timer_stmt
+	:	RETRY_COUNTER NUMBER
+		{
+			lcconf->retry_counter = $2;
+		}
+		EOS
+	|	RETRY_INTERVAL NUMBER unittype_time
+		{
+			lcconf->retry_interval = $2 * $3;
+		}
+		EOS
+	|	RETRY_PERSEND NUMBER
+		{
+			lcconf->count_persend = $2;
+		}
+		EOS
+	|	RETRY_PHASE1 NUMBER unittype_time
+		{
+			lcconf->retry_checkph1 = $2 * $3;
+		}
+		EOS
+	|	RETRY_PHASE2 NUMBER unittype_time
+		{
+			lcconf->wait_ph2complete = $2 * $3;
+		}
+		EOS
+	|	NATT_KA NUMBER unittype_time
+		{
+#ifdef ENABLE_NATT
+        		if (libipsec_opt & LIBIPSEC_OPT_NATT)
+				lcconf->natt_ka_interval = $2 * $3;
+			else
+                		yyerror("libipsec lacks NAT-T support");
+#else
+			yyerror("NAT-T support not compiled in.");
+#endif
+		}
+		EOS
+	;
+
+	/* sainfo */
+sainfo_statement
+	:	SAINFO
+		{
+			cur_sainfo = newsainfo();
+			if (cur_sainfo == NULL) {
+				yyerror("failed to allocate sainfo");
+				return -1;
+			}
+		}
+		sainfo_name sainfo_param BOC sainfo_specs
+		{
+			struct sainfo *check;
+
+			/* default */
+			if (cur_sainfo->algs[algclass_ipsec_enc] == 0) {
+				yyerror("no encryption algorithm at %s",
+					sainfo2str(cur_sainfo));
+				return -1;
+			}
+			if (cur_sainfo->algs[algclass_ipsec_auth] == 0) {
+				yyerror("no authentication algorithm at %s",
+					sainfo2str(cur_sainfo));
+				return -1;
+			}
+			if (cur_sainfo->algs[algclass_ipsec_comp] == 0) {
+				yyerror("no compression algorithm at %s",
+					sainfo2str(cur_sainfo));
+				return -1;
+			}
+
+			/* duplicate check */
+			check = getsainfo(cur_sainfo->idsrc,
+					  cur_sainfo->iddst,
+					  cur_sainfo->id_i,
+					  cur_sainfo->remoteid);
+			if (check && (!check->idsrc && !cur_sainfo->idsrc)) {
+				yyerror("duplicated sainfo: %s",
+					sainfo2str(cur_sainfo));
+				return -1;
+			}
+			inssainfo(cur_sainfo);
+		}
+		EOC
+	;
+sainfo_name
+	:	ANONYMOUS
+		{
+			cur_sainfo->idsrc = NULL;
+			cur_sainfo->iddst = NULL;
+		}
+	|	ANONYMOUS sainfo_id
+		{
+			cur_sainfo->idsrc = NULL;
+			cur_sainfo->iddst = $2;
+		}
+	|	sainfo_id ANONYMOUS
+		{
+			cur_sainfo->idsrc = $1;
+			cur_sainfo->iddst = NULL;
+		}
+	|	sainfo_id sainfo_id
+		{
+			cur_sainfo->idsrc = $1;
+			cur_sainfo->iddst = $2;
+		}
+	;
+sainfo_id
+	:	IDENTIFIERTYPE ADDRSTRING prefix port ul_proto
+		{
+			char portbuf[10];
+			struct sockaddr *saddr;
+
+			if (($5 == IPPROTO_ICMP || $5 == IPPROTO_ICMPV6)
+			 && ($4 != IPSEC_PORT_ANY || $4 != IPSEC_PORT_ANY)) {
+				yyerror("port number must be \"any\".");
+				return -1;
+			}
+
+			snprintf(portbuf, sizeof(portbuf), "%lu", $4);
+			saddr = str2saddr($2->v, portbuf);
+			vfree($2);
+			if (saddr == NULL)
+				return -1;
+
+			switch (saddr->sa_family) {
+			case AF_INET:
+				if ($5 == IPPROTO_ICMPV6) {
+					yyerror("upper layer protocol mismatched.\n");
+					racoon_free(saddr);
+					return -1;
+				}
+				$$ = ipsecdoi_sockaddr2id(saddr,
+										  $3 == ~0 ? (sizeof(struct in_addr) << 3): $3,
+										  $5);
+				break;
+#ifdef INET6
+			case AF_INET6:
+				if ($5 == IPPROTO_ICMP) {
+					yyerror("upper layer protocol mismatched.\n");
+					racoon_free(saddr);
+					return -1;
+				}
+				$$ = ipsecdoi_sockaddr2id(saddr, 
+										  $3 == ~0 ? (sizeof(struct in6_addr) << 3): $3,
+										  $5);
+				break;
+#endif
+			default:
+				yyerror("invalid family: %d", saddr->sa_family);
+				$$ = NULL;
+				break;
+			}
+			racoon_free(saddr);
+			if ($$ == NULL)
+				return -1;
+		}
+	|	IDENTIFIERTYPE ADDRSTRING ADDRRANGE prefix port ul_proto
+		{
+			char portbuf[10];
+			struct sockaddr *laddr = NULL, *haddr = NULL;
+			char *cur = NULL;
+
+			if (($6 == IPPROTO_ICMP || $6 == IPPROTO_ICMPV6)
+			 && ($5 != IPSEC_PORT_ANY || $5 != IPSEC_PORT_ANY)) {
+				yyerror("port number must be \"any\".");
+				return -1;
+			}
+
+			snprintf(portbuf, sizeof(portbuf), "%lu", $5);
+			
+			laddr = str2saddr($2->v, portbuf);
+			if (laddr == NULL) {
+			    return -1;
+			}
+			vfree($2);
+			haddr = str2saddr($3->v, portbuf);
+			if (haddr == NULL) {
+			    racoon_free(laddr);
+			    return -1;
+			}
+			vfree($3);
+
+			switch (laddr->sa_family) {
+			case AF_INET:
+				if ($6 == IPPROTO_ICMPV6) {
+				    yyerror("upper layer protocol mismatched.\n");
+				    if (laddr)
+					racoon_free(laddr);
+				    if (haddr)
+					racoon_free(haddr);
+				    return -1;
+				}
+                                $$ = ipsecdoi_sockrange2id(laddr, haddr, 
+							   $6);
+				break;
+#ifdef INET6
+			case AF_INET6:
+				if ($6 == IPPROTO_ICMP) {
+					yyerror("upper layer protocol mismatched.\n");
+					if (laddr)
+					    racoon_free(laddr);
+					if (haddr)
+					    racoon_free(haddr);
+					return -1;
+				}
+				$$ = ipsecdoi_sockrange2id(laddr, haddr, 
+							       $6);
+				break;
+#endif
+			default:
+				yyerror("invalid family: %d", laddr->sa_family);
+				$$ = NULL;
+				break;
+			}
+			if (laddr)
+			    racoon_free(laddr);
+			if (haddr)
+			    racoon_free(haddr);
+			if ($$ == NULL)
+				return -1;
+		}
+	|	IDENTIFIERTYPE QUOTEDSTRING
+		{
+			struct ipsecdoi_id_b *id_b;
+
+			if ($1 == IDTYPE_ASN1DN) {
+				yyerror("id type forbidden: %d", $1);
+				$$ = NULL;
+				return -1;
+			}
+
+			$2->l--;
+
+			$$ = vmalloc(sizeof(*id_b) + $2->l);
+			if ($$ == NULL) {
+				yyerror("failed to allocate identifier");
+				return -1;
+			}
+
+			id_b = (struct ipsecdoi_id_b *)$$->v;
+			id_b->type = idtype2doi($1);
+
+			id_b->proto_id = 0;
+			id_b->port = 0;
+
+			memcpy($$->v + sizeof(*id_b), $2->v, $2->l);
+		}
+	;
+sainfo_param
+	:	/* nothing */
+		{
+			cur_sainfo->id_i = NULL;
+		}
+	|	FROM IDENTIFIERTYPE identifierstring
+		{
+			struct ipsecdoi_id_b *id_b;
+			vchar_t *idv;
+
+			if (set_identifier(&idv, $2, $3) != 0) {
+				yyerror("failed to set identifer.\n");
+				return -1;
+			}
+			cur_sainfo->id_i = vmalloc(sizeof(*id_b) + idv->l);
+			if (cur_sainfo->id_i == NULL) {
+				yyerror("failed to allocate identifier");
+				return -1;
+			}
+
+			id_b = (struct ipsecdoi_id_b *)cur_sainfo->id_i->v;
+			id_b->type = idtype2doi($2);
+
+			id_b->proto_id = 0;
+			id_b->port = 0;
+
+			memcpy(cur_sainfo->id_i->v + sizeof(*id_b),
+			       idv->v, idv->l);
+			vfree(idv);
+		}
+	|	GROUP QUOTEDSTRING
+		{
+#ifdef ENABLE_HYBRID
+			if ((cur_sainfo->group = vdup($2)) == NULL) {
+				yyerror("failed to set sainfo xauth group.\n");
+				return -1;
+			}
+#else
+			yyerror("racoon not configured with --enable-hybrid");
+			return -1;
+#endif
+ 		}
+	;
+sainfo_specs
+	:	/* nothing */
+	|	sainfo_specs sainfo_spec
+	;
+sainfo_spec
+	:	PFS_GROUP dh_group_num
+		{
+			cur_sainfo->pfs_group = $2;
+		}
+		EOS
+	|	REMOTEID NUMBER
+		{
+			cur_sainfo->remoteid = $2;
+		}
+		EOS
+	|	LIFETIME LIFETYPE_TIME NUMBER unittype_time
+		{
+			cur_sainfo->lifetime = $3 * $4;
+		}
+		EOS
+	|	LIFETIME LIFETYPE_BYTE NUMBER unittype_byte
+		{
+#if 1
+			yyerror("byte lifetime support is deprecated");
+			return -1;
+#else
+			cur_sainfo->lifebyte = fix_lifebyte($3 * $4);
+			if (cur_sainfo->lifebyte == 0)
+				return -1;
+#endif
+		}
+		EOS
+	|	ALGORITHM_CLASS {
+			cur_algclass = $1;
+		}
+		algorithms EOS
+	|	IDENTIFIER IDENTIFIERTYPE
+		{
+			yyerror("it's deprecated to specify a identifier in phase 2");
+		}
+		EOS
+	|	MY_IDENTIFIER IDENTIFIERTYPE QUOTEDSTRING
+		{
+			yyerror("it's deprecated to specify a identifier in phase 2");
+		}
+		EOS
+	;
+
+algorithms
+	:	algorithm
+		{
+			inssainfoalg(&cur_sainfo->algs[cur_algclass], $1);
+		}
+	|	algorithm
+		{
+			inssainfoalg(&cur_sainfo->algs[cur_algclass], $1);
+		}
+		COMMA algorithms
+	;
+algorithm
+	:	ALGORITHMTYPE keylength
+		{
+			int defklen;
+
+			$$ = newsainfoalg();
+			if ($$ == NULL) {
+				yyerror("failed to get algorithm allocation");
+				return -1;
+			}
+
+			$$->alg = algtype2doi(cur_algclass, $1);
+			if ($$->alg == -1) {
+				yyerror("algorithm mismatched");
+				racoon_free($$);
+				$$ = NULL;
+				return -1;
+			}
+
+			defklen = default_keylen(cur_algclass, $1);
+			if (defklen == 0) {
+				if ($2) {
+					yyerror("keylen not allowed");
+					racoon_free($$);
+					$$ = NULL;
+					return -1;
+				}
+			} else {
+				if ($2 && check_keylen(cur_algclass, $1, $2) < 0) {
+					yyerror("invalid keylen %d", $2);
+					racoon_free($$);
+					$$ = NULL;
+					return -1;
+				}
+			}
+
+			if ($2)
+				$$->encklen = $2;
+			else
+				$$->encklen = defklen;
+
+			/* check if it's supported algorithm by kernel */
+			if (!(cur_algclass == algclass_ipsec_auth && $1 == algtype_non_auth)
+			 && pk_checkalg(cur_algclass, $1, $$->encklen)) {
+				int a = algclass2doi(cur_algclass);
+				int b = algtype2doi(cur_algclass, $1);
+				if (a == IPSECDOI_ATTR_AUTH)
+					a = IPSECDOI_PROTO_IPSEC_AH;
+				yyerror("algorithm %s not supported by the kernel (missing module?)",
+					s_ipsecdoi_trns(a, b));
+				racoon_free($$);
+				$$ = NULL;
+				return -1;
+			}
+		}
+	;
+prefix
+	:	/* nothing */ { $$ = ~0; }
+	|	PREFIX { $$ = $1; }
+	;
+port
+	:	/* nothing */ { $$ = IPSEC_PORT_ANY; }
+	|	PORT { $$ = $1; }
+	|	PORTANY { $$ = IPSEC_PORT_ANY; }
+	;
+ul_proto
+	:	NUMBER { $$ = $1; }
+	|	UL_PROTO { $$ = $1; }
+	|	ANY { $$ = IPSEC_ULPROTO_ANY; }
+	;
+keylength
+	:	/* nothing */ { $$ = 0; }
+	|	NUMBER { $$ = $1; }
+	;
+
+	/* remote */
+remote_statement
+	:	REMOTE remote_index INHERIT remote_index
+		{
+			struct remoteconf *new;
+			struct proposalspec *prspec;
+
+			new = copyrmconf($4);
+			if (new == NULL) {
+				yyerror("failed to get remoteconf for %s.", saddr2str ($4));
+				return -1;
+			}
+
+			new->remote = $2;
+			new->inherited_from = getrmconf_strict($4, 1);
+			new->proposal = NULL;
+			new->prhead = NULL;
+			cur_rmconf = new;
+
+			prspec = newprspec();
+			if (prspec == NULL || !cur_rmconf->inherited_from 
+				|| !cur_rmconf->inherited_from->proposal)
+				return -1;
+			prspec->lifetime = cur_rmconf->inherited_from->proposal->lifetime;
+			prspec->lifebyte = cur_rmconf->inherited_from->proposal->lifebyte;
+			insprspec(prspec, &cur_rmconf->prhead);
+		}
+		remote_specs_block
+	|	REMOTE remote_index
+		{
+			struct remoteconf *new;
+			struct proposalspec *prspec;
+
+			new = newrmconf();
+			if (new == NULL) {
+				yyerror("failed to get new remoteconf.");
+				return -1;
+			}
+
+			new->remote = $2;
+			cur_rmconf = new;
+
+			prspec = newprspec();
+			if (prspec == NULL)
+				return -1;
+			prspec->lifetime = oakley_get_defaultlifetime();
+			insprspec(prspec, &cur_rmconf->prhead);
+		}
+		remote_specs_block
+	;
+
+remote_specs_block
+	:	BOC remote_specs EOC
+		{
+			/* check a exchange mode */
+			if (cur_rmconf->etypes == NULL) {
+				yyerror("no exchange mode specified.\n");
+				return -1;
+			}
+
+			if (cur_rmconf->idvtype == IDTYPE_UNDEFINED)
+				cur_rmconf->idvtype = IDTYPE_ADDRESS;
+
+
+			if (cur_rmconf->idvtype == IDTYPE_ASN1DN) {
+				if (cur_rmconf->mycertfile) {
+					if (cur_rmconf->idv)
+						yywarn("Both CERT and ASN1 ID "
+						       "are set. Hope this is OK.\n");
+					/* TODO: Preparse the DN here */
+				} else if (cur_rmconf->idv) {
+					/* OK, using asn1dn without X.509. */
+				} else {
+					yyerror("ASN1 ID not specified "
+						"and no CERT defined!\n");
+					return -1;
+				}
+			}
+			
+			if (cur_rmconf->prhead->spspec == NULL
+				&& cur_rmconf->inherited_from
+				&& cur_rmconf->inherited_from->prhead) {
+				cur_rmconf->prhead->spspec = cur_rmconf->inherited_from->prhead->spspec;
+			}
+			if (set_isakmp_proposal(cur_rmconf, cur_rmconf->prhead) != 0)
+				return -1;
+
+			/* DH group settting if aggressive mode is there. */
+			if (check_etypeok(cur_rmconf, ISAKMP_ETYPE_AGG) != NULL) {
+				struct isakmpsa *p;
+				int b = 0;
+
+				/* DH group */
+				for (p = cur_rmconf->proposal; p; p = p->next) {
+					if (b == 0 || (b && b == p->dh_group)) {
+						b = p->dh_group;
+						continue;
+					}
+					yyerror("DH group must be equal "
+						"in all proposals "
+						"when aggressive mode is "
+						"used.\n");
+					return -1;
+				}
+				cur_rmconf->dh_group = b;
+
+				if (cur_rmconf->dh_group == 0) {
+					yyerror("DH group must be set in the proposal.\n");
+					return -1;
+				}
+
+				/* DH group settting if PFS is required. */
+				if (oakley_setdhgroup(cur_rmconf->dh_group,
+						&cur_rmconf->dhgrp) < 0) {
+					yyerror("failed to set DH value.\n");
+					return -1;
+				}
+			}
+
+			insrmconf(cur_rmconf);
+		}
+	;
+remote_index
+	:	ANONYMOUS ike_port
+		{
+			$$ = newsaddr(sizeof(struct sockaddr));
+			$$->sa_family = AF_UNSPEC;
+			((struct sockaddr_in *)$$)->sin_port = htons($2);
+		}
+	|	ike_addrinfo_port
+		{
+			$$ = $1;
+			if ($$ == NULL) {
+				yyerror("failed to allocate sockaddr");
+				return -1;
+			}
+		}
+	;
+remote_specs
+	:	/* nothing */
+	|	remote_specs remote_spec
+	;
+remote_spec
+	:	EXCHANGE_MODE
+		{
+			cur_rmconf->etypes = NULL;
+		}
+		exchange_types EOS
+	|	DOI DOITYPE { cur_rmconf->doitype = $2; } EOS
+	|	SITUATION SITUATIONTYPE { cur_rmconf->sittype = $2; } EOS
+	|	CERTIFICATE_TYPE cert_spec
+	|	PEERS_CERTFILE QUOTEDSTRING
+		{
+			yywarn("This directive without certtype will be removed!\n");
+			yywarn("Please use 'peers_certfile x509 \"%s\";' instead\n", $2->v);
+			cur_rmconf->getcert_method = ISAKMP_GETCERT_LOCALFILE;
+
+			if (cur_rmconf->peerscertfile != NULL)
+				racoon_free(cur_rmconf->peerscertfile);
+			cur_rmconf->peerscertfile = racoon_strdup($2->v);
+			STRDUP_FATAL(cur_rmconf->peerscertfile);
+			vfree($2);
+		}
+		EOS
+	|	CA_TYPE CERT_X509 QUOTEDSTRING
+		{
+			cur_rmconf->cacerttype = $2;
+			cur_rmconf->getcacert_method = ISAKMP_GETCERT_LOCALFILE;
+			if (cur_rmconf->cacertfile != NULL)
+				racoon_free(cur_rmconf->cacertfile);
+			cur_rmconf->cacertfile = racoon_strdup($3->v);
+			STRDUP_FATAL(cur_rmconf->cacertfile);
+			vfree($3);
+		}
+		EOS
+	|	PEERS_CERTFILE CERT_X509 QUOTEDSTRING
+		{
+			cur_rmconf->getcert_method = ISAKMP_GETCERT_LOCALFILE;
+			if (cur_rmconf->peerscertfile != NULL)
+				racoon_free(cur_rmconf->peerscertfile);
+			cur_rmconf->peerscertfile = racoon_strdup($3->v);
+			STRDUP_FATAL(cur_rmconf->peerscertfile);
+			vfree($3);
+		}
+		EOS
+	|	PEERS_CERTFILE CERT_PLAINRSA QUOTEDSTRING
+		{
+			char path[MAXPATHLEN];
+			int ret = 0;
+
+			getpathname(path, sizeof(path),
+				LC_PATHTYPE_CERT, $3->v);
+			vfree($3);
+
+			if (cur_rmconf->getcert_method == ISAKMP_GETCERT_DNS) {
+				yyerror("Different peers_certfile method "
+					"already defined: %d!\n",
+					cur_rmconf->getcert_method);
+				return -1;
+			}
+			cur_rmconf->getcert_method = ISAKMP_GETCERT_LOCALFILE;
+			if (rsa_parse_file(cur_rmconf->rsa_public, path, RSA_TYPE_PUBLIC)) {
+				yyerror("Couldn't parse keyfile.\n", path);
+				return -1;
+			}
+			plog(LLV_DEBUG, LOCATION, NULL, "Public PlainRSA keyfile parsed: %s\n", path);
+		}
+		EOS
+	|	PEERS_CERTFILE DNSSEC
+		{
+			if (cur_rmconf->getcert_method) {
+				yyerror("Different peers_certfile method already defined!\n");
+				return -1;
+			}
+			cur_rmconf->getcert_method = ISAKMP_GETCERT_DNS;
+			cur_rmconf->peerscertfile = NULL;
+		}
+		EOS
+	|	VERIFY_CERT SWITCH { cur_rmconf->verify_cert = $2; } EOS
+	|	SEND_CERT SWITCH { cur_rmconf->send_cert = $2; } EOS
+	|	SEND_CR SWITCH { cur_rmconf->send_cr = $2; } EOS
+	|	MY_IDENTIFIER IDENTIFIERTYPE identifierstring
+		{
+			if (set_identifier(&cur_rmconf->idv, $2, $3) != 0) {
+				yyerror("failed to set identifer.\n");
+				return -1;
+			}
+			cur_rmconf->idvtype = $2;
+		}
+		EOS
+	|	MY_IDENTIFIER IDENTIFIERTYPE IDENTIFIERQUAL identifierstring
+		{
+			if (set_identifier_qual(&cur_rmconf->idv, $2, $4, $3) != 0) {
+				yyerror("failed to set identifer.\n");
+				return -1;
+			}
+			cur_rmconf->idvtype = $2;
+		}
+		EOS
+	|	XAUTH_LOGIN identifierstring
+		{
+#ifdef ENABLE_HYBRID
+			/* formerly identifier type login */
+			if (xauth_rmconf_used(&cur_rmconf->xauth) == -1) {
+				yyerror("failed to allocate xauth state\n");
+				return -1;
+			}
+			if ((cur_rmconf->xauth->login = vdup($2)) == NULL) {
+				yyerror("failed to set identifer.\n");
+				return -1;
+			}
+#else
+			yyerror("racoon not configured with --enable-hybrid");
+#endif
+		}
+		EOS
+	|	PEERS_IDENTIFIER IDENTIFIERTYPE identifierstring
+		{
+			struct idspec  *id;
+			id = newidspec();
+			if (id == NULL) {
+				yyerror("failed to allocate idspec");
+				return -1;
+			}
+			if (set_identifier(&id->id, $2, $3) != 0) {
+				yyerror("failed to set identifer.\n");
+				racoon_free(id);
+				return -1;
+			}
+			id->idtype = $2;
+			genlist_append (cur_rmconf->idvl_p, id);
+		}
+		EOS
+	|	PEERS_IDENTIFIER IDENTIFIERTYPE IDENTIFIERQUAL identifierstring
+		{
+			struct idspec  *id;
+			id = newidspec();
+			if (id == NULL) {
+				yyerror("failed to allocate idspec");
+				return -1;
+			}
+			if (set_identifier_qual(&id->id, $2, $4, $3) != 0) {
+				yyerror("failed to set identifer.\n");
+				racoon_free(id);
+				return -1;
+			}
+			id->idtype = $2;
+			genlist_append (cur_rmconf->idvl_p, id);
+		}
+		EOS
+	|	VERIFY_IDENTIFIER SWITCH { cur_rmconf->verify_identifier = $2; } EOS
+	|	NONCE_SIZE NUMBER { cur_rmconf->nonce_size = $2; } EOS
+	|	DH_GROUP
+		{
+			yyerror("dh_group cannot be defined here.");
+			return -1;
+		}
+		dh_group_num EOS
+	|	PASSIVE SWITCH { cur_rmconf->passive = $2; } EOS
+	|	IKE_FRAG SWITCH { cur_rmconf->ike_frag = $2; } EOS
+	|	IKE_FRAG REMOTE_FORCE_LEVEL { cur_rmconf->ike_frag = ISAKMP_FRAG_FORCE; } EOS
+	|	ESP_FRAG NUMBER { 
+#ifdef SADB_X_EXT_NAT_T_FRAG
+        		if (libipsec_opt & LIBIPSEC_OPT_FRAG)
+				cur_rmconf->esp_frag = $2; 
+			else
+                		yywarn("libipsec lacks IKE frag support");
+#else
+			yywarn("Your kernel does not support esp_frag");
+#endif
+		} EOS
+	|	SCRIPT QUOTEDSTRING PHASE1_UP { 
+			if (cur_rmconf->script[SCRIPT_PHASE1_UP] != NULL)
+				vfree(cur_rmconf->script[SCRIPT_PHASE1_UP]);
+
+			cur_rmconf->script[SCRIPT_PHASE1_UP] = 
+			    script_path_add(vdup($2));
+		} EOS
+	|	SCRIPT QUOTEDSTRING PHASE1_DOWN { 
+			if (cur_rmconf->script[SCRIPT_PHASE1_DOWN] != NULL)
+				vfree(cur_rmconf->script[SCRIPT_PHASE1_DOWN]);
+
+			cur_rmconf->script[SCRIPT_PHASE1_DOWN] = 
+			    script_path_add(vdup($2));
+		} EOS
+	|	MODE_CFG SWITCH { cur_rmconf->mode_cfg = $2; } EOS
+	|	WEAK_PHASE1_CHECK SWITCH {
+			cur_rmconf->weak_phase1_check = $2;
+		} EOS
+	|	GENERATE_POLICY SWITCH { cur_rmconf->gen_policy = $2; } EOS
+	|	GENERATE_POLICY GENERATE_LEVEL { cur_rmconf->gen_policy = $2; } EOS
+	|	SUPPORT_PROXY SWITCH { cur_rmconf->support_proxy = $2; } EOS
+	|	INITIAL_CONTACT SWITCH { cur_rmconf->ini_contact = $2; } EOS
+	|	NAT_TRAVERSAL SWITCH
+		{
+#ifdef ENABLE_NATT
+        		if (libipsec_opt & LIBIPSEC_OPT_NATT)
+				cur_rmconf->nat_traversal = $2;
+			else
+                		yyerror("libipsec lacks NAT-T support");
+#else
+			yyerror("NAT-T support not compiled in.");
+#endif
+		} EOS
+	|	NAT_TRAVERSAL REMOTE_FORCE_LEVEL
+		{
+#ifdef ENABLE_NATT
+			if (libipsec_opt & LIBIPSEC_OPT_NATT)
+				cur_rmconf->nat_traversal = NATT_FORCE;
+			else
+                		yyerror("libipsec lacks NAT-T support");
+#else
+			yyerror("NAT-T support not compiled in.");
+#endif
+		} EOS
+	|	DPD SWITCH
+		{
+#ifdef ENABLE_DPD
+			cur_rmconf->dpd = $2;
+#else
+			yyerror("DPD support not compiled in.");
+#endif
+		} EOS
+	|	DPD_DELAY NUMBER
+		{
+#ifdef ENABLE_DPD
+			cur_rmconf->dpd_interval = $2;
+#else
+			yyerror("DPD support not compiled in.");
+#endif
+		}
+		EOS
+	|	DPD_RETRY NUMBER
+		{
+#ifdef ENABLE_DPD
+			cur_rmconf->dpd_retry = $2;
+#else
+			yyerror("DPD support not compiled in.");
+#endif
+		}
+		EOS
+	|	DPD_MAXFAIL NUMBER
+		{
+#ifdef ENABLE_DPD
+			cur_rmconf->dpd_maxfails = $2;
+#else
+			yyerror("DPD support not compiled in.");
+#endif
+		}
+		EOS
+	|	PH1ID NUMBER
+		{
+			cur_rmconf->ph1id = $2;
+		}
+		EOS
+	|	LIFETIME LIFETYPE_TIME NUMBER unittype_time
+		{
+			cur_rmconf->prhead->lifetime = $3 * $4;
+		}
+		EOS
+	|	PROPOSAL_CHECK PROPOSAL_CHECK_LEVEL { cur_rmconf->pcheck_level = $2; } EOS
+	|	LIFETIME LIFETYPE_BYTE NUMBER unittype_byte
+		{
+#if 1
+			yyerror("byte lifetime support is deprecated in Phase1");
+			return -1;
+#else
+			yywarn("the lifetime of bytes in phase 1 "
+				"will be ignored at the moment.");
+			cur_rmconf->prhead->lifebyte = fix_lifebyte($3 * $4);
+			if (cur_rmconf->prhead->lifebyte == 0)
+				return -1;
+#endif
+		}
+		EOS
+	|	PROPOSAL
+		{
+			struct secprotospec *spspec;
+
+			spspec = newspspec();
+			if (spspec == NULL)
+				return -1;
+			insspspec(spspec, &cur_rmconf->prhead);
+		}
+		BOC isakmpproposal_specs EOC
+	;
+exchange_types
+	:	/* nothing */
+	|	exchange_types EXCHANGETYPE
+		{
+			struct etypes *new;
+			new = racoon_malloc(sizeof(struct etypes));
+			if (new == NULL) {
+				yyerror("failed to allocate etypes");
+				return -1;
+			}
+			new->type = $2;
+			new->next = NULL;
+			if (cur_rmconf->etypes == NULL)
+				cur_rmconf->etypes = new;
+			else {
+				struct etypes *p;
+				for (p = cur_rmconf->etypes;
+				     p->next != NULL;
+				     p = p->next)
+					;
+				p->next = new;
+			}
+		}
+	;
+cert_spec
+	:	CERT_X509 QUOTEDSTRING QUOTEDSTRING
+		{
+			cur_rmconf->certtype = $1;
+			if (cur_rmconf->mycertfile != NULL)
+				racoon_free(cur_rmconf->mycertfile);
+			cur_rmconf->mycertfile = racoon_strdup($2->v);
+			STRDUP_FATAL(cur_rmconf->mycertfile);
+			vfree($2);
+			if (cur_rmconf->myprivfile != NULL)
+				racoon_free(cur_rmconf->myprivfile);
+			cur_rmconf->myprivfile = racoon_strdup($3->v);
+			STRDUP_FATAL(cur_rmconf->myprivfile);
+			vfree($3);
+		}
+		EOS
+	|	CERT_PLAINRSA QUOTEDSTRING
+		{
+			char path[MAXPATHLEN];
+			int ret = 0;
+
+			getpathname(path, sizeof(path),
+				LC_PATHTYPE_CERT, $2->v);
+			vfree($2);
+
+			cur_rmconf->certtype = $1;
+			cur_rmconf->send_cr = FALSE;
+			cur_rmconf->send_cert = FALSE;
+			cur_rmconf->verify_cert = FALSE;
+			if (rsa_parse_file(cur_rmconf->rsa_private, path, RSA_TYPE_PRIVATE)) {
+				yyerror("Couldn't parse keyfile.\n", path);
+				return -1;
+			}
+			plog(LLV_DEBUG, LOCATION, NULL, "Private PlainRSA keyfile parsed: %s\n", path);
+		}
+		EOS
+	;
+dh_group_num
+	:	ALGORITHMTYPE
+		{
+			$$ = algtype2doi(algclass_isakmp_dh, $1);
+			if ($$ == -1) {
+				yyerror("must be DH group");
+				return -1;
+			}
+		}
+	|	NUMBER
+		{
+			if (ARRAYLEN(num2dhgroup) > $1 && num2dhgroup[$1] != 0) {
+				$$ = num2dhgroup[$1];
+			} else {
+				yyerror("must be DH group");
+				$$ = 0;
+				return -1;
+			}
+		}
+	;
+identifierstring
+	:	/* nothing */ { $$ = NULL; }
+	|	ADDRSTRING { $$ = $1; }
+	|	QUOTEDSTRING { $$ = $1; }
+	;
+isakmpproposal_specs
+	:	/* nothing */
+	|	isakmpproposal_specs isakmpproposal_spec
+	;
+isakmpproposal_spec
+	:	STRENGTH
+		{
+			yyerror("strength directive is obsoleted.");
+		} STRENGTHTYPE EOS
+	|	LIFETIME LIFETYPE_TIME NUMBER unittype_time
+		{
+			cur_rmconf->prhead->spspec->lifetime = $3 * $4;
+		}
+		EOS
+	|	LIFETIME LIFETYPE_BYTE NUMBER unittype_byte
+		{
+#if 1
+			yyerror("byte lifetime support is deprecated");
+			return -1;
+#else
+			cur_rmconf->prhead->spspec->lifebyte = fix_lifebyte($3 * $4);
+			if (cur_rmconf->prhead->spspec->lifebyte == 0)
+				return -1;
+#endif
+		}
+		EOS
+	|	DH_GROUP dh_group_num
+		{
+			cur_rmconf->prhead->spspec->algclass[algclass_isakmp_dh] = $2;
+		}
+		EOS
+	|	GSS_ID QUOTEDSTRING
+		{
+			if (cur_rmconf->prhead->spspec->vendorid != VENDORID_GSSAPI) {
+				yyerror("wrong Vendor ID for gssapi_id");
+				return -1;
+			}
+			if (cur_rmconf->prhead->spspec->gssid != NULL)
+				racoon_free(cur_rmconf->prhead->spspec->gssid);
+			cur_rmconf->prhead->spspec->gssid = 
+			    racoon_strdup($2->v);
+			STRDUP_FATAL(cur_rmconf->prhead->spspec->gssid);
+		}
+		EOS
+	|	ALGORITHM_CLASS ALGORITHMTYPE keylength
+		{
+			int doi;
+			int defklen;
+
+			doi = algtype2doi($1, $2);
+			if (doi == -1) {
+				yyerror("algorithm mismatched 1");
+				return -1;
+			}
+
+			switch ($1) {
+			case algclass_isakmp_enc:
+			/* reject suppressed algorithms */
+#ifndef HAVE_OPENSSL_RC5_H
+				if ($2 == algtype_rc5) {
+					yyerror("algorithm %s not supported",
+					    s_attr_isakmp_enc(doi));
+					return -1;
+				}
+#endif
+#ifndef HAVE_OPENSSL_IDEA_H
+				if ($2 == algtype_idea) {
+					yyerror("algorithm %s not supported",
+					    s_attr_isakmp_enc(doi));
+					return -1;
+				}
+#endif
+
+				cur_rmconf->prhead->spspec->algclass[algclass_isakmp_enc] = doi;
+				defklen = default_keylen($1, $2);
+				if (defklen == 0) {
+					if ($3) {
+						yyerror("keylen not allowed");
+						return -1;
+					}
+				} else {
+					if ($3 && check_keylen($1, $2, $3) < 0) {
+						yyerror("invalid keylen %d", $3);
+						return -1;
+					}
+				}
+				if ($3)
+					cur_rmconf->prhead->spspec->encklen = $3;
+				else
+					cur_rmconf->prhead->spspec->encklen = defklen;
+				break;
+			case algclass_isakmp_hash:
+				cur_rmconf->prhead->spspec->algclass[algclass_isakmp_hash] = doi;
+				break;
+			case algclass_isakmp_ameth:
+				cur_rmconf->prhead->spspec->algclass[algclass_isakmp_ameth] = doi;
+				/*
+				 * We may have to set the Vendor ID for the
+				 * authentication method we're using.
+				 */
+				switch ($2) {
+				case algtype_gssapikrb:
+					if (cur_rmconf->prhead->spspec->vendorid !=
+					    VENDORID_UNKNOWN) {
+						yyerror("Vendor ID mismatch "
+						    "for auth method");
+						return -1;
+					}
+					/*
+					 * For interoperability with Win2k,
+					 * we set the Vendor ID to "GSSAPI".
+					 */
+					cur_rmconf->prhead->spspec->vendorid =
+					    VENDORID_GSSAPI;
+					break;
+				case algtype_rsasig:
+					if (cur_rmconf->certtype == ISAKMP_CERT_PLAINRSA) {
+						if (rsa_list_count(cur_rmconf->rsa_private) == 0) {
+							yyerror ("Private PlainRSA key not set. "
+								"Use directive 'certificate_type plainrsa ...'\n");
+							return -1;
+						}
+						if (rsa_list_count(cur_rmconf->rsa_public) == 0) {
+							yyerror ("Public PlainRSA keys not set. "
+								"Use directive 'peers_certfile plainrsa ...'\n");
+							return -1;
+						}
+					}
+					break;
+				default:
+					break;
+				}
+				break;
+			default:
+				yyerror("algorithm mismatched 2");
+				return -1;
+			}
+		}
+		EOS
+	;
+
+unittype_time
+	:	UNITTYPE_SEC	{ $$ = 1; }
+	|	UNITTYPE_MIN	{ $$ = 60; }
+	|	UNITTYPE_HOUR	{ $$ = (60 * 60); }
+	;
+unittype_byte
+	:	UNITTYPE_BYTE	{ $$ = 1; }
+	|	UNITTYPE_KBYTES	{ $$ = 1024; }
+	|	UNITTYPE_MBYTES	{ $$ = (1024 * 1024); }
+	|	UNITTYPE_TBYTES	{ $$ = (1024 * 1024 * 1024); }
+	;
+%%
+
+static struct proposalspec *
+newprspec()
+{
+	struct proposalspec *new;
+
+	new = racoon_calloc(1, sizeof(*new));
+	if (new == NULL)
+		yyerror("failed to allocate proposal");
+
+	return new;
+}
+
+/*
+ * insert into head of list.
+ */
+static void
+insprspec(prspec, head)
+	struct proposalspec *prspec;
+	struct proposalspec **head;
+{
+	if (*head != NULL)
+		(*head)->prev = prspec;
+	prspec->next = *head;
+	*head = prspec;
+}
+
+static struct secprotospec *
+newspspec()
+{
+	struct secprotospec *new;
+
+	new = racoon_calloc(1, sizeof(*new));
+	if (new == NULL) {
+		yyerror("failed to allocate spproto");
+		return NULL;
+	}
+
+	new->encklen = 0;	/*XXX*/
+
+	/*
+	 * Default to "uknown" vendor -- we will override this
+	 * as necessary.  When we send a Vendor ID payload, an
+	 * "unknown" will be translated to a KAME/racoon ID.
+	 */
+	new->vendorid = VENDORID_UNKNOWN;
+
+	return new;
+}
+
+/*
+ * insert into head of list.
+ */
+static void
+insspspec(spspec, head)
+	struct secprotospec *spspec;
+	struct proposalspec **head;
+{
+	spspec->back = *head;
+
+	if ((*head)->spspec != NULL)
+		(*head)->spspec->prev = spspec;
+	spspec->next = (*head)->spspec;
+	(*head)->spspec = spspec;
+}
+
+/* set final acceptable proposal */
+static int
+set_isakmp_proposal(rmconf, prspec)
+	struct remoteconf *rmconf;
+	struct proposalspec *prspec;
+{
+	struct proposalspec *p;
+	struct secprotospec *s;
+	int prop_no = 1; 
+	int trns_no = 1;
+	int32_t types[MAXALGCLASS];
+
+	p = prspec;
+	if (p->next != 0) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"multiple proposal definition.\n");
+		return -1;
+	}
+
+	/* mandatory check */
+	if (p->spspec == NULL) {
+		yyerror("no remote specification found: %s.\n",
+			saddr2str(rmconf->remote));
+		return -1;
+	}
+	for (s = p->spspec; s != NULL; s = s->next) {
+		/* XXX need more to check */
+		if (s->algclass[algclass_isakmp_enc] == 0) {
+			yyerror("encryption algorithm required.");
+			return -1;
+		}
+		if (s->algclass[algclass_isakmp_hash] == 0) {
+			yyerror("hash algorithm required.");
+			return -1;
+		}
+		if (s->algclass[algclass_isakmp_dh] == 0) {
+			yyerror("DH group required.");
+			return -1;
+		}
+		if (s->algclass[algclass_isakmp_ameth] == 0) {
+			yyerror("authentication method required.");
+			return -1;
+		}
+	}
+
+	/* skip to last part */
+	for (s = p->spspec; s->next != NULL; s = s->next)
+		;
+
+	while (s != NULL) {
+		plog(LLV_DEBUG2, LOCATION, NULL,
+			"lifetime = %ld\n", (long)
+			(s->lifetime ? s->lifetime : p->lifetime));
+		plog(LLV_DEBUG2, LOCATION, NULL,
+			"lifebyte = %d\n",
+			s->lifebyte ? s->lifebyte : p->lifebyte);
+		plog(LLV_DEBUG2, LOCATION, NULL,
+			"encklen=%d\n", s->encklen);
+
+		memset(types, 0, ARRAYLEN(types));
+		types[algclass_isakmp_enc] = s->algclass[algclass_isakmp_enc];
+		types[algclass_isakmp_hash] = s->algclass[algclass_isakmp_hash];
+		types[algclass_isakmp_dh] = s->algclass[algclass_isakmp_dh];
+		types[algclass_isakmp_ameth] =
+		    s->algclass[algclass_isakmp_ameth];
+
+		/* expanding spspec */
+		clean_tmpalgtype();
+		trns_no = expand_isakmpspec(prop_no, trns_no, types,
+				algclass_isakmp_enc, algclass_isakmp_ameth + 1,
+				s->lifetime ? s->lifetime : p->lifetime,
+				s->lifebyte ? s->lifebyte : p->lifebyte,
+				s->encklen, s->vendorid, s->gssid,
+				rmconf);
+		if (trns_no == -1) {
+			plog(LLV_ERROR, LOCATION, NULL,
+				"failed to expand isakmp proposal.\n");
+			return -1;
+		}
+
+		s = s->prev;
+	}
+
+	if (rmconf->proposal == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"no proposal found.\n");
+		return -1;
+	}
+
+	return 0;
+}
+
+static void
+clean_tmpalgtype()
+{
+	int i;
+	for (i = 0; i < MAXALGCLASS; i++)
+		tmpalgtype[i] = 0;	/* means algorithm undefined. */
+}
+
+static int
+expand_isakmpspec(prop_no, trns_no, types,
+		class, last, lifetime, lifebyte, encklen, vendorid, gssid,
+		rmconf)
+	int prop_no, trns_no;
+	int *types, class, last;
+	time_t lifetime;
+	int lifebyte;
+	int encklen;
+	int vendorid;
+	char *gssid;
+	struct remoteconf *rmconf;
+{
+	struct isakmpsa *new;
+
+	/* debugging */
+    {
+	int j;
+	char tb[10];
+	plog(LLV_DEBUG2, LOCATION, NULL,
+		"p:%d t:%d\n", prop_no, trns_no);
+	for (j = class; j < MAXALGCLASS; j++) {
+		snprintf(tb, sizeof(tb), "%d", types[j]);
+		plog(LLV_DEBUG2, LOCATION, NULL,
+			"%s%s%s%s\n",
+			s_algtype(j, types[j]),
+			types[j] ? "(" : "",
+			tb[0] == '0' ? "" : tb,
+			types[j] ? ")" : "");
+	}
+	plog(LLV_DEBUG2, LOCATION, NULL, "\n");
+    }
+
+#define TMPALGTYPE2STR(n) \
+	s_algtype(algclass_isakmp_##n, types[algclass_isakmp_##n])
+		/* check mandatory values */
+		if (types[algclass_isakmp_enc] == 0
+		 || types[algclass_isakmp_ameth] == 0
+		 || types[algclass_isakmp_hash] == 0
+		 || types[algclass_isakmp_dh] == 0) {
+			yyerror("few definition of algorithm "
+				"enc=%s ameth=%s hash=%s dhgroup=%s.\n",
+				TMPALGTYPE2STR(enc),
+				TMPALGTYPE2STR(ameth),
+				TMPALGTYPE2STR(hash),
+				TMPALGTYPE2STR(dh));
+			return -1;
+		}
+#undef TMPALGTYPE2STR
+
+	/* set new sa */
+	new = newisakmpsa();
+	if (new == NULL) {
+		yyerror("failed to allocate isakmp sa");
+		return -1;
+	}
+	new->prop_no = prop_no;
+	new->trns_no = trns_no++;
+	new->lifetime = lifetime;
+	new->lifebyte = lifebyte;
+	new->enctype = types[algclass_isakmp_enc];
+	new->encklen = encklen;
+	new->authmethod = types[algclass_isakmp_ameth];
+	new->hashtype = types[algclass_isakmp_hash];
+	new->dh_group = types[algclass_isakmp_dh];
+	new->vendorid = vendorid;
+#ifdef HAVE_GSSAPI
+	if (new->authmethod == OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB) {
+		if (gssid != NULL) {
+			if ((new->gssid = vmalloc(strlen(gssid))) == NULL) {
+				racoon_free(new);
+				yyerror("failed to allocate gssid");
+				return -1;
+			}
+			memcpy(new->gssid->v, gssid, new->gssid->l);
+			racoon_free(gssid);
+#ifdef ENABLE_HYBRID
+		} else if (rmconf->xauth == NULL) {
+#else
+		} else {
+#endif
+			/*
+			 * Allocate the default ID so that it gets put
+			 * into a GSS ID attribute during the Phase 1
+			 * exchange.
+			 */
+			new->gssid = gssapi_get_default_gss_id();
+		}
+	}
+#endif
+	insisakmpsa(new, rmconf);
+
+	return trns_no;
+}
+
+static int
+listen_addr (struct sockaddr *addr, int udp_encap)
+{
+	struct myaddrs *p;
+
+	p = newmyaddr();
+	if (p == NULL) {
+		yyerror("failed to allocate myaddrs");
+		return -1;
+	}
+	p->addr = addr;
+	if (p->addr == NULL) {
+		yyerror("failed to copy sockaddr ");
+		delmyaddr(p);
+		return -1;
+	}
+	p->udp_encap = udp_encap;
+
+	insmyaddr(p, &lcconf->myaddrs);
+
+	lcconf->autograbaddr = 0;
+	return 0;
+}
+
+#if 0
+/*
+ * fix lifebyte.
+ * Must be more than 1024B because its unit is kilobytes.
+ * That is defined RFC2407.
+ */
+static int
+fix_lifebyte(t)
+	unsigned long t;
+{
+	if (t < 1024) {
+		yyerror("byte size should be more than 1024B.");
+		return 0;
+	}
+
+	return(t / 1024);
+}
+#endif
+
+int
+cfparse()
+{
+	int error;
+
+	yycf_init_buffer();
+
+	if (yycf_switch_buffer(lcconf->racoon_conf) != 0) {
+		plog(LLV_ERROR, LOCATION, NULL, 
+		    "could not read configuration file \"%s\"\n", 
+		    lcconf->racoon_conf);
+		return -1;
+	}
+
+	error = yyparse();
+	if (error != 0) {
+		if (yyerrorcount) {
+			plog(LLV_ERROR, LOCATION, NULL,
+				"fatal parse failure (%d errors)\n",
+				yyerrorcount);
+		} else {
+			plog(LLV_ERROR, LOCATION, NULL,
+				"fatal parse failure.\n");
+		}
+		return -1;
+	}
+
+	if (error == 0 && yyerrorcount) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"parse error is nothing, but yyerrorcount is %d.\n",
+				yyerrorcount);
+		exit(1);
+	}
+
+	yycf_clean_buffer();
+
+	plog(LLV_DEBUG2, LOCATION, NULL, "parse successed.\n");
+
+	return 0;
+}
+
+int
+cfreparse()
+{
+	flushph2();
+	flushph1();
+	flushrmconf();
+	flushsainfo();
+	clean_tmpalgtype();
+	return(cfparse());
+}
+
+#ifdef ENABLE_ADMINPORT
+static void
+adminsock_conf(path, owner, group, mode_dec)
+	vchar_t *path;
+	vchar_t *owner;
+	vchar_t *group;
+	int mode_dec;
+{
+	struct passwd *pw = NULL;
+	struct group *gr = NULL;
+	mode_t mode = 0;
+	uid_t uid;
+	gid_t gid;
+	int isnum;
+
+	adminsock_path = path->v;
+
+	if (owner == NULL)
+		return;
+
+	errno = 0;
+	uid = atoi(owner->v);
+	isnum = !errno;
+	if (((pw = getpwnam(owner->v)) == NULL) && !isnum)
+		yyerror("User \"%s\" does not exist", owner->v);
+
+	if (pw)
+		adminsock_owner = pw->pw_uid;
+	else
+		adminsock_owner = uid;
+
+	if (group == NULL)
+		return;
+
+	errno = 0;
+	gid = atoi(group->v);
+	isnum = !errno;
+	if (((gr = getgrnam(group->v)) == NULL) && !isnum)
+		yyerror("Group \"%s\" does not exist", group->v);
+
+	if (gr)
+		adminsock_group = gr->gr_gid;
+	else
+		adminsock_group = gid;
+
+	if (mode_dec == -1)
+		return;
+
+	if (mode_dec > 777)
+		yyerror("Mode 0%03o is invalid", mode_dec);
+	if (mode_dec >= 400) { mode += 0400; mode_dec -= 400; }
+	if (mode_dec >= 200) { mode += 0200; mode_dec -= 200; }
+	if (mode_dec >= 100) { mode += 0200; mode_dec -= 100; }
+
+	if (mode_dec > 77)
+		yyerror("Mode 0%03o is invalid", mode_dec);
+	if (mode_dec >= 40) { mode += 040; mode_dec -= 40; }
+	if (mode_dec >= 20) { mode += 020; mode_dec -= 20; }
+	if (mode_dec >= 10) { mode += 020; mode_dec -= 10; }
+
+	if (mode_dec > 7)
+		yyerror("Mode 0%03o is invalid", mode_dec);
+	if (mode_dec >= 4) { mode += 04; mode_dec -= 4; }
+	if (mode_dec >= 2) { mode += 02; mode_dec -= 2; }
+	if (mode_dec >= 1) { mode += 02; mode_dec -= 1; }
+	
+	adminsock_mode = mode;
+
+	return;
+}
+#endif
diff --git a/src/racoon/cfparse_proto.h b/src/racoon/cfparse_proto.h
new file mode 100644
index 0000000..139520c
--- /dev/null
+++ b/src/racoon/cfparse_proto.h
@@ -0,0 +1,42 @@
+/*	$NetBSD: cfparse_proto.h,v 1.4 2006/09/09 16:22:09 manu Exp $	*/
+
+/* Id: cfparse_proto.h,v 1.3 2004/06/11 16:00:15 ludvigm Exp */
+
+/*
+ * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _CFPARSE_PROTO_H
+#define _CFPARSE_PROTO_H
+
+/* cfparse.y */
+extern int yyparse __P((void));
+extern int cfparse __P((void));
+extern int cfreparse __P((void));
+
+#endif /* _CFPARSE_PROTO_H */
diff --git a/src/racoon/cftoken.c b/src/racoon/cftoken.c
new file mode 100644
index 0000000..a82b6a4
--- /dev/null
+++ b/src/racoon/cftoken.c
@@ -0,0 +1,4803 @@
+
+#line 3 "cftoken.c"
+
+#define  YY_INT_ALIGNED short int
+
+/* A lexical scanner generated by flex */
+
+#define FLEX_SCANNER
+#define YY_FLEX_MAJOR_VERSION 2
+#define YY_FLEX_MINOR_VERSION 5
+#define YY_FLEX_SUBMINOR_VERSION 35
+#if YY_FLEX_SUBMINOR_VERSION > 0
+#define FLEX_BETA
+#endif
+
+/* First, we deal with  platform-specific or compiler-specific issues. */
+
+/* begin standard C headers. */
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <stdlib.h>
+
+/* end standard C headers. */
+
+/* flex integer type definitions */
+
+#ifndef FLEXINT_H
+#define FLEXINT_H
+
+/* C99 systems have <inttypes.h>. Non-C99 systems may or may not. */
+
+#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
+
+/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h,
+ * if you want the limit (max/min) macros for int types. 
+ */
+#ifndef __STDC_LIMIT_MACROS
+#define __STDC_LIMIT_MACROS 1
+#endif
+
+#include <inttypes.h>
+typedef int8_t flex_int8_t;
+typedef uint8_t flex_uint8_t;
+typedef int16_t flex_int16_t;
+typedef uint16_t flex_uint16_t;
+typedef int32_t flex_int32_t;
+typedef uint32_t flex_uint32_t;
+#else
+typedef signed char flex_int8_t;
+typedef short int flex_int16_t;
+typedef int flex_int32_t;
+typedef unsigned char flex_uint8_t; 
+typedef unsigned short int flex_uint16_t;
+typedef unsigned int flex_uint32_t;
+
+/* Limits of integral types. */
+#ifndef INT8_MIN
+#define INT8_MIN               (-128)
+#endif
+#ifndef INT16_MIN
+#define INT16_MIN              (-32767-1)
+#endif
+#ifndef INT32_MIN
+#define INT32_MIN              (-2147483647-1)
+#endif
+#ifndef INT8_MAX
+#define INT8_MAX               (127)
+#endif
+#ifndef INT16_MAX
+#define INT16_MAX              (32767)
+#endif
+#ifndef INT32_MAX
+#define INT32_MAX              (2147483647)
+#endif
+#ifndef UINT8_MAX
+#define UINT8_MAX              (255U)
+#endif
+#ifndef UINT16_MAX
+#define UINT16_MAX             (65535U)
+#endif
+#ifndef UINT32_MAX
+#define UINT32_MAX             (4294967295U)
+#endif
+
+#endif /* ! C99 */
+
+#endif /* ! FLEXINT_H */
+
+#ifdef __cplusplus
+
+/* The "const" storage-class-modifier is valid. */
+#define YY_USE_CONST
+
+#else	/* ! __cplusplus */
+
+/* C99 requires __STDC__ to be defined as 1. */
+#if defined (__STDC__)
+
+#define YY_USE_CONST
+
+#endif	/* defined (__STDC__) */
+#endif	/* ! __cplusplus */
+
+#ifdef YY_USE_CONST
+#define yyconst const
+#else
+#define yyconst
+#endif
+
+/* Returned upon end-of-file. */
+#define YY_NULL 0
+
+/* Promotes a possibly negative, possibly signed char to an unsigned
+ * integer for use as an array index.  If the signed char is negative,
+ * we want to instead treat it as an 8-bit unsigned char, hence the
+ * double cast.
+ */
+#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c)
+
+/* Enter a start condition.  This macro really ought to take a parameter,
+ * but we do it the disgusting crufty way forced on us by the ()-less
+ * definition of BEGIN.
+ */
+#define BEGIN (yy_start) = 1 + 2 *
+
+/* Translate the current start state into a value that can be later handed
+ * to BEGIN to return to the state.  The YYSTATE alias is for lex
+ * compatibility.
+ */
+#define YY_START (((yy_start) - 1) / 2)
+#define YYSTATE YY_START
+
+/* Action number for EOF rule of a given start state. */
+#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1)
+
+/* Special action meaning "start processing a new file". */
+#define YY_NEW_FILE yyrestart(yyin  )
+
+#define YY_END_OF_BUFFER_CHAR 0
+
+/* Size of default input buffer. */
+#ifndef YY_BUF_SIZE
+#define YY_BUF_SIZE 16384
+#endif
+
+/* The state buf must be large enough to hold one state per character in the main buffer.
+ */
+#define YY_STATE_BUF_SIZE   ((YY_BUF_SIZE + 2) * sizeof(yy_state_type))
+
+#ifndef YY_TYPEDEF_YY_BUFFER_STATE
+#define YY_TYPEDEF_YY_BUFFER_STATE
+typedef struct yy_buffer_state *YY_BUFFER_STATE;
+#endif
+
+extern int yyleng;
+
+extern FILE *yyin, *yyout;
+
+#define EOB_ACT_CONTINUE_SCAN 0
+#define EOB_ACT_END_OF_FILE 1
+#define EOB_ACT_LAST_MATCH 2
+
+    #define YY_LESS_LINENO(n)
+    
+/* Return all but the first "n" matched characters back to the input stream. */
+#define yyless(n) \
+	do \
+		{ \
+		/* Undo effects of setting up yytext. */ \
+        int yyless_macro_arg = (n); \
+        YY_LESS_LINENO(yyless_macro_arg);\
+		*yy_cp = (yy_hold_char); \
+		YY_RESTORE_YY_MORE_OFFSET \
+		(yy_c_buf_p) = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \
+		YY_DO_BEFORE_ACTION; /* set up yytext again */ \
+		} \
+	while ( 0 )
+
+#define unput(c) yyunput( c, (yytext_ptr)  )
+
+#ifndef YY_TYPEDEF_YY_SIZE_T
+#define YY_TYPEDEF_YY_SIZE_T
+typedef size_t yy_size_t;
+#endif
+
+#ifndef YY_STRUCT_YY_BUFFER_STATE
+#define YY_STRUCT_YY_BUFFER_STATE
+struct yy_buffer_state
+	{
+	FILE *yy_input_file;
+
+	char *yy_ch_buf;		/* input buffer */
+	char *yy_buf_pos;		/* current position in input buffer */
+
+	/* Size of input buffer in bytes, not including room for EOB
+	 * characters.
+	 */
+	yy_size_t yy_buf_size;
+
+	/* Number of characters read into yy_ch_buf, not including EOB
+	 * characters.
+	 */
+	int yy_n_chars;
+
+	/* Whether we "own" the buffer - i.e., we know we created it,
+	 * and can realloc() it to grow it, and should free() it to
+	 * delete it.
+	 */
+	int yy_is_our_buffer;
+
+	/* Whether this is an "interactive" input source; if so, and
+	 * if we're using stdio for input, then we want to use getc()
+	 * instead of fread(), to make sure we stop fetching input after
+	 * each newline.
+	 */
+	int yy_is_interactive;
+
+	/* Whether we're considered to be at the beginning of a line.
+	 * If so, '^' rules will be active on the next match, otherwise
+	 * not.
+	 */
+	int yy_at_bol;
+
+    int yy_bs_lineno; /**< The line count. */
+    int yy_bs_column; /**< The column count. */
+    
+	/* Whether to try to fill the input buffer when we reach the
+	 * end of it.
+	 */
+	int yy_fill_buffer;
+
+	int yy_buffer_status;
+
+#define YY_BUFFER_NEW 0
+#define YY_BUFFER_NORMAL 1
+	/* When an EOF's been seen but there's still some text to process
+	 * then we mark the buffer as YY_EOF_PENDING, to indicate that we
+	 * shouldn't try reading from the input source any more.  We might
+	 * still have a bunch of tokens to match, though, because of
+	 * possible backing-up.
+	 *
+	 * When we actually see the EOF, we change the status to "new"
+	 * (via yyrestart()), so that the user can continue scanning by
+	 * just pointing yyin at a new input file.
+	 */
+#define YY_BUFFER_EOF_PENDING 2
+
+	};
+#endif /* !YY_STRUCT_YY_BUFFER_STATE */
+
+/* Stack of input buffers. */
+static size_t yy_buffer_stack_top = 0; /**< index of top of stack. */
+static size_t yy_buffer_stack_max = 0; /**< capacity of stack. */
+static YY_BUFFER_STATE * yy_buffer_stack = 0; /**< Stack as an array. */
+
+/* We provide macros for accessing buffer states in case in the
+ * future we want to put the buffer states in a more general
+ * "scanner state".
+ *
+ * Returns the top of the stack, or NULL.
+ */
+#define YY_CURRENT_BUFFER ( (yy_buffer_stack) \
+                          ? (yy_buffer_stack)[(yy_buffer_stack_top)] \
+                          : NULL)
+
+/* Same as previous macro, but useful when we know that the buffer stack is not
+ * NULL or when we need an lvalue. For internal use only.
+ */
+#define YY_CURRENT_BUFFER_LVALUE (yy_buffer_stack)[(yy_buffer_stack_top)]
+
+/* yy_hold_char holds the character lost when yytext is formed. */
+static char yy_hold_char;
+static int yy_n_chars;		/* number of characters read into yy_ch_buf */
+int yyleng;
+
+/* Points to current character in buffer. */
+static char *yy_c_buf_p = (char *) 0;
+static int yy_init = 0;		/* whether we need to initialize */
+static int yy_start = 0;	/* start state number */
+
+/* Flag which is used to allow yywrap()'s to do buffer switches
+ * instead of setting up a fresh yyin.  A bit of a hack ...
+ */
+static int yy_did_buffer_switch_on_eof;
+
+void yyrestart (FILE *input_file  );
+void yy_switch_to_buffer (YY_BUFFER_STATE new_buffer  );
+YY_BUFFER_STATE yy_create_buffer (FILE *file,int size  );
+void yy_delete_buffer (YY_BUFFER_STATE b  );
+void yy_flush_buffer (YY_BUFFER_STATE b  );
+void yypush_buffer_state (YY_BUFFER_STATE new_buffer  );
+void yypop_buffer_state (void );
+
+static void yyensure_buffer_stack (void );
+static void yy_load_buffer_state (void );
+static void yy_init_buffer (YY_BUFFER_STATE b,FILE *file  );
+
+#define YY_FLUSH_BUFFER yy_flush_buffer(YY_CURRENT_BUFFER )
+
+YY_BUFFER_STATE yy_scan_buffer (char *base,yy_size_t size  );
+YY_BUFFER_STATE yy_scan_string (yyconst char *yy_str  );
+YY_BUFFER_STATE yy_scan_bytes (yyconst char *bytes,int len  );
+
+void *yyalloc (yy_size_t  );
+void *yyrealloc (void *,yy_size_t  );
+void yyfree (void *  );
+
+#define yy_new_buffer yy_create_buffer
+
+#define yy_set_interactive(is_interactive) \
+	{ \
+	if ( ! YY_CURRENT_BUFFER ){ \
+        yyensure_buffer_stack (); \
+		YY_CURRENT_BUFFER_LVALUE =    \
+            yy_create_buffer(yyin,YY_BUF_SIZE ); \
+	} \
+	YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \
+	}
+
+#define yy_set_bol(at_bol) \
+	{ \
+	if ( ! YY_CURRENT_BUFFER ){\
+        yyensure_buffer_stack (); \
+		YY_CURRENT_BUFFER_LVALUE =    \
+            yy_create_buffer(yyin,YY_BUF_SIZE ); \
+	} \
+	YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \
+	}
+
+#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol)
+
+/* Begin user sect3 */
+
+typedef unsigned char YY_CHAR;
+
+FILE *yyin = (FILE *) 0, *yyout = (FILE *) 0;
+
+typedef int yy_state_type;
+
+extern int yylineno;
+
+int yylineno = 1;
+
+extern char *yytext;
+#define yytext_ptr yytext
+
+static yy_state_type yy_get_previous_state (void );
+static yy_state_type yy_try_NUL_trans (yy_state_type current_state  );
+static int yy_get_next_buffer (void );
+static void yy_fatal_error (yyconst char msg[]  );
+
+/* Done after the current pattern has been matched and before the
+ * corresponding action - sets up yytext.
+ */
+#define YY_DO_BEFORE_ACTION \
+	(yytext_ptr) = yy_bp; \
+	(yytext_ptr) -= (yy_more_len); \
+	yyleng = (size_t) (yy_cp - (yytext_ptr)); \
+	(yy_hold_char) = *yy_cp; \
+	*yy_cp = '\0'; \
+	(yy_c_buf_p) = yy_cp;
+
+#define YY_NUM_RULES 301
+#define YY_END_OF_BUFFER 302
+/* This struct is not used in this scanner,
+   but its presence is necessary. */
+struct yy_trans_info
+	{
+	flex_int32_t yy_verify;
+	flex_int32_t yy_nxt;
+	};
+static yyconst flex_int16_t yy_accept[1781] =
+    {   0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+      302,  300,  296,  297,  300,  298,  300,  300,  292,  292,
+      292,  295,  299,  283,  300,  300,  300,  300,  295,  295,
+      295,  295,  295,  295,  300,  300,  300,  300,  300,  300,
+      300,  300,  300,  300,  300,  300,  300,  300,  300,  300,
+      295,  300,  300,  300,  300,  300,  300,  300,  300,  295,
+      300,  300,    2,    6,   14,  295,  295,  300,  300,  300,
+
+       17,   28,  295,  295,  300,  300,  300,  295,  300,  300,
+      300,   30,   36,  295,  295,  300,  300,   38,   45,  295,
+      300,  300,  300,   92,   99,   89,  295,  295,  295,  295,
+      300,  300,  300,  300,  300,  300,  300,  300,   62,   90,
+      295,  295,  300,  300,  300,  300,   47,   60,  107,  300,
+      295,  295,  300,  106,  119,  295,  295,  295,  295,  300,
+      300,  300,  300,  300,  300,  108,  295,  300,  123,  126,
+      295,  295,  295,  295,  295,  295,  300,  300,  300,  300,
+      300,  300,  300,  300,  300,  300,  300,  300,  300,  300,
+      300,  124,  295,  295,  295,  295,  300,  300,  300,  300,
+
+      183,  184,  197,  300,  300,  296,    0,  294,  298,  202,
+      200,  295,  295,  292,    0,  295,    0,  284,  285,  286,
+        0,  295,  295,  204,    0,    0,    0,  295,  295,  295,
+        0,  295,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,  291,    0,
+        0,  198,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,  295,  295,    0,    0,    0,
+        0,  295,    0,    0,  291,    0,    0,    0,    0,    0,
+
+      295,    0,    0,    0,    0,    0,    0,    0,    0,  295,
+        0,  295,    0,  295,    0,    0,    0,    0,    0,    0,
+        0,  291,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,  295,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,  295,    0,  295,  295,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,  291,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+
+        0,    0,    0,    0,    0,    0,  202,  202,  200,  295,
+      293,  295,    0,  201,  295,  222,    0,    0,    0,    0,
+        0,    0,  295,  211,    0,  295,  203,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,  248,  237,
+      288,    0,    0,    0,  199,  246,    0,  219,  213,    0,
+        0,  287,    0,    0,  281,  208,    0,    0,  209,    0,
+        0,    0,  290,    0,    0,    0,    0,    0,    0,   19,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+      295,    0,    0,    0,    0,    0,  295,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+
+        0,    0,    0,    0,  295,    0,    0,    0,  295,    0,
+        0,    0,    0,    0,    0,    0,    0,   78,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,  103,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,  130,  170,  203,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,  287,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+
+        0,    0,    0,    0,    0,    0,  202,  200,  212,    0,
+        0,    0,    0,  283,    0,    0,    0,    0,    0,    0,
+        0,  282,  275,    0,    0,  289,    0,  206,  214,    0,
+        0,  236,  288,    0,    0,    0,  221,    0,    0,    0,
+        0,    0,    0,  287,  238,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    7,    0,    0,    0,    0,    0,    0,    3,
+        0,    0,    0,    0,    0,    0,    0,    0,   23,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,  295,   65,
+
+        0,    0,   79,    0,    0,    0,    0,   76,    0,    0,
+        0,    0,    0,    0,    0,    0,   51,    0,   49,   50,
+        0,    0,    0,    0,  104,    0,    0,  115,    0,    0,
+        0,    0,    0,    0,    0,  114,    0,    0,    0,  127,
+      169,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,  128,
+        0,    0,    0,    0,  161,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,  168,    0,
+        0,    0,  143,    0,    0,  187,    0,    0,    0,    0,
+        0,    0,  186,    0,    0,  217,    0,    0,    0,  283,
+
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+      289,    0,  207,    0,  276,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,  239,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,   91,    0,    4,    0,    0,    0,    0,    0,
+        0,   24,   20,    0,    0,    0,    0,    0,    0,   41,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,   75,   66,    0,    0,    0,
+        0,    0,    0,    0,    0,   67,    0,    0,    0,    0,
+
+      102,    0,  105,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,  164,    0,    0,    0,
+        0,    0,    0,  163,    0,  159,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+      174,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,  279,    0,    0,    0,    0,
+        0,    0,    0,  261,    0,    0,    0,    0,    0,    0,
+      205,  288,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,  262,  263,  260,  287,  241,    0,
+
+        0,    0,  243,  245,  278,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,   37,    0,    0,    0,  120,  100,
+        5,    0,    0,    0,    0,    0,   11,   25,   26,   27,
+       22,    0,    0,    0,    0,    0,    0,    0,   39,    0,
+        0,    0,    0,    0,   96,   97,    0,    0,    0,    0,
+       81,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+       77,    0,    0,   74,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,  146,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,  177,    0,    0,    0,  162,    0,  153,    0,    0,
+        0,    0,    0,    0,  192,    0,    0,    0,  195,    0,
+      277,    0,    0,  215,    0,  247,    0,    0,  235,  252,
+      253,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,  249,    0,    0,    0,    0,    0,    0,    0,    0,
+      224,    0,    0,    0,    0,    0,    0,    0,   15,   46,
+        0,   29,    1,    0,    0,    8,   13,    0,   21,    0,
+        0,    0,    0,    0,    0,    0,    0,   93,    0,    0,
+       95,    0,    0,    0,    0,    0,    0,    0,   85,    0,
+
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,   53,   54,   52,   48,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,  122,    0,  142,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,  166,
+        0,    0,    0,    0,    0,  154,  134,    0,  149,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,  216,  225,  280,  218,  210,    0,  227,    0,    0,
+        0,  250,  251,  254,  255,  256,  257,  258,  226,  220,
+        0,  223,  240,  242,  244,    0,    0,    0,    0,    0,
+
+        0,    0,   61,   12,    0,    0,    0,    0,    0,    0,
+        0,   43,    0,    0,   94,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,   64,   63,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,  113,    0,    0,  110,    0,    0,    0,  150,    0,
+        0,    0,  176,    0,    0,    0,    0,  175,    0,    0,
+        0,    0,  167,  180,    0,    0,    0,    0,    0,    0,
+        0,    0,  182,    0,    0,    0,    0,    0,    0,    0,
+        0,  191,    0,    0,    0,  185,  196,    0,  228,    0,
+        0,    0,    0,    0,    0,  274,  273,    0,    0,    0,
+
+        0,    0,    0,    0,    0,    0,   31,    0,   42,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,   84,
+       87,   80,    0,   86,    0,   56,    0,   57,    0,   55,
+      101,    0,    0,    0,    0,    0,  109,  121,    0,    0,
+      171,    0,  172,    0,    0,    0,    0,    0,  135,  131,
+      165,    0,    0,    0,    0,    0,    0,  178,  144,    0,
+      148,  132,    0,    0,    0,    0,    0,    0,    0,    0,
+      193,    0,  264,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,  194,   16,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,   73,    0,    0,    0,    0,    0,
+
+        0,    0,    0,   58,    0,    0,    0,    0,  111,    0,
+      129,    0,    0,    0,    0,  136,    0,    0,    0,    0,
+      151,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,  230,    0,    0,    0,  232,  234,
+        0,    0,    0,    0,    0,    0,    0,    0,   10,    0,
+        0,    0,    0,    0,   40,    0,    0,   70,   69,    0,
+       72,    0,    0,   88,    0,   59,    0,    0,    0,    0,
+        0,  173,    0,    0,    0,    0,    0,    0,    0,    0,
+      179,    0,    0,    0,  147,    0,    0,  138,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+
+        0,    0,    0,    0,    0,    0,    0,    0,   34,    0,
+        0,    0,    0,   71,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,  155,
+        0,    0,    0,    0,    0,    0,  229,  231,  233,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,   82,    0,   83,    0,    0,
+        0,  112,    0,  125,    0,  133,    0,  137,  158,    0,
+        0,    0,  156,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,  259,    0,    0,    0,    0,   18,    9,   35,
+       33,    0,   44,   98,   68,    0,    0,    0,    0,    0,
+
+        0,  145,    0,  160,    0,    0,    0,    0,  190,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,  152,  157,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,  270,  269,  272,  271,   32,    0,    0,
+        0,  141,  139,    0,    0,    0,    0,  268,  266,  267,
+      265,    0,    0,    0,  140,  181,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+      116,    0,  188,    0,  118,  189,    0,    0,  117,    0
+    } ;
+
+static yyconst flex_int32_t yy_ec[256] =
+    {   0,
+        1,    1,    1,    1,    1,    1,    1,    1,    2,    3,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    2,    1,    4,    5,    1,    6,    1,    1,    1,
+        1,    1,    1,    7,    8,    9,   10,   11,   12,   13,
+       14,   15,   16,   17,   18,   19,   20,   21,   22,    1,
+        1,    1,    1,    1,   23,   24,   23,   23,   23,   23,
+       25,   25,   25,   25,   26,   25,   27,   25,   25,   25,
+       25,   25,   25,   28,   25,   25,   25,   25,   25,   25,
+       29,    1,   30,    1,   31,    1,   32,   33,   34,   35,
+
+       36,   37,   38,   39,   40,   41,   42,   43,   44,   45,
+       46,   47,   48,   49,   50,   51,   52,   53,   54,   55,
+       56,   57,   58,    1,   59,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1
+    } ;
+
+static yyconst flex_int32_t yy_meta[60] =
+    {   0,
+        1,    1,    2,    1,    1,    3,    1,    1,    3,    1,
+        4,    4,    4,    4,    4,    4,    4,    4,    4,    4,
+        5,    1,    6,    6,    7,    7,    7,    7,    1,    1,
+        1,    6,    6,    6,    6,    6,    6,    7,    7,    7,
+        7,    7,    7,    7,    7,    7,    7,    7,    7,    7,
+        7,    7,    7,    7,    7,    7,    7,    1,    1
+    } ;
+
+static yyconst flex_int16_t yy_base[1793] =
+    {   0,
+        0,    0,   26,   44,   27,   58,   68,   87, 2115, 2114,
+       90,  106,  103,  114,  134,  136,   98,  143,  196,    0,
+      165,  167,    0,    0,    0,    0,  215,  227,  279,    0,
+       31,   40,  332,    0,  360,  388,    0,    0,   61,   81,
+     2135, 2138, 2132, 2138, 2129,    0,    0,    0,  442, 2077,
+      130, 2125, 2138, 2124, 2105, 2104, 2103,    0,  172,   93,
+       75,  169,  226,  100, 2076,  135,  120,  174, 2068,  222,
+       16,   77, 2075,  208,  199,  229,  231, 2087, 2090, 2085,
+      261, 2070,  237,  252,  254,  164,  268,  238,  293,  285,
+      229,  245, 2138, 2138, 2138,  297,  269,  297,  140,  307,
+
+     2138, 2138,  300,  339,  367,  181, 2087,  388,  316,  375,
+      377, 2138, 2138, 2083,  394,  402,  431, 2138, 2138,  458,
+      446,  264,  322, 2138, 2138, 2138,   71,  463,  466,  465,
+      285,  473,  454,  480,  485,  489,  501, 2077, 2138, 2138,
+     2065,  503,  389,   51,  489, 2079, 2138, 2138, 2138, 2082,
+     2068,  357,  305, 2138, 2138, 2060,  493,  518,  521,  526,
+      280,  512,   82,  529,  538, 2138, 2066,  540, 2138, 2138,
+     2072,  544,  545,  574,  556,  561,  354,  570,  252,  428,
+      562,  582,  451,  550,  589,  596,  606,  581, 2073, 2072,
+      498, 2138, 2055,  616,  627,  631, 2056,  611,  587,  624,
+
+     2138, 2138, 2138,  385,  618, 2103, 2100, 2138,    0, 2097,
+        0,    0, 2096, 2046,    0,  374, 2065, 2138, 2138, 2138,
+     2069,  181,  592, 2138, 2053, 2051, 2045,  635,  308,  643,
+     2045,   61, 2047, 2050, 2057, 2041, 2058, 2037, 2055, 2043,
+     2050, 2051, 2028, 2048, 2032, 2065, 2035, 2044, 2033, 2034,
+     2039, 2138, 2035, 2038,  425, 2032, 2040, 2037, 2038, 2036,
+     2030, 2020, 2028, 2019, 2017, 2027, 2017, 2009, 2010, 2015,
+     2008, 2021, 2022, 2023, 2004, 2015, 2017,  610,  502, 2007,
+     2010,  448, 2000, 2002, 2011,  648,  645, 2012, 2010, 2008,
+     1994,  664, 1993, 2004,  638, 1991, 2005, 1983, 1992, 1987,
+
+      656, 1985, 2002, 1984, 1980, 1980, 1979, 1980, 1996,  665,
+     1976,  499, 1981,  667, 1975, 1978, 1989, 1990, 1987, 1975,
+     1968, 1973, 1973, 1966, 1969, 1979, 1960, 1969, 1961, 1965,
+     1958,  646, 1963,  634, 1958, 1973,  546, 1960,  642, 1958,
+     1957, 1951, 1950, 1956, 1965, 1962, 1960, 1965, 1945, 1950,
+      664, 1947, 1953, 1953,  668, 1939,  681,  684, 1957, 1957,
+     1937, 1946, 1950, 1937,  671, 1934, 1937, 1945, 1944,  309,
+      661,  547, 1942, 1938, 1942, 1945, 1924, 1929, 1937, 1922,
+     1935,  694, 1938,  673, 1921, 1919,  511, 1916, 1917,  440,
+      669, 1925,  671, 1932, 1952, 1910, 1910, 1909, 1928, 1924,
+
+     1907, 1906, 1918,  677, 1903, 1916,    0, 1946,    0,    0,
+        0,  686, 1915, 2138,  704, 2138, 1938, 1895, 1912, 1911,
+     1895, 1894,  716, 1913, 1893,  717, 2138, 1906, 1896, 1908,
+     1905, 1889, 1888, 1889, 1903, 1888, 1893, 1890, 2138, 2138,
+      677, 1884, 1899, 1886, 2138, 2138, 1897, 2138, 2138, 1882,
+      688,  682,  727, 1881, 2138, 2138, 1889, 1887, 2138, 1874,
+     1887, 1870, 2138, 1873,  703,  710, 1876, 1871, 1866, 2138,
+      709, 1881, 1876, 1861, 1867, 1867, 1875, 1864, 1857, 1859,
+      724, 1856, 1863, 1868, 1873, 1863,  738, 1856, 1855, 1860,
+     1854, 1855, 1857, 1861, 1855, 1854, 1861, 1850, 1851, 1845,
+
+     1853, 1837, 1837, 1836,  740, 1846, 1839, 1846,  741, 1867,
+     1829, 1837, 1832, 1846, 1827,  704,  718, 2138, 1845, 1832,
+     1834, 1837, 1832, 1820, 1820, 1820, 1832, 1832, 1815, 1814,
+      706, 1814, 1807, 1817, 2138, 1817, 1808, 1820, 1822, 1810,
+     1807,  718, 1819, 1814, 1822, 1806, 1815, 1805, 1813, 1799,
+     1811, 1810, 1794, 1793, 1803, 1804, 1791, 2138, 1809, 1808,
+     1804, 1798, 1802, 1799,  720, 1803, 1782, 1796, 1795, 1783,
+     1793, 1783,  724, 1787, 1795,  730, 1769, 1774, 1774, 1782,
+     1771, 1780, 1772, 1766, 1777,  726, 1781, 1763, 1774, 1766,
+     1776, 1763, 1770, 1767, 1788, 1756, 1767, 1769, 1766, 1754,
+
+      736, 1763, 1765, 1764, 1759, 1790,    0, 2138, 2138, 1765,
+     1760, 1760, 1757, 1743, 1749, 1779, 1745, 1757,  730, 1748,
+     1775, 2138, 2138, 1739, 1754, 1734, 1743, 1765, 2138, 1737,
+     1745, 2138, 2138, 1728,  779, 1746, 1746, 1726, 1740, 1729,
+     1737, 1732, 1726, 2138, 2138,  764, 1751, 1757, 1732, 1718,
+     1726, 1734, 1718, 1724, 1719, 1721, 1709, 1707, 1724, 1721,
+     1725, 1715, 2138, 1704, 1702, 1715, 1702, 1704, 1702, 1717,
+     1695,  737, 1694, 1705, 1694, 1696, 1704, 1692, 2138, 1703,
+     1699, 1686, 1693, 1690, 1701, 1689, 1700, 1688, 1697, 1679,
+     1680, 1697, 1691, 1690, 1673, 1693, 1687, 1691,  763, 2138,
+
+     1674, 1668, 2138, 1676, 1703, 1685, 1670, 2138, 1677, 1683,
+     1661, 1681, 1660, 1674, 1694, 1677, 2138, 1676, 2138, 2138,
+     1657, 1665, 1674, 1647, 2138, 1655, 1665, 1650, 1650, 1642,
+     1646, 1645, 1660, 1656, 1642, 2138, 1636, 1642, 1654, 2138,
+     1639, 1632,  738, 1643, 1637, 1649,  764, 1647, 1632, 1650,
+     1645, 1631, 1628, 1641, 1637, 1638, 1641, 1642, 1622, 2138,
+     1641, 1636, 1619, 1633, 2138, 1628, 1617, 1631, 1629, 1619,
+     1617, 1622, 1614, 1624, 1628, 1626, 1623, 1610, 2138, 1603,
+     1617, 1622, 2138, 1613, 1615, 1600, 1600, 1592, 1607, 1599,
+     1614, 1593, 2138, 1598, 1630, 2138, 1591, 1593, 1595, 2138,
+
+      116,  169,  177,  189,  299,  376,  394,  769,  410,  737,
+     2138,  561, 2138,  603, 2138,  639,  789,  768,  778,  790,
+      790,  786,  792,  754,  771,  770,  778,  777,  759,  776,
+      781,  800,  805,  805,  809,  772, 2138,  774,  788,  777,
+      796,  792,  794,  790,  796,  795,  788,  800,  790,  800,
+      801,  792, 2138,  788, 2138,  793,  804,  807,  800,  805,
+      794,  833, 2138,  793,  805,  801,  800,  809,  803,  805,
+      813,  810,  807,  823,  807,  819,  817,  851,  820,  828,
+      818,  818,  826,  839,  836,  841, 2138,  823,  825,  826,
+      826,  827,  833,  850,  838, 2138,  851,  849,  849,  840,
+
+     2138,  843, 2138,  843,  854,  844,  852,  853,  858,  848,
+      862,  855,  860,  851,  855,  867, 2138,  859,  872,  871,
+      876,  873,  861, 2138,  866, 2138,  880,  873,  865,  883,
+      867,  886,  875,  879,  886,  885,  873,  892,  871,  894,
+     2138,  914,  896,  878,  880,  879,  897,  898,  882,  883,
+      886,  900,  881,  891,  908,  895,  895,  895,  908,  904,
+      913,  906,  935,  931,  899, 2138,  900,  911,  933,  909,
+      918,  941,  922, 2138,  941,  943,  929,  926,  923,  932,
+     2138,  914,  952,  952,  952,  950,  949,  955,  952,  952,
+      922,  929,  943,  940, 2138, 2138, 2138,  927, 2138,  962,
+
+      960,  968, 2138, 2138, 2138,  942,  934,  952,  937,  930,
+      956,  951,  953,  952, 2138,  954,  954,  946, 2138, 2138,
+     2138,  944,  955,  960,  961,  966, 2138, 2138, 2138, 2138,
+     2138,  961,  960,  957,  962,  972,  958,  969,  975,  976,
+      959,  977,  974,  976, 2138, 2138,  961,  964,  968,  976,
+     2138,  970,  966,  968,  983,  977,  979,  980,  977,  984,
+     2138,  993,  991, 2138,  992,  979,  997,  980,  986,  978,
+      998,  990,  991,  987,  989,  989, 1004,  998,  998,  998,
+     1005, 1000,  996,  998, 1013, 1010,  999, 2138, 1009,  998,
+     1003, 1023, 1018, 1006, 1021, 1027, 1017, 1021, 1027, 1023,
+
+     1020, 1028, 1021, 1035, 1018, 1033, 1036, 1040, 1024, 1042,
+     1039, 2138, 1021, 1042, 1039, 2138, 1029, 2138, 1050, 1043,
+     1040, 1033, 1033, 1035, 2138, 1057, 1047, 1048, 2138, 1050,
+     2138, 1055, 1063, 2138, 1060, 2138, 1084, 1083, 2138, 2138,
+     2138, 1057, 1084, 1069, 1067, 1088, 1087, 1086, 1093, 1090,
+     1093, 2138, 1096, 1071, 1077, 1063, 1070, 1097, 1100, 1104,
+     2138, 1083, 1079, 1070, 1071, 1091, 1087, 1084, 2138, 2138,
+     1087, 2138, 2138, 1094, 1093, 2138, 2138, 1079, 2138, 1076,
+     1099, 1074, 1098, 1099, 1099, 1090, 1104, 2138, 1094, 1102,
+     2138, 1099, 1094, 1089, 1093, 1091, 1113, 1099, 2138, 1114,
+
+     1132, 1133, 1097, 1093, 1101, 1107, 1117, 1119, 1109, 1106,
+     1113, 1122, 2138, 2138, 2138, 2138, 1107, 1120, 1111, 1122,
+     1123, 1128, 1114, 1114, 1132, 1116, 2138, 1129, 2138, 1136,
+     1124, 1140, 1136, 1125, 1137, 1140, 1141, 1138, 1123, 1142,
+     1150, 1131, 1137, 1131, 1149, 1148, 1136, 1135, 1149, 2138,
+     1154, 1156, 1157, 1143, 1151, 2138, 2138, 1146, 2138, 1150,
+     1166, 1164, 1167, 1154, 1161, 1155, 1163, 1165, 1168, 1172,
+     1174, 2138, 2138, 2138, 2138, 2138, 1162, 2138, 1200, 1165,
+     1167, 2138, 2138, 2138, 2138, 2138, 2138, 2138, 2138, 2138,
+     1182, 2138, 2138, 2138, 2138, 1174, 1185, 1179, 1190, 1190,
+
+     1179, 1189, 2138, 2138, 1194, 1191, 1192, 1186, 1194, 1192,
+     1190, 2138, 1201, 1199, 2138, 1188, 1191, 1185, 1189, 1193,
+     1191, 1206, 1190, 1198, 2138, 2138, 1197, 1209, 1196, 1197,
+     1197, 1200, 1198, 1209, 1219, 1204, 1204, 1221, 1216, 1211,
+     1222, 2138, 1219, 1213, 2138, 1211, 1209, 1231, 2138, 1208,
+     1233, 1210, 2138, 1236, 1237, 1233, 1239, 2138, 1237, 1216,
+     1233, 1238, 2138, 2138, 1235, 1240, 1220, 1229, 1243, 1234,
+     1234, 1250, 1252, 1233, 1240, 1242, 1251, 1253, 1240, 1253,
+     1258, 2138, 1247, 1259, 1249, 2138, 2138, 1263, 2138, 1281,
+     1279, 1287, 1250, 1269, 1267, 2138, 2138, 1272, 1273, 1253,
+
+     1272, 1258, 1257, 1274, 1279, 1275, 1282, 1278, 2138, 1264,
+     1281, 1285, 1280, 1272, 1286, 1270, 1288, 1277, 1275, 2138,
+     2138, 2138, 1271, 2138, 1272, 2138, 1280, 2138, 1292, 2138,
+     2138, 1297, 1284, 1286, 1283, 1296, 2138, 2138, 1298, 1284,
+     2138, 1296, 2138, 1293, 1291, 1290, 1294, 1295, 2138, 2138,
+     2138, 1305, 1294, 1308, 1294, 1301, 1293, 2138, 2138, 1314,
+     2138, 2138, 1309, 1301, 1302, 1316, 1317, 1314, 1323, 1311,
+     2138, 1308, 2138, 1341, 1346, 1346, 1350, 1333, 1334, 1335,
+     1333, 1334, 1324, 2138, 2138, 1334, 1340, 1321, 1328, 1331,
+     1341, 1325, 1328, 1335, 2138, 1329, 1344, 1330, 1346, 1341,
+
+     1352, 1352, 1342, 2138, 1340, 1339, 1346, 1361, 2138, 1353,
+     2138, 1358, 1352, 1350, 1351, 2138, 1353, 1354, 1360, 1351,
+     2138, 1365, 1352, 1359, 1366, 1359, 1361, 1357, 1364, 1398,
+     1366, 1361, 1382, 1374, 2138, 1399, 1397, 1405, 2138, 2138,
+     1384, 1385, 1378, 1378, 1386, 1380, 1388, 1390, 2138, 1384,
+     1395, 1390, 1393, 1388, 2138, 1395, 1392, 2138, 2138, 1390,
+     2138, 1404, 1401, 2138, 1389, 2138, 1399, 1409, 1409, 1406,
+     1412, 2138, 1409, 1402, 1403, 1396, 1412, 1417, 1410, 1411,
+     2138, 1416, 1436, 1399, 2138, 1404, 1425, 2138, 1417, 1426,
+     1408, 1443, 1446, 1449, 1420, 1428, 1422, 1430, 1431, 1428,
+
+     1420, 1430, 1422, 1429, 1437, 1434, 1424, 1431, 2138, 1427,
+     1425, 1443, 1440, 2138, 1439, 1436, 1451, 1441, 1436, 1435,
+     1451, 1448, 1433, 1458, 1442, 1449, 1450, 1457, 1461, 2138,
+     1440, 1457, 1464, 1453, 1457, 1462, 2138, 2138, 2138, 1462,
+     1454, 1464, 1456, 1450, 1471, 1455, 1473, 1457, 1475, 1456,
+     1470, 1475, 1477, 1466, 1481, 2138, 1473, 2138, 1474, 1477,
+     1483, 2138, 1466, 2138, 1489, 2138, 1490, 2138, 2138, 1489,
+     1486, 1485, 2138, 1491, 1490, 1485, 1493, 1488, 1497, 1481,
+     1499, 1483, 2138, 1492, 1502, 1494, 1504, 2138, 2138, 2138,
+     2138, 1490, 2138, 2138, 2138, 1511, 1505, 1498, 1498, 1490,
+
+     1496, 2138, 1512, 2138, 1509, 1514, 1520, 1506, 2138, 1508,
+     1518, 1510, 1520, 1506, 1509, 1508, 1511, 1522, 1530, 1517,
+     1515, 1529, 2138, 2138, 1517, 1531, 1534, 1525, 1521, 1520,
+     1523, 1522, 1525, 2138, 2138, 2138, 2138, 2138, 1532, 1527,
+     1537, 2138, 2138, 1529, 1537, 1544, 1541, 2138, 2138, 2138,
+     2138, 1544, 1543, 1533, 2138, 2138, 1534, 1535, 1541, 1537,
+     1550, 1551, 1552, 1543, 1554, 1550, 1549, 1552, 1557, 1554,
+     2138, 1564, 2138, 1549, 2138, 2138, 1562, 1558, 2138, 2138,
+     1602, 1609, 1613, 1607, 1617, 1620, 1622, 1625, 1626, 1630,
+     1633, 1627
+
+    } ;
+
+static yyconst flex_int16_t yy_def[1793] =
+    {   0,
+     1780,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,   19,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,   29,
+        1,    1,    1,   33,    1,    1,    1,    1,    1,    1,
+     1780, 1780, 1780, 1780, 1781, 1782, 1783, 1784, 1780,   49,
+       49, 1785, 1780, 1785, 1780, 1780, 1780, 1786, 1785, 1785,
+     1785, 1785, 1785, 1785, 1780, 1780, 1780, 1780, 1780, 1780,
+     1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780,
+     1785, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1785,
+     1780, 1780, 1780, 1780, 1780, 1785, 1785, 1780, 1780, 1780,
+
+     1780, 1780, 1785, 1785, 1780, 1780, 1780, 1785, 1780, 1780,
+     1780, 1780, 1780,   59, 1785, 1780, 1780, 1780, 1780, 1785,
+     1780, 1780, 1780, 1780, 1780, 1780,   59, 1785, 1785, 1785,
+     1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780,
+       59, 1785, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1786,
+       59, 1785, 1780, 1780, 1780,   59, 1785, 1785, 1785, 1780,
+     1780, 1780, 1780, 1780, 1780, 1780,   59, 1780, 1780, 1780,
+       59,  142, 1785, 1785, 1785, 1785, 1780, 1780, 1780, 1780,
+     1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780,
+     1780, 1780,   59, 1785, 1785, 1785, 1780, 1780, 1780, 1780,
+
+     1780, 1780, 1780, 1780, 1780, 1780, 1781, 1780, 1782, 1787,
+     1788, 1789, 1785,   49, 1790, 1785, 1780, 1780, 1780, 1780,
+     1786, 1785, 1785, 1780, 1780, 1780, 1780, 1785, 1785, 1785,
+     1780, 1785, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780,
+     1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780,
+     1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780,
+     1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780,
+     1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780,
+     1780, 1780, 1780, 1780, 1780, 1785, 1785, 1780, 1780, 1780,
+     1780, 1785, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780,
+
+     1785, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1785,
+     1780, 1785, 1780, 1785, 1780, 1780, 1780, 1780, 1780, 1780,
+     1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780,
+     1780, 1785, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780,
+     1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780,
+     1780, 1780, 1780, 1780, 1785, 1780, 1785, 1785, 1780, 1780,
+     1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780,
+     1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780,
+     1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780,
+     1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780,
+
+     1780, 1780, 1780, 1780, 1780, 1780, 1791, 1787, 1792, 1789,
+     1790, 1785, 1780, 1780, 1785, 1780, 1780, 1780, 1780, 1780,
+     1780, 1780, 1785, 1780, 1780, 1785, 1780, 1780, 1780, 1780,
+     1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780,
+     1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780,
+     1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780,
+     1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780,
+     1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780,
+     1785, 1780, 1780, 1780, 1780, 1780, 1785, 1780, 1780, 1780,
+     1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780,
+
+     1780, 1780, 1780, 1780, 1785, 1780, 1780, 1780, 1785, 1780,
+     1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780,
+     1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780,
+     1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780,
+     1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780,
+     1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780,
+     1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780,
+     1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780,
+     1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780,
+     1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780,
+
+     1780, 1780, 1780, 1780, 1780, 1780, 1791, 1780, 1780, 1780,
+     1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780,
+     1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780,
+     1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780,
+     1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780,
+     1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780,
+     1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780,
+     1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780,
+     1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780,
+     1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1785, 1780,
+
+     1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780,
+     1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780,
+     1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780,
+     1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780,
+     1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780,
+     1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780,
+     1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780,
+     1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780,
+     1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780,
+     1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780,
+
+     1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780,
+     1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780,
+     1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780,
+     1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780,
+     1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780,
+     1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780,
+     1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780,
+     1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780,
+     1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780,
+     1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780,
+
+     1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780,
+     1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780,
+     1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780,
+     1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780,
+     1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780,
+     1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780,
+     1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780,
+     1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780,
+     1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780,
+     1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780,
+
+     1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780,
+     1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780,
+     1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780,
+     1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780,
+     1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780,
+     1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780,
+     1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780,
+     1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780,
+     1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780,
+     1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780,
+
+     1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780,
+     1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780,
+     1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780,
+     1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780,
+     1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780,
+     1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780,
+     1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780,
+     1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780,
+     1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780,
+     1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780,
+
+     1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780,
+     1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780,
+     1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780,
+     1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780,
+     1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780,
+     1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780,
+     1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780,
+     1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780,
+     1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780,
+     1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780,
+
+     1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780,
+     1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780,
+     1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780,
+     1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780,
+     1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780,
+     1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780,
+     1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780,
+     1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780,
+     1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780,
+     1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780,
+
+     1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780,
+     1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780,
+     1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780,
+     1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780,
+     1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780,
+     1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780,
+     1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780,
+     1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780,
+     1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780,
+     1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780,
+
+     1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780,
+     1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780,
+     1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780,
+     1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780,
+     1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780,
+     1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780,
+     1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780,
+     1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780,
+     1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780,
+     1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780,
+
+     1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780,
+     1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780,
+     1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780,
+     1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780,
+     1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780,
+     1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780,
+     1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780,
+     1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780,
+     1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780,
+     1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780,
+
+     1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780,
+     1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780,
+     1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780,
+     1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780,
+     1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780,
+     1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780,
+     1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780,
+     1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780,    0,
+     1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780,
+     1780, 1780
+
+    } ;
+
+static yyconst flex_int16_t yy_nxt[2198] =
+    {   0,
+       42,   43,   44,   45,   46,   42,   42,   47,   42,   48,
+       49,   50,   50,   51,   50,   50,   50,   50,   50,   50,
+       52,   53,   52,   54,   42,   55,   56,   57,   58,   42,
+       42,   59,   60,   61,   62,   63,   64,   65,   66,   67,
+       42,   68,   69,   70,   71,   72,   73,   42,   74,   75,
+       76,   77,   78,   42,   79,   80,   42,   42,   42,   81,
+       90,  249,  167,   82,   91,   83,  212,  250,   84,   85,
+      168,  167,   86,  426,   87,   88,   89,   81,   92,  168,
+      212,   82,  203,   83,   93,   94,   84,   85,  169,   95,
+       86,   90,   87,   88,   89,   91,  335,  169,  212,  254,
+
+       96,   97,  203,  204,  310,  212,  228,   98,   95,   92,
+      229,  102,  205,  251,   99,   93,   94,  100,  349,   96,
+       97,  252,  311,  204,  103,  104,   98,  102,  253,  105,
+      254,  120,  205,   99,  106,  226,  100,  121,  108,  234,
+      103,  104,  122,  107,  123,  105,  109,  235,  227,  108,
+      106,  110,  111,  240,  241,  124,  125,  109,  968,  107,
+      112,  113,  110,  111,  216,  114,  242,  114,  115,  217,
+      115,  112,  113,  116,  212,  116,  120,  212,  237,  289,
+      238,  969,  121,  117, 1780,  117,  212,  122,  290,  123,
+      239,  118,  119,  118,  119,  278,  141,  142,  141,  142,
+
+      124,  125,  126,  143,  230,  143,  222,  223,  970,  243,
+      224,  144,  279,  144,  145,  415,  145,  146,  231,  146,
+      244,  225,  147,  148,  147,  148,  295,  127,  128,  129,
+      130,  212,  250,  131,  258,  132,  149,  259,  133,  971,
+      134,  255,  135,  150,  136,  137,  151,  256,  149,  138,
+      260,  152,  153,  139,  140,  150,  246,  257,  151,  232,
+      261,  247,  262,  152,  153,  265,  212,  248,  263,  281,
+      240,  272,  154,  258,  212,  233,  259,  284,  236,  265,
+      266,  273,  264,  242,  154,  155,  274,  372,  246,  260,
+      212,  275,  228,  247,  285,  307,  229,  276,  244,  277,
+
+      228,  255,  212,  280,  287,  212,  270,  256,  245,  249,
+      156,  157,  158,  212,  159,  250,  228,  257,  160,  347,
+      229,  161,  162,  283,  261,  163,  262,  164,  286,  165,
+      240,  241,  282,  316,  236,  292,  245,  166,  170,  226,
+      291,  288,  258,  242,  212,  259,  264,  298,  567,  231,
+      246,  972,  227,  341,  236,  247,  422,  308,  260,  568,
+      309,  248,  212,  171,  172,  173,  174,  175,  176,  177,
+      254,  178,  232,  179,  180,  181,  182,  183,  184,  212,
+      185,  186,  187,  188,  189,  190,  191,  293,  233,  367,
+      192,  193,  194,  212,  195,  196,  234,  197,  198,  212,
+
+      240,  241,  199,  236,  235,  340,  299,  973,  255,  412,
+      200,  294,  258,  242,  256,  259,  405,  201,  202,  193,
+      194,  232,  195,  196,  257,  197,  198,  300,  260,  230,
+      199,  974,  237,  302,  334,  240,  241,  233,  200,  448,
+      449,  245,  297,  231,  239,  201,  202,  212,  242,  977,
+      213,  303,  214,  214,  214,  214,  214,  214,  214,  214,
+      214,  214,  213,  212,  213,  213,  258,  373,  212,  259,
+      212,  212,  454,  213,  213,  213,  213,  213,  213,  240,
+      241,  304,  260,  379,  245,  457,  590,  251,  318,  228,
+      306,  477,  242,  229,  312,  252,  215,  228,  212,  319,
+
+      314,  229,  253,  305,  212,  226,  240,  241,  212,  315,
+      245,  313,  320,  395,  231,  321,  323,  317,  227,  242,
+      326,  324,  255,  212,  258,  322,  212,  259,  256,  396,
+      325,  250,  327,  254,  332,  226,  258,  447,  257,  259,
+      336,  474,  333,  507,  586,  226,  246,  328,  343,  228,
+      212,  247,  260,  229,  232,  587,  329,  248,  227,  240,
+      346,  212,  255,  344,  350,  345,  212,  348,  256,  261,
+      233,  262,  242,  240,  241,  355,  357,  351,  257,  212,
+      358,  380,  570, 1780,  353,  381,  242,  359,  382,  232,
+      461,  264,  383,  374,  532,  980,  246,  212,  384,  356,
+
+      234,  247,  437,  240,  368,  364,  366,  375,  235,  230,
+      365,  369,  360,  377,  370,  265,  371,  376,  361,  362,
+      363,  212,  255,  231,  385,  392,  403,  378,  256,  386,
+      266,  387,  212,  250,  259,  388,  212,  261,  257,  262,
+      212,  416,  402,  245,  472,  391,  389,  390,  212,  981,
+      212,  212,  265,  212,  237,  261,  238,  262,  226,  264,
+      473,  212,  230,  404,  232,  399,  239,  266,  406,  212,
+      212,  398,  212,  212,  982,  400,  231,  264,  420,  423,
+      233,  481,  443,  529,  421,  432,  212,  534,  490,  212,
+      415,  212,  424,  482,  436,  527,  487,  535,  505,  496,
+
+      423,  457,  561,  509,  562,  580,  457,  547,  447,  212,
+      569,  553,  591,  424,  457,  461,  424,  551,  583,  593,
+      604,  212,  212,  640,  420,  581,  633,  643,  634,  212,
+      421,  644,  554,  656,  624,  609,  641,  642,  645,  646,
+      647,  629,  648,  212,  661,  212,  212,  706,  636,  629,
+      649,  629,  611,  708,  657,  635,  721,  707,  618,  761,
+      636,  621,  731,  764,  753,  671,  789,  790,  212,  805,
+      635,  643,  699,  806,  774,  644,  857,  916,  985,  832,
+      978,  803,  803,  618,  975,  695,  979,  976,  986,  677,
+      817,  818,  819,  820,  833,  821,  822,  823,  920,  983,
+
+      987,  988,  989,  990,  984,  991,  992,  921,  993,  994,
+      995,  996,  922,  997,  883,  998,  999, 1000, 1001, 1003,
+     1002, 1004, 1005, 1006, 1007, 1008, 1009, 1010, 1011, 1012,
+     1013, 1014, 1015, 1016, 1017, 1018, 1019, 1020, 1021, 1022,
+     1023, 1024, 1025, 1026, 1027, 1028, 1029, 1030, 1031, 1032,
+     1033, 1034, 1035, 1036, 1037, 1038, 1039, 1040, 1041, 1042,
+     1043, 1044, 1045, 1046, 1047, 1048, 1051, 1052, 1053, 1054,
+     1055, 1056, 1057, 1058, 1059, 1060, 1061, 1049, 1050, 1062,
+     1063, 1064, 1065, 1069, 1071, 1072, 1073, 1074, 1066, 1075,
+     1076, 1077, 1078, 1079, 1067, 1070, 1080, 1081, 1082, 1083,
+
+     1084, 1085, 1068, 1086, 1087, 1088, 1089, 1090, 1091, 1092,
+     1093, 1094, 1095, 1096, 1097, 1098, 1099, 1100, 1101, 1102,
+     1103, 1104, 1105, 1106, 1107, 1108, 1109, 1110, 1111, 1112,
+     1113, 1114, 1115, 1116, 1117, 1118, 1119, 1120, 1121, 1122,
+     1123, 1124, 1125, 1126, 1127, 1128, 1129, 1130, 1131, 1132,
+     1133, 1134, 1135, 1136, 1137, 1139, 1140, 1138, 1141, 1142,
+     1143, 1144, 1145,  633, 1146, 1147, 1148, 1149, 1150, 1151,
+     1152, 1153, 1154, 1155, 1156, 1157,  644, 1158, 1159, 1160,
+     1161, 1162, 1163, 1164, 1166, 1165, 1167, 1168, 1169, 1170,
+     1171, 1172, 1173, 1174, 1175, 1176, 1177, 1178, 1179, 1180,
+
+     1181, 1182, 1183, 1184, 1185, 1186, 1187, 1188, 1189, 1190,
+     1191, 1192, 1193, 1194, 1195, 1196, 1197, 1198, 1199, 1200,
+     1201, 1202, 1203, 1204, 1205, 1206, 1208, 1209, 1210, 1212,
+     1213, 1214, 1211, 1215, 1216, 1207, 1217, 1218, 1219, 1220,
+     1221, 1222, 1223, 1224, 1225, 1226, 1227, 1228, 1229, 1230,
+     1231, 1232, 1233, 1234, 1235, 1236, 1237, 1238, 1240, 1241,
+     1242, 1243, 1244, 1245, 1246, 1247, 1248, 1249, 1250, 1251,
+     1253, 1239, 1254, 1255, 1256, 1252, 1257, 1258, 1260, 1261,
+     1262, 1263, 1264, 1265, 1266, 1267, 1164, 1268, 1165, 1269,
+     1259, 1270, 1271, 1272, 1273, 1274, 1275, 1276, 1277, 1278,
+
+     1279, 1280, 1282, 1283, 1284, 1285, 1286, 1287, 1288, 1289,
+     1290, 1291, 1292, 1293, 1294, 1281, 1295, 1296, 1297, 1298,
+     1299, 1300, 1301, 1302, 1303, 1304, 1305, 1306, 1307, 1308,
+     1309, 1310, 1311, 1312, 1313, 1314, 1315, 1316, 1317, 1318,
+     1319, 1320, 1321, 1322, 1323, 1324, 1325, 1326, 1327, 1328,
+     1329, 1330, 1331, 1332, 1333, 1334, 1335, 1336, 1337, 1338,
+     1339, 1340, 1341, 1342, 1343, 1344, 1345, 1346, 1347, 1348,
+     1349, 1350, 1351, 1352, 1353, 1354, 1355, 1356, 1357, 1358,
+     1359, 1360, 1361, 1362, 1363, 1364, 1365, 1366, 1367, 1368,
+     1369, 1370, 1372, 1373, 1374, 1375, 1376, 1377, 1379, 1380,
+
+     1381, 1382, 1383, 1378, 1384, 1385, 1277, 1386, 1371, 1387,
+     1388, 1389, 1390, 1391, 1393, 1392, 1394, 1395, 1396, 1397,
+     1398, 1399, 1400, 1401, 1402, 1403, 1404, 1405, 1406, 1407,
+     1408, 1409, 1410, 1411, 1412, 1413, 1414, 1415, 1416, 1417,
+     1418, 1419, 1420, 1421, 1422, 1423, 1424, 1425, 1426, 1427,
+     1428, 1429, 1430, 1431, 1432, 1433, 1434, 1435, 1436, 1437,
+     1438, 1439, 1440, 1441, 1442, 1443, 1444, 1445, 1446, 1447,
+     1448, 1449, 1450, 1451, 1452, 1453, 1454, 1455, 1456, 1457,
+     1458, 1459, 1460, 1461, 1462, 1463, 1465, 1466, 1464, 1467,
+     1468, 1469, 1470, 1471, 1472, 1473, 1474, 1476, 1477, 1478,
+
+     1479, 1480, 1481, 1482, 1483, 1484, 1485, 1486, 1487, 1488,
+     1489, 1475, 1490, 1491, 1492, 1493, 1494, 1495, 1496, 1497,
+     1498, 1499, 1500, 1501, 1502, 1503, 1504, 1505, 1506, 1507,
+     1508, 1509, 1510, 1511, 1512, 1513, 1514, 1515, 1516, 1517,
+     1518, 1519, 1520, 1521, 1522, 1523, 1524, 1525, 1526, 1527,
+     1528, 1529, 1530, 1531, 1532, 1533, 1534, 1535, 1536, 1537,
+     1539, 1538, 1540, 1541, 1542, 1543, 1544, 1546, 1548, 1549,
+     1550, 1551, 1552, 1553, 1554, 1555, 1556, 1557, 1558, 1559,
+     1560, 1561, 1545, 1547, 1562, 1563, 1564, 1565, 1566, 1567,
+     1568, 1569, 1570, 1571, 1572, 1573, 1574, 1575, 1576, 1577,
+
+     1578, 1579, 1580, 1581, 1582, 1583, 1584, 1585, 1586, 1587,
+     1588, 1589, 1590, 1591, 1592, 1593, 1594, 1595, 1597, 1599,
+     1600, 1601, 1602, 1603, 1604, 1605, 1606, 1607, 1608, 1609,
+     1610, 1611, 1612, 1596, 1598, 1613, 1614, 1615, 1616, 1617,
+     1618, 1619, 1620, 1621, 1622, 1623, 1624, 1625, 1626, 1627,
+     1628, 1629, 1630, 1631, 1632, 1633, 1634, 1635, 1636, 1637,
+     1638, 1639, 1640, 1641, 1642, 1643, 1644, 1645, 1646, 1647,
+     1648, 1649, 1650, 1651, 1652, 1653, 1654, 1655, 1656, 1657,
+     1658, 1659, 1660, 1661, 1662, 1663, 1664, 1665, 1666, 1667,
+     1668, 1669, 1670, 1671, 1672, 1673, 1674, 1675, 1676, 1677,
+
+     1678, 1679, 1680, 1681, 1682, 1683, 1684, 1685, 1686, 1687,
+     1688, 1689, 1690, 1691, 1692, 1693, 1694, 1695, 1696, 1697,
+     1698, 1699, 1700, 1701, 1702, 1703, 1704, 1705, 1706, 1707,
+     1708, 1709, 1710, 1711, 1712, 1713, 1714, 1715, 1716, 1717,
+     1718, 1719, 1720, 1721, 1722, 1723, 1724, 1725, 1726, 1727,
+     1728, 1729, 1730, 1731, 1732, 1733, 1734, 1735, 1736, 1737,
+     1738, 1739, 1740, 1741, 1742, 1743, 1744, 1745, 1746, 1747,
+     1748, 1749, 1750, 1751, 1752, 1753, 1754, 1755, 1756, 1757,
+     1758, 1759, 1760, 1761, 1762, 1763, 1764, 1765, 1766, 1767,
+     1768, 1769, 1770, 1771, 1772, 1773, 1774, 1775, 1776, 1777,
+
+     1778, 1779,  207,  207,  207,  207,  207,  207,  207,  209,
+      211,  209,  209,  209,  209,  209,  210,  210,  210,  213,
+      213,  213,  213,  221,  408,  408,  408,  408,  409,  410,
+      608,  410,  410,  411,  967,  411,  607,  966,  607,  607,
+      965,  964,  963,  962,  961,  960,  959,  958,  957,  800,
+      956,  955,  954,  953,  952,  951,  950,  949,  948,  947,
+      946,  945,  944,  943,  942,  941,  940,  939,  938,  937,
+      936,  935,  934,  933,  932,  931,  930,  929,  928,  927,
+      926,  925,  924,  923,  919,  918,  917,  915,  800,  914,
+      913,  912,  911,  910,  909,  908,  907,  906,  905,  800,
+
+      904,  903,  902,  901,  900,  899,  898,  897,  896,  895,
+      894,  893,  892,  891,  890,  889,  888,  887,  886,  885,
+      884,  882,  881,  880,  879,  878,  877,  876,  875,  874,
+      873,  872,  871,  870,  869,  868,  867,  866,  865,  864,
+      863,  862,  861,  860,  859,  858,  856,  839,  855,  854,
+      853,  852,  851,  850,  849,  848,  847,  846,  845,  844,
+      843,  842,  841,  840,  839,  838,  837,  836,  835,  834,
+      831,  830,  829,  828,  827,  826,  825,  824,  816,  815,
+      814,  813,  812,  811,  810,  809,  808,  807,  804,  803,
+      802,  801,  800,  799,  798,  797,  796,  795,  794,  793,
+
+      792,  791,  788,  787,  786,  785,  784,  783,  782,  781,
+      780,  779,  778,  777,  776,  775,  773,  772,  771,  770,
+      769,  768,  767,  766,  765,  763,  762,  760,  759,  758,
+      757,  756,  755,  754,  752,  751,  750,  749,  748,  747,
+      746,  745,  744,  743,  742,  741,  740,  739,  738,  737,
+      736,  735,  734,  733,  732,  730,  729,  728,  727,  726,
+      725,  724,  723,  722,  720,  719,  718,  717,  716,  715,
+      714,  713,  712,  711,  710,  709,  705,  704,  703,  702,
+      701,  700,  698,  697,  696,  694,  693,  692,  691,  690,
+      689,  688,  687,  686,  685,  684,  683,  682,  681,  680,
+
+      679,  678,  676,  675,  674,  673,  672,  670,  669,  668,
+      667,  666,  665,  664,  663,  662,  660,  659,  658,  655,
+      654,  653,  652,  651,  650,  649,  639,  638,  637,  636,
+      635,  632,  631,  630,  629,  628,  627,  626,  625,  624,
+      623,  622,  620,  619,  617,  616,  615,  614,  613,  612,
+      610,  407,  606,  605,  603,  602,  601,  600,  599,  598,
+      597,  596,  595,  594,  592,  589,  588,  585,  584,  582,
+      579,  578,  577,  576,  575,  574,  573,  572,  571,  566,
+      565,  564,  563,  560,  559,  558,  557,  556,  555,  552,
+      550,  549,  548,  546,  545,  544,  543,  542,  541,  540,
+
+      539,  538,  537,  536,  533,  531,  530,  528,  526,  525,
+      524,  523,  522,  521,  520,  519,  518,  517,  516,  515,
+      514,  513,  512,  511,  510,  508,  506,  504,  503,  502,
+      501,  500,  499,  498,  497,  495,  494,  493,  492,  491,
+      489,  488,  486,  485,  484,  483,  480,  479,  478,  476,
+      475,  471,  470,  469,  468,  467,  466,  465,  464,  463,
+      462,  461,  460,  459,  458,  457,  456,  455,  454,  453,
+      452,  451,  450,  447,  446,  445,  444,  443,  442,  441,
+      440,  439,  438,  437,  436,  435,  434,  433,  432,  431,
+      430,  429,  428,  427,  425,  419,  418,  417,  414,  413,
+
+     1780,  212,  407,  208,  206,  401,  397,  394,  393,  354,
+      352,  342,  339,  338,  337,  331,  330,  301,  296,  271,
+      269,  268,  267,  254,  245,  236,  220,  219,  218,  212,
+      212, 1780,  208,  206, 1780,  101,  101,   41, 1780, 1780,
+     1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780,
+     1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780,
+     1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780,
+     1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780,
+     1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780,
+     1780, 1780, 1780, 1780, 1780, 1780, 1780
+
+    } ;
+
+static yyconst flex_int16_t yy_chk[2198] =
+    {   0,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    3,
+        5,   71,   31,    3,    5,    3,  232,   71,    3,    3,
+       31,   32,    3,  232,    3,    3,    3,    4,    5,   32,
+       61,    4,   39,    4,    5,    5,    4,    4,   31,    7,
+        4,    6,    4,    4,    4,    6,  144,   32,   60,  144,
+
+        7,    7,   40,   39,  127,   64,   61,    7,    8,    6,
+       61,   11,   39,   72,    7,    6,    6,    7,  163,    8,
+        8,   72,  127,   40,   11,   11,    8,   12,   72,   11,
+      163,   17,   40,    8,   11,   60,    8,   17,   13,   64,
+       12,   12,   17,   11,   17,   12,   13,   64,   60,   14,
+       12,   13,   13,   67,   67,   17,   17,   14,  801,   12,
+       13,   13,   14,   14,   51,   15,   67,   16,   15,   51,
+       16,   14,   14,   15,   62,   16,   18,   59,   66,   99,
+       66,  802,   18,   15,   51,   16,  222,   18,   99,   18,
+       66,   15,   15,   16,   16,   86,   21,   21,   22,   22,
+
+       18,   18,   19,   21,   62,   22,   59,   59,  803,   68,
+       59,   21,   86,   22,   21,  222,   22,   21,   62,   22,
+       68,   59,   21,   21,   22,   22,  106,   19,   19,   19,
+       19,   63,  106,   19,   75,   19,   27,   75,   19,  804,
+       19,   74,   19,   27,   19,   19,   27,   74,   28,   19,
+       75,   27,   27,   19,   19,   28,   70,   74,   28,   63,
+       76,   70,   76,   28,   28,   77,   81,   70,   76,   88,
+       83,   83,   27,   88,   97,   63,   88,   91,   91,   92,
+       77,   83,   76,   83,   28,   29,   84,  179,   85,   88,
+       90,   84,   81,   85,   92,  122,   81,   84,  179,   85,
+
+       97,   87,   96,   87,   97,  103,   81,   87,   84,  122,
+       29,   29,   29,  229,   29,  122,   90,   87,   29,  161,
+       90,   29,   29,   90,   89,   29,   89,   29,   96,   29,
+       98,   98,   89,  131,  131,  103,  161,   29,   33,   96,
+      100,   98,  100,   98,  104,  100,   89,  109,  370,  103,
+      109,  805,   96,  153,  153,  109,  229,  123,  100,  370,
+      123,  109,  152,   33,   33,   33,   33,   33,   33,   33,
+      123,   33,  104,   33,   33,   33,   33,   33,   33,  216,
+       33,   33,   33,   33,   33,   33,   33,  104,  104,  177,
+       33,   35,   35,  108,   35,   35,  152,   35,   35,  115,
+
+      105,  105,   35,  177,  152,  152,  110,  806,  110,  216,
+       35,  105,  111,  105,  110,  111,  204,   35,   35,   36,
+       36,  108,   36,   36,  110,   36,   36,  111,  111,  115,
+       36,  807,  143,  115,  143,  116,  116,  108,   36,  255,
+      255,  204,  108,  115,  143,   36,   36,   49,  116,  809,
+       49,  116,   49,   49,   49,   49,   49,   49,   49,   49,
+       49,   49,   49,  120,   49,   49,  117,  180,  128,  117,
+      130,  129,  390,   49,   49,   49,   49,   49,   49,  121,
+      121,  117,  117,  183,  180,  282,  390,  183,  133,  120,
+      121,  282,  121,  120,  128,  183,   49,  129,  157,  133,
+
+      130,  129,  183,  120,  312,  128,  132,  132,  142,  130,
+      133,  129,  134,  191,  130,  134,  135,  132,  128,  132,
+      136,  135,  136,  158,  145,  134,  159,  145,  136,  191,
+      135,  134,  137,  135,  142,  157,  137,  279,  136,  137,
+      145,  279,  142,  312,  387,  142,  162,  137,  157,  158,
+      173,  162,  137,  158,  159,  387,  137,  162,  142,  160,
+      160,  175,  164,  158,  164,  159,  176,  162,  164,  165,
+      159,  165,  160,  168,  168,  172,  173,  165,  164,  174,
+      173,  184,  372,  172,  168,  184,  168,  173,  184,  175,
+      337,  165,  184,  181,  337,  812,  181,  223,  184,  172,
+
+      176,  181,  372,  178,  178,  175,  176,  181,  176,  174,
+      175,  178,  174,  182,  178,  188,  178,  181,  174,  174,
+      174,  194,  185,  174,  185,  188,  199,  182,  185,  186,
+      188,  186,  195,  182,  186,  186,  196,  187,  185,  187,
+      228,  223,  198,  199,  278,  187,  186,  186,  230,  814,
+      287,  332,  205,  286,  198,  200,  198,  200,  194,  187,
+      278,  301,  195,  200,  196,  195,  198,  205,  205,  292,
+      310,  194,  314,  355,  816,  196,  195,  200,  228,  230,
+      196,  286,  295,  334,  228,  334,  357,  339,  295,  358,
+      301,  412,  230,  287,  371,  332,  292,  339,  310,  301,
+
+      292,  351,  365,  314,  365,  382,  391,  351,  384,  415,
+      371,  357,  391,  292,  404,  393,  314,  355,  384,  393,
+      404,  423,  426,  451,  357,  382,  441,  452,  441,  481,
+      357,  452,  358,  465,  465,  412,  451,  451,  453,  453,
+      453,  466,  453,  487,  471,  505,  509,  516,  517,  542,
+      531,  565,  415,  517,  466,  471,  531,  516,  423,  573,
+      576,  426,  542,  576,  565,  481,  601,  601,  699,  619,
+      573,  586,  509,  619,  586,  586,  672,  743,  818,  646,
+      810,  672,  743,  509,  808,  505,  810,  808,  819,  487,
+      635,  635,  635,  635,  646,  635,  635,  635,  747,  817,
+
+      820,  821,  822,  823,  817,  824,  825,  747,  826,  827,
+      828,  829,  747,  830,  699,  831,  832,  833,  833,  834,
+      833,  835,  836,  838,  839,  840,  841,  842,  843,  844,
+      845,  846,  847,  848,  849,  850,  851,  852,  854,  856,
+      857,  858,  859,  860,  861,  862,  862,  862,  864,  865,
+      866,  867,  868,  869,  870,  871,  872,  873,  874,  875,
+      876,  877,  878,  878,  879,  880,  881,  882,  883,  884,
+      885,  886,  888,  889,  890,  891,  892,  880,  880,  893,
+      894,  895,  897,  898,  899,  900,  902,  904,  897,  905,
+      906,  907,  908,  909,  897,  898,  910,  911,  912,  913,
+
+      914,  915,  897,  916,  918,  919,  920,  921,  922,  923,
+      925,  927,  928,  929,  930,  931,  932,  933,  934,  935,
+      936,  937,  938,  939,  940,  942,  943,  944,  945,  946,
+      947,  948,  949,  950,  951,  952,  953,  954,  955,  956,
+      957,  958,  959,  960,  961,  962,  963,  964,  965,  967,
+      968,  969,  970,  971,  972,  973,  975,  972,  976,  977,
+      978,  979,  980,  982,  983,  984,  985,  986,  987,  988,
+      989,  990,  991,  992,  993,  994,  998, 1000, 1001, 1002,
+     1006, 1007, 1008, 1009, 1010, 1009, 1011, 1012, 1013, 1014,
+     1016, 1017, 1018, 1022, 1023, 1024, 1025, 1026, 1032, 1033,
+
+     1034, 1035, 1036, 1037, 1038, 1039, 1040, 1041, 1042, 1043,
+     1044, 1047, 1048, 1049, 1050, 1052, 1053, 1054, 1055, 1056,
+     1057, 1058, 1059, 1060, 1062, 1063, 1065, 1066, 1067, 1068,
+     1069, 1070, 1067, 1071, 1072, 1063, 1073, 1074, 1075, 1076,
+     1077, 1078, 1079, 1080, 1081, 1082, 1083, 1084, 1085, 1086,
+     1087, 1089, 1090, 1091, 1092, 1093, 1094, 1095, 1096, 1097,
+     1098, 1099, 1100, 1101, 1102, 1103, 1104, 1105, 1106, 1107,
+     1108, 1095, 1109, 1110, 1111, 1107, 1113, 1114, 1115, 1117,
+     1119, 1120, 1121, 1122, 1123, 1124, 1121, 1126, 1121, 1127,
+     1114, 1128, 1130, 1132, 1133, 1135, 1137, 1138, 1142, 1143,
+
+     1144, 1145, 1146, 1147, 1148, 1149, 1150, 1151, 1153, 1154,
+     1155, 1156, 1157, 1158, 1159, 1145, 1160, 1162, 1163, 1164,
+     1165, 1166, 1167, 1168, 1171, 1174, 1175, 1178, 1180, 1181,
+     1182, 1183, 1184, 1185, 1186, 1187, 1189, 1190, 1192, 1193,
+     1194, 1195, 1196, 1197, 1198, 1200, 1201, 1202, 1203, 1204,
+     1205, 1206, 1207, 1208, 1209, 1210, 1211, 1212, 1217, 1218,
+     1219, 1220, 1221, 1222, 1223, 1224, 1225, 1226, 1228, 1230,
+     1231, 1232, 1233, 1234, 1235, 1236, 1237, 1238, 1239, 1240,
+     1241, 1242, 1243, 1244, 1245, 1246, 1247, 1248, 1249, 1251,
+     1252, 1253, 1254, 1255, 1258, 1260, 1261, 1262, 1263, 1264,
+
+     1265, 1266, 1267, 1262, 1268, 1269, 1268, 1270, 1253, 1271,
+     1277, 1279, 1279, 1279, 1280, 1279, 1281, 1291, 1296, 1297,
+     1298, 1299, 1300, 1301, 1302, 1305, 1306, 1307, 1308, 1309,
+     1310, 1311, 1313, 1314, 1316, 1317, 1318, 1319, 1320, 1321,
+     1322, 1323, 1324, 1327, 1328, 1329, 1330, 1331, 1332, 1333,
+     1334, 1335, 1336, 1337, 1338, 1339, 1340, 1341, 1343, 1344,
+     1346, 1347, 1348, 1350, 1351, 1352, 1354, 1355, 1356, 1357,
+     1359, 1360, 1361, 1362, 1365, 1366, 1367, 1368, 1369, 1370,
+     1371, 1372, 1373, 1374, 1375, 1376, 1377, 1378, 1376, 1379,
+     1380, 1381, 1383, 1384, 1385, 1388, 1390, 1391, 1392, 1393,
+
+     1394, 1395, 1398, 1399, 1400, 1401, 1402, 1403, 1404, 1405,
+     1406, 1390, 1407, 1408, 1410, 1411, 1412, 1413, 1414, 1415,
+     1416, 1417, 1418, 1419, 1423, 1425, 1427, 1429, 1432, 1433,
+     1434, 1435, 1436, 1439, 1440, 1442, 1444, 1445, 1446, 1447,
+     1448, 1452, 1453, 1454, 1455, 1456, 1457, 1460, 1463, 1464,
+     1465, 1466, 1467, 1468, 1469, 1470, 1472, 1474, 1475, 1475,
+     1476, 1475, 1477, 1478, 1479, 1480, 1481, 1482, 1483, 1486,
+     1487, 1488, 1489, 1490, 1491, 1492, 1493, 1494, 1496, 1497,
+     1498, 1499, 1481, 1482, 1500, 1501, 1502, 1503, 1505, 1506,
+     1507, 1508, 1510, 1512, 1513, 1514, 1515, 1517, 1518, 1519,
+
+     1520, 1522, 1523, 1524, 1525, 1526, 1527, 1528, 1529, 1530,
+     1531, 1532, 1533, 1534, 1536, 1537, 1538, 1541, 1542, 1543,
+     1544, 1545, 1546, 1547, 1548, 1550, 1551, 1552, 1553, 1554,
+     1556, 1557, 1560, 1541, 1542, 1562, 1563, 1565, 1567, 1568,
+     1569, 1570, 1571, 1573, 1574, 1575, 1576, 1577, 1578, 1579,
+     1580, 1582, 1583, 1584, 1586, 1587, 1589, 1590, 1591, 1592,
+     1593, 1594, 1595, 1596, 1597, 1598, 1599, 1600, 1601, 1602,
+     1603, 1604, 1605, 1606, 1607, 1608, 1610, 1611, 1612, 1613,
+     1615, 1616, 1617, 1618, 1619, 1620, 1621, 1622, 1623, 1624,
+     1625, 1626, 1627, 1628, 1629, 1631, 1632, 1633, 1634, 1635,
+
+     1636, 1640, 1641, 1642, 1643, 1644, 1645, 1646, 1647, 1648,
+     1649, 1650, 1651, 1652, 1653, 1654, 1655, 1657, 1659, 1660,
+     1661, 1663, 1665, 1667, 1670, 1671, 1672, 1674, 1675, 1676,
+     1677, 1678, 1679, 1680, 1681, 1682, 1684, 1685, 1686, 1687,
+     1692, 1696, 1697, 1698, 1699, 1700, 1701, 1703, 1705, 1706,
+     1707, 1708, 1710, 1711, 1712, 1713, 1714, 1715, 1716, 1717,
+     1718, 1719, 1720, 1721, 1722, 1725, 1726, 1727, 1728, 1729,
+     1730, 1731, 1732, 1733, 1739, 1740, 1741, 1744, 1745, 1746,
+     1747, 1752, 1753, 1754, 1757, 1758, 1759, 1760, 1761, 1762,
+     1763, 1764, 1765, 1766, 1767, 1768, 1769, 1770, 1772, 1774,
+
+     1777, 1778, 1781, 1781, 1781, 1781, 1781, 1781, 1781, 1782,
+     1784, 1782, 1782, 1782, 1782, 1782, 1783, 1783, 1783, 1785,
+     1785, 1785, 1785, 1786, 1787, 1787, 1787, 1787, 1788, 1789,
+     1792, 1789, 1789, 1790,  799, 1790, 1791,  798, 1791, 1791,
+      797,  795,  794,  792,  791,  790,  789,  788,  787,  786,
+      785,  784,  782,  781,  780,  778,  777,  776,  775,  774,
+      773,  772,  771,  770,  769,  768,  767,  766,  764,  763,
+      762,  761,  759,  758,  757,  756,  755,  754,  753,  752,
+      751,  750,  749,  748,  746,  745,  744,  742,  741,  739,
+      738,  737,  735,  734,  733,  732,  731,  730,  729,  728,
+
+      727,  726,  724,  723,  722,  721,  718,  716,  715,  714,
+      713,  712,  711,  710,  709,  707,  706,  705,  704,  702,
+      701,  698,  697,  696,  695,  694,  693,  692,  691,  690,
+      689,  688,  687,  686,  685,  684,  683,  682,  681,  680,
+      678,  677,  676,  675,  674,  673,  671,  670,  669,  668,
+      667,  666,  665,  664,  662,  661,  660,  659,  658,  657,
+      656,  655,  654,  653,  652,  651,  650,  649,  648,  647,
+      643,  642,  641,  640,  639,  638,  637,  636,  634,  631,
+      630,  628,  627,  626,  625,  624,  621,  620,  618,  617,
+      616,  615,  614,  613,  612,  611,  610,  606,  605,  604,
+
+      603,  602,  600,  599,  598,  597,  596,  595,  594,  593,
+      592,  591,  590,  589,  588,  587,  585,  584,  583,  582,
+      581,  580,  579,  578,  577,  575,  574,  572,  571,  570,
+      569,  568,  567,  566,  564,  563,  562,  561,  560,  559,
+      557,  556,  555,  554,  553,  552,  551,  550,  549,  548,
+      547,  546,  545,  544,  543,  541,  540,  539,  538,  537,
+      536,  534,  533,  532,  530,  529,  528,  527,  526,  525,
+      524,  523,  522,  521,  520,  519,  515,  514,  513,  512,
+      511,  510,  508,  507,  506,  504,  503,  502,  501,  500,
+      499,  498,  497,  496,  495,  494,  493,  492,  491,  490,
+
+      489,  488,  486,  485,  484,  483,  482,  480,  479,  478,
+      477,  476,  475,  474,  473,  472,  469,  468,  467,  464,
+      462,  461,  460,  458,  457,  454,  450,  447,  444,  443,
+      442,  438,  437,  436,  435,  434,  433,  432,  431,  430,
+      429,  428,  425,  424,  422,  421,  420,  419,  418,  417,
+      413,  408,  406,  405,  403,  402,  401,  400,  399,  398,
+      397,  396,  395,  394,  392,  389,  388,  386,  385,  383,
+      381,  380,  379,  378,  377,  376,  375,  374,  373,  369,
+      368,  367,  366,  364,  363,  362,  361,  360,  359,  356,
+      354,  353,  352,  350,  349,  348,  347,  346,  345,  344,
+
+      343,  342,  341,  340,  338,  336,  335,  333,  331,  330,
+      329,  328,  327,  326,  325,  324,  323,  322,  321,  320,
+      319,  318,  317,  316,  315,  313,  311,  309,  308,  307,
+      306,  305,  304,  303,  302,  300,  299,  298,  297,  296,
+      294,  293,  291,  290,  289,  288,  285,  284,  283,  281,
+      280,  277,  276,  275,  274,  273,  272,  271,  270,  269,
+      268,  267,  266,  265,  264,  263,  262,  261,  260,  259,
+      258,  257,  256,  254,  253,  251,  250,  249,  248,  247,
+      246,  245,  244,  243,  242,  241,  240,  239,  238,  237,
+      236,  235,  234,  233,  231,  227,  226,  225,  221,  217,
+
+      214,  213,  210,  207,  206,  197,  193,  190,  189,  171,
+      167,  156,  151,  150,  146,  141,  138,  114,  107,   82,
+       80,   79,   78,   73,   69,   65,   57,   56,   55,   54,
+       52,   50,   45,   43,   41,   10,    9, 1780, 1780, 1780,
+     1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780,
+     1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780,
+     1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780,
+     1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780,
+     1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780, 1780,
+     1780, 1780, 1780, 1780, 1780, 1780, 1780
+
+    } ;
+
+static yy_state_type yy_last_accepting_state;
+static char *yy_last_accepting_cpos;
+
+extern int yy_flex_debug;
+int yy_flex_debug = 0;
+
+/* The intent behind this definition is that it'll catch
+ * any uses of REJECT which flex missed.
+ */
+#define REJECT reject_used_but_not_detected
+static int yy_more_flag = 0;
+static int yy_more_len = 0;
+#define yymore() ((yy_more_flag) = 1)
+#define YY_MORE_ADJ (yy_more_len)
+#define YY_RESTORE_YY_MORE_OFFSET
+char *yytext;
+#line 1 "cftoken.l"
+/*	$NetBSD: cftoken.l,v 1.11.4.2 2007/09/03 18:07:29 mgrooms Exp $	*/
+/* Id: cftoken.l,v 1.53 2006/08/22 18:17:17 manubsd Exp */
+#line 6 "cftoken.l"
+/*
+ * Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002 and 2003 WIDE Project.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+
+#include <netinet/in.h>
+#include PATH_IPSEC_H
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <limits.h>
+#include <ctype.h>
+#include <glob.h>
+#ifdef HAVE_STDARG_H
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
+
+#include "var.h"
+#include "misc.h"
+#include "vmbuf.h"
+#include "plog.h"
+#include "debug.h"
+
+#include "algorithm.h"
+#include "cfparse_proto.h"
+#include "cftoken_proto.h"
+#include "localconf.h"
+#include "oakley.h"
+#include "isakmp_var.h"
+#include "isakmp.h"
+#include "ipsec_doi.h"
+#include "policy.h"
+#include "proposal.h"
+#include "remoteconf.h"
+#ifdef GC
+#include "gcmalloc.h"
+#endif
+
+#include "cfparse.h"
+
+int yyerrorcount = 0;
+
+#if defined(YIPS_DEBUG)
+#  define YYDB plog(LLV_DEBUG2, LOCATION, NULL,                                \
+		"begin <%d>%s\n", yy_start, yytext);
+#  define YYD {                                                                \
+	plog(LLV_DEBUG2, LOCATION, NULL, "<%d>%s",                             \
+	    yy_start, loglevel >= LLV_DEBUG2 ? "\n" : "");                     \
+}
+#else
+#  define YYDB
+#  define YYD
+#endif /* defined(YIPS_DEBUG) */
+
+#define MAX_INCLUDE_DEPTH 10
+
+static struct include_stack {
+	char *path;
+	FILE *fp;
+	YY_BUFFER_STATE prevstate;
+	int lineno;
+	glob_t matches;
+	int matchon;
+} incstack[MAX_INCLUDE_DEPTH];
+static int incstackp = 0;
+
+static int yy_first_time = 1;
+/* common seciton */
+/*octet		(([01]?{digit}?{digit})|((2([0-4]{digit}))|(25[0-5]))) */
+
+
+
+
+
+
+#line 1640 "cftoken.c"
+
+#define INITIAL 0
+#define S_INI 1
+#define S_PRIV 2
+#define S_PTH 3
+#define S_INF 4
+#define S_LOG 5
+#define S_PAD 6
+#define S_LST 7
+#define S_RTRY 8
+#define S_CFG 9
+#define S_LDAP 10
+#define S_ALGST 11
+#define S_ALGCL 12
+#define S_SAINF 13
+#define S_SAINFS 14
+#define S_RMT 15
+#define S_RMTS 16
+#define S_RMTP 17
+#define S_SA 18
+#define S_GSSENC 19
+
+#ifndef YY_NO_UNISTD_H
+/* Special case for "unistd.h", since it is non-ANSI. We include it way
+ * down here because we want the user's section 1 to have been scanned first.
+ * The user has a chance to override it with an option.
+ */
+#include <unistd.h>
+#endif
+
+#ifndef YY_EXTRA_TYPE
+#define YY_EXTRA_TYPE void *
+#endif
+
+static int yy_init_globals (void );
+
+/* Accessor methods to globals.
+   These are made visible to non-reentrant scanners for convenience. */
+
+int yylex_destroy (void );
+
+int yyget_debug (void );
+
+void yyset_debug (int debug_flag  );
+
+YY_EXTRA_TYPE yyget_extra (void );
+
+void yyset_extra (YY_EXTRA_TYPE user_defined  );
+
+FILE *yyget_in (void );
+
+void yyset_in  (FILE * in_str  );
+
+FILE *yyget_out (void );
+
+void yyset_out  (FILE * out_str  );
+
+int yyget_leng (void );
+
+char *yyget_text (void );
+
+int yyget_lineno (void );
+
+void yyset_lineno (int line_number  );
+
+/* Macros after this point can all be overridden by user definitions in
+ * section 1.
+ */
+#ifdef ANDROID_CHANGES
+#include <fcntl.h>
+
+int glob (__const char *__restrict __pattern, int __flags, int *__errfunc, glob_t *__restrict __pglob) {
+	// Just simply open the config file instead.
+	int fd = open(__pattern, O_RDONLY);
+	if (fd > 0) {
+		__pglob->gl_pathc = 1;
+		__pglob->gl_pathv = (char**) malloc(sizeof(char*));
+		__pglob->gl_pathv[0] = __pattern;
+		__pglob->gl_offs = 0;
+		close(fd);
+		return 0;
+  	}
+	return -1;
+}
+
+void globfree(glob_t *pglob) {
+	if (pglob->gl_pathc != 0) {
+		free(pglob->gl_pathv);
+	}
+}
+#endif
+
+#ifndef YY_SKIP_YYWRAP
+#ifdef __cplusplus
+extern "C" int yywrap (void );
+#else
+extern int yywrap (void );
+#endif
+#endif
+
+    static void yyunput (int c,char *buf_ptr  );
+    
+#ifndef yytext_ptr
+static void yy_flex_strncpy (char *,yyconst char *,int );
+#endif
+
+#ifdef YY_NEED_STRLEN
+static int yy_flex_strlen (yyconst char * );
+#endif
+
+#ifndef YY_NO_INPUT
+
+#ifdef __cplusplus
+static int yyinput (void );
+#else
+static int input (void );
+#endif
+
+#endif
+
+/* Amount of stuff to slurp up with each read. */
+#ifndef YY_READ_BUF_SIZE
+#define YY_READ_BUF_SIZE 8192
+#endif
+
+/* Copy whatever the last rule matched to the standard output. */
+#ifndef ECHO
+/* This used to be an fputs(), but since the string might contain NUL's,
+ * we now use fwrite().
+ */
+#define ECHO fwrite( yytext, yyleng, 1, yyout )
+#endif
+
+/* Gets input and stuffs it into "buf".  number of characters read, or YY_NULL,
+ * is returned in "result".
+ */
+#ifndef YY_INPUT
+#define YY_INPUT(buf,result,max_size) \
+	if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \
+		{ \
+		int c = '*'; \
+		size_t n; \
+		for ( n = 0; n < max_size && \
+			     (c = getc( yyin )) != EOF && c != '\n'; ++n ) \
+			buf[n] = (char) c; \
+		if ( c == '\n' ) \
+			buf[n++] = (char) c; \
+		if ( c == EOF && ferror( yyin ) ) \
+			YY_FATAL_ERROR( "input in flex scanner failed" ); \
+		result = n; \
+		} \
+	else \
+		{ \
+		errno=0; \
+		while ( (result = fread(buf, 1, max_size, yyin))==0 && ferror(yyin)) \
+			{ \
+			if( errno != EINTR) \
+				{ \
+				YY_FATAL_ERROR( "input in flex scanner failed" ); \
+				break; \
+				} \
+			errno=0; \
+			clearerr(yyin); \
+			} \
+		}\
+\
+
+#endif
+
+/* No semi-colon after return; correct usage is to write "yyterminate();" -
+ * we don't want an extra ';' after the "return" because that will cause
+ * some compilers to complain about unreachable statements.
+ */
+#ifndef yyterminate
+#define yyterminate() return YY_NULL
+#endif
+
+/* Number of entries by which start-condition stack grows. */
+#ifndef YY_START_STACK_INCR
+#define YY_START_STACK_INCR 25
+#endif
+
+/* Report a fatal error. */
+#ifndef YY_FATAL_ERROR
+#define YY_FATAL_ERROR(msg) yy_fatal_error( msg )
+#endif
+
+/* end tables serialization structures and prototypes */
+
+/* Default declaration of generated scanner - a define so the user can
+ * easily add parameters.
+ */
+#ifndef YY_DECL
+#define YY_DECL_IS_OURS 1
+
+extern int yylex (void);
+
+#define YY_DECL int yylex (void)
+#endif /* !YY_DECL */
+
+/* Code executed at the beginning of each rule, after yytext and yyleng
+ * have been set up.
+ */
+#ifndef YY_USER_ACTION
+#define YY_USER_ACTION
+#endif
+
+/* Code executed at the end of each rule. */
+#ifndef YY_BREAK
+#define YY_BREAK break;
+#endif
+
+#define YY_RULE_SETUP \
+	YY_USER_ACTION
+
+/** The main scanner function which does all the work.
+ */
+YY_DECL
+{
+	register yy_state_type yy_current_state;
+	register char *yy_cp, *yy_bp;
+	register int yy_act;
+    
+#line 142 "cftoken.l"
+
+
+	if (yy_first_time) {
+		BEGIN S_INI;
+		yy_first_time = 0;
+	}
+
+
+	/* privsep */
+#line 1851 "cftoken.c"
+
+	if ( !(yy_init) )
+		{
+		(yy_init) = 1;
+
+#ifdef YY_USER_INIT
+		YY_USER_INIT;
+#endif
+
+		if ( ! (yy_start) )
+			(yy_start) = 1;	/* first start state */
+
+		if ( ! yyin )
+			yyin = stdin;
+
+		if ( ! yyout )
+			yyout = stdout;
+
+		if ( ! YY_CURRENT_BUFFER ) {
+			yyensure_buffer_stack ();
+			YY_CURRENT_BUFFER_LVALUE =
+				yy_create_buffer(yyin,YY_BUF_SIZE );
+		}
+
+		yy_load_buffer_state( );
+		}
+
+	while ( 1 )		/* loops until end-of-file is reached */
+		{
+		(yy_more_len) = 0;
+		if ( (yy_more_flag) )
+			{
+			(yy_more_len) = (yy_c_buf_p) - (yytext_ptr);
+			(yy_more_flag) = 0;
+			}
+		yy_cp = (yy_c_buf_p);
+
+		/* Support of yytext. */
+		*yy_cp = (yy_hold_char);
+
+		/* yy_bp points to the position in yy_ch_buf of the start of
+		 * the current run.
+		 */
+		yy_bp = yy_cp;
+
+		yy_current_state = (yy_start);
+yy_match:
+		do
+			{
+			register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)];
+			if ( yy_accept[yy_current_state] )
+				{
+				(yy_last_accepting_state) = yy_current_state;
+				(yy_last_accepting_cpos) = yy_cp;
+				}
+			while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+				{
+				yy_current_state = (int) yy_def[yy_current_state];
+				if ( yy_current_state >= 1781 )
+					yy_c = yy_meta[(unsigned int) yy_c];
+				}
+			yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+			++yy_cp;
+			}
+		while ( yy_base[yy_current_state] != 2138 );
+
+yy_find_action:
+		yy_act = yy_accept[yy_current_state];
+		if ( yy_act == 0 )
+			{ /* have to back up */
+			yy_cp = (yy_last_accepting_cpos);
+			yy_current_state = (yy_last_accepting_state);
+			yy_act = yy_accept[yy_current_state];
+			}
+
+		YY_DO_BEFORE_ACTION;
+
+do_action:	/* This label is used only to access EOF actions. */
+
+		switch ( yy_act )
+	{ /* beginning of action switch */
+			case 0: /* must back up */
+			/* undo the effects of YY_DO_BEFORE_ACTION */
+			*yy_cp = (yy_hold_char);
+			yy_cp = (yy_last_accepting_cpos);
+			yy_current_state = (yy_last_accepting_state);
+			goto yy_find_action;
+
+case 1:
+YY_RULE_SETUP
+#line 151 "cftoken.l"
+{ BEGIN S_PRIV; YYDB; return(PRIVSEP); }
+	YY_BREAK
+case 2:
+YY_RULE_SETUP
+#line 152 "cftoken.l"
+{ return(BOC); }
+	YY_BREAK
+case 3:
+YY_RULE_SETUP
+#line 153 "cftoken.l"
+{ YYD; return(USER); }
+	YY_BREAK
+case 4:
+YY_RULE_SETUP
+#line 154 "cftoken.l"
+{ YYD; return(GROUP); }
+	YY_BREAK
+case 5:
+YY_RULE_SETUP
+#line 155 "cftoken.l"
+{ YYD; return(CHROOT); }
+	YY_BREAK
+case 6:
+YY_RULE_SETUP
+#line 156 "cftoken.l"
+{ BEGIN S_INI; return(EOC); }
+	YY_BREAK
+/* path */
+case 7:
+YY_RULE_SETUP
+#line 159 "cftoken.l"
+{ BEGIN S_PTH; YYDB; return(PATH); }
+	YY_BREAK
+case 8:
+YY_RULE_SETUP
+#line 160 "cftoken.l"
+{ YYD; yylval.num = LC_PATHTYPE_INCLUDE;
+				return(PATHTYPE); }
+	YY_BREAK
+case 9:
+YY_RULE_SETUP
+#line 162 "cftoken.l"
+{ YYD; yylval.num = LC_PATHTYPE_PSK;
+				return(PATHTYPE); }
+	YY_BREAK
+case 10:
+YY_RULE_SETUP
+#line 164 "cftoken.l"
+{ YYD; yylval.num = LC_PATHTYPE_CERT;
+				return(PATHTYPE); }
+	YY_BREAK
+case 11:
+YY_RULE_SETUP
+#line 166 "cftoken.l"
+{ YYD; yylval.num = LC_PATHTYPE_SCRIPT;
+				return(PATHTYPE); }
+	YY_BREAK
+case 12:
+YY_RULE_SETUP
+#line 168 "cftoken.l"
+{ YYD; yylval.num = LC_PATHTYPE_BACKUPSA;
+				return(PATHTYPE); }
+	YY_BREAK
+case 13:
+YY_RULE_SETUP
+#line 170 "cftoken.l"
+{ YYD; yylval.num = LC_PATHTYPE_PIDFILE;
+				return(PATHTYPE); }
+	YY_BREAK
+case 14:
+YY_RULE_SETUP
+#line 172 "cftoken.l"
+{ BEGIN S_INI; YYDB; return(EOS); }
+	YY_BREAK
+/* include */
+case 15:
+YY_RULE_SETUP
+#line 175 "cftoken.l"
+{ YYDB; return(INCLUDE); }
+	YY_BREAK
+/* self information */
+case 16:
+YY_RULE_SETUP
+#line 178 "cftoken.l"
+{ BEGIN S_INF; YYDB; yywarn("it is obsoleted.  use \"my_identifier\" in each remote directives."); return(IDENTIFIER); }
+	YY_BREAK
+case 17:
+YY_RULE_SETUP
+#line 179 "cftoken.l"
+{ BEGIN S_INI; return(EOS); }
+	YY_BREAK
+/* special */
+case 18:
+YY_RULE_SETUP
+#line 182 "cftoken.l"
+{ YYDB; return(COMPLEX_BUNDLE); }
+	YY_BREAK
+/* logging */
+case 19:
+YY_RULE_SETUP
+#line 185 "cftoken.l"
+{ BEGIN S_LOG; YYDB; return(LOGGING); }
+	YY_BREAK
+case 20:
+YY_RULE_SETUP
+#line 186 "cftoken.l"
+{ YYD; yylval.num = LLV_ERROR; return(LOGLEV); }
+	YY_BREAK
+case 21:
+YY_RULE_SETUP
+#line 187 "cftoken.l"
+{ YYD; yylval.num = LLV_WARNING; return(LOGLEV); }
+	YY_BREAK
+case 22:
+YY_RULE_SETUP
+#line 188 "cftoken.l"
+{ YYD; yylval.num = LLV_NOTIFY; return(LOGLEV); }
+	YY_BREAK
+case 23:
+YY_RULE_SETUP
+#line 189 "cftoken.l"
+{ YYD; yylval.num = LLV_INFO; return(LOGLEV); }
+	YY_BREAK
+case 24:
+YY_RULE_SETUP
+#line 190 "cftoken.l"
+{ YYD; yylval.num = LLV_DEBUG; return(LOGLEV); }
+	YY_BREAK
+case 25:
+YY_RULE_SETUP
+#line 191 "cftoken.l"
+{ YYD; yylval.num = LLV_DEBUG2; return(LOGLEV); }
+	YY_BREAK
+case 26:
+YY_RULE_SETUP
+#line 192 "cftoken.l"
+{ YYD; yywarn("it is obsoleted.  use \"debug2\""); yylval.num = LLV_DEBUG2; return(LOGLEV); }
+	YY_BREAK
+case 27:
+YY_RULE_SETUP
+#line 193 "cftoken.l"
+{ YYD; yywarn("it is obsoleted.  use \"debug2\""); yylval.num = LLV_DEBUG2; return(LOGLEV); }
+	YY_BREAK
+case 28:
+YY_RULE_SETUP
+#line 194 "cftoken.l"
+{ BEGIN S_INI; return(EOS); }
+	YY_BREAK
+/* padding */
+case 29:
+YY_RULE_SETUP
+#line 197 "cftoken.l"
+{ BEGIN S_PAD; YYDB; return(PADDING); }
+	YY_BREAK
+case 30:
+YY_RULE_SETUP
+#line 198 "cftoken.l"
+{ return(BOC); }
+	YY_BREAK
+case 31:
+YY_RULE_SETUP
+#line 199 "cftoken.l"
+{ YYD; return(PAD_RANDOMIZE); }
+	YY_BREAK
+case 32:
+YY_RULE_SETUP
+#line 200 "cftoken.l"
+{ YYD; return(PAD_RANDOMIZELEN); }
+	YY_BREAK
+case 33:
+YY_RULE_SETUP
+#line 201 "cftoken.l"
+{ YYD; return(PAD_MAXLEN); }
+	YY_BREAK
+case 34:
+YY_RULE_SETUP
+#line 202 "cftoken.l"
+{ YYD; return(PAD_STRICT); }
+	YY_BREAK
+case 35:
+YY_RULE_SETUP
+#line 203 "cftoken.l"
+{ YYD; return(PAD_EXCLTAIL); }
+	YY_BREAK
+case 36:
+YY_RULE_SETUP
+#line 204 "cftoken.l"
+{ BEGIN S_INI; return(EOC); }
+	YY_BREAK
+/* listen */
+case 37:
+YY_RULE_SETUP
+#line 207 "cftoken.l"
+{ BEGIN S_LST; YYDB; return(LISTEN); }
+	YY_BREAK
+case 38:
+YY_RULE_SETUP
+#line 208 "cftoken.l"
+{ return(BOC); }
+	YY_BREAK
+case 39:
+YY_RULE_SETUP
+#line 209 "cftoken.l"
+{ YYD; return(X_ISAKMP); }
+	YY_BREAK
+case 40:
+YY_RULE_SETUP
+#line 210 "cftoken.l"
+{ YYD; return(X_ISAKMP_NATT); }
+	YY_BREAK
+case 41:
+YY_RULE_SETUP
+#line 211 "cftoken.l"
+{ YYD; return(X_ADMIN); }
+	YY_BREAK
+case 42:
+YY_RULE_SETUP
+#line 212 "cftoken.l"
+{ YYD; return(ADMINSOCK); }
+	YY_BREAK
+case 43:
+YY_RULE_SETUP
+#line 213 "cftoken.l"
+{ YYD; return(DISABLED); }
+	YY_BREAK
+case 44:
+YY_RULE_SETUP
+#line 214 "cftoken.l"
+{ YYD; return(STRICT_ADDRESS); }
+	YY_BREAK
+case 45:
+YY_RULE_SETUP
+#line 215 "cftoken.l"
+{ BEGIN S_INI; return(EOC); }
+	YY_BREAK
+/* ldap config */
+case 46:
+YY_RULE_SETUP
+#line 218 "cftoken.l"
+{ BEGIN S_LDAP; YYDB; return(LDAPCFG); }
+	YY_BREAK
+case 47:
+YY_RULE_SETUP
+#line 219 "cftoken.l"
+{ return(BOC); }
+	YY_BREAK
+case 48:
+YY_RULE_SETUP
+#line 220 "cftoken.l"
+{ YYD; return(LDAP_PVER); }
+	YY_BREAK
+case 49:
+YY_RULE_SETUP
+#line 221 "cftoken.l"
+{ YYD; return(LDAP_HOST); }
+	YY_BREAK
+case 50:
+YY_RULE_SETUP
+#line 222 "cftoken.l"
+{ YYD; return(LDAP_PORT); }
+	YY_BREAK
+case 51:
+YY_RULE_SETUP
+#line 223 "cftoken.l"
+{ YYD; return(LDAP_BASE); }
+	YY_BREAK
+case 52:
+YY_RULE_SETUP
+#line 224 "cftoken.l"
+{ YYD; return(LDAP_SUBTREE); }
+	YY_BREAK
+case 53:
+YY_RULE_SETUP
+#line 225 "cftoken.l"
+{ YYD; return(LDAP_BIND_DN); }
+	YY_BREAK
+case 54:
+YY_RULE_SETUP
+#line 226 "cftoken.l"
+{ YYD; return(LDAP_BIND_PW); }
+	YY_BREAK
+case 55:
+YY_RULE_SETUP
+#line 227 "cftoken.l"
+{ YYD; return(LDAP_ATTR_USER); }
+	YY_BREAK
+case 56:
+YY_RULE_SETUP
+#line 228 "cftoken.l"
+{ YYD; return(LDAP_ATTR_ADDR); }
+	YY_BREAK
+case 57:
+YY_RULE_SETUP
+#line 229 "cftoken.l"
+{ YYD; return(LDAP_ATTR_MASK); }
+	YY_BREAK
+case 58:
+YY_RULE_SETUP
+#line 230 "cftoken.l"
+{ YYD; return(LDAP_ATTR_GROUP); }
+	YY_BREAK
+case 59:
+YY_RULE_SETUP
+#line 231 "cftoken.l"
+{ YYD; return(LDAP_ATTR_MEMBER); }
+	YY_BREAK
+case 60:
+YY_RULE_SETUP
+#line 232 "cftoken.l"
+{ BEGIN S_INI; return(EOC); }
+	YY_BREAK
+/* mode_cfg */
+case 61:
+YY_RULE_SETUP
+#line 235 "cftoken.l"
+{ BEGIN S_CFG; YYDB; return(MODECFG); }
+	YY_BREAK
+case 62:
+YY_RULE_SETUP
+#line 236 "cftoken.l"
+{ return(BOC); }
+	YY_BREAK
+case 63:
+YY_RULE_SETUP
+#line 237 "cftoken.l"
+{ YYD; return(CFG_NET4); }
+	YY_BREAK
+case 64:
+YY_RULE_SETUP
+#line 238 "cftoken.l"
+{ YYD; return(CFG_MASK4); }
+	YY_BREAK
+case 65:
+YY_RULE_SETUP
+#line 239 "cftoken.l"
+{ YYD; return(CFG_DNS4); }
+	YY_BREAK
+case 66:
+YY_RULE_SETUP
+#line 240 "cftoken.l"
+{ YYD; return(CFG_NBNS4); }
+	YY_BREAK
+case 67:
+YY_RULE_SETUP
+#line 241 "cftoken.l"
+{ YYD; return(CFG_NBNS4); }
+	YY_BREAK
+case 68:
+YY_RULE_SETUP
+#line 242 "cftoken.l"
+{ YYD; return(CFG_DEFAULT_DOMAIN); }
+	YY_BREAK
+case 69:
+YY_RULE_SETUP
+#line 243 "cftoken.l"
+{ YYD; return(CFG_AUTH_SOURCE); }
+	YY_BREAK
+case 70:
+YY_RULE_SETUP
+#line 244 "cftoken.l"
+{ YYD; return(CFG_AUTH_GROUPS); }
+	YY_BREAK
+case 71:
+YY_RULE_SETUP
+#line 245 "cftoken.l"
+{ YYD; return(CFG_GROUP_SOURCE); }
+	YY_BREAK
+case 72:
+YY_RULE_SETUP
+#line 246 "cftoken.l"
+{ YYD; return(CFG_CONF_SOURCE); }
+	YY_BREAK
+case 73:
+YY_RULE_SETUP
+#line 247 "cftoken.l"
+{ YYD; return(CFG_ACCOUNTING); }
+	YY_BREAK
+case 74:
+YY_RULE_SETUP
+#line 248 "cftoken.l"
+{ YYD; return(CFG_SYSTEM); }
+	YY_BREAK
+case 75:
+YY_RULE_SETUP
+#line 249 "cftoken.l"
+{ YYD; return(CFG_LOCAL); }
+	YY_BREAK
+case 76:
+YY_RULE_SETUP
+#line 250 "cftoken.l"
+{ YYD; return(CFG_NONE); }
+	YY_BREAK
+case 77:
+YY_RULE_SETUP
+#line 251 "cftoken.l"
+{ YYD; return(CFG_RADIUS); }
+	YY_BREAK
+case 78:
+YY_RULE_SETUP
+#line 252 "cftoken.l"
+{ YYD; return(CFG_PAM); }
+	YY_BREAK
+case 79:
+YY_RULE_SETUP
+#line 253 "cftoken.l"
+{ YYD; return(CFG_LDAP); }
+	YY_BREAK
+case 80:
+YY_RULE_SETUP
+#line 254 "cftoken.l"
+{ YYD; return(CFG_POOL_SIZE); }
+	YY_BREAK
+case 81:
+YY_RULE_SETUP
+#line 255 "cftoken.l"
+{ YYD; return(CFG_MOTD); }
+	YY_BREAK
+case 82:
+YY_RULE_SETUP
+#line 256 "cftoken.l"
+{ YYD; return(CFG_AUTH_THROTTLE); }
+	YY_BREAK
+case 83:
+YY_RULE_SETUP
+#line 257 "cftoken.l"
+{ YYD; return(CFG_SPLIT_NETWORK); }
+	YY_BREAK
+case 84:
+YY_RULE_SETUP
+#line 258 "cftoken.l"
+{ YYD; return(CFG_SPLIT_LOCAL); }
+	YY_BREAK
+case 85:
+YY_RULE_SETUP
+#line 259 "cftoken.l"
+{ YYD; return(CFG_SPLIT_INCLUDE); }
+	YY_BREAK
+case 86:
+YY_RULE_SETUP
+#line 260 "cftoken.l"
+{ YYD; return(CFG_SPLIT_DNS); }
+	YY_BREAK
+case 87:
+YY_RULE_SETUP
+#line 261 "cftoken.l"
+{ YYD; return(CFG_PFS_GROUP); }
+	YY_BREAK
+case 88:
+YY_RULE_SETUP
+#line 262 "cftoken.l"
+{ YYD; return(CFG_SAVE_PASSWD); }
+	YY_BREAK
+case 89:
+YY_RULE_SETUP
+#line 263 "cftoken.l"
+{ YYD; return(COMMA); }
+	YY_BREAK
+case 90:
+YY_RULE_SETUP
+#line 264 "cftoken.l"
+{ BEGIN S_INI; return(EOC); }
+	YY_BREAK
+/* timer */
+case 91:
+YY_RULE_SETUP
+#line 267 "cftoken.l"
+{ BEGIN S_RTRY; YYDB; return(RETRY); }
+	YY_BREAK
+case 92:
+YY_RULE_SETUP
+#line 268 "cftoken.l"
+{ return(BOC); }
+	YY_BREAK
+case 93:
+YY_RULE_SETUP
+#line 269 "cftoken.l"
+{ YYD; return(RETRY_COUNTER); }
+	YY_BREAK
+case 94:
+YY_RULE_SETUP
+#line 270 "cftoken.l"
+{ YYD; return(RETRY_INTERVAL); }
+	YY_BREAK
+case 95:
+YY_RULE_SETUP
+#line 271 "cftoken.l"
+{ YYD; return(RETRY_PERSEND); }
+	YY_BREAK
+case 96:
+YY_RULE_SETUP
+#line 272 "cftoken.l"
+{ YYD; return(RETRY_PHASE1); }
+	YY_BREAK
+case 97:
+YY_RULE_SETUP
+#line 273 "cftoken.l"
+{ YYD; return(RETRY_PHASE2); }
+	YY_BREAK
+case 98:
+YY_RULE_SETUP
+#line 274 "cftoken.l"
+{ YYD; return(NATT_KA); }
+	YY_BREAK
+case 99:
+YY_RULE_SETUP
+#line 275 "cftoken.l"
+{ BEGIN S_INI; return(EOC); }
+	YY_BREAK
+/* sainfo */
+case 100:
+YY_RULE_SETUP
+#line 278 "cftoken.l"
+{ BEGIN S_SAINF; YYDB; return(SAINFO); }
+	YY_BREAK
+case 101:
+YY_RULE_SETUP
+#line 279 "cftoken.l"
+{ YYD; return(ANONYMOUS); }
+	YY_BREAK
+case 102:
+YY_RULE_SETUP
+#line 280 "cftoken.l"
+{ YYD; return(PORTANY); }
+	YY_BREAK
+case 103:
+YY_RULE_SETUP
+#line 281 "cftoken.l"
+{ YYD; return(ANY); }
+	YY_BREAK
+case 104:
+YY_RULE_SETUP
+#line 282 "cftoken.l"
+{ YYD; return(FROM); }
+	YY_BREAK
+case 105:
+YY_RULE_SETUP
+#line 283 "cftoken.l"
+{ YYD; return(GROUP); }
+	YY_BREAK
+/* sainfo spec */
+case 106:
+YY_RULE_SETUP
+#line 285 "cftoken.l"
+{ BEGIN S_SAINFS; return(BOC); }
+	YY_BREAK
+case 107:
+YY_RULE_SETUP
+#line 286 "cftoken.l"
+{ BEGIN S_INI; return(EOS); }
+	YY_BREAK
+case 108:
+YY_RULE_SETUP
+#line 287 "cftoken.l"
+{ BEGIN S_INI; return(EOC); }
+	YY_BREAK
+case 109:
+YY_RULE_SETUP
+#line 288 "cftoken.l"
+{ YYD; return(PFS_GROUP); }
+	YY_BREAK
+case 110:
+YY_RULE_SETUP
+#line 289 "cftoken.l"
+{ YYD; return(REMOTEID); }
+	YY_BREAK
+case 111:
+YY_RULE_SETUP
+#line 290 "cftoken.l"
+{ YYD; yywarn("it is obsoleted.  use \"my_identifier\"."); return(IDENTIFIER); }
+	YY_BREAK
+case 112:
+YY_RULE_SETUP
+#line 291 "cftoken.l"
+{ YYD; return(MY_IDENTIFIER); }
+	YY_BREAK
+case 113:
+YY_RULE_SETUP
+#line 292 "cftoken.l"
+{ YYD; return(LIFETIME); }
+	YY_BREAK
+case 114:
+YY_RULE_SETUP
+#line 293 "cftoken.l"
+{ YYD; return(LIFETYPE_TIME); }
+	YY_BREAK
+case 115:
+YY_RULE_SETUP
+#line 294 "cftoken.l"
+{ YYD; return(LIFETYPE_BYTE); }
+	YY_BREAK
+case 116:
+YY_RULE_SETUP
+#line 295 "cftoken.l"
+{ YYD; yylval.num = algclass_ipsec_enc; return(ALGORITHM_CLASS); }
+	YY_BREAK
+case 117:
+YY_RULE_SETUP
+#line 296 "cftoken.l"
+{ YYD; yylval.num = algclass_ipsec_auth; return(ALGORITHM_CLASS); }
+	YY_BREAK
+case 118:
+YY_RULE_SETUP
+#line 297 "cftoken.l"
+{ YYD; yylval.num = algclass_ipsec_comp; return(ALGORITHM_CLASS); }
+	YY_BREAK
+case 119:
+YY_RULE_SETUP
+#line 298 "cftoken.l"
+{ YYD; return(COMMA); }
+	YY_BREAK
+/* remote */
+case 120:
+YY_RULE_SETUP
+#line 301 "cftoken.l"
+{ BEGIN S_RMT; YYDB; return(REMOTE); }
+	YY_BREAK
+case 121:
+YY_RULE_SETUP
+#line 302 "cftoken.l"
+{ YYD; return(ANONYMOUS); }
+	YY_BREAK
+case 122:
+YY_RULE_SETUP
+#line 303 "cftoken.l"
+{ YYD; return(INHERIT); }
+	YY_BREAK
+/* remote spec */
+case 123:
+YY_RULE_SETUP
+#line 305 "cftoken.l"
+{ BEGIN S_RMTS; return(BOC); }
+	YY_BREAK
+case 124:
+YY_RULE_SETUP
+#line 306 "cftoken.l"
+{ BEGIN S_INI; return(EOC); }
+	YY_BREAK
+case 125:
+YY_RULE_SETUP
+#line 307 "cftoken.l"
+{ YYD; return(EXCHANGE_MODE); }
+	YY_BREAK
+case 126:
+YY_RULE_SETUP
+#line 308 "cftoken.l"
+{ YYD; /* XXX ignored, but to be handled. */ ; }
+	YY_BREAK
+case 127:
+YY_RULE_SETUP
+#line 309 "cftoken.l"
+{ YYD; yylval.num = ISAKMP_ETYPE_BASE; return(EXCHANGETYPE); }
+	YY_BREAK
+case 128:
+YY_RULE_SETUP
+#line 310 "cftoken.l"
+{ YYD; yylval.num = ISAKMP_ETYPE_IDENT; return(EXCHANGETYPE); }
+	YY_BREAK
+case 129:
+YY_RULE_SETUP
+#line 311 "cftoken.l"
+{ YYD; yylval.num = ISAKMP_ETYPE_AGG; return(EXCHANGETYPE); }
+	YY_BREAK
+case 130:
+YY_RULE_SETUP
+#line 312 "cftoken.l"
+{ YYD; return(DOI); }
+	YY_BREAK
+case 131:
+YY_RULE_SETUP
+#line 313 "cftoken.l"
+{ YYD; yylval.num = IPSEC_DOI; return(DOITYPE); }
+	YY_BREAK
+case 132:
+YY_RULE_SETUP
+#line 314 "cftoken.l"
+{ YYD; return(SITUATION); }
+	YY_BREAK
+case 133:
+YY_RULE_SETUP
+#line 315 "cftoken.l"
+{ YYD; yylval.num = IPSECDOI_SIT_IDENTITY_ONLY; return(SITUATIONTYPE); }
+	YY_BREAK
+case 134:
+YY_RULE_SETUP
+#line 316 "cftoken.l"
+{ YYD; yylval.num = IPSECDOI_SIT_SECRECY; return(SITUATIONTYPE); }
+	YY_BREAK
+case 135:
+YY_RULE_SETUP
+#line 317 "cftoken.l"
+{ YYD; yylval.num = IPSECDOI_SIT_INTEGRITY; return(SITUATIONTYPE); }
+	YY_BREAK
+case 136:
+YY_RULE_SETUP
+#line 318 "cftoken.l"
+{ YYD; yywarn("it is obsoleted.  use \"my_identifier\"."); return(IDENTIFIER); }
+	YY_BREAK
+case 137:
+YY_RULE_SETUP
+#line 319 "cftoken.l"
+{ YYD; return(MY_IDENTIFIER); }
+	YY_BREAK
+case 138:
+YY_RULE_SETUP
+#line 320 "cftoken.l"
+{ YYD; return(XAUTH_LOGIN); /* formerly identifier type login */ }
+	YY_BREAK
+case 139:
+YY_RULE_SETUP
+#line 321 "cftoken.l"
+{ YYD; return(PEERS_IDENTIFIER); }
+	YY_BREAK
+case 140:
+YY_RULE_SETUP
+#line 322 "cftoken.l"
+{ YYD; return(VERIFY_IDENTIFIER); }
+	YY_BREAK
+case 141:
+YY_RULE_SETUP
+#line 323 "cftoken.l"
+{ YYD; return(CERTIFICATE_TYPE); }
+	YY_BREAK
+case 142:
+YY_RULE_SETUP
+#line 324 "cftoken.l"
+{ YYD; return(CA_TYPE); }
+	YY_BREAK
+case 143:
+YY_RULE_SETUP
+#line 325 "cftoken.l"
+{ YYD; yylval.num = ISAKMP_CERT_X509SIGN; return(CERT_X509); }
+	YY_BREAK
+case 144:
+YY_RULE_SETUP
+#line 326 "cftoken.l"
+{ YYD; yylval.num = ISAKMP_CERT_PLAINRSA; return(CERT_PLAINRSA); }
+	YY_BREAK
+case 145:
+YY_RULE_SETUP
+#line 327 "cftoken.l"
+{ YYD; return(PEERS_CERTFILE); }
+	YY_BREAK
+case 146:
+YY_RULE_SETUP
+#line 328 "cftoken.l"
+{ YYD; return(DNSSEC); }
+	YY_BREAK
+case 147:
+YY_RULE_SETUP
+#line 329 "cftoken.l"
+{ YYD; return(VERIFY_CERT); }
+	YY_BREAK
+case 148:
+YY_RULE_SETUP
+#line 330 "cftoken.l"
+{ YYD; return(SEND_CERT); }
+	YY_BREAK
+case 149:
+YY_RULE_SETUP
+#line 331 "cftoken.l"
+{ YYD; return(SEND_CR); }
+	YY_BREAK
+case 150:
+YY_RULE_SETUP
+#line 332 "cftoken.l"
+{ YYD; return(DH_GROUP); }
+	YY_BREAK
+case 151:
+YY_RULE_SETUP
+#line 333 "cftoken.l"
+{ YYD; return(NONCE_SIZE); }
+	YY_BREAK
+case 152:
+YY_RULE_SETUP
+#line 334 "cftoken.l"
+{ YYD; return(GENERATE_POLICY); }
+	YY_BREAK
+case 153:
+YY_RULE_SETUP
+#line 335 "cftoken.l"
+{ YYD; yylval.num = GENERATE_POLICY_UNIQUE; return(GENERATE_LEVEL); }
+	YY_BREAK
+case 154:
+YY_RULE_SETUP
+#line 336 "cftoken.l"
+{ YYD; yylval.num = GENERATE_POLICY_REQUIRE; return(GENERATE_LEVEL); }
+	YY_BREAK
+case 155:
+YY_RULE_SETUP
+#line 337 "cftoken.l"
+{ YYD; yywarn("it is obsoleted.  use \"support_proxy\"."); return(SUPPORT_PROXY); }
+	YY_BREAK
+case 156:
+YY_RULE_SETUP
+#line 338 "cftoken.l"
+{ YYD; return(SUPPORT_PROXY); }
+	YY_BREAK
+case 157:
+YY_RULE_SETUP
+#line 339 "cftoken.l"
+{ YYD; return(INITIAL_CONTACT); }
+	YY_BREAK
+case 158:
+YY_RULE_SETUP
+#line 340 "cftoken.l"
+{ YYD; return(NAT_TRAVERSAL); }
+	YY_BREAK
+case 159:
+YY_RULE_SETUP
+#line 341 "cftoken.l"
+{ YYD; return(REMOTE_FORCE_LEVEL); }
+	YY_BREAK
+case 160:
+YY_RULE_SETUP
+#line 342 "cftoken.l"
+{ YYD; return(PROPOSAL_CHECK); }
+	YY_BREAK
+case 161:
+YY_RULE_SETUP
+#line 343 "cftoken.l"
+{ YYD; yylval.num = PROP_CHECK_OBEY; return(PROPOSAL_CHECK_LEVEL); }
+	YY_BREAK
+case 162:
+YY_RULE_SETUP
+#line 344 "cftoken.l"
+{ YYD; yylval.num = PROP_CHECK_STRICT; return(PROPOSAL_CHECK_LEVEL); }
+	YY_BREAK
+case 163:
+YY_RULE_SETUP
+#line 345 "cftoken.l"
+{ YYD; yylval.num = PROP_CHECK_EXACT; return(PROPOSAL_CHECK_LEVEL); }
+	YY_BREAK
+case 164:
+YY_RULE_SETUP
+#line 346 "cftoken.l"
+{ YYD; yylval.num = PROP_CHECK_CLAIM; return(PROPOSAL_CHECK_LEVEL); }
+	YY_BREAK
+case 165:
+YY_RULE_SETUP
+#line 347 "cftoken.l"
+{ YYD; return(KEEPALIVE); }
+	YY_BREAK
+case 166:
+YY_RULE_SETUP
+#line 348 "cftoken.l"
+{ YYD; return(PASSIVE); }
+	YY_BREAK
+case 167:
+YY_RULE_SETUP
+#line 349 "cftoken.l"
+{ YYD; return(LIFETIME); }
+	YY_BREAK
+case 168:
+YY_RULE_SETUP
+#line 350 "cftoken.l"
+{ YYD; return(LIFETYPE_TIME); }
+	YY_BREAK
+case 169:
+YY_RULE_SETUP
+#line 351 "cftoken.l"
+{ YYD; return(LIFETYPE_BYTE); }
+	YY_BREAK
+case 170:
+YY_RULE_SETUP
+#line 352 "cftoken.l"
+{ YYD; return(DPD); }
+	YY_BREAK
+case 171:
+YY_RULE_SETUP
+#line 353 "cftoken.l"
+{ YYD; return(DPD_DELAY); }
+	YY_BREAK
+case 172:
+YY_RULE_SETUP
+#line 354 "cftoken.l"
+{ YYD; return(DPD_RETRY); }
+	YY_BREAK
+case 173:
+YY_RULE_SETUP
+#line 355 "cftoken.l"
+{ YYD; return(DPD_MAXFAIL); }
+	YY_BREAK
+case 174:
+YY_RULE_SETUP
+#line 356 "cftoken.l"
+{ YYD; return(PH1ID); }
+	YY_BREAK
+case 175:
+YY_RULE_SETUP
+#line 357 "cftoken.l"
+{ YYD; return(IKE_FRAG); }
+	YY_BREAK
+case 176:
+YY_RULE_SETUP
+#line 358 "cftoken.l"
+{ YYD; return(ESP_FRAG); }
+	YY_BREAK
+case 177:
+YY_RULE_SETUP
+#line 359 "cftoken.l"
+{ YYD; return(SCRIPT); }
+	YY_BREAK
+case 178:
+YY_RULE_SETUP
+#line 360 "cftoken.l"
+{ YYD; return(PHASE1_UP); }
+	YY_BREAK
+case 179:
+YY_RULE_SETUP
+#line 361 "cftoken.l"
+{ YYD; return(PHASE1_DOWN); }
+	YY_BREAK
+case 180:
+YY_RULE_SETUP
+#line 362 "cftoken.l"
+{ YYD; return(MODE_CFG); }
+	YY_BREAK
+case 181:
+YY_RULE_SETUP
+#line 363 "cftoken.l"
+{ YYD; return(WEAK_PHASE1_CHECK); }
+	YY_BREAK
+/* remote proposal */
+case 182:
+YY_RULE_SETUP
+#line 365 "cftoken.l"
+{ BEGIN S_RMTP; YYDB; return(PROPOSAL); }
+	YY_BREAK
+case 183:
+YY_RULE_SETUP
+#line 366 "cftoken.l"
+{ return(BOC); }
+	YY_BREAK
+case 184:
+YY_RULE_SETUP
+#line 367 "cftoken.l"
+{ BEGIN S_RMTS; return(EOC); }
+	YY_BREAK
+case 185:
+YY_RULE_SETUP
+#line 368 "cftoken.l"
+{ YYD; return(LIFETIME); }
+	YY_BREAK
+case 186:
+YY_RULE_SETUP
+#line 369 "cftoken.l"
+{ YYD; return(LIFETYPE_TIME); }
+	YY_BREAK
+case 187:
+YY_RULE_SETUP
+#line 370 "cftoken.l"
+{ YYD; return(LIFETYPE_BYTE); }
+	YY_BREAK
+case 188:
+YY_RULE_SETUP
+#line 371 "cftoken.l"
+{ YYD; yylval.num = algclass_isakmp_enc; return(ALGORITHM_CLASS); }
+	YY_BREAK
+case 189:
+YY_RULE_SETUP
+#line 372 "cftoken.l"
+{ YYD; yylval.num = algclass_isakmp_ameth; return(ALGORITHM_CLASS); }
+	YY_BREAK
+case 190:
+YY_RULE_SETUP
+#line 373 "cftoken.l"
+{ YYD; yylval.num = algclass_isakmp_hash; return(ALGORITHM_CLASS); }
+	YY_BREAK
+case 191:
+YY_RULE_SETUP
+#line 374 "cftoken.l"
+{ YYD; return(DH_GROUP); }
+	YY_BREAK
+case 192:
+YY_RULE_SETUP
+#line 375 "cftoken.l"
+{ YYD; return(GSS_ID); }
+	YY_BREAK
+case 193:
+YY_RULE_SETUP
+#line 376 "cftoken.l"
+{ YYD; return(GSS_ID); } /* for back compatibility */
+	YY_BREAK
+/* GSS ID encoding type (global) */
+case 194:
+YY_RULE_SETUP
+#line 379 "cftoken.l"
+{ BEGIN S_GSSENC; YYDB; return(GSS_ID_ENC); }
+	YY_BREAK
+case 195:
+YY_RULE_SETUP
+#line 380 "cftoken.l"
+{ YYD; yylval.num = LC_GSSENC_LATIN1;
+				return(GSS_ID_ENCTYPE); }
+	YY_BREAK
+case 196:
+YY_RULE_SETUP
+#line 382 "cftoken.l"
+{ YYD; yylval.num = LC_GSSENC_UTF16LE;
+				return(GSS_ID_ENCTYPE); }
+	YY_BREAK
+case 197:
+YY_RULE_SETUP
+#line 384 "cftoken.l"
+{ BEGIN S_INI; YYDB; return(EOS); }
+	YY_BREAK
+/* parameter */
+case 198:
+YY_RULE_SETUP
+#line 387 "cftoken.l"
+{ YYD; yylval.num = TRUE; return(SWITCH); }
+	YY_BREAK
+case 199:
+YY_RULE_SETUP
+#line 388 "cftoken.l"
+{ YYD; yylval.num = FALSE; return(SWITCH); }
+	YY_BREAK
+/* prefix */
+case 200:
+YY_RULE_SETUP
+#line 391 "cftoken.l"
+{
+			YYD;
+			yytext++;
+			yylval.num = atoi(yytext);
+			return(PREFIX);
+		}
+	YY_BREAK
+/* port number */
+case 201:
+YY_RULE_SETUP
+#line 399 "cftoken.l"
+{
+			char *p = yytext;
+			YYD;
+			while (*++p != ']') ;
+			*p = 0;
+			yytext++;
+			yylval.num = atoi(yytext);
+			return(PORT);
+		}
+	YY_BREAK
+/* address range */
+case 202:
+YY_RULE_SETUP
+#line 410 "cftoken.l"
+{
+                        YYD;
+                        yytext++;
+			yylval.val = vmalloc(yyleng + 1);
+			if (yylval.val == NULL) {
+				yyerror("vmalloc failed");
+				return -1;
+			}
+			memcpy(yylval.val->v, yytext, yylval.val->l);
+                        return(ADDRRANGE);
+                } 
+	YY_BREAK
+/* upper protocol */
+case 203:
+YY_RULE_SETUP
+#line 423 "cftoken.l"
+{ YYD; yylval.num = IPPROTO_ESP; return(UL_PROTO); }
+	YY_BREAK
+case 204:
+YY_RULE_SETUP
+#line 424 "cftoken.l"
+{ YYD; yylval.num = IPPROTO_AH; return(UL_PROTO); }
+	YY_BREAK
+case 205:
+YY_RULE_SETUP
+#line 425 "cftoken.l"
+{ YYD; yylval.num = IPPROTO_IPCOMP; return(UL_PROTO); }
+	YY_BREAK
+case 206:
+YY_RULE_SETUP
+#line 426 "cftoken.l"
+{ YYD; yylval.num = IPPROTO_ICMP; return(UL_PROTO); }
+	YY_BREAK
+case 207:
+YY_RULE_SETUP
+#line 427 "cftoken.l"
+{ YYD; yylval.num = IPPROTO_ICMPV6; return(UL_PROTO); }
+	YY_BREAK
+case 208:
+YY_RULE_SETUP
+#line 428 "cftoken.l"
+{ YYD; yylval.num = IPPROTO_TCP; return(UL_PROTO); }
+	YY_BREAK
+case 209:
+YY_RULE_SETUP
+#line 429 "cftoken.l"
+{ YYD; yylval.num = IPPROTO_UDP; return(UL_PROTO); }
+	YY_BREAK
+/* algorithm type */
+case 210:
+YY_RULE_SETUP
+#line 432 "cftoken.l"
+{ YYD; yylval.num = algtype_des_iv64;	return(ALGORITHMTYPE); }
+	YY_BREAK
+case 211:
+YY_RULE_SETUP
+#line 433 "cftoken.l"
+{ YYD; yylval.num = algtype_des;	return(ALGORITHMTYPE); }
+	YY_BREAK
+case 212:
+YY_RULE_SETUP
+#line 434 "cftoken.l"
+{ YYD; yylval.num = algtype_3des;	return(ALGORITHMTYPE); }
+	YY_BREAK
+case 213:
+YY_RULE_SETUP
+#line 435 "cftoken.l"
+{ YYD; yylval.num = algtype_rc5;	return(ALGORITHMTYPE); }
+	YY_BREAK
+case 214:
+YY_RULE_SETUP
+#line 436 "cftoken.l"
+{ YYD; yylval.num = algtype_idea;	return(ALGORITHMTYPE); }
+	YY_BREAK
+case 215:
+YY_RULE_SETUP
+#line 437 "cftoken.l"
+{ YYD; yylval.num = algtype_cast128;	return(ALGORITHMTYPE); }
+	YY_BREAK
+case 216:
+YY_RULE_SETUP
+#line 438 "cftoken.l"
+{ YYD; yylval.num = algtype_blowfish;	return(ALGORITHMTYPE); }
+	YY_BREAK
+case 217:
+YY_RULE_SETUP
+#line 439 "cftoken.l"
+{ YYD; yylval.num = algtype_3idea;	return(ALGORITHMTYPE); }
+	YY_BREAK
+case 218:
+YY_RULE_SETUP
+#line 440 "cftoken.l"
+{ YYD; yylval.num = algtype_des_iv32;	return(ALGORITHMTYPE); }
+	YY_BREAK
+case 219:
+YY_RULE_SETUP
+#line 441 "cftoken.l"
+{ YYD; yylval.num = algtype_rc4;	return(ALGORITHMTYPE); }
+	YY_BREAK
+case 220:
+YY_RULE_SETUP
+#line 442 "cftoken.l"
+{ YYD; yylval.num = algtype_null_enc;	return(ALGORITHMTYPE); }
+	YY_BREAK
+case 221:
+YY_RULE_SETUP
+#line 443 "cftoken.l"
+{ YYD; yylval.num = algtype_null_enc;	return(ALGORITHMTYPE); }
+	YY_BREAK
+case 222:
+YY_RULE_SETUP
+#line 444 "cftoken.l"
+{ YYD; yylval.num = algtype_aes;	return(ALGORITHMTYPE); }
+	YY_BREAK
+case 223:
+YY_RULE_SETUP
+#line 445 "cftoken.l"
+{ YYD; yylval.num = algtype_aes;	return(ALGORITHMTYPE); }
+	YY_BREAK
+case 224:
+YY_RULE_SETUP
+#line 446 "cftoken.l"
+{ YYD; yylval.num = algtype_twofish;	return(ALGORITHMTYPE); }
+	YY_BREAK
+case 225:
+YY_RULE_SETUP
+#line 447 "cftoken.l"
+{ YYD; yylval.num = algtype_camellia;	return(ALGORITHMTYPE); }
+	YY_BREAK
+case 226:
+YY_RULE_SETUP
+#line 448 "cftoken.l"
+{ YYD; yylval.num = algtype_non_auth;	return(ALGORITHMTYPE); }
+	YY_BREAK
+case 227:
+YY_RULE_SETUP
+#line 449 "cftoken.l"
+{ YYD; yylval.num = algtype_hmac_md5;	return(ALGORITHMTYPE); }
+	YY_BREAK
+case 228:
+YY_RULE_SETUP
+#line 450 "cftoken.l"
+{ YYD; yylval.num = algtype_hmac_sha1;	return(ALGORITHMTYPE); }
+	YY_BREAK
+case 229:
+YY_RULE_SETUP
+#line 451 "cftoken.l"
+{ YYD; yylval.num = algtype_hmac_sha2_256;	return(ALGORITHMTYPE); }
+	YY_BREAK
+case 230:
+YY_RULE_SETUP
+#line 452 "cftoken.l"
+{ YYD; yylval.num = algtype_hmac_sha2_256;	return(ALGORITHMTYPE); }
+	YY_BREAK
+case 231:
+YY_RULE_SETUP
+#line 453 "cftoken.l"
+{ YYD; yylval.num = algtype_hmac_sha2_384;	return(ALGORITHMTYPE); }
+	YY_BREAK
+case 232:
+YY_RULE_SETUP
+#line 454 "cftoken.l"
+{ YYD; yylval.num = algtype_hmac_sha2_384;	return(ALGORITHMTYPE); }
+	YY_BREAK
+case 233:
+YY_RULE_SETUP
+#line 455 "cftoken.l"
+{ YYD; yylval.num = algtype_hmac_sha2_512;	return(ALGORITHMTYPE); }
+	YY_BREAK
+case 234:
+YY_RULE_SETUP
+#line 456 "cftoken.l"
+{ YYD; yylval.num = algtype_hmac_sha2_512;	return(ALGORITHMTYPE); }
+	YY_BREAK
+case 235:
+YY_RULE_SETUP
+#line 457 "cftoken.l"
+{ YYD; yylval.num = algtype_des_mac;	return(ALGORITHMTYPE); }
+	YY_BREAK
+case 236:
+YY_RULE_SETUP
+#line 458 "cftoken.l"
+{ YYD; yylval.num = algtype_kpdk;	return(ALGORITHMTYPE); }
+	YY_BREAK
+case 237:
+YY_RULE_SETUP
+#line 459 "cftoken.l"
+{ YYD; yylval.num = algtype_md5;	return(ALGORITHMTYPE); }
+	YY_BREAK
+case 238:
+YY_RULE_SETUP
+#line 460 "cftoken.l"
+{ YYD; yylval.num = algtype_sha1;	return(ALGORITHMTYPE); }
+	YY_BREAK
+case 239:
+YY_RULE_SETUP
+#line 461 "cftoken.l"
+{ YYD; yylval.num = algtype_tiger;	return(ALGORITHMTYPE); }
+	YY_BREAK
+case 240:
+YY_RULE_SETUP
+#line 462 "cftoken.l"
+{ YYD; yylval.num = algtype_sha2_256;	return(ALGORITHMTYPE); }
+	YY_BREAK
+case 241:
+YY_RULE_SETUP
+#line 463 "cftoken.l"
+{ YYD; yylval.num = algtype_sha2_256;	return(ALGORITHMTYPE); }
+	YY_BREAK
+case 242:
+YY_RULE_SETUP
+#line 464 "cftoken.l"
+{ YYD; yylval.num = algtype_sha2_384;	return(ALGORITHMTYPE); }
+	YY_BREAK
+case 243:
+YY_RULE_SETUP
+#line 465 "cftoken.l"
+{ YYD; yylval.num = algtype_sha2_384;	return(ALGORITHMTYPE); }
+	YY_BREAK
+case 244:
+YY_RULE_SETUP
+#line 466 "cftoken.l"
+{ YYD; yylval.num = algtype_sha2_512;	return(ALGORITHMTYPE); }
+	YY_BREAK
+case 245:
+YY_RULE_SETUP
+#line 467 "cftoken.l"
+{ YYD; yylval.num = algtype_sha2_512;	return(ALGORITHMTYPE); }
+	YY_BREAK
+case 246:
+YY_RULE_SETUP
+#line 468 "cftoken.l"
+{ YYD; yylval.num = algtype_oui;	return(ALGORITHMTYPE); }
+	YY_BREAK
+case 247:
+YY_RULE_SETUP
+#line 469 "cftoken.l"
+{ YYD; yylval.num = algtype_deflate;	return(ALGORITHMTYPE); }
+	YY_BREAK
+case 248:
+YY_RULE_SETUP
+#line 470 "cftoken.l"
+{ YYD; yylval.num = algtype_lzs;	return(ALGORITHMTYPE); }
+	YY_BREAK
+case 249:
+YY_RULE_SETUP
+#line 471 "cftoken.l"
+{ YYD; yylval.num = algtype_modp768;	return(ALGORITHMTYPE); }
+	YY_BREAK
+case 250:
+YY_RULE_SETUP
+#line 472 "cftoken.l"
+{ YYD; yylval.num = algtype_modp1024;	return(ALGORITHMTYPE); }
+	YY_BREAK
+case 251:
+YY_RULE_SETUP
+#line 473 "cftoken.l"
+{ YYD; yylval.num = algtype_modp1536;	return(ALGORITHMTYPE); }
+	YY_BREAK
+case 252:
+YY_RULE_SETUP
+#line 474 "cftoken.l"
+{ YYD; yylval.num = algtype_ec2n155;	return(ALGORITHMTYPE); }
+	YY_BREAK
+case 253:
+YY_RULE_SETUP
+#line 475 "cftoken.l"
+{ YYD; yylval.num = algtype_ec2n185;	return(ALGORITHMTYPE); }
+	YY_BREAK
+case 254:
+YY_RULE_SETUP
+#line 476 "cftoken.l"
+{ YYD; yylval.num = algtype_modp2048;	return(ALGORITHMTYPE); }
+	YY_BREAK
+case 255:
+YY_RULE_SETUP
+#line 477 "cftoken.l"
+{ YYD; yylval.num = algtype_modp3072;	return(ALGORITHMTYPE); }
+	YY_BREAK
+case 256:
+YY_RULE_SETUP
+#line 478 "cftoken.l"
+{ YYD; yylval.num = algtype_modp4096;	return(ALGORITHMTYPE); }
+	YY_BREAK
+case 257:
+YY_RULE_SETUP
+#line 479 "cftoken.l"
+{ YYD; yylval.num = algtype_modp6144;	return(ALGORITHMTYPE); }
+	YY_BREAK
+case 258:
+YY_RULE_SETUP
+#line 480 "cftoken.l"
+{ YYD; yylval.num = algtype_modp8192;	return(ALGORITHMTYPE); }
+	YY_BREAK
+case 259:
+YY_RULE_SETUP
+#line 481 "cftoken.l"
+{ YYD; yylval.num = algtype_psk;	return(ALGORITHMTYPE); }
+	YY_BREAK
+case 260:
+YY_RULE_SETUP
+#line 482 "cftoken.l"
+{ YYD; yylval.num = algtype_rsasig;	return(ALGORITHMTYPE); }
+	YY_BREAK
+case 261:
+YY_RULE_SETUP
+#line 483 "cftoken.l"
+{ YYD; yylval.num = algtype_dsssig;	return(ALGORITHMTYPE); }
+	YY_BREAK
+case 262:
+YY_RULE_SETUP
+#line 484 "cftoken.l"
+{ YYD; yylval.num = algtype_rsaenc;	return(ALGORITHMTYPE); }
+	YY_BREAK
+case 263:
+YY_RULE_SETUP
+#line 485 "cftoken.l"
+{ YYD; yylval.num = algtype_rsarev;	return(ALGORITHMTYPE); }
+	YY_BREAK
+case 264:
+YY_RULE_SETUP
+#line 486 "cftoken.l"
+{ YYD; yylval.num = algtype_gssapikrb;	return(ALGORITHMTYPE); }
+	YY_BREAK
+case 265:
+YY_RULE_SETUP
+#line 487 "cftoken.l"
+{
+#ifdef ENABLE_HYBRID
+	YYD; yylval.num = algtype_hybrid_rsa_s; return(ALGORITHMTYPE);
+#else
+	yyerror("racoon not configured with --enable-hybrid");
+#endif
+}
+	YY_BREAK
+case 266:
+YY_RULE_SETUP
+#line 494 "cftoken.l"
+{
+#ifdef ENABLE_HYBRID
+	YYD; yylval.num = algtype_hybrid_dss_s; return(ALGORITHMTYPE);
+#else
+	yyerror("racoon not configured with --enable-hybrid");
+#endif
+}
+	YY_BREAK
+case 267:
+YY_RULE_SETUP
+#line 501 "cftoken.l"
+{
+#ifdef ENABLE_HYBRID
+	YYD; yylval.num = algtype_hybrid_rsa_c; return(ALGORITHMTYPE);
+#else
+	yyerror("racoon not configured with --enable-hybrid");
+#endif
+}
+	YY_BREAK
+case 268:
+YY_RULE_SETUP
+#line 508 "cftoken.l"
+{
+#ifdef ENABLE_HYBRID
+	YYD; yylval.num = algtype_hybrid_dss_c; return(ALGORITHMTYPE);
+#else
+	yyerror("racoon not configured with --enable-hybrid");
+#endif
+}
+	YY_BREAK
+case 269:
+YY_RULE_SETUP
+#line 515 "cftoken.l"
+{
+#ifdef ENABLE_HYBRID
+	YYD; yylval.num = algtype_xauth_psk_s; return(ALGORITHMTYPE);
+#else
+	yyerror("racoon not configured with --enable-hybrid");
+#endif
+}
+	YY_BREAK
+case 270:
+YY_RULE_SETUP
+#line 522 "cftoken.l"
+{
+#ifdef ENABLE_HYBRID
+	YYD; yylval.num = algtype_xauth_psk_c; return(ALGORITHMTYPE);
+#else
+	yyerror("racoon not configured with --enable-hybrid");
+#endif
+}
+	YY_BREAK
+case 271:
+YY_RULE_SETUP
+#line 529 "cftoken.l"
+{
+#ifdef ENABLE_HYBRID
+	YYD; yylval.num = algtype_xauth_rsa_s; return(ALGORITHMTYPE);
+#else
+	yyerror("racoon not configured with --enable-hybrid");
+#endif
+}
+	YY_BREAK
+case 272:
+YY_RULE_SETUP
+#line 536 "cftoken.l"
+{
+#ifdef ENABLE_HYBRID
+	YYD; yylval.num = algtype_xauth_rsa_c; return(ALGORITHMTYPE);
+#else
+	yyerror("racoon not configured with --enable-hybrid");
+#endif
+}
+	YY_BREAK
+/* identifier type */
+case 273:
+YY_RULE_SETUP
+#line 546 "cftoken.l"
+{ YYD; yywarn("it is obsoleted."); return(VENDORID); }
+	YY_BREAK
+case 274:
+YY_RULE_SETUP
+#line 547 "cftoken.l"
+{ YYD; yylval.num = IDTYPE_USERFQDN; return(IDENTIFIERTYPE); }
+	YY_BREAK
+case 275:
+YY_RULE_SETUP
+#line 548 "cftoken.l"
+{ YYD; yylval.num = IDTYPE_FQDN; return(IDENTIFIERTYPE); }
+	YY_BREAK
+case 276:
+YY_RULE_SETUP
+#line 549 "cftoken.l"
+{ YYD; yylval.num = IDTYPE_KEYID; return(IDENTIFIERTYPE); }
+	YY_BREAK
+case 277:
+YY_RULE_SETUP
+#line 550 "cftoken.l"
+{ YYD; yylval.num = IDTYPE_ADDRESS; return(IDENTIFIERTYPE); }
+	YY_BREAK
+case 278:
+YY_RULE_SETUP
+#line 551 "cftoken.l"
+{ YYD; yylval.num = IDTYPE_SUBNET; return(IDENTIFIERTYPE); }
+	YY_BREAK
+case 279:
+YY_RULE_SETUP
+#line 552 "cftoken.l"
+{ YYD; yylval.num = IDTYPE_ASN1DN; return(IDENTIFIERTYPE); }
+	YY_BREAK
+case 280:
+YY_RULE_SETUP
+#line 553 "cftoken.l"
+{ YYD; yywarn("certname will be obsoleted in near future."); yylval.num = IDTYPE_ASN1DN; return(IDENTIFIERTYPE); }
+	YY_BREAK
+/* identifier qualifier */
+case 281:
+YY_RULE_SETUP
+#line 556 "cftoken.l"
+{ YYD; yylval.num = IDQUAL_TAG;  return(IDENTIFIERQUAL); }
+	YY_BREAK
+case 282:
+YY_RULE_SETUP
+#line 557 "cftoken.l"
+{ YYD; yylval.num = IDQUAL_FILE; return(IDENTIFIERQUAL); }
+	YY_BREAK
+/* units */
+case 283:
+YY_RULE_SETUP
+#line 560 "cftoken.l"
+{ YYD; return(UNITTYPE_BYTE); }
+	YY_BREAK
+case 284:
+YY_RULE_SETUP
+#line 561 "cftoken.l"
+{ YYD; return(UNITTYPE_KBYTES); }
+	YY_BREAK
+case 285:
+YY_RULE_SETUP
+#line 562 "cftoken.l"
+{ YYD; return(UNITTYPE_MBYTES); }
+	YY_BREAK
+case 286:
+YY_RULE_SETUP
+#line 563 "cftoken.l"
+{ YYD; return(UNITTYPE_TBYTES); }
+	YY_BREAK
+case 287:
+YY_RULE_SETUP
+#line 564 "cftoken.l"
+{ YYD; return(UNITTYPE_SEC); }
+	YY_BREAK
+case 288:
+YY_RULE_SETUP
+#line 565 "cftoken.l"
+{ YYD; return(UNITTYPE_MIN); }
+	YY_BREAK
+case 289:
+YY_RULE_SETUP
+#line 566 "cftoken.l"
+{ YYD; return(UNITTYPE_HOUR); }
+	YY_BREAK
+/* boolean */
+case 290:
+YY_RULE_SETUP
+#line 569 "cftoken.l"
+{ YYD; yylval.num = TRUE; return(BOOLEAN); }
+	YY_BREAK
+case 291:
+YY_RULE_SETUP
+#line 570 "cftoken.l"
+{ YYD; yylval.num = FALSE; return(BOOLEAN); }
+	YY_BREAK
+case 292:
+YY_RULE_SETUP
+#line 572 "cftoken.l"
+{
+			char *bp;
+
+			YYD;
+			yylval.num = strtol(yytext, &bp, 10);
+			return(NUMBER);
+		}
+	YY_BREAK
+case 293:
+YY_RULE_SETUP
+#line 580 "cftoken.l"
+{
+			char *p;
+
+			YYD; 
+			yylval.val = vmalloc(yyleng + (yyleng & 1) + 1);
+			if (yylval.val == NULL) {
+				yyerror("vmalloc failed");
+				return -1;
+			}
+
+			p = yylval.val->v;
+			*p++ = '0';
+			*p++ = 'x';
+
+			/* fixed string if length is odd. */
+			if (yyleng & 1)
+				*p++ = '0';
+			memcpy(p, &yytext[2], yyleng - 1);
+
+			return(HEXSTRING);
+		}
+	YY_BREAK
+case 294:
+/* rule 294 can match eol */
+YY_RULE_SETUP
+#line 602 "cftoken.l"
+{
+			char *p = yytext;
+
+			YYD;
+			while (*++p != '"') ;
+			*p = '\0';
+
+			yylval.val = vmalloc(yyleng - 1);
+			if (yylval.val == NULL) {
+				yyerror("vmalloc failed");
+				return -1;
+			}
+			memcpy(yylval.val->v, &yytext[1], yylval.val->l);
+
+			return(QUOTEDSTRING);
+		}
+	YY_BREAK
+case 295:
+YY_RULE_SETUP
+#line 619 "cftoken.l"
+{
+			YYD;
+
+			yylval.val = vmalloc(yyleng + 1);
+			if (yylval.val == NULL) {
+				yyerror("vmalloc failed");
+				return -1;
+			}
+			memcpy(yylval.val->v, yytext, yylval.val->l);
+
+			return(ADDRSTRING);
+		}
+	YY_BREAK
+case YY_STATE_EOF(INITIAL):
+case YY_STATE_EOF(S_INI):
+case YY_STATE_EOF(S_PRIV):
+case YY_STATE_EOF(S_PTH):
+case YY_STATE_EOF(S_INF):
+case YY_STATE_EOF(S_LOG):
+case YY_STATE_EOF(S_PAD):
+case YY_STATE_EOF(S_LST):
+case YY_STATE_EOF(S_RTRY):
+case YY_STATE_EOF(S_CFG):
+case YY_STATE_EOF(S_LDAP):
+case YY_STATE_EOF(S_ALGST):
+case YY_STATE_EOF(S_ALGCL):
+case YY_STATE_EOF(S_SAINF):
+case YY_STATE_EOF(S_SAINFS):
+case YY_STATE_EOF(S_RMT):
+case YY_STATE_EOF(S_RMTS):
+case YY_STATE_EOF(S_RMTP):
+case YY_STATE_EOF(S_SA):
+case YY_STATE_EOF(S_GSSENC):
+#line 632 "cftoken.l"
+{
+			yy_delete_buffer(YY_CURRENT_BUFFER);
+			incstackp--;
+    nextfile:
+			if (incstack[incstackp].matchon <
+			    incstack[incstackp].matches.gl_pathc) {
+				char* filepath = incstack[incstackp].matches.gl_pathv[incstack[incstackp].matchon];
+				incstack[incstackp].matchon++;
+				incstackp++;
+				if (yycf_set_buffer(filepath) != 0) {
+					incstackp--;
+					goto nextfile;
+				}
+				yy_switch_to_buffer(yy_create_buffer(yyin,YY_BUF_SIZE));
+				BEGIN(S_INI);
+			} else {
+				globfree(&incstack[incstackp].matches);
+				if (incstackp == 0)
+					yyterminate();
+				else
+					yy_switch_to_buffer(incstack[incstackp].prevstate);
+			}
+		}
+	YY_BREAK
+/* ... */
+case 296:
+YY_RULE_SETUP
+#line 657 "cftoken.l"
+{ ; }
+	YY_BREAK
+case 297:
+/* rule 297 can match eol */
+YY_RULE_SETUP
+#line 658 "cftoken.l"
+{ incstack[incstackp].lineno++; }
+	YY_BREAK
+case 298:
+YY_RULE_SETUP
+#line 659 "cftoken.l"
+{ YYD; }
+	YY_BREAK
+case 299:
+YY_RULE_SETUP
+#line 660 "cftoken.l"
+{ return(EOS); }
+	YY_BREAK
+case 300:
+YY_RULE_SETUP
+#line 661 "cftoken.l"
+{ yymore(); }
+	YY_BREAK
+case 301:
+YY_RULE_SETUP
+#line 663 "cftoken.l"
+ECHO;
+	YY_BREAK
+#line 3650 "cftoken.c"
+
+	case YY_END_OF_BUFFER:
+		{
+		/* Amount of text matched not including the EOB char. */
+		int yy_amount_of_matched_text = (int) (yy_cp - (yytext_ptr)) - 1;
+
+		/* Undo the effects of YY_DO_BEFORE_ACTION. */
+		*yy_cp = (yy_hold_char);
+		YY_RESTORE_YY_MORE_OFFSET
+
+		if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW )
+			{
+			/* We're scanning a new file or input source.  It's
+			 * possible that this happened because the user
+			 * just pointed yyin at a new source and called
+			 * yylex().  If so, then we have to assure
+			 * consistency between YY_CURRENT_BUFFER and our
+			 * globals.  Here is the right place to do so, because
+			 * this is the first action (other than possibly a
+			 * back-up) that will match for the new input source.
+			 */
+			(yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
+			YY_CURRENT_BUFFER_LVALUE->yy_input_file = yyin;
+			YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL;
+			}
+
+		/* Note that here we test for yy_c_buf_p "<=" to the position
+		 * of the first EOB in the buffer, since yy_c_buf_p will
+		 * already have been incremented past the NUL character
+		 * (since all states make transitions on EOB to the
+		 * end-of-buffer state).  Contrast this with the test
+		 * in input().
+		 */
+		if ( (yy_c_buf_p) <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] )
+			{ /* This was really a NUL. */
+			yy_state_type yy_next_state;
+
+			(yy_c_buf_p) = (yytext_ptr) + yy_amount_of_matched_text;
+
+			yy_current_state = yy_get_previous_state(  );
+
+			/* Okay, we're now positioned to make the NUL
+			 * transition.  We couldn't have
+			 * yy_get_previous_state() go ahead and do it
+			 * for us because it doesn't know how to deal
+			 * with the possibility of jamming (and we don't
+			 * want to build jamming into it because then it
+			 * will run more slowly).
+			 */
+
+			yy_next_state = yy_try_NUL_trans( yy_current_state );
+
+			yy_bp = (yytext_ptr) + YY_MORE_ADJ;
+
+			if ( yy_next_state )
+				{
+				/* Consume the NUL. */
+				yy_cp = ++(yy_c_buf_p);
+				yy_current_state = yy_next_state;
+				goto yy_match;
+				}
+
+			else
+				{
+				yy_cp = (yy_c_buf_p);
+				goto yy_find_action;
+				}
+			}
+
+		else switch ( yy_get_next_buffer(  ) )
+			{
+			case EOB_ACT_END_OF_FILE:
+				{
+				(yy_did_buffer_switch_on_eof) = 0;
+
+				if ( yywrap( ) )
+					{
+					/* Note: because we've taken care in
+					 * yy_get_next_buffer() to have set up
+					 * yytext, we can now set up
+					 * yy_c_buf_p so that if some total
+					 * hoser (like flex itself) wants to
+					 * call the scanner after we return the
+					 * YY_NULL, it'll still work - another
+					 * YY_NULL will get returned.
+					 */
+					(yy_c_buf_p) = (yytext_ptr) + YY_MORE_ADJ;
+
+					yy_act = YY_STATE_EOF(YY_START);
+					goto do_action;
+					}
+
+				else
+					{
+					if ( ! (yy_did_buffer_switch_on_eof) )
+						YY_NEW_FILE;
+					}
+				break;
+				}
+
+			case EOB_ACT_CONTINUE_SCAN:
+				(yy_c_buf_p) =
+					(yytext_ptr) + yy_amount_of_matched_text;
+
+				yy_current_state = yy_get_previous_state(  );
+
+				yy_cp = (yy_c_buf_p);
+				yy_bp = (yytext_ptr) + YY_MORE_ADJ;
+				goto yy_match;
+
+			case EOB_ACT_LAST_MATCH:
+				(yy_c_buf_p) =
+				&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)];
+
+				yy_current_state = yy_get_previous_state(  );
+
+				yy_cp = (yy_c_buf_p);
+				yy_bp = (yytext_ptr) + YY_MORE_ADJ;
+				goto yy_find_action;
+			}
+		break;
+		}
+
+	default:
+		YY_FATAL_ERROR(
+			"fatal flex scanner internal error--no action found" );
+	} /* end of action switch */
+		} /* end of scanning one token */
+} /* end of yylex */
+
+/* yy_get_next_buffer - try to read in a new buffer
+ *
+ * Returns a code representing an action:
+ *	EOB_ACT_LAST_MATCH -
+ *	EOB_ACT_CONTINUE_SCAN - continue scanning from current position
+ *	EOB_ACT_END_OF_FILE - end of file
+ */
+static int yy_get_next_buffer (void)
+{
+    	register char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf;
+	register char *source = (yytext_ptr);
+	register int number_to_move, i;
+	int ret_val;
+
+	if ( (yy_c_buf_p) > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] )
+		YY_FATAL_ERROR(
+		"fatal flex scanner internal error--end of buffer missed" );
+
+	if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 )
+		{ /* Don't try to fill the buffer, so this is an EOF. */
+		if ( (yy_c_buf_p) - (yytext_ptr) - YY_MORE_ADJ == 1 )
+			{
+			/* We matched a single character, the EOB, so
+			 * treat this as a final EOF.
+			 */
+			return EOB_ACT_END_OF_FILE;
+			}
+
+		else
+			{
+			/* We matched some text prior to the EOB, first
+			 * process it.
+			 */
+			return EOB_ACT_LAST_MATCH;
+			}
+		}
+
+	/* Try to read more data. */
+
+	/* First move last chars to start of buffer. */
+	number_to_move = (int) ((yy_c_buf_p) - (yytext_ptr)) - 1;
+
+	for ( i = 0; i < number_to_move; ++i )
+		*(dest++) = *(source++);
+
+	if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING )
+		/* don't do the read, it's not guaranteed to return an EOF,
+		 * just force an EOF
+		 */
+		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars) = 0;
+
+	else
+		{
+			int num_to_read =
+			YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1;
+
+		while ( num_to_read <= 0 )
+			{ /* Not enough room in the buffer - grow it. */
+
+			/* just a shorter name for the current buffer */
+			YY_BUFFER_STATE b = YY_CURRENT_BUFFER;
+
+			int yy_c_buf_p_offset =
+				(int) ((yy_c_buf_p) - b->yy_ch_buf);
+
+			if ( b->yy_is_our_buffer )
+				{
+				int new_size = b->yy_buf_size * 2;
+
+				if ( new_size <= 0 )
+					b->yy_buf_size += b->yy_buf_size / 8;
+				else
+					b->yy_buf_size *= 2;
+
+				b->yy_ch_buf = (char *)
+					/* Include room in for 2 EOB chars. */
+					yyrealloc((void *) b->yy_ch_buf,b->yy_buf_size + 2  );
+				}
+			else
+				/* Can't grow it, we don't own it. */
+				b->yy_ch_buf = 0;
+
+			if ( ! b->yy_ch_buf )
+				YY_FATAL_ERROR(
+				"fatal error - scanner input buffer overflow" );
+
+			(yy_c_buf_p) = &b->yy_ch_buf[yy_c_buf_p_offset];
+
+			num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size -
+						number_to_move - 1;
+
+			}
+
+		if ( num_to_read > YY_READ_BUF_SIZE )
+			num_to_read = YY_READ_BUF_SIZE;
+
+		/* Read in more data. */
+		YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]),
+			(yy_n_chars), (size_t) num_to_read );
+
+		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
+		}
+
+	if ( (yy_n_chars) == 0 )
+		{
+		if ( number_to_move == YY_MORE_ADJ )
+			{
+			ret_val = EOB_ACT_END_OF_FILE;
+			yyrestart(yyin  );
+			}
+
+		else
+			{
+			ret_val = EOB_ACT_LAST_MATCH;
+			YY_CURRENT_BUFFER_LVALUE->yy_buffer_status =
+				YY_BUFFER_EOF_PENDING;
+			}
+		}
+
+	else
+		ret_val = EOB_ACT_CONTINUE_SCAN;
+
+	if ((yy_size_t) ((yy_n_chars) + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) {
+		/* Extend the array by 50%, plus the number we really need. */
+		yy_size_t new_size = (yy_n_chars) + number_to_move + ((yy_n_chars) >> 1);
+		YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) yyrealloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size  );
+		if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
+			YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" );
+	}
+
+	(yy_n_chars) += number_to_move;
+	YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] = YY_END_OF_BUFFER_CHAR;
+	YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] = YY_END_OF_BUFFER_CHAR;
+
+	(yytext_ptr) = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0];
+
+	return ret_val;
+}
+
+/* yy_get_previous_state - get the state just before the EOB char was reached */
+
+    static yy_state_type yy_get_previous_state (void)
+{
+	register yy_state_type yy_current_state;
+	register char *yy_cp;
+    
+	yy_current_state = (yy_start);
+
+	for ( yy_cp = (yytext_ptr) + YY_MORE_ADJ; yy_cp < (yy_c_buf_p); ++yy_cp )
+		{
+		register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1);
+		if ( yy_accept[yy_current_state] )
+			{
+			(yy_last_accepting_state) = yy_current_state;
+			(yy_last_accepting_cpos) = yy_cp;
+			}
+		while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+			{
+			yy_current_state = (int) yy_def[yy_current_state];
+			if ( yy_current_state >= 1781 )
+				yy_c = yy_meta[(unsigned int) yy_c];
+			}
+		yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+		}
+
+	return yy_current_state;
+}
+
+/* yy_try_NUL_trans - try to make a transition on the NUL character
+ *
+ * synopsis
+ *	next_state = yy_try_NUL_trans( current_state );
+ */
+    static yy_state_type yy_try_NUL_trans  (yy_state_type yy_current_state )
+{
+	register int yy_is_jam;
+    	register char *yy_cp = (yy_c_buf_p);
+
+	register YY_CHAR yy_c = 1;
+	if ( yy_accept[yy_current_state] )
+		{
+		(yy_last_accepting_state) = yy_current_state;
+		(yy_last_accepting_cpos) = yy_cp;
+		}
+	while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+		{
+		yy_current_state = (int) yy_def[yy_current_state];
+		if ( yy_current_state >= 1781 )
+			yy_c = yy_meta[(unsigned int) yy_c];
+		}
+	yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+	yy_is_jam = (yy_current_state == 1780);
+
+	return yy_is_jam ? 0 : yy_current_state;
+}
+
+    static void yyunput (int c, register char * yy_bp )
+{
+	register char *yy_cp;
+    
+    yy_cp = (yy_c_buf_p);
+
+	/* undo effects of setting up yytext */
+	*yy_cp = (yy_hold_char);
+
+	if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 )
+		{ /* need to shift things up to make room */
+		/* +2 for EOB chars. */
+		register int number_to_move = (yy_n_chars) + 2;
+		register char *dest = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[
+					YY_CURRENT_BUFFER_LVALUE->yy_buf_size + 2];
+		register char *source =
+				&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move];
+
+		while ( source > YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
+			*--dest = *--source;
+
+		yy_cp += (int) (dest - source);
+		yy_bp += (int) (dest - source);
+		YY_CURRENT_BUFFER_LVALUE->yy_n_chars =
+			(yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_buf_size;
+
+		if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 )
+			YY_FATAL_ERROR( "flex scanner push-back overflow" );
+		}
+
+	*--yy_cp = (char) c;
+
+	(yytext_ptr) = yy_bp;
+	(yy_hold_char) = *yy_cp;
+	(yy_c_buf_p) = yy_cp;
+}
+
+#ifndef YY_NO_INPUT
+#ifdef __cplusplus
+    static int yyinput (void)
+#else
+    static int input  (void)
+#endif
+
+{
+	int c;
+    
+	*(yy_c_buf_p) = (yy_hold_char);
+
+	if ( *(yy_c_buf_p) == YY_END_OF_BUFFER_CHAR )
+		{
+		/* yy_c_buf_p now points to the character we want to return.
+		 * If this occurs *before* the EOB characters, then it's a
+		 * valid NUL; if not, then we've hit the end of the buffer.
+		 */
+		if ( (yy_c_buf_p) < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] )
+			/* This was really a NUL. */
+			*(yy_c_buf_p) = '\0';
+
+		else
+			{ /* need more input */
+			int offset = (yy_c_buf_p) - (yytext_ptr);
+			++(yy_c_buf_p);
+
+			switch ( yy_get_next_buffer(  ) )
+				{
+				case EOB_ACT_LAST_MATCH:
+					/* This happens because yy_g_n_b()
+					 * sees that we've accumulated a
+					 * token and flags that we need to
+					 * try matching the token before
+					 * proceeding.  But for input(),
+					 * there's no matching to consider.
+					 * So convert the EOB_ACT_LAST_MATCH
+					 * to EOB_ACT_END_OF_FILE.
+					 */
+
+					/* Reset buffer status. */
+					yyrestart(yyin );
+
+					/*FALLTHROUGH*/
+
+				case EOB_ACT_END_OF_FILE:
+					{
+					if ( yywrap( ) )
+						return EOF;
+
+					if ( ! (yy_did_buffer_switch_on_eof) )
+						YY_NEW_FILE;
+#ifdef __cplusplus
+					return yyinput();
+#else
+					return input();
+#endif
+					}
+
+				case EOB_ACT_CONTINUE_SCAN:
+					(yy_c_buf_p) = (yytext_ptr) + offset;
+					break;
+				}
+			}
+		}
+
+	c = *(unsigned char *) (yy_c_buf_p);	/* cast for 8-bit char's */
+	*(yy_c_buf_p) = '\0';	/* preserve yytext */
+	(yy_hold_char) = *++(yy_c_buf_p);
+
+	return c;
+}
+#endif	/* ifndef YY_NO_INPUT */
+
+/** Immediately switch to a different input stream.
+ * @param input_file A readable stream.
+ * 
+ * @note This function does not reset the start condition to @c INITIAL .
+ */
+    void yyrestart  (FILE * input_file )
+{
+    
+	if ( ! YY_CURRENT_BUFFER ){
+        yyensure_buffer_stack ();
+		YY_CURRENT_BUFFER_LVALUE =
+            yy_create_buffer(yyin,YY_BUF_SIZE );
+	}
+
+	yy_init_buffer(YY_CURRENT_BUFFER,input_file );
+	yy_load_buffer_state( );
+}
+
+/** Switch to a different input buffer.
+ * @param new_buffer The new input buffer.
+ * 
+ */
+    void yy_switch_to_buffer  (YY_BUFFER_STATE  new_buffer )
+{
+    
+	/* TODO. We should be able to replace this entire function body
+	 * with
+	 *		yypop_buffer_state();
+	 *		yypush_buffer_state(new_buffer);
+     */
+	yyensure_buffer_stack ();
+	if ( YY_CURRENT_BUFFER == new_buffer )
+		return;
+
+	if ( YY_CURRENT_BUFFER )
+		{
+		/* Flush out information for old buffer. */
+		*(yy_c_buf_p) = (yy_hold_char);
+		YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p);
+		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
+		}
+
+	YY_CURRENT_BUFFER_LVALUE = new_buffer;
+	yy_load_buffer_state( );
+
+	/* We don't actually know whether we did this switch during
+	 * EOF (yywrap()) processing, but the only time this flag
+	 * is looked at is after yywrap() is called, so it's safe
+	 * to go ahead and always set it.
+	 */
+	(yy_did_buffer_switch_on_eof) = 1;
+}
+
+static void yy_load_buffer_state  (void)
+{
+    	(yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
+	(yytext_ptr) = (yy_c_buf_p) = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos;
+	yyin = YY_CURRENT_BUFFER_LVALUE->yy_input_file;
+	(yy_hold_char) = *(yy_c_buf_p);
+}
+
+/** Allocate and initialize an input buffer state.
+ * @param file A readable stream.
+ * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE.
+ * 
+ * @return the allocated buffer state.
+ */
+    YY_BUFFER_STATE yy_create_buffer  (FILE * file, int  size )
+{
+	YY_BUFFER_STATE b;
+    
+	b = (YY_BUFFER_STATE) yyalloc(sizeof( struct yy_buffer_state )  );
+	if ( ! b )
+		YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
+
+	b->yy_buf_size = size;
+
+	/* yy_ch_buf has to be 2 characters longer than the size given because
+	 * we need to put in 2 end-of-buffer characters.
+	 */
+	b->yy_ch_buf = (char *) yyalloc(b->yy_buf_size + 2  );
+	if ( ! b->yy_ch_buf )
+		YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
+
+	b->yy_is_our_buffer = 1;
+
+	yy_init_buffer(b,file );
+
+	return b;
+}
+
+/** Destroy the buffer.
+ * @param b a buffer created with yy_create_buffer()
+ * 
+ */
+    void yy_delete_buffer (YY_BUFFER_STATE  b )
+{
+    
+	if ( ! b )
+		return;
+
+	if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */
+		YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0;
+
+	if ( b->yy_is_our_buffer )
+		yyfree((void *) b->yy_ch_buf  );
+
+	yyfree((void *) b  );
+}
+
+#ifndef __cplusplus
+extern int isatty (int );
+#endif /* __cplusplus */
+    
+/* Initializes or reinitializes a buffer.
+ * This function is sometimes called more than once on the same buffer,
+ * such as during a yyrestart() or at EOF.
+ */
+    static void yy_init_buffer  (YY_BUFFER_STATE  b, FILE * file )
+
+{
+	int oerrno = errno;
+    
+	yy_flush_buffer(b );
+
+	b->yy_input_file = file;
+	b->yy_fill_buffer = 1;
+
+    /* If b is the current buffer, then yy_init_buffer was _probably_
+     * called from yyrestart() or through yy_get_next_buffer.
+     * In that case, we don't want to reset the lineno or column.
+     */
+    if (b != YY_CURRENT_BUFFER){
+        b->yy_bs_lineno = 1;
+        b->yy_bs_column = 0;
+    }
+
+        b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0;
+    
+	errno = oerrno;
+}
+
+/** Discard all buffered characters. On the next scan, YY_INPUT will be called.
+ * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER.
+ * 
+ */
+    void yy_flush_buffer (YY_BUFFER_STATE  b )
+{
+    	if ( ! b )
+		return;
+
+	b->yy_n_chars = 0;
+
+	/* We always need two end-of-buffer characters.  The first causes
+	 * a transition to the end-of-buffer state.  The second causes
+	 * a jam in that state.
+	 */
+	b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR;
+	b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR;
+
+	b->yy_buf_pos = &b->yy_ch_buf[0];
+
+	b->yy_at_bol = 1;
+	b->yy_buffer_status = YY_BUFFER_NEW;
+
+	if ( b == YY_CURRENT_BUFFER )
+		yy_load_buffer_state( );
+}
+
+/** Pushes the new state onto the stack. The new state becomes
+ *  the current state. This function will allocate the stack
+ *  if necessary.
+ *  @param new_buffer The new state.
+ *  
+ */
+void yypush_buffer_state (YY_BUFFER_STATE new_buffer )
+{
+    	if (new_buffer == NULL)
+		return;
+
+	yyensure_buffer_stack();
+
+	/* This block is copied from yy_switch_to_buffer. */
+	if ( YY_CURRENT_BUFFER )
+		{
+		/* Flush out information for old buffer. */
+		*(yy_c_buf_p) = (yy_hold_char);
+		YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p);
+		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
+		}
+
+	/* Only push if top exists. Otherwise, replace top. */
+	if (YY_CURRENT_BUFFER)
+		(yy_buffer_stack_top)++;
+	YY_CURRENT_BUFFER_LVALUE = new_buffer;
+
+	/* copied from yy_switch_to_buffer. */
+	yy_load_buffer_state( );
+	(yy_did_buffer_switch_on_eof) = 1;
+}
+
+/** Removes and deletes the top of the stack, if present.
+ *  The next element becomes the new top.
+ *  
+ */
+void yypop_buffer_state (void)
+{
+    	if (!YY_CURRENT_BUFFER)
+		return;
+
+	yy_delete_buffer(YY_CURRENT_BUFFER );
+	YY_CURRENT_BUFFER_LVALUE = NULL;
+	if ((yy_buffer_stack_top) > 0)
+		--(yy_buffer_stack_top);
+
+	if (YY_CURRENT_BUFFER) {
+		yy_load_buffer_state( );
+		(yy_did_buffer_switch_on_eof) = 1;
+	}
+}
+
+/* Allocates the stack if it does not exist.
+ *  Guarantees space for at least one push.
+ */
+static void yyensure_buffer_stack (void)
+{
+	int num_to_alloc;
+    
+	if (!(yy_buffer_stack)) {
+
+		/* First allocation is just for 2 elements, since we don't know if this
+		 * scanner will even need a stack. We use 2 instead of 1 to avoid an
+		 * immediate realloc on the next call.
+         */
+		num_to_alloc = 1;
+		(yy_buffer_stack) = (struct yy_buffer_state**)yyalloc
+								(num_to_alloc * sizeof(struct yy_buffer_state*)
+								);
+		if ( ! (yy_buffer_stack) )
+			YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" );
+								  
+		memset((yy_buffer_stack), 0, num_to_alloc * sizeof(struct yy_buffer_state*));
+				
+		(yy_buffer_stack_max) = num_to_alloc;
+		(yy_buffer_stack_top) = 0;
+		return;
+	}
+
+	if ((yy_buffer_stack_top) >= ((yy_buffer_stack_max)) - 1){
+
+		/* Increase the buffer to prepare for a possible push. */
+		int grow_size = 8 /* arbitrary grow size */;
+
+		num_to_alloc = (yy_buffer_stack_max) + grow_size;
+		(yy_buffer_stack) = (struct yy_buffer_state**)yyrealloc
+								((yy_buffer_stack),
+								num_to_alloc * sizeof(struct yy_buffer_state*)
+								);
+		if ( ! (yy_buffer_stack) )
+			YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" );
+
+		/* zero only the new slots.*/
+		memset((yy_buffer_stack) + (yy_buffer_stack_max), 0, grow_size * sizeof(struct yy_buffer_state*));
+		(yy_buffer_stack_max) = num_to_alloc;
+	}
+}
+
+/** Setup the input buffer state to scan directly from a user-specified character buffer.
+ * @param base the character buffer
+ * @param size the size in bytes of the character buffer
+ * 
+ * @return the newly allocated buffer state object. 
+ */
+YY_BUFFER_STATE yy_scan_buffer  (char * base, yy_size_t  size )
+{
+	YY_BUFFER_STATE b;
+    
+	if ( size < 2 ||
+	     base[size-2] != YY_END_OF_BUFFER_CHAR ||
+	     base[size-1] != YY_END_OF_BUFFER_CHAR )
+		/* They forgot to leave room for the EOB's. */
+		return 0;
+
+	b = (YY_BUFFER_STATE) yyalloc(sizeof( struct yy_buffer_state )  );
+	if ( ! b )
+		YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" );
+
+	b->yy_buf_size = size - 2;	/* "- 2" to take care of EOB's */
+	b->yy_buf_pos = b->yy_ch_buf = base;
+	b->yy_is_our_buffer = 0;
+	b->yy_input_file = 0;
+	b->yy_n_chars = b->yy_buf_size;
+	b->yy_is_interactive = 0;
+	b->yy_at_bol = 1;
+	b->yy_fill_buffer = 0;
+	b->yy_buffer_status = YY_BUFFER_NEW;
+
+	yy_switch_to_buffer(b  );
+
+	return b;
+}
+
+/** Setup the input buffer state to scan a string. The next call to yylex() will
+ * scan from a @e copy of @a str.
+ * @param yystr a NUL-terminated string to scan
+ * 
+ * @return the newly allocated buffer state object.
+ * @note If you want to scan bytes that may contain NUL values, then use
+ *       yy_scan_bytes() instead.
+ */
+YY_BUFFER_STATE yy_scan_string (yyconst char * yystr )
+{
+    
+	return yy_scan_bytes(yystr,strlen(yystr) );
+}
+
+/** Setup the input buffer state to scan the given bytes. The next call to yylex() will
+ * scan from a @e copy of @a bytes.
+ * @param bytes the byte buffer to scan
+ * @param len the number of bytes in the buffer pointed to by @a bytes.
+ * 
+ * @return the newly allocated buffer state object.
+ */
+YY_BUFFER_STATE yy_scan_bytes  (yyconst char * yybytes, int  _yybytes_len )
+{
+	YY_BUFFER_STATE b;
+	char *buf;
+	yy_size_t n;
+	int i;
+    
+	/* Get memory for full buffer, including space for trailing EOB's. */
+	n = _yybytes_len + 2;
+	buf = (char *) yyalloc(n  );
+	if ( ! buf )
+		YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" );
+
+	for ( i = 0; i < _yybytes_len; ++i )
+		buf[i] = yybytes[i];
+
+	buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR;
+
+	b = yy_scan_buffer(buf,n );
+	if ( ! b )
+		YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" );
+
+	/* It's okay to grow etc. this buffer, and we should throw it
+	 * away when we're done.
+	 */
+	b->yy_is_our_buffer = 1;
+
+	return b;
+}
+
+#ifndef YY_EXIT_FAILURE
+#define YY_EXIT_FAILURE 2
+#endif
+
+static void yy_fatal_error (yyconst char* msg )
+{
+    	(void) fprintf( stderr, "%s\n", msg );
+	exit( YY_EXIT_FAILURE );
+}
+
+/* Redefine yyless() so it works in section 3 code. */
+
+#undef yyless
+#define yyless(n) \
+	do \
+		{ \
+		/* Undo effects of setting up yytext. */ \
+        int yyless_macro_arg = (n); \
+        YY_LESS_LINENO(yyless_macro_arg);\
+		yytext[yyleng] = (yy_hold_char); \
+		(yy_c_buf_p) = yytext + yyless_macro_arg; \
+		(yy_hold_char) = *(yy_c_buf_p); \
+		*(yy_c_buf_p) = '\0'; \
+		yyleng = yyless_macro_arg; \
+		} \
+	while ( 0 )
+
+/* Accessor  methods (get/set functions) to struct members. */
+
+/** Get the current line number.
+ * 
+ */
+int yyget_lineno  (void)
+{
+        
+    return yylineno;
+}
+
+/** Get the input stream.
+ * 
+ */
+FILE *yyget_in  (void)
+{
+        return yyin;
+}
+
+/** Get the output stream.
+ * 
+ */
+FILE *yyget_out  (void)
+{
+        return yyout;
+}
+
+/** Get the length of the current token.
+ * 
+ */
+int yyget_leng  (void)
+{
+        return yyleng;
+}
+
+/** Get the current token.
+ * 
+ */
+
+char *yyget_text  (void)
+{
+        return yytext;
+}
+
+/** Set the current line number.
+ * @param line_number
+ * 
+ */
+void yyset_lineno (int  line_number )
+{
+    
+    yylineno = line_number;
+}
+
+/** Set the input stream. This does not discard the current
+ * input buffer.
+ * @param in_str A readable stream.
+ * 
+ * @see yy_switch_to_buffer
+ */
+void yyset_in (FILE *  in_str )
+{
+        yyin = in_str ;
+}
+
+void yyset_out (FILE *  out_str )
+{
+        yyout = out_str ;
+}
+
+int yyget_debug  (void)
+{
+        return yy_flex_debug;
+}
+
+void yyset_debug (int  bdebug )
+{
+        yy_flex_debug = bdebug ;
+}
+
+static int yy_init_globals (void)
+{
+        /* Initialization is the same as for the non-reentrant scanner.
+     * This function is called from yylex_destroy(), so don't allocate here.
+     */
+
+    (yy_buffer_stack) = 0;
+    (yy_buffer_stack_top) = 0;
+    (yy_buffer_stack_max) = 0;
+    (yy_c_buf_p) = (char *) 0;
+    (yy_init) = 0;
+    (yy_start) = 0;
+
+/* Defined in main.c */
+#ifdef YY_STDINIT
+    yyin = stdin;
+    yyout = stdout;
+#else
+    yyin = (FILE *) 0;
+    yyout = (FILE *) 0;
+#endif
+
+    /* For future reference: Set errno on error, since we are called by
+     * yylex_init()
+     */
+    return 0;
+}
+
+/* yylex_destroy is for both reentrant and non-reentrant scanners. */
+int yylex_destroy  (void)
+{
+    
+    /* Pop the buffer stack, destroying each element. */
+	while(YY_CURRENT_BUFFER){
+		yy_delete_buffer(YY_CURRENT_BUFFER  );
+		YY_CURRENT_BUFFER_LVALUE = NULL;
+		yypop_buffer_state();
+	}
+
+	/* Destroy the stack itself. */
+	yyfree((yy_buffer_stack) );
+	(yy_buffer_stack) = NULL;
+
+    /* Reset the globals. This is important in a non-reentrant scanner so the next time
+     * yylex() is called, initialization will occur. */
+    yy_init_globals( );
+
+    return 0;
+}
+
+/*
+ * Internal utility routines.
+ */
+
+#ifndef yytext_ptr
+static void yy_flex_strncpy (char* s1, yyconst char * s2, int n )
+{
+	register int i;
+	for ( i = 0; i < n; ++i )
+		s1[i] = s2[i];
+}
+#endif
+
+#ifdef YY_NEED_STRLEN
+static int yy_flex_strlen (yyconst char * s )
+{
+	register int n;
+	for ( n = 0; s[n]; ++n )
+		;
+
+	return n;
+}
+#endif
+
+void *yyalloc (yy_size_t  size )
+{
+	return (void *) malloc( size );
+}
+
+void *yyrealloc  (void * ptr, yy_size_t  size )
+{
+	/* The cast to (char *) in the following accommodates both
+	 * implementations that use char* generic pointers, and those
+	 * that use void* generic pointers.  It works with the latter
+	 * because both ANSI C and C++ allow castless assignment from
+	 * any pointer type to void*, and deal with argument conversions
+	 * as though doing an assignment.
+	 */
+	return (void *) realloc( (char *) ptr, size );
+}
+
+void yyfree (void * ptr )
+{
+	free( (char *) ptr );	/* see yyrealloc() for (char *) cast */
+}
+
+#define YYTABLES_NAME "yytables"
+
+#line 663 "cftoken.l"
+
+
+
+void
+yyerror(char *s, ...)
+{
+	char fmt[512];
+
+	va_list ap;
+#ifdef HAVE_STDARG_H
+	va_start(ap, s);
+#else
+	va_start(ap);
+#endif
+	snprintf(fmt, sizeof(fmt), "%s:%d: \"%s\" %s\n",
+		incstack[incstackp].path, incstack[incstackp].lineno,
+		yytext, s);
+	plogv(LLV_ERROR, LOCATION, NULL, fmt, ap);
+	va_end(ap);
+
+	yyerrorcount++;
+}
+
+void
+yywarn(char *s, ...)
+{
+	char fmt[512];
+
+	va_list ap;
+#ifdef HAVE_STDARG_H
+	va_start(ap, s);
+#else
+	va_start(ap);
+#endif
+	snprintf(fmt, sizeof(fmt), "%s:%d: \"%s\" %s\n",
+		incstack[incstackp].path, incstack[incstackp].lineno,
+		yytext, s);
+	plogv(LLV_WARNING, LOCATION, NULL, fmt, ap);
+	va_end(ap);
+}
+
+int
+yycf_switch_buffer(path)
+	char *path;
+{
+	char *filepath = NULL;
+
+	/* got the include file name */
+	if (incstackp >= MAX_INCLUDE_DEPTH) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"Includes nested too deeply");
+		return -1;
+	}
+
+	if (glob(path, GLOB_TILDE, NULL, &incstack[incstackp].matches) != 0 ||
+	    incstack[incstackp].matches.gl_pathc == 0) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"glob found no matches for path \"%s\"\n", path);
+		return -1;
+	}
+	incstack[incstackp].matchon = 0;
+	incstack[incstackp].prevstate = YY_CURRENT_BUFFER;
+
+    nextmatch:
+	if (incstack[incstackp].matchon >= incstack[incstackp].matches.gl_pathc)
+		return -1;
+	filepath =
+	    incstack[incstackp].matches.gl_pathv[incstack[incstackp].matchon];
+	incstack[incstackp].matchon++;
+	incstackp++;
+
+	if (yycf_set_buffer(filepath) != 0) {
+	      incstackp--;
+	      goto nextmatch;
+	}
+
+	yy_switch_to_buffer(yy_create_buffer(yyin,YY_BUF_SIZE));
+
+	BEGIN(S_INI);
+
+	return 0;
+}
+
+int
+yycf_set_buffer(path)
+	char *path;
+{
+	yyin = fopen(path, "r");
+	if (yyin == NULL) {
+		fprintf(stderr, "failed to open file %s (%s)\n",
+			path, strerror(errno));
+		plog(LLV_ERROR, LOCATION, NULL,
+			"failed to open file %s (%s)\n",
+			path, strerror(errno));
+		return -1;
+	}
+
+	/* initialize */
+	incstack[incstackp].fp = yyin;
+	if (incstack[incstackp].path != NULL)
+		racoon_free(incstack[incstackp].path);
+	incstack[incstackp].path = racoon_strdup(path);
+	STRDUP_FATAL(incstack[incstackp].path);
+	incstack[incstackp].lineno = 1;
+	plog(LLV_DEBUG, LOCATION, NULL,
+		"reading config file %s\n", path);
+
+	return 0;
+}
+
+void
+yycf_init_buffer()
+{
+	int i;
+
+	for (i = 0; i < MAX_INCLUDE_DEPTH; i++)
+		memset(&incstack[i], 0, sizeof(incstack[i]));
+	incstackp = 0;
+}
+
+void
+yycf_clean_buffer()
+{
+	int i;
+
+	for (i = 0; i < MAX_INCLUDE_DEPTH; i++) {
+		if (incstack[i].path != NULL) {
+			fclose(incstack[i].fp);
+			racoon_free(incstack[i].path);
+			incstack[i].path = NULL;
+		}
+	}
+}
+
+
diff --git a/src/racoon/cftoken.l b/src/racoon/cftoken.l
new file mode 100644
index 0000000..23282e0
--- /dev/null
+++ b/src/racoon/cftoken.l
@@ -0,0 +1,797 @@
+/*	$NetBSD: cftoken.l,v 1.11.4.2 2007/09/03 18:07:29 mgrooms Exp $	*/
+
+/* Id: cftoken.l,v 1.53 2006/08/22 18:17:17 manubsd Exp */
+
+%{
+/*
+ * Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002 and 2003 WIDE Project.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+
+#include <netinet/in.h>
+#include PATH_IPSEC_H
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <limits.h>
+#include <ctype.h>
+#ifndef ANDROID_CHANGES
+#include <glob.h>
+#endif
+#ifdef HAVE_STDARG_H
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
+
+#include "var.h"
+#include "misc.h"
+#include "vmbuf.h"
+#include "plog.h"
+#include "debug.h"
+
+#include "algorithm.h"
+#include "cfparse_proto.h"
+#include "cftoken_proto.h"
+#include "localconf.h"
+#include "oakley.h"
+#include "isakmp_var.h"
+#include "isakmp.h"
+#include "ipsec_doi.h"
+#include "policy.h"
+#include "proposal.h"
+#include "remoteconf.h"
+#ifdef GC
+#include "gcmalloc.h"
+#endif
+
+#include "cfparse.h"
+
+int yyerrorcount = 0;
+
+#if defined(YIPS_DEBUG)
+#  define YYDB plog(LLV_DEBUG2, LOCATION, NULL,                                \
+		"begin <%d>%s\n", yy_start, yytext);
+#  define YYD {                                                                \
+	plog(LLV_DEBUG2, LOCATION, NULL, "<%d>%s",                             \
+	    yy_start, loglevel >= LLV_DEBUG2 ? "\n" : "");                     \
+}
+#else
+#  define YYDB
+#  define YYD
+#endif /* defined(YIPS_DEBUG) */
+
+#define MAX_INCLUDE_DEPTH 10
+
+static struct include_stack {
+	char *path;
+	FILE *fp;
+	YY_BUFFER_STATE prevstate;
+	int lineno;
+	glob_t matches;
+	int matchon;
+} incstack[MAX_INCLUDE_DEPTH];
+static int incstackp = 0;
+
+static int yy_first_time = 1;
+%}
+
+/* common seciton */
+nl		\n
+ws		[ \t]+
+digit		[0-9]
+letter		[A-Za-z]
+hexdigit	[0-9A-Fa-f]
+/*octet		(([01]?{digit}?{digit})|((2([0-4]{digit}))|(25[0-5]))) */
+special		[()+\|\?\*]
+comma		\,
+dot		\.
+slash		\/
+bcl		\{
+ecl		\}
+blcl		\[
+elcl		\]
+hyphen          \-
+percent		\%
+semi		\;
+comment		\#.*
+ccomment	"/*"
+bracketstring	\<[^>]*\>
+quotedstring	\"[^"]*\"
+addrstring	[a-fA-F0-9:]([a-fA-F0-9:\.]*|[a-fA-F0-9:\.]*%[a-zA-Z0-9]*)
+decstring	{digit}+
+hexstring	0x{hexdigit}+
+
+%s S_INI S_PRIV S_PTH S_INF S_LOG S_PAD S_LST S_RTRY S_CFG S_LDAP
+%s S_ALGST S_ALGCL
+%s S_SAINF S_SAINFS
+%s S_RMT S_RMTS S_RMTP
+%s S_SA
+%s S_GSSENC
+
+%%
+%{
+	if (yy_first_time) {
+		BEGIN S_INI;
+		yy_first_time = 0;
+	}
+%}
+
+	/* privsep */
+<S_INI>privsep		{ BEGIN S_PRIV; YYDB; return(PRIVSEP); }
+<S_PRIV>{bcl}		{ return(BOC); }
+<S_PRIV>user		{ YYD; return(USER); }
+<S_PRIV>group		{ YYD; return(GROUP); }
+<S_PRIV>chroot		{ YYD; return(CHROOT); }
+<S_PRIV>{ecl}		{ BEGIN S_INI; return(EOC); }
+
+	/* path */
+<S_INI>path		{ BEGIN S_PTH; YYDB; return(PATH); }
+<S_PTH>include		{ YYD; yylval.num = LC_PATHTYPE_INCLUDE;
+				return(PATHTYPE); }
+<S_PTH>pre_shared_key	{ YYD; yylval.num = LC_PATHTYPE_PSK;
+				return(PATHTYPE); }
+<S_PTH>certificate	{ YYD; yylval.num = LC_PATHTYPE_CERT;
+				return(PATHTYPE); }
+<S_PTH>script		{ YYD; yylval.num = LC_PATHTYPE_SCRIPT;
+				return(PATHTYPE); }
+<S_PTH>backupsa		{ YYD; yylval.num = LC_PATHTYPE_BACKUPSA;
+				return(PATHTYPE); }
+<S_PTH>pidfile		{ YYD; yylval.num = LC_PATHTYPE_PIDFILE;
+				return(PATHTYPE); }
+<S_PTH>{semi}		{ BEGIN S_INI; YYDB; return(EOS); }
+
+	/* include */
+<S_INI>include		{ YYDB; return(INCLUDE); }
+
+	/* self information */
+<S_INI>identifier	{ BEGIN S_INF; YYDB; yywarn("it is obsoleted.  use \"my_identifier\" in each remote directives."); return(IDENTIFIER); }
+<S_INF>{semi}		{ BEGIN S_INI; return(EOS); }
+
+	/* special */
+<S_INI>complex_bundle	{ YYDB; return(COMPLEX_BUNDLE); }
+
+	/* logging */
+<S_INI>log		{ BEGIN S_LOG; YYDB; return(LOGGING); }
+<S_LOG>error		{ YYD; yylval.num = LLV_ERROR; return(LOGLEV); }
+<S_LOG>warning		{ YYD; yylval.num = LLV_WARNING; return(LOGLEV); }
+<S_LOG>notify		{ YYD; yylval.num = LLV_NOTIFY; return(LOGLEV); }
+<S_LOG>info		{ YYD; yylval.num = LLV_INFO; return(LOGLEV); }
+<S_LOG>debug		{ YYD; yylval.num = LLV_DEBUG; return(LOGLEV); }
+<S_LOG>debug2		{ YYD; yylval.num = LLV_DEBUG2; return(LOGLEV); }
+<S_LOG>debug3		{ YYD; yywarn("it is obsoleted.  use \"debug2\""); yylval.num = LLV_DEBUG2; return(LOGLEV); }
+<S_LOG>debug4		{ YYD; yywarn("it is obsoleted.  use \"debug2\""); yylval.num = LLV_DEBUG2; return(LOGLEV); }
+<S_LOG>{semi}		{ BEGIN S_INI; return(EOS); }
+
+	/* padding */
+<S_INI>padding		{ BEGIN S_PAD; YYDB; return(PADDING); }
+<S_PAD>{bcl}		{ return(BOC); }
+<S_PAD>randomize	{ YYD; return(PAD_RANDOMIZE); }
+<S_PAD>randomize_length	{ YYD; return(PAD_RANDOMIZELEN); }
+<S_PAD>maximum_length	{ YYD; return(PAD_MAXLEN); }
+<S_PAD>strict_check	{ YYD; return(PAD_STRICT); }
+<S_PAD>exclusive_tail	{ YYD; return(PAD_EXCLTAIL); }
+<S_PAD>{ecl}		{ BEGIN S_INI; return(EOC); }
+
+	/* listen */
+<S_INI>listen		{ BEGIN S_LST; YYDB; return(LISTEN); }
+<S_LST>{bcl}		{ return(BOC); }
+<S_LST>isakmp		{ YYD; return(X_ISAKMP); }
+<S_LST>isakmp_natt	{ YYD; return(X_ISAKMP_NATT); }
+<S_LST>admin		{ YYD; return(X_ADMIN); }
+<S_LST>adminsock	{ YYD; return(ADMINSOCK); }
+<S_LST>disabled		{ YYD; return(DISABLED); }
+<S_LST>strict_address	{ YYD; return(STRICT_ADDRESS); }
+<S_LST>{ecl}		{ BEGIN S_INI; return(EOC); }
+
+	/* ldap config */
+<S_INI>ldapcfg		{ BEGIN S_LDAP; YYDB; return(LDAPCFG); }
+<S_LDAP>{bcl}		{ return(BOC); }
+<S_LDAP>version		{ YYD; return(LDAP_PVER); }
+<S_LDAP>host		{ YYD; return(LDAP_HOST); }
+<S_LDAP>port		{ YYD; return(LDAP_PORT); }
+<S_LDAP>base		{ YYD; return(LDAP_BASE); }
+<S_LDAP>subtree		{ YYD; return(LDAP_SUBTREE); }
+<S_LDAP>bind_dn		{ YYD; return(LDAP_BIND_DN); }
+<S_LDAP>bind_pw		{ YYD; return(LDAP_BIND_PW); }
+<S_LDAP>attr_user	{ YYD; return(LDAP_ATTR_USER); }
+<S_LDAP>attr_addr	{ YYD; return(LDAP_ATTR_ADDR); }
+<S_LDAP>attr_mask	{ YYD; return(LDAP_ATTR_MASK); }
+<S_LDAP>attr_group	{ YYD; return(LDAP_ATTR_GROUP); }
+<S_LDAP>attr_member	{ YYD; return(LDAP_ATTR_MEMBER); }
+<S_LDAP>{ecl}		{ BEGIN S_INI; return(EOC); }
+
+	/* mode_cfg */
+<S_INI>mode_cfg		{ BEGIN S_CFG; YYDB; return(MODECFG); }
+<S_CFG>{bcl}		{ return(BOC); }
+<S_CFG>network4		{ YYD; return(CFG_NET4); }
+<S_CFG>netmask4		{ YYD; return(CFG_MASK4); }
+<S_CFG>dns4		{ YYD; return(CFG_DNS4); }
+<S_CFG>nbns4		{ YYD; return(CFG_NBNS4); }
+<S_CFG>wins4		{ YYD; return(CFG_NBNS4); }
+<S_CFG>default_domain	{ YYD; return(CFG_DEFAULT_DOMAIN); }
+<S_CFG>auth_source	{ YYD; return(CFG_AUTH_SOURCE); }
+<S_CFG>auth_groups	{ YYD; return(CFG_AUTH_GROUPS); }
+<S_CFG>group_source	{ YYD; return(CFG_GROUP_SOURCE); }
+<S_CFG>conf_source	{ YYD; return(CFG_CONF_SOURCE); }
+<S_CFG>accounting	{ YYD; return(CFG_ACCOUNTING); }
+<S_CFG>system		{ YYD; return(CFG_SYSTEM); }
+<S_CFG>local		{ YYD; return(CFG_LOCAL); }
+<S_CFG>none		{ YYD; return(CFG_NONE); }
+<S_CFG>radius		{ YYD; return(CFG_RADIUS); }
+<S_CFG>pam		{ YYD; return(CFG_PAM); }
+<S_CFG>ldap		{ YYD; return(CFG_LDAP); }
+<S_CFG>pool_size	{ YYD; return(CFG_POOL_SIZE); }
+<S_CFG>banner		{ YYD; return(CFG_MOTD); }
+<S_CFG>auth_throttle	{ YYD; return(CFG_AUTH_THROTTLE); }
+<S_CFG>split_network	{ YYD; return(CFG_SPLIT_NETWORK); }
+<S_CFG>local_lan	{ YYD; return(CFG_SPLIT_LOCAL); }
+<S_CFG>include		{ YYD; return(CFG_SPLIT_INCLUDE); }
+<S_CFG>split_dns	{ YYD; return(CFG_SPLIT_DNS); }
+<S_CFG>pfs_group	{ YYD; return(CFG_PFS_GROUP); }
+<S_CFG>save_passwd	{ YYD; return(CFG_SAVE_PASSWD); }
+<S_CFG>{comma}		{ YYD; return(COMMA); }
+<S_CFG>{ecl}		{ BEGIN S_INI; return(EOC); }
+
+	/* timer */
+<S_INI>timer		{ BEGIN S_RTRY; YYDB; return(RETRY); }
+<S_RTRY>{bcl}		{ return(BOC); }
+<S_RTRY>counter		{ YYD; return(RETRY_COUNTER); }
+<S_RTRY>interval	{ YYD; return(RETRY_INTERVAL); }
+<S_RTRY>persend		{ YYD; return(RETRY_PERSEND); }
+<S_RTRY>phase1		{ YYD; return(RETRY_PHASE1); }
+<S_RTRY>phase2		{ YYD; return(RETRY_PHASE2); }
+<S_RTRY>natt_keepalive	{ YYD; return(NATT_KA); }
+<S_RTRY>{ecl}		{ BEGIN S_INI; return(EOC); }
+
+	/* sainfo */
+<S_INI>sainfo		{ BEGIN S_SAINF; YYDB; return(SAINFO); }
+<S_SAINF>anonymous	{ YYD; return(ANONYMOUS); }
+<S_SAINF>{blcl}any{elcl}	{ YYD; return(PORTANY); }
+<S_SAINF>any		{ YYD; return(ANY); }
+<S_SAINF>from		{ YYD; return(FROM); }
+<S_SAINF>group		{ YYD; return(GROUP); }
+	/* sainfo spec */
+<S_SAINF>{bcl}		{ BEGIN S_SAINFS; return(BOC); }
+<S_SAINF>{semi}		{ BEGIN S_INI; return(EOS); }
+<S_SAINFS>{ecl}		{ BEGIN S_INI; return(EOC); }
+<S_SAINFS>pfs_group	{ YYD; return(PFS_GROUP); }
+<S_SAINFS>remoteid	{ YYD; return(REMOTEID); }
+<S_SAINFS>identifier	{ YYD; yywarn("it is obsoleted.  use \"my_identifier\"."); return(IDENTIFIER); }
+<S_SAINFS>my_identifier	{ YYD; return(MY_IDENTIFIER); }
+<S_SAINFS>lifetime	{ YYD; return(LIFETIME); }
+<S_SAINFS>time		{ YYD; return(LIFETYPE_TIME); }
+<S_SAINFS>byte		{ YYD; return(LIFETYPE_BYTE); }
+<S_SAINFS>encryption_algorithm { YYD; yylval.num = algclass_ipsec_enc; return(ALGORITHM_CLASS); }
+<S_SAINFS>authentication_algorithm { YYD; yylval.num = algclass_ipsec_auth; return(ALGORITHM_CLASS); }
+<S_SAINFS>compression_algorithm	{ YYD; yylval.num = algclass_ipsec_comp; return(ALGORITHM_CLASS); }
+<S_SAINFS>{comma}	{ YYD; return(COMMA); }
+
+	/* remote */
+<S_INI>remote		{ BEGIN S_RMT; YYDB; return(REMOTE); }
+<S_RMT>anonymous	{ YYD; return(ANONYMOUS); }
+<S_RMT>inherit		{ YYD; return(INHERIT); }
+	/* remote spec */
+<S_RMT>{bcl}		{ BEGIN S_RMTS; return(BOC); }
+<S_RMTS>{ecl}		{ BEGIN S_INI; return(EOC); }
+<S_RMTS>exchange_mode	{ YYD; return(EXCHANGE_MODE); }
+<S_RMTS>{comma}		{ YYD; /* XXX ignored, but to be handled. */ ; }
+<S_RMTS>base		{ YYD; yylval.num = ISAKMP_ETYPE_BASE; return(EXCHANGETYPE); }
+<S_RMTS>main		{ YYD; yylval.num = ISAKMP_ETYPE_IDENT; return(EXCHANGETYPE); }
+<S_RMTS>aggressive	{ YYD; yylval.num = ISAKMP_ETYPE_AGG; return(EXCHANGETYPE); }
+<S_RMTS>doi		{ YYD; return(DOI); }
+<S_RMTS>ipsec_doi	{ YYD; yylval.num = IPSEC_DOI; return(DOITYPE); }
+<S_RMTS>situation	{ YYD; return(SITUATION); }
+<S_RMTS>identity_only	{ YYD; yylval.num = IPSECDOI_SIT_IDENTITY_ONLY; return(SITUATIONTYPE); }
+<S_RMTS>secrecy		{ YYD; yylval.num = IPSECDOI_SIT_SECRECY; return(SITUATIONTYPE); }
+<S_RMTS>integrity	{ YYD; yylval.num = IPSECDOI_SIT_INTEGRITY; return(SITUATIONTYPE); }
+<S_RMTS>identifier	{ YYD; yywarn("it is obsoleted.  use \"my_identifier\"."); return(IDENTIFIER); }
+<S_RMTS>my_identifier	{ YYD; return(MY_IDENTIFIER); }
+<S_RMTS>xauth_login	{ YYD; return(XAUTH_LOGIN); /* formerly identifier type login */ }
+<S_RMTS>peers_identifier	{ YYD; return(PEERS_IDENTIFIER); }
+<S_RMTS>verify_identifier	{ YYD; return(VERIFY_IDENTIFIER); }
+<S_RMTS>certificate_type	{ YYD; return(CERTIFICATE_TYPE); }
+<S_RMTS>ca_type		{ YYD; return(CA_TYPE); }
+<S_RMTS>x509		{ YYD; yylval.num = ISAKMP_CERT_X509SIGN; return(CERT_X509); }
+<S_RMTS>plain_rsa	{ YYD; yylval.num = ISAKMP_CERT_PLAINRSA; return(CERT_PLAINRSA); }
+<S_RMTS>peers_certfile	{ YYD; return(PEERS_CERTFILE); }
+<S_RMTS>dnssec		{ YYD; return(DNSSEC); }
+<S_RMTS>verify_cert	{ YYD; return(VERIFY_CERT); }
+<S_RMTS>send_cert	{ YYD; return(SEND_CERT); }
+<S_RMTS>send_cr		{ YYD; return(SEND_CR); }
+<S_RMTS>dh_group	{ YYD; return(DH_GROUP); }
+<S_RMTS>nonce_size	{ YYD; return(NONCE_SIZE); }
+<S_RMTS>generate_policy	{ YYD; return(GENERATE_POLICY); }
+<S_RMTS>unique		{ YYD; yylval.num = GENERATE_POLICY_UNIQUE; return(GENERATE_LEVEL); }
+<S_RMTS>require		{ YYD; yylval.num = GENERATE_POLICY_REQUIRE; return(GENERATE_LEVEL); }
+<S_RMTS>support_mip6	{ YYD; yywarn("it is obsoleted.  use \"support_proxy\"."); return(SUPPORT_PROXY); }
+<S_RMTS>support_proxy	{ YYD; return(SUPPORT_PROXY); }
+<S_RMTS>initial_contact	{ YYD; return(INITIAL_CONTACT); }
+<S_RMTS>nat_traversal	{ YYD; return(NAT_TRAVERSAL); }
+<S_RMTS>force		{ YYD; return(REMOTE_FORCE_LEVEL); }
+<S_RMTS>proposal_check	{ YYD; return(PROPOSAL_CHECK); }
+<S_RMTS>obey		{ YYD; yylval.num = PROP_CHECK_OBEY; return(PROPOSAL_CHECK_LEVEL); }
+<S_RMTS>strict		{ YYD; yylval.num = PROP_CHECK_STRICT; return(PROPOSAL_CHECK_LEVEL); }
+<S_RMTS>exact		{ YYD; yylval.num = PROP_CHECK_EXACT; return(PROPOSAL_CHECK_LEVEL); }
+<S_RMTS>claim		{ YYD; yylval.num = PROP_CHECK_CLAIM; return(PROPOSAL_CHECK_LEVEL); }
+<S_RMTS>keepalive	{ YYD; return(KEEPALIVE); }
+<S_RMTS>passive		{ YYD; return(PASSIVE); }
+<S_RMTS>lifetime	{ YYD; return(LIFETIME); }
+<S_RMTS>time		{ YYD; return(LIFETYPE_TIME); }
+<S_RMTS>byte		{ YYD; return(LIFETYPE_BYTE); }
+<S_RMTS>dpd			{ YYD; return(DPD); }
+<S_RMTS>dpd_delay	{ YYD; return(DPD_DELAY); }
+<S_RMTS>dpd_retry	{ YYD; return(DPD_RETRY); }
+<S_RMTS>dpd_maxfail	{ YYD; return(DPD_MAXFAIL); }
+<S_RMTS>ph1id		{ YYD; return(PH1ID); }
+<S_RMTS>ike_frag	{ YYD; return(IKE_FRAG); }
+<S_RMTS>esp_frag	{ YYD; return(ESP_FRAG); }
+<S_RMTS>script		{ YYD; return(SCRIPT); }
+<S_RMTS>phase1_up	{ YYD; return(PHASE1_UP); }
+<S_RMTS>phase1_down	{ YYD; return(PHASE1_DOWN); }
+<S_RMTS>mode_cfg	{ YYD; return(MODE_CFG); }
+<S_RMTS>weak_phase1_check { YYD; return(WEAK_PHASE1_CHECK); }
+	/* remote proposal */
+<S_RMTS>proposal	{ BEGIN S_RMTP; YYDB; return(PROPOSAL); }
+<S_RMTP>{bcl}		{ return(BOC); }
+<S_RMTP>{ecl}		{ BEGIN S_RMTS; return(EOC); }
+<S_RMTP>lifetime	{ YYD; return(LIFETIME); }
+<S_RMTP>time		{ YYD; return(LIFETYPE_TIME); }
+<S_RMTP>byte		{ YYD; return(LIFETYPE_BYTE); }
+<S_RMTP>encryption_algorithm { YYD; yylval.num = algclass_isakmp_enc; return(ALGORITHM_CLASS); }
+<S_RMTP>authentication_method { YYD; yylval.num = algclass_isakmp_ameth; return(ALGORITHM_CLASS); }
+<S_RMTP>hash_algorithm	{ YYD; yylval.num = algclass_isakmp_hash; return(ALGORITHM_CLASS); }
+<S_RMTP>dh_group	{ YYD; return(DH_GROUP); }
+<S_RMTP>gss_id		{ YYD; return(GSS_ID); }
+<S_RMTP>gssapi_id	{ YYD; return(GSS_ID); } /* for back compatibility */
+
+	/* GSS ID encoding type (global) */
+<S_INI>gss_id_enc	{ BEGIN S_GSSENC; YYDB; return(GSS_ID_ENC); }
+<S_GSSENC>latin1	{ YYD; yylval.num = LC_GSSENC_LATIN1;
+				return(GSS_ID_ENCTYPE); }
+<S_GSSENC>utf-16le	{ YYD; yylval.num = LC_GSSENC_UTF16LE;
+				return(GSS_ID_ENCTYPE); }
+<S_GSSENC>{semi}	{ BEGIN S_INI; YYDB; return(EOS); }
+
+	/* parameter */
+on		{ YYD; yylval.num = TRUE; return(SWITCH); }
+off		{ YYD; yylval.num = FALSE; return(SWITCH); }
+
+	/* prefix */
+{slash}{digit}{1,3} {
+			YYD;
+			yytext++;
+			yylval.num = atoi(yytext);
+			return(PREFIX);
+		}
+
+	/* port number */
+{blcl}{decstring}{elcl}	{
+			char *p = yytext;
+			YYD;
+			while (*++p != ']') ;
+			*p = 0;
+			yytext++;
+			yylval.num = atoi(yytext);
+			return(PORT);
+		}
+
+	/* address range */
+{hyphen}{addrstring} {
+                        YYD;
+                        yytext++;
+			yylval.val = vmalloc(yyleng + 1);
+			if (yylval.val == NULL) {
+				yyerror("vmalloc failed");
+				return -1;
+			}
+			memcpy(yylval.val->v, yytext, yylval.val->l);
+                        return(ADDRRANGE);
+                } 
+
+	/* upper protocol */
+esp		{ YYD; yylval.num = IPPROTO_ESP; return(UL_PROTO); }
+ah		{ YYD; yylval.num = IPPROTO_AH; return(UL_PROTO); }
+ipcomp		{ YYD; yylval.num = IPPROTO_IPCOMP; return(UL_PROTO); }
+icmp		{ YYD; yylval.num = IPPROTO_ICMP; return(UL_PROTO); }
+icmp6		{ YYD; yylval.num = IPPROTO_ICMPV6; return(UL_PROTO); }
+tcp		{ YYD; yylval.num = IPPROTO_TCP; return(UL_PROTO); }
+udp		{ YYD; yylval.num = IPPROTO_UDP; return(UL_PROTO); }
+
+	/* algorithm type */
+des_iv64	{ YYD; yylval.num = algtype_des_iv64;	return(ALGORITHMTYPE); }
+des		{ YYD; yylval.num = algtype_des;	return(ALGORITHMTYPE); }
+3des		{ YYD; yylval.num = algtype_3des;	return(ALGORITHMTYPE); }
+rc5		{ YYD; yylval.num = algtype_rc5;	return(ALGORITHMTYPE); }
+idea 		{ YYD; yylval.num = algtype_idea;	return(ALGORITHMTYPE); }
+cast128		{ YYD; yylval.num = algtype_cast128;	return(ALGORITHMTYPE); }
+blowfish	{ YYD; yylval.num = algtype_blowfish;	return(ALGORITHMTYPE); }
+3idea		{ YYD; yylval.num = algtype_3idea;	return(ALGORITHMTYPE); }
+des_iv32	{ YYD; yylval.num = algtype_des_iv32;	return(ALGORITHMTYPE); }
+rc4 		{ YYD; yylval.num = algtype_rc4;	return(ALGORITHMTYPE); }
+null_enc	{ YYD; yylval.num = algtype_null_enc;	return(ALGORITHMTYPE); }
+null		{ YYD; yylval.num = algtype_null_enc;	return(ALGORITHMTYPE); }
+aes		{ YYD; yylval.num = algtype_aes;	return(ALGORITHMTYPE); }
+rijndael	{ YYD; yylval.num = algtype_aes;	return(ALGORITHMTYPE); }
+twofish		{ YYD; yylval.num = algtype_twofish;	return(ALGORITHMTYPE); }
+camellia	{ YYD; yylval.num = algtype_camellia;	return(ALGORITHMTYPE); }
+non_auth	{ YYD; yylval.num = algtype_non_auth;	return(ALGORITHMTYPE); }
+hmac_md5	{ YYD; yylval.num = algtype_hmac_md5;	return(ALGORITHMTYPE); }
+hmac_sha1	{ YYD; yylval.num = algtype_hmac_sha1;	return(ALGORITHMTYPE); }
+hmac_sha2_256	{ YYD; yylval.num = algtype_hmac_sha2_256;	return(ALGORITHMTYPE); }
+hmac_sha256	{ YYD; yylval.num = algtype_hmac_sha2_256;	return(ALGORITHMTYPE); }
+hmac_sha2_384	{ YYD; yylval.num = algtype_hmac_sha2_384;	return(ALGORITHMTYPE); }
+hmac_sha384	{ YYD; yylval.num = algtype_hmac_sha2_384;	return(ALGORITHMTYPE); }
+hmac_sha2_512	{ YYD; yylval.num = algtype_hmac_sha2_512;	return(ALGORITHMTYPE); }
+hmac_sha512	{ YYD; yylval.num = algtype_hmac_sha2_512;	return(ALGORITHMTYPE); }
+des_mac		{ YYD; yylval.num = algtype_des_mac;	return(ALGORITHMTYPE); }
+kpdk		{ YYD; yylval.num = algtype_kpdk;	return(ALGORITHMTYPE); }
+md5		{ YYD; yylval.num = algtype_md5;	return(ALGORITHMTYPE); }
+sha1		{ YYD; yylval.num = algtype_sha1;	return(ALGORITHMTYPE); }
+tiger		{ YYD; yylval.num = algtype_tiger;	return(ALGORITHMTYPE); }
+sha2_256	{ YYD; yylval.num = algtype_sha2_256;	return(ALGORITHMTYPE); }
+sha256		{ YYD; yylval.num = algtype_sha2_256;	return(ALGORITHMTYPE); }
+sha2_384	{ YYD; yylval.num = algtype_sha2_384;	return(ALGORITHMTYPE); }
+sha384		{ YYD; yylval.num = algtype_sha2_384;	return(ALGORITHMTYPE); }
+sha2_512	{ YYD; yylval.num = algtype_sha2_512;	return(ALGORITHMTYPE); }
+sha512		{ YYD; yylval.num = algtype_sha2_512;	return(ALGORITHMTYPE); }
+oui		{ YYD; yylval.num = algtype_oui;	return(ALGORITHMTYPE); }
+deflate		{ YYD; yylval.num = algtype_deflate;	return(ALGORITHMTYPE); }
+lzs		{ YYD; yylval.num = algtype_lzs;	return(ALGORITHMTYPE); }
+modp768		{ YYD; yylval.num = algtype_modp768;	return(ALGORITHMTYPE); }
+modp1024	{ YYD; yylval.num = algtype_modp1024;	return(ALGORITHMTYPE); }
+modp1536	{ YYD; yylval.num = algtype_modp1536;	return(ALGORITHMTYPE); }
+ec2n155		{ YYD; yylval.num = algtype_ec2n155;	return(ALGORITHMTYPE); }
+ec2n185		{ YYD; yylval.num = algtype_ec2n185;	return(ALGORITHMTYPE); }
+modp2048	{ YYD; yylval.num = algtype_modp2048;	return(ALGORITHMTYPE); }
+modp3072	{ YYD; yylval.num = algtype_modp3072;	return(ALGORITHMTYPE); }
+modp4096	{ YYD; yylval.num = algtype_modp4096;	return(ALGORITHMTYPE); }
+modp6144	{ YYD; yylval.num = algtype_modp6144;	return(ALGORITHMTYPE); }
+modp8192	{ YYD; yylval.num = algtype_modp8192;	return(ALGORITHMTYPE); }
+pre_shared_key	{ YYD; yylval.num = algtype_psk;	return(ALGORITHMTYPE); }
+rsasig		{ YYD; yylval.num = algtype_rsasig;	return(ALGORITHMTYPE); }
+dsssig		{ YYD; yylval.num = algtype_dsssig;	return(ALGORITHMTYPE); }
+rsaenc		{ YYD; yylval.num = algtype_rsaenc;	return(ALGORITHMTYPE); }
+rsarev		{ YYD; yylval.num = algtype_rsarev;	return(ALGORITHMTYPE); }
+gssapi_krb	{ YYD; yylval.num = algtype_gssapikrb;	return(ALGORITHMTYPE); }
+hybrid_rsa_server {
+#ifdef ENABLE_HYBRID
+	YYD; yylval.num = algtype_hybrid_rsa_s; return(ALGORITHMTYPE);
+#else
+	yyerror("racoon not configured with --enable-hybrid");
+#endif
+}
+hybrid_dss_server {
+#ifdef ENABLE_HYBRID
+	YYD; yylval.num = algtype_hybrid_dss_s; return(ALGORITHMTYPE);
+#else
+	yyerror("racoon not configured with --enable-hybrid");
+#endif
+}
+hybrid_rsa_client {
+#ifdef ENABLE_HYBRID
+	YYD; yylval.num = algtype_hybrid_rsa_c; return(ALGORITHMTYPE);
+#else
+	yyerror("racoon not configured with --enable-hybrid");
+#endif
+}
+hybrid_dss_client {
+#ifdef ENABLE_HYBRID
+	YYD; yylval.num = algtype_hybrid_dss_c; return(ALGORITHMTYPE);
+#else
+	yyerror("racoon not configured with --enable-hybrid");
+#endif
+}
+xauth_psk_server {
+#ifdef ENABLE_HYBRID
+	YYD; yylval.num = algtype_xauth_psk_s; return(ALGORITHMTYPE);
+#else
+	yyerror("racoon not configured with --enable-hybrid");
+#endif
+}
+xauth_psk_client {
+#ifdef ENABLE_HYBRID
+	YYD; yylval.num = algtype_xauth_psk_c; return(ALGORITHMTYPE);
+#else
+	yyerror("racoon not configured with --enable-hybrid");
+#endif
+}
+xauth_rsa_server {
+#ifdef ENABLE_HYBRID
+	YYD; yylval.num = algtype_xauth_rsa_s; return(ALGORITHMTYPE);
+#else
+	yyerror("racoon not configured with --enable-hybrid");
+#endif
+}
+xauth_rsa_client {
+#ifdef ENABLE_HYBRID
+	YYD; yylval.num = algtype_xauth_rsa_c; return(ALGORITHMTYPE);
+#else
+	yyerror("racoon not configured with --enable-hybrid");
+#endif
+}
+
+
+	/* identifier type */
+vendor_id	{ YYD; yywarn("it is obsoleted."); return(VENDORID); }
+user_fqdn	{ YYD; yylval.num = IDTYPE_USERFQDN; return(IDENTIFIERTYPE); }
+fqdn		{ YYD; yylval.num = IDTYPE_FQDN; return(IDENTIFIERTYPE); }
+keyid		{ YYD; yylval.num = IDTYPE_KEYID; return(IDENTIFIERTYPE); }
+address		{ YYD; yylval.num = IDTYPE_ADDRESS; return(IDENTIFIERTYPE); }
+subnet		{ YYD; yylval.num = IDTYPE_SUBNET; return(IDENTIFIERTYPE); }
+asn1dn		{ YYD; yylval.num = IDTYPE_ASN1DN; return(IDENTIFIERTYPE); }
+certname	{ YYD; yywarn("certname will be obsoleted in near future."); yylval.num = IDTYPE_ASN1DN; return(IDENTIFIERTYPE); }
+
+	/* identifier qualifier */
+tag		{ YYD; yylval.num = IDQUAL_TAG;  return(IDENTIFIERQUAL); }
+file		{ YYD; yylval.num = IDQUAL_FILE; return(IDENTIFIERQUAL); }
+
+	/* units */
+B|byte|bytes		{ YYD; return(UNITTYPE_BYTE); }
+KB			{ YYD; return(UNITTYPE_KBYTES); }
+MB			{ YYD; return(UNITTYPE_MBYTES); }
+TB			{ YYD; return(UNITTYPE_TBYTES); }
+sec|secs|second|seconds	{ YYD; return(UNITTYPE_SEC); }
+min|mins|minute|minutes	{ YYD; return(UNITTYPE_MIN); }
+hour|hours		{ YYD; return(UNITTYPE_HOUR); }
+
+	/* boolean */
+yes		{ YYD; yylval.num = TRUE; return(BOOLEAN); }
+no		{ YYD; yylval.num = FALSE; return(BOOLEAN); }
+
+{decstring}	{
+			char *bp;
+
+			YYD;
+			yylval.num = strtol(yytext, &bp, 10);
+			return(NUMBER);
+		}
+
+{hexstring}	{
+			char *p;
+
+			YYD; 
+			yylval.val = vmalloc(yyleng + (yyleng & 1) + 1);
+			if (yylval.val == NULL) {
+				yyerror("vmalloc failed");
+				return -1;
+			}
+
+			p = yylval.val->v;
+			*p++ = '0';
+			*p++ = 'x';
+
+			/* fixed string if length is odd. */
+			if (yyleng & 1)
+				*p++ = '0';
+			memcpy(p, &yytext[2], yyleng - 1);
+
+			return(HEXSTRING);
+		}
+
+{quotedstring}	{
+			char *p = yytext;
+
+			YYD;
+			while (*++p != '"') ;
+			*p = '\0';
+
+			yylval.val = vmalloc(yyleng - 1);
+			if (yylval.val == NULL) {
+				yyerror("vmalloc failed");
+				return -1;
+			}
+			memcpy(yylval.val->v, &yytext[1], yylval.val->l);
+
+			return(QUOTEDSTRING);
+		}
+
+{addrstring}	{
+			YYD;
+
+			yylval.val = vmalloc(yyleng + 1);
+			if (yylval.val == NULL) {
+				yyerror("vmalloc failed");
+				return -1;
+			}
+			memcpy(yylval.val->v, yytext, yylval.val->l);
+
+			return(ADDRSTRING);
+		}
+
+<<EOF>>		{
+			yy_delete_buffer(YY_CURRENT_BUFFER);
+			incstackp--;
+    nextfile:
+			if (incstack[incstackp].matchon <
+			    incstack[incstackp].matches.gl_pathc) {
+				char* filepath = incstack[incstackp].matches.gl_pathv[incstack[incstackp].matchon];
+				incstack[incstackp].matchon++;
+				incstackp++;
+				if (yycf_set_buffer(filepath) != 0) {
+					incstackp--;
+					goto nextfile;
+				}
+				yy_switch_to_buffer(yy_create_buffer(yyin, YY_BUF_SIZE));
+				BEGIN(S_INI);
+			} else {
+				globfree(&incstack[incstackp].matches);
+				if (incstackp == 0)
+					yyterminate();
+				else
+					yy_switch_to_buffer(incstack[incstackp].prevstate);
+			}
+		}
+
+	/* ... */
+{ws}		{ ; }
+{nl}		{ incstack[incstackp].lineno++; }
+{comment}	{ YYD; }
+{semi}		{ return(EOS); }
+.		{ yymore(); }
+
+%%
+
+void
+yyerror(char *s, ...)
+{
+	char fmt[512];
+
+	va_list ap;
+#ifdef HAVE_STDARG_H
+	va_start(ap, s);
+#else
+	va_start(ap);
+#endif
+	snprintf(fmt, sizeof(fmt), "%s:%d: \"%s\" %s\n",
+		incstack[incstackp].path, incstack[incstackp].lineno,
+		yytext, s);
+	plogv(LLV_ERROR, LOCATION, NULL, fmt, ap);
+	va_end(ap);
+
+	yyerrorcount++;
+}
+
+void
+yywarn(char *s, ...)
+{
+	char fmt[512];
+
+	va_list ap;
+#ifdef HAVE_STDARG_H
+	va_start(ap, s);
+#else
+	va_start(ap);
+#endif
+	snprintf(fmt, sizeof(fmt), "%s:%d: \"%s\" %s\n",
+		incstack[incstackp].path, incstack[incstackp].lineno,
+		yytext, s);
+	plogv(LLV_WARNING, LOCATION, NULL, fmt, ap);
+	va_end(ap);
+}
+
+int
+yycf_switch_buffer(path)
+	char *path;
+{
+	char *filepath = NULL;
+
+	/* got the include file name */
+	if (incstackp >= MAX_INCLUDE_DEPTH) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"Includes nested too deeply");
+		return -1;
+	}
+
+	if (glob(path, GLOB_TILDE, NULL, &incstack[incstackp].matches) != 0 ||
+	    incstack[incstackp].matches.gl_pathc == 0) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"glob found no matches for path \"%s\"\n", path);
+		return -1;
+	}
+	incstack[incstackp].matchon = 0;
+	incstack[incstackp].prevstate = YY_CURRENT_BUFFER;
+
+    nextmatch:
+	if (incstack[incstackp].matchon >= incstack[incstackp].matches.gl_pathc)
+		return -1;
+	filepath =
+	    incstack[incstackp].matches.gl_pathv[incstack[incstackp].matchon];
+	incstack[incstackp].matchon++;
+	incstackp++;
+
+	if (yycf_set_buffer(filepath) != 0) {
+	      incstackp--;
+	      goto nextmatch;
+	}
+
+	yy_switch_to_buffer(yy_create_buffer(yyin, YY_BUF_SIZE));
+
+	BEGIN(S_INI);
+
+	return 0;
+}
+
+int
+yycf_set_buffer(path)
+	char *path;
+{
+	yyin = fopen(path, "r");
+	if (yyin == NULL) {
+		fprintf(stderr, "failed to open file %s (%s)\n",
+			path, strerror(errno));
+		plog(LLV_ERROR, LOCATION, NULL,
+			"failed to open file %s (%s)\n",
+			path, strerror(errno));
+		return -1;
+	}
+
+	/* initialize */
+	incstack[incstackp].fp = yyin;
+	if (incstack[incstackp].path != NULL)
+		racoon_free(incstack[incstackp].path);
+	incstack[incstackp].path = racoon_strdup(path);
+	STRDUP_FATAL(incstack[incstackp].path);
+	incstack[incstackp].lineno = 1;
+	plog(LLV_DEBUG, LOCATION, NULL,
+		"reading config file %s\n", path);
+
+	return 0;
+}
+
+void
+yycf_init_buffer()
+{
+	int i;
+
+	for (i = 0; i < MAX_INCLUDE_DEPTH; i++)
+		memset(&incstack[i], 0, sizeof(incstack[i]));
+	incstackp = 0;
+}
+
+void
+yycf_clean_buffer()
+{
+	int i;
+
+	for (i = 0; i < MAX_INCLUDE_DEPTH; i++) {
+		if (incstack[i].path != NULL) {
+			fclose(incstack[i].fp);
+			racoon_free(incstack[i].path);
+			incstack[i].path = NULL;
+		}
+	}
+}
+
diff --git a/src/racoon/cftoken_proto.h b/src/racoon/cftoken_proto.h
new file mode 100644
index 0000000..41cb939
--- /dev/null
+++ b/src/racoon/cftoken_proto.h
@@ -0,0 +1,48 @@
+/*	$NetBSD: cftoken_proto.h,v 1.4 2006/09/09 16:22:09 manu Exp $	*/
+
+/* Id: cftoken_proto.h,v 1.3 2004/06/11 16:00:15 ludvigm Exp */
+
+/*
+ * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _CFTOKEN_PROTO_H
+#define _CFTOKEN_PROTO_H
+
+extern int yyerrorcount;
+
+extern int yylex __P((void));
+extern void yyerror __P((char *, ...));
+extern void yywarn __P((char *, ...));
+
+extern int yycf_switch_buffer __P((char *));
+extern int yycf_set_buffer __P((char *));
+extern void yycf_init_buffer __P((void));
+extern void yycf_clean_buffer __P((void));
+
+#endif /* _CFTOKEN_PROTO_H */
diff --git a/src/racoon/contrib/sp.pl b/src/racoon/contrib/sp.pl
new file mode 100644
index 0000000..d1f9caf
--- /dev/null
+++ b/src/racoon/contrib/sp.pl
@@ -0,0 +1,21 @@
+#! /usr/pkg/bin/perl
+
+die "insufficient arguments" if (scalar(@ARGV) < 2);
+$src = $ARGV[0];
+$dst = $ARGV[1];
+$mode = 'transport';
+if (scalar(@ARGV) > 2) {
+	$mode = $ARGV[2];
+}
+
+open(OUT, "|setkey -c");
+if ($mode eq 'transport') {
+	print STDERR "install esp transport mode: $src -> $dst\n";
+	print OUT "spdadd $src $dst any -P out ipsec esp/transport//require;\n";
+	print OUT "spdadd $dst $src any -P in ipsec esp/transport//require;\n";
+} elsif ($mode eq 'delete') {
+	print STDERR "delete policy: $src -> $dst\n";
+	print OUT "spddelete $src $dst any -P out;\n";
+	print OUT "spddelete $dst $src any -P in;\n";
+}
+close(OUT);
diff --git a/src/racoon/crypto_openssl.c b/src/racoon/crypto_openssl.c
new file mode 100644
index 0000000..5b4de1a
--- /dev/null
+++ b/src/racoon/crypto_openssl.c
@@ -0,0 +1,2687 @@
+/*	$NetBSD: crypto_openssl.c,v 1.11.6.4 2008/07/15 00:55:48 mgrooms Exp $	*/
+
+/* Id: crypto_openssl.c,v 1.47 2006/05/06 20:42:09 manubsd Exp */
+
+/*
+ * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include <sys/types.h>
+#include <sys/param.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <limits.h>
+#include <string.h>
+
+/* get openssl/ssleay version number */
+#include <openssl/opensslv.h>
+
+#if !defined(OPENSSL_VERSION_NUMBER) || (OPENSSL_VERSION_NUMBER < 0x0090602fL)
+#error OpenSSL version 0.9.6 or later required.
+#endif
+
+#include <openssl/pem.h>
+#include <openssl/evp.h>
+#include <openssl/x509.h>
+#include <openssl/x509v3.h>
+#include <openssl/x509_vfy.h>
+#include <openssl/bn.h>
+#include <openssl/dh.h>
+#include <openssl/md5.h>
+#include <openssl/sha.h>
+#include <openssl/hmac.h>
+#include <openssl/des.h>
+#include <openssl/crypto.h>
+#ifdef HAVE_OPENSSL_ENGINE_H
+#include <openssl/engine.h>
+#endif
+#ifndef ANDROID_CHANGES	// Not support blowfish and cast.
+#include <openssl/blowfish.h>
+#include <openssl/cast.h>
+#endif
+#include <openssl/err.h>
+#ifdef HAVE_OPENSSL_RC5_H
+#include <openssl/rc5.h>
+#endif
+#ifdef HAVE_OPENSSL_IDEA_H
+#include <openssl/idea.h>
+#endif
+#if defined(HAVE_OPENSSL_AES_H)
+#include <openssl/aes.h>
+#elif defined(HAVE_OPENSSL_RIJNDAEL_H)
+#include <openssl/rijndael.h>
+#else
+#include "crypto/rijndael/rijndael-api-fst.h"
+#endif
+#if defined(HAVE_OPENSSL_CAMELLIA_H)
+#include <openssl/camellia.h>
+#endif
+#ifdef WITH_SHA2
+#ifdef HAVE_OPENSSL_SHA2_H
+#include <openssl/sha2.h>
+#else
+#include "crypto/sha2/sha2.h"
+#endif
+#endif
+#include "plog.h"
+
+/* 0.9.7 stuff? */
+#if OPENSSL_VERSION_NUMBER < 0x0090700fL
+typedef STACK_OF(GENERAL_NAME) GENERAL_NAMES;
+#else
+#define USE_NEW_DES_API
+#endif
+
+#define OpenSSL_BUG()	do { plog(LLV_ERROR, LOCATION, NULL, "OpenSSL function failed\n"); } while(0)
+
+#include "var.h"
+#include "misc.h"
+#include "vmbuf.h"
+#include "plog.h"
+#include "crypto_openssl.h"
+#include "debug.h"
+#include "gcmalloc.h"
+
+/*
+ * I hate to cast every parameter to des_xx into void *, but it is
+ * necessary for SSLeay/OpenSSL portability.  It sucks.
+ */
+
+static int cb_check_cert_local __P((int, X509_STORE_CTX *));
+static int cb_check_cert_remote __P((int, X509_STORE_CTX *));
+static X509 *mem2x509 __P((vchar_t *));
+
+static caddr_t eay_hmac_init __P((vchar_t *, const EVP_MD *));
+
+#ifdef ANDROID_CHANGES
+const EVP_CIPHER *EVP_cast5_cbc() {
+	fprintf(stderr, "FIX ME ! function %s() is not implemented in %s:%d\n", __FUNCTION__, __FILE__, __LINE__);
+	return NULL;
+}
+
+const EVP_CIPHER *EVP_bf_cbc() {
+	fprintf(stderr, "FIX ME ! function %s() is not implemented in %s:%d\n", __FUNCTION__, __FILE__, __LINE__);
+	return NULL;
+}
+#endif
+
+/* X509 Certificate */
+/*
+ * convert the string of the subject name into DER
+ * e.g. str = "C=JP, ST=Kanagawa";
+ */
+vchar_t *
+eay_str2asn1dn(str, len)
+	const char *str;
+	int len;
+{
+	X509_NAME *name;
+	char *buf;
+	char *field, *value;
+	int i, j;
+	vchar_t *ret = NULL;
+	caddr_t p;
+
+	if (len == -1)
+		len = strlen(str);
+
+	buf = racoon_malloc(len + 1);
+	if (!buf) {
+		plog(LLV_WARNING, LOCATION, NULL,"failed to allocate buffer\n");
+		return NULL;
+	}
+	memcpy(buf, str, len);
+
+	name = X509_NAME_new();
+
+	field = &buf[0];
+	value = NULL;
+	for (i = 0; i < len; i++) {
+		if (!value && buf[i] == '=') {
+			buf[i] = '\0';
+			value = &buf[i + 1];
+			continue;
+		} else if (buf[i] == ',' || buf[i] == '/') {
+			buf[i] = '\0';
+
+			plog(LLV_DEBUG, LOCATION, NULL, "DN: %s=%s\n",
+			     field, value);
+
+			if (!value) goto err;
+			if (!X509_NAME_add_entry_by_txt(name, field,
+					(value[0] == '*' && value[1] == 0) ? 
+						V_ASN1_PRINTABLESTRING : MBSTRING_ASC,
+					(unsigned char *) value, -1, -1, 0)) {
+				plog(LLV_ERROR, LOCATION, NULL, 
+				     "Invalid DN field: %s=%s\n",
+				     field, value);
+				plog(LLV_ERROR, LOCATION, NULL, 
+				     "%s\n", eay_strerror());
+				goto err;
+			}
+			for (j = i + 1; j < len; j++) {
+				if (buf[j] != ' ')
+					break;
+			}
+			field = &buf[j];
+			value = NULL;
+			continue;
+		}
+	}
+	buf[len] = '\0';
+
+	plog(LLV_DEBUG, LOCATION, NULL, "DN: %s=%s\n",
+	     field, value);
+
+	if (!value) goto err;
+	if (!X509_NAME_add_entry_by_txt(name, field,
+			(value[0] == '*' && value[1] == 0) ? 
+				V_ASN1_PRINTABLESTRING : MBSTRING_ASC,
+			(unsigned char *) value, -1, -1, 0)) {
+		plog(LLV_ERROR, LOCATION, NULL, 
+		     "Invalid DN field: %s=%s\n",
+		     field, value);
+		plog(LLV_ERROR, LOCATION, NULL, 
+		     "%s\n", eay_strerror());
+		goto err;
+	}
+
+	i = i2d_X509_NAME(name, NULL);
+	if (!i)
+		goto err;
+	ret = vmalloc(i);
+	if (!ret)
+		goto err;
+	p = ret->v;
+	i = i2d_X509_NAME(name, (void *)&p);
+	if (!i)
+		goto err;
+
+	return ret;
+
+    err:
+	if (buf)
+		racoon_free(buf);
+	if (name)
+		X509_NAME_free(name);
+	if (ret)
+		vfree(ret);
+	return NULL;
+}
+
+/*
+ * convert the hex string of the subject name into DER
+ */
+vchar_t *
+eay_hex2asn1dn(const char *hex, int len)
+{
+	BIGNUM *bn = BN_new();
+	char *binbuf;
+	size_t binlen;
+	vchar_t *ret = NULL;
+	
+	if (len == -1)
+		len = strlen(hex);
+
+	if (BN_hex2bn(&bn, hex) != len) {
+		plog(LLV_ERROR, LOCATION, NULL, 
+		     "conversion of Hex-encoded ASN1 string to binary failed: %s\n",
+		     eay_strerror());
+		goto out;
+	}
+	
+	binlen = BN_num_bytes(bn);
+	ret = vmalloc(binlen);
+	if (!ret) {
+		plog(LLV_WARNING, LOCATION, NULL,"failed to allocate buffer\n");
+		return NULL;
+	}
+	binbuf = ret->v;
+
+	BN_bn2bin(bn, (unsigned char *) binbuf);
+
+out:
+	BN_free(bn);
+
+	return ret;
+}
+
+/*
+ * The following are derived from code in crypto/x509/x509_cmp.c
+ * in OpenSSL0.9.7c:
+ * X509_NAME_wildcmp() adds wildcard matching to the original
+ * X509_NAME_cmp(), nocase_cmp() and nocase_spacenorm_cmp() are as is.
+ */
+#include <ctype.h>
+/* Case insensitive string comparision */
+static int nocase_cmp(const ASN1_STRING *a, const ASN1_STRING *b)
+{
+	int i;
+
+	if (a->length != b->length)
+		return (a->length - b->length);
+
+	for (i=0; i<a->length; i++)
+	{
+		int ca, cb;
+
+		ca = tolower(a->data[i]);
+		cb = tolower(b->data[i]);
+
+		if (ca != cb)
+			return(ca-cb);
+	}
+	return 0;
+}
+
+/* Case insensitive string comparision with space normalization 
+ * Space normalization - ignore leading, trailing spaces, 
+ *       multiple spaces between characters are replaced by single space  
+ */
+static int nocase_spacenorm_cmp(const ASN1_STRING *a, const ASN1_STRING *b)
+{
+	unsigned char *pa = NULL, *pb = NULL;
+	int la, lb;
+	
+	la = a->length;
+	lb = b->length;
+	pa = a->data;
+	pb = b->data;
+
+	/* skip leading spaces */
+	while (la > 0 && isspace(*pa))
+	{
+		la--;
+		pa++;
+	}
+	while (lb > 0 && isspace(*pb))
+	{
+		lb--;
+		pb++;
+	}
+
+	/* skip trailing spaces */
+	while (la > 0 && isspace(pa[la-1]))
+		la--;
+	while (lb > 0 && isspace(pb[lb-1]))
+		lb--;
+
+	/* compare strings with space normalization */
+	while (la > 0 && lb > 0)
+	{
+		int ca, cb;
+
+		/* compare character */
+		ca = tolower(*pa);
+		cb = tolower(*pb);
+		if (ca != cb)
+			return (ca - cb);
+
+		pa++; pb++;
+		la--; lb--;
+
+		if (la <= 0 || lb <= 0)
+			break;
+
+		/* is white space next character ? */
+		if (isspace(*pa) && isspace(*pb))
+		{
+			/* skip remaining white spaces */
+			while (la > 0 && isspace(*pa))
+			{
+				la--;
+				pa++;
+			}
+			while (lb > 0 && isspace(*pb))
+			{
+				lb--;
+				pb++;
+			}
+		}
+	}
+	if (la > 0 || lb > 0)
+		return la - lb;
+
+	return 0;
+}
+
+static int X509_NAME_wildcmp(const X509_NAME *a, const X509_NAME *b)
+{
+    int i,j;
+    X509_NAME_ENTRY *na,*nb;
+
+    if (sk_X509_NAME_ENTRY_num(a->entries)
+	!= sk_X509_NAME_ENTRY_num(b->entries))
+	    return sk_X509_NAME_ENTRY_num(a->entries)
+	      -sk_X509_NAME_ENTRY_num(b->entries);
+    for (i=sk_X509_NAME_ENTRY_num(a->entries)-1; i>=0; i--)
+    {
+	    na=sk_X509_NAME_ENTRY_value(a->entries,i);
+	    nb=sk_X509_NAME_ENTRY_value(b->entries,i);
+	    j=OBJ_cmp(na->object,nb->object);
+	    if (j) return(j);
+	    if ((na->value->length == 1 && na->value->data[0] == '*')
+	     || (nb->value->length == 1 && nb->value->data[0] == '*'))
+		    continue;
+	    j=na->value->type-nb->value->type;
+	    if (j) return(j);
+	    if (na->value->type == V_ASN1_PRINTABLESTRING)
+		    j=nocase_spacenorm_cmp(na->value, nb->value);
+	    else if (na->value->type == V_ASN1_IA5STRING
+		    && OBJ_obj2nid(na->object) == NID_pkcs9_emailAddress)
+		    j=nocase_cmp(na->value, nb->value);
+	    else
+		    {
+		    j=na->value->length-nb->value->length;
+		    if (j) return(j);
+		    j=memcmp(na->value->data,nb->value->data,
+			    na->value->length);
+		    }
+	    if (j) return(j);
+	    j=na->set-nb->set;
+	    if (j) return(j);
+    }
+
+    return(0);
+}
+
+/*
+ * compare two subjectNames.
+ * OUT:        0: equal
+ *	positive:
+ *	      -1: other error.
+ */
+int
+eay_cmp_asn1dn(n1, n2)
+	vchar_t *n1, *n2;
+{
+	X509_NAME *a = NULL, *b = NULL;
+	caddr_t p;
+	int i = -1;
+
+	p = n1->v;
+	if (!d2i_X509_NAME(&a, (void *)&p, n1->l))
+		goto end;
+	p = n2->v;
+	if (!d2i_X509_NAME(&b, (void *)&p, n2->l))
+		goto end;
+
+	i = X509_NAME_wildcmp(a, b);
+
+    end:
+	if (a)
+		X509_NAME_free(a);
+	if (b)
+		X509_NAME_free(b);
+	return i;
+}
+
+/*
+ * this functions is derived from apps/verify.c in OpenSSL0.9.5
+ */
+int
+eay_check_x509cert(cert, CApath, CAfile, local)
+	vchar_t *cert;
+	char *CApath;
+	char *CAfile;
+	int local;
+{
+	X509_STORE *cert_ctx = NULL;
+	X509_LOOKUP *lookup = NULL;
+	X509 *x509 = NULL;
+	X509_STORE_CTX *csc;
+	int error = -1;
+
+	cert_ctx = X509_STORE_new();
+	if (cert_ctx == NULL)
+		goto end;
+
+	if (local)
+		X509_STORE_set_verify_cb_func(cert_ctx, cb_check_cert_local);
+	else 
+		X509_STORE_set_verify_cb_func(cert_ctx, cb_check_cert_remote);
+
+	lookup = X509_STORE_add_lookup(cert_ctx, X509_LOOKUP_file());
+	if (lookup == NULL)
+		goto end;
+
+	X509_LOOKUP_load_file(lookup, CAfile, 
+	    (CAfile == NULL) ? X509_FILETYPE_DEFAULT : X509_FILETYPE_PEM);
+
+	lookup = X509_STORE_add_lookup(cert_ctx, X509_LOOKUP_hash_dir());
+	if (lookup == NULL)
+		goto end;
+	error = X509_LOOKUP_add_dir(lookup, CApath, X509_FILETYPE_PEM);
+	if(!error) {
+		error = -1;
+		goto end;
+	}
+	error = -1;	/* initialized */
+
+	/* read the certificate to be verified */
+	x509 = mem2x509(cert);
+	if (x509 == NULL)
+		goto end;
+
+	csc = X509_STORE_CTX_new();
+	if (csc == NULL)
+		goto end;
+	X509_STORE_CTX_init(csc, cert_ctx, x509, NULL);
+#if OPENSSL_VERSION_NUMBER >= 0x00907000L
+	X509_STORE_CTX_set_flags (csc, X509_V_FLAG_CRL_CHECK);
+	X509_STORE_CTX_set_flags (csc, X509_V_FLAG_CRL_CHECK_ALL);
+#endif
+	error = X509_verify_cert(csc);
+	X509_STORE_CTX_cleanup(csc);
+
+	/*
+	 * if x509_verify_cert() is successful then the value of error is
+	 * set non-zero.
+	 */
+	error = error ? 0 : -1;
+
+end:
+	if (error)
+		plog(LLV_WARNING, LOCATION, NULL,"%s\n", eay_strerror());
+	if (cert_ctx != NULL)
+		X509_STORE_free(cert_ctx);
+	if (x509 != NULL)
+		X509_free(x509);
+
+	return(error);
+}
+
+/*
+ * callback function for verifing certificate.
+ * this function is derived from cb() in openssl/apps/s_server.c
+ */
+static int
+cb_check_cert_local(ok, ctx)
+	int ok;
+	X509_STORE_CTX *ctx;
+{
+	char buf[256];
+	int log_tag;
+
+	if (!ok) {
+		X509_NAME_oneline(
+				X509_get_subject_name(ctx->current_cert),
+				buf,
+				256);
+		/*
+		 * since we are just checking the certificates, it is
+		 * ok if they are self signed. But we should still warn
+		 * the user.
+ 		 */
+		switch (ctx->error) {
+		case X509_V_ERR_CERT_HAS_EXPIRED:
+		case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
+		case X509_V_ERR_INVALID_CA:
+		case X509_V_ERR_PATH_LENGTH_EXCEEDED:
+		case X509_V_ERR_INVALID_PURPOSE:
+		case X509_V_ERR_UNABLE_TO_GET_CRL:
+			ok = 1;
+			log_tag = LLV_WARNING;
+			break;
+		default:
+			log_tag = LLV_ERROR;
+		}
+		plog(log_tag, LOCATION, NULL,
+			"%s(%d) at depth:%d SubjectName:%s\n",
+			X509_verify_cert_error_string(ctx->error),
+			ctx->error,
+			ctx->error_depth,
+			buf);
+	}
+	ERR_clear_error();
+
+	return ok;
+}
+
+/*
+ * callback function for verifing remote certificates.
+ * this function is derived from cb() in openssl/apps/s_server.c
+ */
+static int
+cb_check_cert_remote(ok, ctx)
+	int ok;
+	X509_STORE_CTX *ctx;
+{
+	char buf[256];
+	int log_tag;
+
+	if (!ok) {
+		X509_NAME_oneline(
+				X509_get_subject_name(ctx->current_cert),
+				buf,
+				256);
+		switch (ctx->error) {
+		case X509_V_ERR_UNABLE_TO_GET_CRL:
+			ok = 1;
+			log_tag = LLV_WARNING;
+			break;
+		default:
+			log_tag = LLV_ERROR;
+		}
+		plog(log_tag, LOCATION, NULL,
+			"%s(%d) at depth:%d SubjectName:%s\n",
+			X509_verify_cert_error_string(ctx->error),
+			ctx->error,
+			ctx->error_depth,
+			buf);
+	}
+	ERR_clear_error();
+
+	return ok;
+}
+
+/*
+ * get a subjectAltName from X509 certificate.
+ */
+vchar_t *
+eay_get_x509asn1subjectname(cert)
+	vchar_t *cert;
+{
+	X509 *x509 = NULL;
+	u_char *bp;
+	vchar_t *name = NULL;
+	int len;
+
+	bp = (unsigned char *) cert->v;
+
+	x509 = mem2x509(cert);
+	if (x509 == NULL)
+		goto error;
+
+	/* get the length of the name */
+	len = i2d_X509_NAME(x509->cert_info->subject, NULL);
+	name = vmalloc(len);
+	if (!name)
+		goto error;
+	/* get the name */
+	bp = (unsigned char *) name->v;
+	len = i2d_X509_NAME(x509->cert_info->subject, &bp);
+
+	X509_free(x509);
+
+	return name;
+
+error:
+	plog(LLV_ERROR, LOCATION, NULL, "%s\n", eay_strerror());
+
+	if (name != NULL) 
+		vfree(name);
+
+	if (x509 != NULL)
+		X509_free(x509);
+
+	return NULL;
+}
+
+/*
+ * get the subjectAltName from X509 certificate.
+ * the name must be terminated by '\0'.
+ */
+int
+eay_get_x509subjectaltname(cert, altname, type, pos)
+	vchar_t *cert;
+	char **altname;
+	int *type;
+	int pos;
+{
+	X509 *x509 = NULL;
+	GENERAL_NAMES *gens = NULL;
+	GENERAL_NAME *gen;
+	int len;
+	int error = -1;
+
+	*altname = NULL;
+	*type = GENT_OTHERNAME;
+
+	x509 = mem2x509(cert);
+	if (x509 == NULL)
+		goto end;
+
+	gens = X509_get_ext_d2i(x509, NID_subject_alt_name, NULL, NULL);
+	if (gens == NULL)
+		goto end;
+
+	/* there is no data at "pos" */
+	if (pos > sk_GENERAL_NAME_num(gens))
+		goto end;
+
+	gen = sk_GENERAL_NAME_value(gens, pos - 1);
+
+	/* read DNSName / Email */
+	if (gen->type == GEN_DNS	||
+		gen->type == GEN_EMAIL	||
+		gen->type == GEN_URI )
+	{
+		/* make sure if the data is terminated by '\0'. */
+		if (gen->d.ia5->data[gen->d.ia5->length] != '\0')
+		{
+			plog(LLV_ERROR, LOCATION, NULL,
+				 "data is not terminated by NUL.");
+			racoon_hexdump(gen->d.ia5->data, gen->d.ia5->length + 1);
+			goto end;
+		}
+		
+		len = gen->d.ia5->length + 1;
+		*altname = racoon_malloc(len);
+		if (!*altname)
+			goto end;
+		
+		strlcpy(*altname, (char *) gen->d.ia5->data, len);
+		*type = gen->type;
+		error = 0;
+	}
+	/* read IP address */
+	else if (gen->type == GEN_IPADD)
+	{
+		unsigned char p[5], *ip;
+		ip = p;
+		
+		/* only support IPv4 */
+		if (gen->d.ip->length != 4)
+			goto end;
+		
+		/* convert Octet String to String
+		 * XXX ???????
+		 */
+		/*i2d_ASN1_OCTET_STRING(gen->d.ip,&ip);*/
+		ip = gen->d.ip->data;
+
+		/* XXX Magic, enough for an IPv4 address
+		 */
+		*altname = racoon_malloc(20);
+		if (!*altname)
+			goto end;
+		
+		sprintf(*altname, "%u.%u.%u.%u", ip[0], ip[1], ip[2], ip[3]);
+		*type = gen->type;
+		error = 0;
+	}
+	/* XXX other possible types ?
+	 * For now, error will be -1 if unsupported type
+	 */
+
+end:
+	if (error) {
+		if (*altname) {
+			racoon_free(*altname);
+			*altname = NULL;
+		}
+		plog(LLV_ERROR, LOCATION, NULL, "%s\n", eay_strerror());
+	}
+	if (x509)
+		X509_free(x509);
+	if (gens)
+		/* free the whole stack. */
+		sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free);
+
+	return error;
+}
+
+
+/*
+ * decode a X509 certificate and make a readable text terminated '\n'.
+ * return the buffer allocated, so must free it later.
+ */
+char *
+eay_get_x509text(cert)
+	vchar_t *cert;
+{
+	X509 *x509 = NULL;
+	BIO *bio = NULL;
+	char *text = NULL;
+	u_char *bp = NULL;
+	int len = 0;
+	int error = -1;
+
+	x509 = mem2x509(cert);
+	if (x509 == NULL)
+		goto end;
+
+	bio = BIO_new(BIO_s_mem());
+	if (bio == NULL)
+		goto end;
+
+	error = X509_print(bio, x509);
+	if (error != 1) {
+		error = -1;
+		goto end;
+	}
+
+	len = BIO_get_mem_data(bio, &bp);
+	text = racoon_malloc(len + 1);
+	if (text == NULL)
+		goto end;
+	memcpy(text, bp, len);
+	text[len] = '\0';
+
+	error = 0;
+
+    end:
+	if (error) {
+		if (text) {
+			racoon_free(text);
+			text = NULL;
+		}
+		plog(LLV_ERROR, LOCATION, NULL, "%s\n", eay_strerror());
+	}
+	if (bio)
+		BIO_free(bio);
+	if (x509)
+		X509_free(x509);
+
+	return text;
+}
+
+/* get X509 structure from buffer. */
+static X509 *
+mem2x509(cert)
+	vchar_t *cert;
+{
+	X509 *x509;
+
+#ifndef EAYDEBUG
+    {
+	u_char *bp;
+
+	bp = (unsigned char *) cert->v;
+
+	x509 = d2i_X509(NULL, (void *)&bp, cert->l);
+    }
+#else
+    {
+	BIO *bio;
+	int len;
+
+	bio = BIO_new(BIO_s_mem());
+	if (bio == NULL)
+		return NULL;
+	len = BIO_write(bio, cert->v, cert->l);
+	if (len == -1)
+		return NULL;
+	x509 = PEM_read_bio_X509(bio, NULL, NULL, NULL);
+	BIO_free(bio);
+    }
+#endif
+	return x509;
+}
+
+/*
+ * get a X509 certificate from local file.
+ * a certificate must be PEM format.
+ * Input:
+ *	path to a certificate.
+ * Output:
+ *	NULL if error occured
+ *	other is the cert.
+ */
+vchar_t *
+eay_get_x509cert(path)
+	char *path;
+{
+	FILE *fp;
+	X509 *x509;
+	vchar_t *cert;
+	u_char *bp;
+	int len;
+	int error;
+
+	/* Read private key */
+	fp = fopen(path, "r");
+	if (fp == NULL)
+		return NULL;
+	x509 = PEM_read_X509(fp, NULL, NULL, NULL);
+	fclose (fp);
+
+	if (x509 == NULL)
+		return NULL;
+
+	len = i2d_X509(x509, NULL);
+	cert = vmalloc(len);
+	if (cert == NULL) {
+		X509_free(x509);
+		return NULL;
+	}
+	bp = (unsigned char *) cert->v;
+	error = i2d_X509(x509, &bp);
+	X509_free(x509);
+
+	if (error == 0) {
+		vfree(cert);
+		return NULL;
+	}
+
+	return cert;
+}
+
+/*
+ * check a X509 signature
+ *	XXX: to be get hash type from my cert ?
+ *		to be handled EVP_dss().
+ * OUT: return -1 when error.
+ *	0
+ */
+int
+eay_check_x509sign(source, sig, cert)
+	vchar_t *source;
+	vchar_t *sig;
+	vchar_t *cert;
+{
+	X509 *x509;
+	u_char *bp;
+	EVP_PKEY *evp;
+	int res;
+
+	bp = (unsigned char *) cert->v;
+
+	x509 = d2i_X509(NULL, (void *)&bp, cert->l);
+	if (x509 == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL, "d2i_X509(): %s\n", eay_strerror());
+		return -1;
+	}
+
+	evp = X509_get_pubkey(x509);
+	if (! evp) {
+		plog(LLV_ERROR, LOCATION, NULL, "X509_get_pubkey(): %s\n", eay_strerror());
+		return -1;
+	}
+
+	res = eay_rsa_verify(source, sig, evp->pkey.rsa);
+
+	EVP_PKEY_free(evp);
+
+	return res;
+}
+
+/*
+ * check RSA signature
+ * OUT: return -1 when error.
+ *	0 on success
+ */
+int
+eay_check_rsasign(source, sig, rsa)
+	vchar_t *source;
+	vchar_t *sig;
+	RSA *rsa;
+{
+	return eay_rsa_verify(source, sig, rsa);
+}
+
+/*
+ * get PKCS#1 Private Key of PEM format from local file.
+ */
+vchar_t *
+eay_get_pkcs1privkey(path)
+	char *path;
+{
+	FILE *fp;
+	EVP_PKEY *evp = NULL;
+	vchar_t *pkey = NULL;
+	u_char *bp;
+	int pkeylen;
+	int error = -1;
+
+	/* Read private key */
+	fp = fopen(path, "r");
+	if (fp == NULL)
+		return NULL;
+
+	evp = PEM_read_PrivateKey(fp, NULL, NULL, NULL);
+
+	fclose (fp);
+
+	if (evp == NULL)
+		return NULL;
+
+	pkeylen = i2d_PrivateKey(evp, NULL);
+	if (pkeylen == 0)
+		goto end;
+	pkey = vmalloc(pkeylen);
+	if (pkey == NULL)
+		goto end;
+	bp = (unsigned char *) pkey->v;
+	pkeylen = i2d_PrivateKey(evp, &bp);
+	if (pkeylen == 0)
+		goto end;
+
+	error = 0;
+
+end:
+	if (evp != NULL)
+		EVP_PKEY_free(evp);
+	if (error != 0 && pkey != NULL) {
+		vfree(pkey);
+		pkey = NULL;
+	}
+
+	return pkey;
+}
+
+/*
+ * get PKCS#1 Public Key of PEM format from local file.
+ */
+vchar_t *
+eay_get_pkcs1pubkey(path)
+	char *path;
+{
+	FILE *fp;
+	EVP_PKEY *evp = NULL;
+	vchar_t *pkey = NULL;
+	X509 *x509 = NULL;
+	u_char *bp;
+	int pkeylen;
+	int error = -1;
+
+	/* Read private key */
+	fp = fopen(path, "r");
+	if (fp == NULL)
+		return NULL;
+
+	x509 = PEM_read_X509(fp, NULL, NULL, NULL);
+
+	fclose (fp);
+
+	if (x509 == NULL)
+		return NULL;
+  
+	/* Get public key - eay */
+	evp = X509_get_pubkey(x509);
+	if (evp == NULL)
+		return NULL;
+
+	pkeylen = i2d_PublicKey(evp, NULL);
+	if (pkeylen == 0)
+		goto end;
+	pkey = vmalloc(pkeylen);
+	if (pkey == NULL)
+		goto end;
+	bp = (unsigned char *) pkey->v;
+	pkeylen = i2d_PublicKey(evp, &bp);
+	if (pkeylen == 0)
+		goto end;
+
+	error = 0;
+end:
+	if (evp != NULL)
+		EVP_PKEY_free(evp);
+	if (error != 0 && pkey != NULL) {
+		vfree(pkey);
+		pkey = NULL;
+	}
+
+	return pkey;
+}
+
+vchar_t *
+eay_get_x509sign(src, privkey)
+	vchar_t *src, *privkey;
+{
+	EVP_PKEY *evp;
+	u_char *bp = (unsigned char *) privkey->v;
+	vchar_t *sig = NULL;
+	int len;
+	int pad = RSA_PKCS1_PADDING;
+
+	/* XXX to be handled EVP_PKEY_DSA */
+	evp = d2i_PrivateKey(EVP_PKEY_RSA, NULL, (void *)&bp, privkey->l);
+	if (evp == NULL)
+		return NULL;
+
+	sig = eay_rsa_sign(src, evp->pkey.rsa);
+
+	EVP_PKEY_free(evp);
+
+	return sig;
+}
+
+vchar_t *
+eay_get_rsasign(src, rsa)
+	vchar_t *src;
+	RSA *rsa;
+{
+	return eay_rsa_sign(src, rsa);
+}
+
+vchar_t *
+eay_rsa_sign(vchar_t *src, RSA *rsa)
+{
+	int len;
+	vchar_t *sig = NULL;
+	int pad = RSA_PKCS1_PADDING;
+
+	len = RSA_size(rsa);
+
+	sig = vmalloc(len);
+	if (sig == NULL)
+		return NULL;
+
+	len = RSA_private_encrypt(src->l, (unsigned char *) src->v, 
+			(unsigned char *) sig->v, rsa, pad);
+
+	if (len == 0 || len != sig->l) {
+		vfree(sig);
+		sig = NULL;
+	}
+
+	return sig;
+}
+
+int
+eay_rsa_verify(src, sig, rsa)
+	vchar_t *src, *sig;
+	RSA *rsa;
+{
+	vchar_t *xbuf = NULL;
+	int pad = RSA_PKCS1_PADDING;
+	int len = 0;
+	int error;
+
+	len = RSA_size(rsa);
+	xbuf = vmalloc(len);
+	if (xbuf == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL, "%s\n", eay_strerror());
+		return -1;
+	}
+
+	len = RSA_public_decrypt(sig->l, (unsigned char *) sig->v, 
+			(unsigned char *) xbuf->v, rsa, pad);
+	if (len == 0 || len != src->l) {
+		plog(LLV_ERROR, LOCATION, NULL, "%s\n", eay_strerror());
+		vfree(xbuf);
+		return -1;
+	}
+
+	error = memcmp(src->v, xbuf->v, src->l);
+	vfree(xbuf);
+	if (error != 0)
+		return -1;
+
+	return 0;
+}
+
+/*
+ * get error string
+ * MUST load ERR_load_crypto_strings() first.
+ */
+char *
+eay_strerror()
+{
+	static char ebuf[512];
+	int len = 0, n;
+	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){
+		n = snprintf(ebuf + len, sizeof(ebuf) - len,
+				"%lu:%s:%s:%d:%s ",
+				es, ERR_error_string(l, buf), file, line,
+				(flags & ERR_TXT_STRING) ? data : "");
+		if (n < 0 || n >= sizeof(ebuf) - len)
+			break;
+		len += n;
+		if (sizeof(ebuf) < len)
+			break;
+	}
+
+	return ebuf;
+}
+
+vchar_t *
+evp_crypt(vchar_t *data, vchar_t *key, vchar_t *iv, const EVP_CIPHER *e, int enc)
+{
+	vchar_t *res;
+	EVP_CIPHER_CTX ctx;
+
+	if (!e)
+		return NULL;
+
+	if (data->l % EVP_CIPHER_block_size(e))
+		return NULL;
+
+	if ((res = vmalloc(data->l)) == NULL)
+		return NULL;
+
+	EVP_CIPHER_CTX_init(&ctx);
+
+	switch(EVP_CIPHER_nid(e)){
+	case NID_bf_cbc:
+	case NID_bf_ecb:
+	case NID_bf_cfb64:
+	case NID_bf_ofb64:
+	case NID_cast5_cbc:
+	case NID_cast5_ecb:
+	case NID_cast5_cfb64:
+	case NID_cast5_ofb64:
+		/* XXX: can we do that also for algos with a fixed key size ?
+		 */
+		/* init context without key/iv
+         */
+        if (!EVP_CipherInit(&ctx, e, NULL, NULL, enc))
+        {
+            OpenSSL_BUG();
+            vfree(res);
+            return NULL;
+        }
+		
+        /* update key size
+         */
+        if (!EVP_CIPHER_CTX_set_key_length(&ctx, key->l))
+        {
+            OpenSSL_BUG();
+            vfree(res);
+            return NULL;
+        }
+
+        /* finalize context init with desired key size
+         */
+        if (!EVP_CipherInit(&ctx, NULL, (u_char *) key->v,
+							(u_char *) iv->v, enc))
+        {
+            OpenSSL_BUG();
+            vfree(res);
+            return NULL;
+		}
+		break;
+	default:
+		if (!EVP_CipherInit(&ctx, e, (u_char *) key->v, 
+							(u_char *) iv->v, enc)) {
+			OpenSSL_BUG();
+			vfree(res);
+			return NULL;
+		}
+	}
+
+	/* disable openssl padding */
+	EVP_CIPHER_CTX_set_padding(&ctx, 0); 
+	
+	if (!EVP_Cipher(&ctx, (u_char *) res->v, (u_char *) data->v, data->l)) {
+		OpenSSL_BUG();
+		vfree(res);
+		return NULL;
+	}
+
+	EVP_CIPHER_CTX_cleanup(&ctx);
+
+	return res;
+}
+
+int
+evp_weakkey(vchar_t *key, const EVP_CIPHER *e)
+{
+	return 0;
+}
+
+int
+evp_keylen(int len, const EVP_CIPHER *e)
+{
+	if (!e)
+		return -1;
+	/* EVP functions return lengths in bytes, ipsec-tools
+	 * uses lengths in bits, therefore conversion is required. --AK
+	 */
+	if (len != 0 && len != (EVP_CIPHER_key_length(e) << 3))
+		return -1;
+	
+	return EVP_CIPHER_key_length(e) << 3;
+}
+
+/*
+ * DES-CBC
+ */
+vchar_t *
+eay_des_encrypt(data, key, iv)
+	vchar_t *data, *key, *iv;
+{
+	return evp_crypt(data, key, iv, EVP_des_cbc(), 1);
+}
+
+vchar_t *
+eay_des_decrypt(data, key, iv)
+	vchar_t *data, *key, *iv;
+{
+	return evp_crypt(data, key, iv, EVP_des_cbc(), 0);
+}
+
+int
+eay_des_weakkey(key)
+	vchar_t *key;
+{
+#ifdef USE_NEW_DES_API
+	return DES_is_weak_key((void *)key->v);
+#else
+	return des_is_weak_key((void *)key->v);
+#endif
+}
+
+int
+eay_des_keylen(len)
+	int len;
+{
+	return evp_keylen(len, EVP_des_cbc());
+}
+
+#ifdef HAVE_OPENSSL_IDEA_H
+/*
+ * IDEA-CBC
+ */
+vchar_t *
+eay_idea_encrypt(data, key, iv)
+	vchar_t *data, *key, *iv;
+{
+	vchar_t *res;
+	IDEA_KEY_SCHEDULE ks;
+
+	idea_set_encrypt_key((unsigned char *)key->v, &ks);
+
+	/* allocate buffer for result */
+	if ((res = vmalloc(data->l)) == NULL)
+		return NULL;
+
+	/* decryption data */
+	idea_cbc_encrypt((unsigned char *)data->v, (unsigned char *)res->v, data->l,
+			&ks, (unsigned char *)iv->v, IDEA_ENCRYPT);
+
+	return res;
+}
+
+vchar_t *
+eay_idea_decrypt(data, key, iv)
+	vchar_t *data, *key, *iv;
+{
+	vchar_t *res;
+	IDEA_KEY_SCHEDULE ks, dks;
+
+	idea_set_encrypt_key((unsigned char *)key->v, &ks);
+	idea_set_decrypt_key(&ks, &dks);
+
+	/* allocate buffer for result */
+	if ((res = vmalloc(data->l)) == NULL)
+		return NULL;
+
+	/* decryption data */
+	idea_cbc_encrypt((unsigned char *)data->v, (unsigned char *)res->v, data->l,
+			&dks, (unsigned char *)iv->v, IDEA_DECRYPT);
+
+	return res;
+}
+
+int
+eay_idea_weakkey(key)
+	vchar_t *key;
+{
+	return 0;       /* XXX */
+}
+
+int
+eay_idea_keylen(len)
+	int len;
+{
+	if (len != 0 && len != 128)
+		return -1;
+	return 128;
+}
+#endif
+
+/*
+ * BLOWFISH-CBC
+ */
+vchar_t *
+eay_bf_encrypt(data, key, iv)
+	vchar_t *data, *key, *iv;
+{
+	return evp_crypt(data, key, iv, EVP_bf_cbc(), 1);
+}
+
+vchar_t *
+eay_bf_decrypt(data, key, iv)
+	vchar_t *data, *key, *iv;
+{
+	return evp_crypt(data, key, iv, EVP_bf_cbc(), 0);
+}
+
+int
+eay_bf_weakkey(key)
+	vchar_t *key;
+{
+	return 0;	/* XXX to be done. refer to RFC 2451 */
+}
+
+int
+eay_bf_keylen(len)
+	int len;
+{
+	if (len == 0)
+		return 448;
+	if (len < 40 || len > 448)
+		return -1;
+	return len;
+}
+
+#ifdef HAVE_OPENSSL_RC5_H
+/*
+ * RC5-CBC
+ */
+vchar_t *
+eay_rc5_encrypt(data, key, iv)
+	vchar_t *data, *key, *iv;
+{
+	vchar_t *res;
+	RC5_32_KEY ks;
+
+	/* in RFC 2451, there is information about the number of round. */
+	RC5_32_set_key(&ks, key->l, (unsigned char *)key->v, 16);
+
+	/* allocate buffer for result */
+	if ((res = vmalloc(data->l)) == NULL)
+		return NULL;
+
+	/* decryption data */
+	RC5_32_cbc_encrypt((unsigned char *)data->v, (unsigned char *)res->v, data->l,
+		&ks, (unsigned char *)iv->v, RC5_ENCRYPT);
+
+	return res;
+}
+
+vchar_t *
+eay_rc5_decrypt(data, key, iv)
+	vchar_t *data, *key, *iv;
+{
+	vchar_t *res;
+	RC5_32_KEY ks;
+
+	/* in RFC 2451, there is information about the number of round. */
+	RC5_32_set_key(&ks, key->l, (unsigned char *)key->v, 16);
+
+	/* allocate buffer for result */
+	if ((res = vmalloc(data->l)) == NULL)
+		return NULL;
+
+	/* decryption data */
+	RC5_32_cbc_encrypt((unsigned char *)data->v, (unsigned char *)res->v, data->l,
+		&ks, (unsigned char *)iv->v, RC5_DECRYPT);
+
+	return res;
+}
+
+int
+eay_rc5_weakkey(key)
+	vchar_t *key;
+{
+	return 0;       /* No known weak keys when used with 16 rounds. */
+
+}
+
+int
+eay_rc5_keylen(len)
+	int len;
+{
+	if (len == 0)
+		return 128;
+	if (len < 40 || len > 2040)
+		return -1;
+	return len;
+}
+#endif
+
+/*
+ * 3DES-CBC
+ */
+vchar_t *
+eay_3des_encrypt(data, key, iv)
+	vchar_t *data, *key, *iv;
+{
+	return evp_crypt(data, key, iv, EVP_des_ede3_cbc(), 1);
+}
+
+vchar_t *
+eay_3des_decrypt(data, key, iv)
+	vchar_t *data, *key, *iv;
+{
+	return evp_crypt(data, key, iv, EVP_des_ede3_cbc(), 0);
+}
+
+int
+eay_3des_weakkey(key)
+	vchar_t *key;
+{
+#ifdef USE_NEW_DES_API
+	return (DES_is_weak_key((void *)key->v) ||
+	    DES_is_weak_key((void *)(key->v + 8)) ||
+	    DES_is_weak_key((void *)(key->v + 16)));
+#else
+	if (key->l < 24)
+		return 0;
+
+	return (des_is_weak_key((void *)key->v) ||
+	    des_is_weak_key((void *)(key->v + 8)) ||
+	    des_is_weak_key((void *)(key->v + 16)));
+#endif
+}
+
+int
+eay_3des_keylen(len)
+	int len;
+{
+	if (len != 0 && len != 192)
+		return -1;
+	return 192;
+}
+
+/*
+ * CAST-CBC
+ */
+vchar_t *
+eay_cast_encrypt(data, key, iv)
+	vchar_t *data, *key, *iv;
+{
+	return evp_crypt(data, key, iv, EVP_cast5_cbc(), 1);
+}
+
+vchar_t *
+eay_cast_decrypt(data, key, iv)
+	vchar_t *data, *key, *iv;
+{
+	return evp_crypt(data, key, iv, EVP_cast5_cbc(), 0);
+}
+
+int
+eay_cast_weakkey(key)
+	vchar_t *key;
+{
+	return 0;	/* No known weak keys. */
+}
+
+int
+eay_cast_keylen(len)
+	int len;
+{
+	if (len == 0)
+		return 128;
+	if (len < 40 || len > 128)
+		return -1;
+	return len;
+}
+
+/*
+ * AES(RIJNDAEL)-CBC
+ */
+#ifndef HAVE_OPENSSL_AES_H
+vchar_t *
+eay_aes_encrypt(data, key, iv)
+	vchar_t *data, *key, *iv;
+{
+	vchar_t *res;
+	keyInstance k;
+	cipherInstance c;
+
+	memset(&k, 0, sizeof(k));
+	if (rijndael_makeKey(&k, DIR_ENCRYPT, key->l << 3, key->v) < 0)
+		return NULL;
+
+	/* allocate buffer for result */
+	if ((res = vmalloc(data->l)) == NULL)
+		return NULL;
+
+	/* encryption data */
+	memset(&c, 0, sizeof(c));
+	if (rijndael_cipherInit(&c, MODE_CBC, iv->v) < 0){
+		vfree(res);
+		return NULL;
+	}
+	if (rijndael_blockEncrypt(&c, &k, data->v, data->l << 3, res->v) < 0){
+		vfree(res);
+		return NULL;
+	}
+
+	return res;
+}
+
+vchar_t *
+eay_aes_decrypt(data, key, iv)
+	vchar_t *data, *key, *iv;
+{
+	vchar_t *res;
+	keyInstance k;
+	cipherInstance c;
+
+	memset(&k, 0, sizeof(k));
+	if (rijndael_makeKey(&k, DIR_DECRYPT, key->l << 3, key->v) < 0)
+		return NULL;
+
+	/* allocate buffer for result */
+	if ((res = vmalloc(data->l)) == NULL)
+		return NULL;
+
+	/* decryption data */
+	memset(&c, 0, sizeof(c));
+	if (rijndael_cipherInit(&c, MODE_CBC, iv->v) < 0){
+		vfree(res);
+		return NULL;
+	}
+	if (rijndael_blockDecrypt(&c, &k, data->v, data->l << 3, res->v) < 0){
+		vfree(res);
+		return NULL;
+	}
+
+	return res;
+}
+#else
+static inline const EVP_CIPHER *
+aes_evp_by_keylen(int keylen)
+{
+	switch(keylen) {
+		case 16:
+		case 128:
+			return EVP_aes_128_cbc();
+		case 24:
+		case 192:
+			return EVP_aes_192_cbc();
+		case 32:
+		case 256:
+			return EVP_aes_256_cbc();
+		default:
+			return NULL;
+	}
+}
+
+vchar_t *
+eay_aes_encrypt(data, key, iv)
+       vchar_t *data, *key, *iv;
+{
+	return evp_crypt(data, key, iv, aes_evp_by_keylen(key->l), 1);
+}
+
+vchar_t *
+eay_aes_decrypt(data, key, iv)
+       vchar_t *data, *key, *iv;
+{
+	return evp_crypt(data, key, iv, aes_evp_by_keylen(key->l), 0);
+}
+#endif
+
+int
+eay_aes_weakkey(key)
+	vchar_t *key;
+{
+	return 0;
+}
+
+int
+eay_aes_keylen(len)
+	int len;
+{
+	if (len == 0)
+		return 128;
+	if (len != 128 && len != 192 && len != 256)
+		return -1;
+	return len;
+}
+
+#if defined(HAVE_OPENSSL_CAMELLIA_H)
+/*
+ * CAMELLIA-CBC
+ */
+static inline const EVP_CIPHER *
+camellia_evp_by_keylen(int keylen)
+{
+	switch(keylen) {
+		case 16:
+		case 128:
+			return EVP_camellia_128_cbc();
+		case 24:
+		case 192:
+			return EVP_camellia_192_cbc();
+		case 32:
+		case 256:
+			return EVP_camellia_256_cbc();
+		default:
+			return NULL;
+	}
+}
+
+vchar_t *
+eay_camellia_encrypt(data, key, iv)
+       vchar_t *data, *key, *iv;
+{
+	return evp_crypt(data, key, iv, camellia_evp_by_keylen(key->l), 1);
+}
+
+vchar_t *
+eay_camellia_decrypt(data, key, iv)
+       vchar_t *data, *key, *iv;
+{
+	return evp_crypt(data, key, iv, camellia_evp_by_keylen(key->l), 0);
+}
+
+int
+eay_camellia_weakkey(key)
+	vchar_t *key;
+{
+	return 0;
+}
+
+int
+eay_camellia_keylen(len)
+	int len;
+{
+	if (len == 0)
+		return 128;
+	if (len != 128 && len != 192 && len != 256)
+		return -1;
+	return len;
+}
+
+#endif
+
+/* for ipsec part */
+int
+eay_null_hashlen()
+{
+	return 0;
+}
+
+int
+eay_kpdk_hashlen()
+{
+	return 0;
+}
+
+int
+eay_twofish_keylen(len)
+	int len;
+{
+	if (len < 0 || len > 256)
+		return -1;
+	return len;
+}
+
+int
+eay_null_keylen(len)
+	int len;
+{
+	return 0;
+}
+
+/*
+ * HMAC functions
+ */
+static caddr_t
+eay_hmac_init(key, md)
+	vchar_t *key;
+	const EVP_MD *md;
+{
+	HMAC_CTX *c = racoon_malloc(sizeof(*c));
+
+	HMAC_Init(c, key->v, key->l, md);
+
+	return (caddr_t)c;
+}
+
+#ifdef WITH_SHA2
+/*
+ * HMAC SHA2-512
+ */
+vchar_t *
+eay_hmacsha2_512_one(key, data)
+	vchar_t *key, *data;
+{
+	vchar_t *res;
+	caddr_t ctx;
+
+	ctx = eay_hmacsha2_512_init(key);
+	eay_hmacsha2_512_update(ctx, data);
+	res = eay_hmacsha2_512_final(ctx);
+
+	return(res);
+}
+
+caddr_t
+eay_hmacsha2_512_init(key)
+	vchar_t *key;
+{
+	return eay_hmac_init(key, EVP_sha2_512());
+}
+
+void
+eay_hmacsha2_512_update(c, data)
+	caddr_t c;
+	vchar_t *data;
+{
+	HMAC_Update((HMAC_CTX *)c, (unsigned char *) data->v, data->l);
+}
+
+vchar_t *
+eay_hmacsha2_512_final(c)
+	caddr_t c;
+{
+	vchar_t *res;
+	unsigned int l;
+
+	if ((res = vmalloc(SHA512_DIGEST_LENGTH)) == 0)
+		return NULL;
+
+	HMAC_Final((HMAC_CTX *)c, (unsigned char *) res->v, &l);
+	res->l = l;
+	HMAC_cleanup((HMAC_CTX *)c);
+	(void)racoon_free(c);
+
+	if (SHA512_DIGEST_LENGTH != res->l) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"hmac sha2_512 length mismatch %zd.\n", res->l);
+		vfree(res);
+		return NULL;
+	}
+
+	return(res);
+}
+
+/*
+ * HMAC SHA2-384
+ */
+vchar_t *
+eay_hmacsha2_384_one(key, data)
+	vchar_t *key, *data;
+{
+	vchar_t *res;
+	caddr_t ctx;
+
+	ctx = eay_hmacsha2_384_init(key);
+	eay_hmacsha2_384_update(ctx, data);
+	res = eay_hmacsha2_384_final(ctx);
+
+	return(res);
+}
+
+caddr_t
+eay_hmacsha2_384_init(key)
+	vchar_t *key;
+{
+	return eay_hmac_init(key, EVP_sha2_384());
+}
+
+void
+eay_hmacsha2_384_update(c, data)
+	caddr_t c;
+	vchar_t *data;
+{
+	HMAC_Update((HMAC_CTX *)c, (unsigned char *) data->v, data->l);
+}
+
+vchar_t *
+eay_hmacsha2_384_final(c)
+	caddr_t c;
+{
+	vchar_t *res;
+	unsigned int l;
+
+	if ((res = vmalloc(SHA384_DIGEST_LENGTH)) == 0)
+		return NULL;
+
+	HMAC_Final((HMAC_CTX *)c, (unsigned char *) res->v, &l);
+	res->l = l;
+	HMAC_cleanup((HMAC_CTX *)c);
+	(void)racoon_free(c);
+
+	if (SHA384_DIGEST_LENGTH != res->l) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"hmac sha2_384 length mismatch %zd.\n", res->l);
+		vfree(res);
+		return NULL;
+	}
+
+	return(res);
+}
+
+/*
+ * HMAC SHA2-256
+ */
+vchar_t *
+eay_hmacsha2_256_one(key, data)
+	vchar_t *key, *data;
+{
+	vchar_t *res;
+	caddr_t ctx;
+
+	ctx = eay_hmacsha2_256_init(key);
+	eay_hmacsha2_256_update(ctx, data);
+	res = eay_hmacsha2_256_final(ctx);
+
+	return(res);
+}
+
+caddr_t
+eay_hmacsha2_256_init(key)
+	vchar_t *key;
+{
+	return eay_hmac_init(key, EVP_sha2_256());
+}
+
+void
+eay_hmacsha2_256_update(c, data)
+	caddr_t c;
+	vchar_t *data;
+{
+	HMAC_Update((HMAC_CTX *)c, (unsigned char *) data->v, data->l);
+}
+
+vchar_t *
+eay_hmacsha2_256_final(c)
+	caddr_t c;
+{
+	vchar_t *res;
+	unsigned int l;
+
+	if ((res = vmalloc(SHA256_DIGEST_LENGTH)) == 0)
+		return NULL;
+
+	HMAC_Final((HMAC_CTX *)c, (unsigned char *) res->v, &l);
+	res->l = l;
+	HMAC_cleanup((HMAC_CTX *)c);
+	(void)racoon_free(c);
+
+	if (SHA256_DIGEST_LENGTH != res->l) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"hmac sha2_256 length mismatch %zd.\n", res->l);
+		vfree(res);
+		return NULL;
+	}
+
+	return(res);
+}
+#endif	/* WITH_SHA2 */
+
+/*
+ * HMAC SHA1
+ */
+vchar_t *
+eay_hmacsha1_one(key, data)
+	vchar_t *key, *data;
+{
+	vchar_t *res;
+	caddr_t ctx;
+
+	ctx = eay_hmacsha1_init(key);
+	eay_hmacsha1_update(ctx, data);
+	res = eay_hmacsha1_final(ctx);
+
+	return(res);
+}
+
+caddr_t
+eay_hmacsha1_init(key)
+	vchar_t *key;
+{
+	return eay_hmac_init(key, EVP_sha1());
+}
+
+void
+eay_hmacsha1_update(c, data)
+	caddr_t c;
+	vchar_t *data;
+{
+	HMAC_Update((HMAC_CTX *)c, (unsigned char *) data->v, data->l);
+}
+
+vchar_t *
+eay_hmacsha1_final(c)
+	caddr_t c;
+{
+	vchar_t *res;
+	unsigned int l;
+
+	if ((res = vmalloc(SHA_DIGEST_LENGTH)) == 0)
+		return NULL;
+
+	HMAC_Final((HMAC_CTX *)c, (unsigned char *) res->v, &l);
+	res->l = l;
+	HMAC_cleanup((HMAC_CTX *)c);
+	(void)racoon_free(c);
+
+	if (SHA_DIGEST_LENGTH != res->l) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"hmac sha1 length mismatch %zd.\n", res->l);
+		vfree(res);
+		return NULL;
+	}
+
+	return(res);
+}
+
+/*
+ * HMAC MD5
+ */
+vchar_t *
+eay_hmacmd5_one(key, data)
+	vchar_t *key, *data;
+{
+	vchar_t *res;
+	caddr_t ctx;
+
+	ctx = eay_hmacmd5_init(key);
+	eay_hmacmd5_update(ctx, data);
+	res = eay_hmacmd5_final(ctx);
+
+	return(res);
+}
+
+caddr_t
+eay_hmacmd5_init(key)
+	vchar_t *key;
+{
+	return eay_hmac_init(key, EVP_md5());
+}
+
+void
+eay_hmacmd5_update(c, data)
+	caddr_t c;
+	vchar_t *data;
+{
+	HMAC_Update((HMAC_CTX *)c, (unsigned char *) data->v, data->l);
+}
+
+vchar_t *
+eay_hmacmd5_final(c)
+	caddr_t c;
+{
+	vchar_t *res;
+	unsigned int l;
+
+	if ((res = vmalloc(MD5_DIGEST_LENGTH)) == 0)
+		return NULL;
+
+	HMAC_Final((HMAC_CTX *)c, (unsigned char *) res->v, &l);
+	res->l = l;
+	HMAC_cleanup((HMAC_CTX *)c);
+	(void)racoon_free(c);
+
+	if (MD5_DIGEST_LENGTH != res->l) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"hmac md5 length mismatch %zd.\n", res->l);
+		vfree(res);
+		return NULL;
+	}
+
+	return(res);
+}
+
+#ifdef WITH_SHA2
+/*
+ * SHA2-512 functions
+ */
+caddr_t
+eay_sha2_512_init()
+{
+	SHA512_CTX *c = racoon_malloc(sizeof(*c));
+
+	SHA512_Init(c);
+
+	return((caddr_t)c);
+}
+
+void
+eay_sha2_512_update(c, data)
+	caddr_t c;
+	vchar_t *data;
+{
+	SHA512_Update((SHA512_CTX *)c, (unsigned char *) data->v, data->l);
+
+	return;
+}
+
+vchar_t *
+eay_sha2_512_final(c)
+	caddr_t c;
+{
+	vchar_t *res;
+
+	if ((res = vmalloc(SHA512_DIGEST_LENGTH)) == 0)
+		return(0);
+
+	SHA512_Final((unsigned char *) res->v, (SHA512_CTX *)c);
+	(void)racoon_free(c);
+
+	return(res);
+}
+
+vchar_t *
+eay_sha2_512_one(data)
+	vchar_t *data;
+{
+	caddr_t ctx;
+	vchar_t *res;
+
+	ctx = eay_sha2_512_init();
+	eay_sha2_512_update(ctx, data);
+	res = eay_sha2_512_final(ctx);
+
+	return(res);
+}
+
+int
+eay_sha2_512_hashlen()
+{
+	return SHA512_DIGEST_LENGTH << 3;
+}
+#endif
+
+#ifdef WITH_SHA2
+/*
+ * SHA2-384 functions
+ */
+caddr_t
+eay_sha2_384_init()
+{
+	SHA384_CTX *c = racoon_malloc(sizeof(*c));
+
+	SHA384_Init(c);
+
+	return((caddr_t)c);
+}
+
+void
+eay_sha2_384_update(c, data)
+	caddr_t c;
+	vchar_t *data;
+{
+	SHA384_Update((SHA384_CTX *)c, (unsigned char *) data->v, data->l);
+
+	return;
+}
+
+vchar_t *
+eay_sha2_384_final(c)
+	caddr_t c;
+{
+	vchar_t *res;
+
+	if ((res = vmalloc(SHA384_DIGEST_LENGTH)) == 0)
+		return(0);
+
+	SHA384_Final((unsigned char *) res->v, (SHA384_CTX *)c);
+	(void)racoon_free(c);
+
+	return(res);
+}
+
+vchar_t *
+eay_sha2_384_one(data)
+	vchar_t *data;
+{
+	caddr_t ctx;
+	vchar_t *res;
+
+	ctx = eay_sha2_384_init();
+	eay_sha2_384_update(ctx, data);
+	res = eay_sha2_384_final(ctx);
+
+	return(res);
+}
+
+int
+eay_sha2_384_hashlen()
+{
+	return SHA384_DIGEST_LENGTH << 3;
+}
+#endif
+
+#ifdef WITH_SHA2
+/*
+ * SHA2-256 functions
+ */
+caddr_t
+eay_sha2_256_init()
+{
+	SHA256_CTX *c = racoon_malloc(sizeof(*c));
+
+	SHA256_Init(c);
+
+	return((caddr_t)c);
+}
+
+void
+eay_sha2_256_update(c, data)
+	caddr_t c;
+	vchar_t *data;
+{
+	SHA256_Update((SHA256_CTX *)c, (unsigned char *) data->v, data->l);
+
+	return;
+}
+
+vchar_t *
+eay_sha2_256_final(c)
+	caddr_t c;
+{
+	vchar_t *res;
+
+	if ((res = vmalloc(SHA256_DIGEST_LENGTH)) == 0)
+		return(0);
+
+	SHA256_Final((unsigned char *) res->v, (SHA256_CTX *)c);
+	(void)racoon_free(c);
+
+	return(res);
+}
+
+vchar_t *
+eay_sha2_256_one(data)
+	vchar_t *data;
+{
+	caddr_t ctx;
+	vchar_t *res;
+
+	ctx = eay_sha2_256_init();
+	eay_sha2_256_update(ctx, data);
+	res = eay_sha2_256_final(ctx);
+
+	return(res);
+}
+
+int
+eay_sha2_256_hashlen()
+{
+	return SHA256_DIGEST_LENGTH << 3;
+}
+#endif
+
+/*
+ * SHA functions
+ */
+caddr_t
+eay_sha1_init()
+{
+	SHA_CTX *c = racoon_malloc(sizeof(*c));
+
+	SHA1_Init(c);
+
+	return((caddr_t)c);
+}
+
+void
+eay_sha1_update(c, data)
+	caddr_t c;
+	vchar_t *data;
+{
+	SHA1_Update((SHA_CTX *)c, data->v, data->l);
+
+	return;
+}
+
+vchar_t *
+eay_sha1_final(c)
+	caddr_t c;
+{
+	vchar_t *res;
+
+	if ((res = vmalloc(SHA_DIGEST_LENGTH)) == 0)
+		return(0);
+
+	SHA1_Final((unsigned char *) res->v, (SHA_CTX *)c);
+	(void)racoon_free(c);
+
+	return(res);
+}
+
+vchar_t *
+eay_sha1_one(data)
+	vchar_t *data;
+{
+	caddr_t ctx;
+	vchar_t *res;
+
+	ctx = eay_sha1_init();
+	eay_sha1_update(ctx, data);
+	res = eay_sha1_final(ctx);
+
+	return(res);
+}
+
+int
+eay_sha1_hashlen()
+{
+	return SHA_DIGEST_LENGTH << 3;
+}
+
+/*
+ * MD5 functions
+ */
+caddr_t
+eay_md5_init()
+{
+	MD5_CTX *c = racoon_malloc(sizeof(*c));
+
+	MD5_Init(c);
+
+	return((caddr_t)c);
+}
+
+void
+eay_md5_update(c, data)
+	caddr_t c;
+	vchar_t *data;
+{
+	MD5_Update((MD5_CTX *)c, data->v, data->l);
+
+	return;
+}
+
+vchar_t *
+eay_md5_final(c)
+	caddr_t c;
+{
+	vchar_t *res;
+
+	if ((res = vmalloc(MD5_DIGEST_LENGTH)) == 0)
+		return(0);
+
+	MD5_Final((unsigned char *) res->v, (MD5_CTX *)c);
+	(void)racoon_free(c);
+
+	return(res);
+}
+
+vchar_t *
+eay_md5_one(data)
+	vchar_t *data;
+{
+	caddr_t ctx;
+	vchar_t *res;
+
+	ctx = eay_md5_init();
+	eay_md5_update(ctx, data);
+	res = eay_md5_final(ctx);
+
+	return(res);
+}
+
+int
+eay_md5_hashlen()
+{
+	return MD5_DIGEST_LENGTH << 3;
+}
+
+/*
+ * eay_set_random
+ *   size: number of bytes.
+ */
+vchar_t *
+eay_set_random(size)
+	u_int32_t size;
+{
+	BIGNUM *r = NULL;
+	vchar_t *res = 0;
+
+	if ((r = BN_new()) == NULL)
+		goto end;
+	BN_rand(r, size * 8, 0, 0);
+	eay_bn2v(&res, r);
+
+end:
+	if (r)
+		BN_free(r);
+	return(res);
+}
+
+/* DH */
+int
+eay_dh_generate(prime, g, publen, pub, priv)
+	vchar_t *prime, **pub, **priv;
+	u_int publen;
+	u_int32_t g;
+{
+	BIGNUM *p = NULL;
+	DH *dh = NULL;
+	int error = -1;
+
+	/* initialize */
+	/* pre-process to generate number */
+	if (eay_v2bn(&p, prime) < 0)
+		goto end;
+
+	if ((dh = DH_new()) == NULL)
+		goto end;
+	dh->p = p;
+	p = NULL;	/* p is now part of dh structure */
+	dh->g = NULL;
+	if ((dh->g = BN_new()) == NULL)
+		goto end;
+	if (!BN_set_word(dh->g, g))
+		goto end;
+
+	if (publen != 0)
+		dh->length = publen;
+
+	/* generate public and private number */
+	if (!DH_generate_key(dh))
+		goto end;
+
+	/* copy results to buffers */
+	if (eay_bn2v(pub, dh->pub_key) < 0)
+		goto end;
+	if (eay_bn2v(priv, dh->priv_key) < 0) {
+		vfree(*pub);
+		goto end;
+	}
+
+	error = 0;
+
+end:
+	if (dh != NULL)
+		DH_free(dh);
+	if (p != 0)
+		BN_free(p);
+	return(error);
+}
+
+int
+eay_dh_compute(prime, g, pub, priv, pub2, key)
+	vchar_t *prime, *pub, *priv, *pub2, **key;
+	u_int32_t g;
+{
+	BIGNUM *dh_pub = NULL;
+	DH *dh = NULL;
+	int l;
+	unsigned char *v = NULL;
+	int error = -1;
+
+	/* make public number to compute */
+	if (eay_v2bn(&dh_pub, pub2) < 0)
+		goto end;
+
+	/* make DH structure */
+	if ((dh = DH_new()) == NULL)
+		goto end;
+	if (eay_v2bn(&dh->p, prime) < 0)
+		goto end;
+	if (eay_v2bn(&dh->pub_key, pub) < 0)
+		goto end;
+	if (eay_v2bn(&dh->priv_key, priv) < 0)
+		goto end;
+	dh->length = pub2->l * 8;
+
+	dh->g = NULL;
+	if ((dh->g = BN_new()) == NULL)
+		goto end;
+	if (!BN_set_word(dh->g, g))
+		goto end;
+
+	if ((v = racoon_calloc(prime->l, sizeof(u_char))) == NULL)
+		goto end;
+	if ((l = DH_compute_key(v, dh_pub, dh)) == -1)
+		goto end;
+	memcpy((*key)->v + (prime->l - l), v, l);
+
+	error = 0;
+
+end:
+	if (dh_pub != NULL)
+		BN_free(dh_pub);
+	if (dh != NULL)
+		DH_free(dh);
+	if (v != NULL)
+		racoon_free(v);
+	return(error);
+}
+
+/*
+ * convert vchar_t <-> BIGNUM.
+ *
+ * vchar_t: unit is u_char, network endian, most significant byte first.
+ * BIGNUM: unit is BN_ULONG, each of BN_ULONG is in host endian,
+ *	least significant BN_ULONG must come first.
+ *
+ * hex value of "0x3ffe050104" is represented as follows:
+ *	vchar_t: 3f fe 05 01 04
+ *	BIGNUM (BN_ULONG = u_int8_t): 04 01 05 fe 3f
+ *	BIGNUM (BN_ULONG = u_int16_t): 0x0104 0xfe05 0x003f
+ *	BIGNUM (BN_ULONG = u_int32_t_t): 0xfe050104 0x0000003f
+ */
+int
+eay_v2bn(bn, var)
+	BIGNUM **bn;
+	vchar_t *var;
+{
+	if ((*bn = BN_bin2bn((unsigned char *) var->v, var->l, NULL)) == NULL)
+		return -1;
+
+	return 0;
+}
+
+int
+eay_bn2v(var, bn)
+	vchar_t **var;
+	BIGNUM *bn;
+{
+	*var = vmalloc(bn->top * BN_BYTES);
+	if (*var == NULL)
+		return(-1);
+
+	(*var)->l = BN_bn2bin(bn, (unsigned char *) (*var)->v);
+
+	return 0;
+}
+
+void
+eay_init()
+{
+	OpenSSL_add_all_algorithms();
+	ERR_load_crypto_strings();
+#ifdef HAVE_OPENSSL_ENGINE_H
+	ENGINE_load_builtin_engines();
+	ENGINE_register_all_complete();
+#endif
+}
+
+vchar_t *
+base64_decode(char *in, long inlen)
+{
+	BIO *bio=NULL, *b64=NULL;
+	vchar_t *res = NULL;
+	char *outb;
+	long outlen;
+
+	outb = malloc(inlen * 2);
+	if (outb == NULL)
+		goto out;
+	bio = BIO_new_mem_buf(in, inlen);
+	b64 = BIO_new(BIO_f_base64());
+	BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
+	bio = BIO_push(b64, bio);
+
+	outlen = BIO_read(bio, outb, inlen * 2);
+	if (outlen <= 0) {
+		plog(LLV_ERROR, LOCATION, NULL, "%s\n", eay_strerror());
+		goto out;
+	}
+
+	res = vmalloc(outlen);
+	if (!res)
+		goto out;
+
+	memcpy(res->v, outb, outlen);
+
+out:
+	if (outb)
+		free(outb);
+	if (bio)
+		BIO_free_all(bio);
+
+	return res;
+}
+
+vchar_t *
+base64_encode(char *in, long inlen)
+{
+	BIO *bio=NULL, *b64=NULL;
+	char *ptr;
+	long plen = -1;
+	vchar_t *res = NULL;
+
+	bio = BIO_new(BIO_s_mem());
+	b64 = BIO_new(BIO_f_base64());
+	BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
+	bio = BIO_push(b64, bio);
+
+	BIO_write(bio, in, inlen);
+	BIO_flush(bio);
+
+	plen = BIO_get_mem_data(bio, &ptr);
+	res = vmalloc(plen+1);
+	if (!res)
+		goto out;
+	
+	memcpy (res->v, ptr, plen);
+	res->v[plen] = '\0';
+
+out:	
+	if (bio)
+		BIO_free_all(bio);
+
+	return res;
+}
+
+static RSA *
+binbuf_pubkey2rsa(vchar_t *binbuf)
+{
+	BIGNUM *exp, *mod;
+	RSA *rsa_pub = NULL;
+
+	if (binbuf->v[0] > binbuf->l - 1) {
+		plog(LLV_ERROR, LOCATION, NULL, "Plain RSA pubkey format error: decoded string doesn't make sense.\n");
+		goto out;
+	}
+
+	exp = BN_bin2bn((unsigned char *) (binbuf->v + 1), binbuf->v[0], NULL);
+	mod = BN_bin2bn((unsigned char *) (binbuf->v + binbuf->v[0] + 1), 
+			binbuf->l - binbuf->v[0] - 1, NULL);
+	rsa_pub = RSA_new();
+
+	if (!exp || !mod || !rsa_pub) {
+		plog(LLV_ERROR, LOCATION, NULL, "Plain RSA pubkey parsing error: %s\n", eay_strerror());
+		if (exp)
+			BN_free(exp);
+		if (mod)
+			BN_free(exp);
+		if (rsa_pub)
+			RSA_free(rsa_pub);
+		rsa_pub = NULL;
+		goto out;
+	}
+	
+	rsa_pub->n = mod;
+	rsa_pub->e = exp;
+
+out:
+	return rsa_pub;
+}
+
+RSA *
+base64_pubkey2rsa(char *in)
+{
+	BIGNUM *exp, *mod;
+	RSA *rsa_pub = NULL;
+	vchar_t *binbuf;
+
+	if (strncmp(in, "0s", 2) != 0) {
+		plog(LLV_ERROR, LOCATION, NULL, "Plain RSA pubkey format error: doesn't start with '0s'\n");
+		return NULL;
+	}
+
+	binbuf = base64_decode(in + 2, strlen(in + 2));
+	if (!binbuf) {
+		plog(LLV_ERROR, LOCATION, NULL, "Plain RSA pubkey format error: Base64 decoding failed.\n");
+		return NULL;
+	}
+	
+	if (binbuf->v[0] > binbuf->l - 1) {
+		plog(LLV_ERROR, LOCATION, NULL, "Plain RSA pubkey format error: decoded string doesn't make sense.\n");
+		goto out;
+	}
+
+	rsa_pub = binbuf_pubkey2rsa(binbuf);
+
+out:
+	if (binbuf)
+		vfree(binbuf);
+
+	return rsa_pub;
+}
+
+RSA *
+bignum_pubkey2rsa(BIGNUM *in)
+{
+	RSA *rsa_pub = NULL;
+	vchar_t *binbuf;
+
+	binbuf = vmalloc(BN_num_bytes(in));
+	if (!binbuf) {
+		plog(LLV_ERROR, LOCATION, NULL, "Plain RSA pubkey conversion: memory allocation failed..\n");
+		return NULL;
+	}
+	
+	BN_bn2bin(in, (unsigned char *) binbuf->v);
+
+	rsa_pub = binbuf_pubkey2rsa(binbuf);
+
+out:
+	if (binbuf)
+		vfree(binbuf);
+
+	return rsa_pub;
+}
+
+u_int32_t
+eay_random()
+{
+	u_int32_t result;
+	vchar_t *vrand;
+
+	vrand = eay_set_random(sizeof(result));
+	memcpy(&result, vrand->v, sizeof(result));
+	vfree(vrand);
+
+	return result;
+}
+
+const char *
+eay_version()
+{
+	return SSLeay_version(SSLEAY_VERSION);
+}
diff --git a/src/racoon/crypto_openssl.h b/src/racoon/crypto_openssl.h
new file mode 100644
index 0000000..9a17de8
--- /dev/null
+++ b/src/racoon/crypto_openssl.h
@@ -0,0 +1,234 @@
+/*	$NetBSD: crypto_openssl.h,v 1.5 2006/10/06 12:02:27 manu Exp $	*/
+
+/* Id: crypto_openssl.h,v 1.11 2004/11/13 11:28:01 manubsd Exp */
+
+/*
+ * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _CRYPTO_OPENSSL_H
+#define _CRYPTO_OPENSSL_H
+
+#include "crypto_openssl.h"
+
+#include <openssl/x509v3.h>
+#include <openssl/rsa.h>
+
+#define GENT_OTHERNAME	GEN_OTHERNAME
+#define GENT_EMAIL	GEN_EMAIL
+#define GENT_DNS	GEN_DNS
+#define GENT_X400	GEN_X400
+#define GENT_DIRNAME	GEN_DIRNAME
+#define GENT_EDIPARTY	GEN_EDIPARTY
+#define GENT_URI	GEN_URI
+#define GENT_IPADD	GEN_IPADD
+#define GENT_RID	GEN_RID
+
+extern vchar_t *eay_str2asn1dn __P((const char *, int));
+extern vchar_t *eay_hex2asn1dn __P((const char *, int));
+extern int eay_cmp_asn1dn __P((vchar_t *, vchar_t *));
+extern int eay_check_x509cert __P((vchar_t *, char *, char *, int));
+extern vchar_t *eay_get_x509asn1subjectname __P((vchar_t *));
+extern int eay_get_x509subjectaltname __P((vchar_t *, char **, int *, int));
+extern char *eay_get_x509text __P((vchar_t *));
+extern vchar_t *eay_get_x509cert __P((char *));
+extern vchar_t *eay_get_x509sign __P((vchar_t *, vchar_t *));
+extern int eay_check_x509sign __P((vchar_t *, vchar_t *, vchar_t *));
+
+extern int eay_check_rsasign __P((vchar_t *, vchar_t *, RSA *));
+extern vchar_t *eay_get_rsasign __P((vchar_t *, RSA *));
+
+/* RSA */
+extern vchar_t *eay_rsa_sign __P((vchar_t *, RSA *));
+extern int eay_rsa_verify __P((vchar_t *, vchar_t *, RSA *));
+
+/* ASN.1 */
+extern vchar_t *eay_get_pkcs1privkey __P((char *));
+extern vchar_t *eay_get_pkcs1pubkey __P((char *));
+
+/* string error */
+extern char *eay_strerror __P((void));
+
+/* OpenSSL initialization */
+extern void eay_init __P((void));
+
+/* Generic EVP */
+extern vchar_t *evp_crypt __P((vchar_t *data, vchar_t *key, vchar_t *iv,
+			       const EVP_CIPHER *e, int enc));
+extern int evp_weakkey __P((vchar_t *key, const EVP_CIPHER *e));
+extern int evp_keylen __P((int len, const EVP_CIPHER *e));
+
+/* DES */
+extern vchar_t *eay_des_encrypt __P((vchar_t *, vchar_t *, vchar_t *));
+extern vchar_t *eay_des_decrypt __P((vchar_t *, vchar_t *, vchar_t *));
+extern int eay_des_weakkey __P((vchar_t *));
+extern int eay_des_keylen __P((int));
+
+/* IDEA */
+extern vchar_t *eay_idea_encrypt __P((vchar_t *, vchar_t *, vchar_t *));
+extern vchar_t *eay_idea_decrypt __P((vchar_t *, vchar_t *, vchar_t *));
+extern int eay_idea_weakkey __P((vchar_t *));
+extern int eay_idea_keylen __P((int));
+
+/* blowfish */
+extern vchar_t *eay_bf_encrypt __P((vchar_t *, vchar_t *, vchar_t *));
+extern vchar_t *eay_bf_decrypt __P((vchar_t *, vchar_t *, vchar_t *));
+extern int eay_bf_weakkey __P((vchar_t *));
+extern int eay_bf_keylen __P((int));
+
+/* RC5 */
+extern vchar_t *eay_rc5_encrypt __P((vchar_t *, vchar_t *, vchar_t *));
+extern vchar_t *eay_rc5_decrypt __P((vchar_t *, vchar_t *, vchar_t *));
+extern int eay_rc5_weakkey __P((vchar_t *));
+extern int eay_rc5_keylen __P((int));
+
+/* 3DES */
+extern vchar_t *eay_3des_encrypt __P((vchar_t *, vchar_t *, vchar_t *));
+extern vchar_t *eay_3des_decrypt __P((vchar_t *, vchar_t *, vchar_t *));
+extern int eay_3des_weakkey __P((vchar_t *));
+extern int eay_3des_keylen __P((int));
+
+/* CAST */
+extern vchar_t *eay_cast_encrypt __P((vchar_t *, vchar_t *, vchar_t *));
+extern vchar_t *eay_cast_decrypt __P((vchar_t *, vchar_t *, vchar_t *));
+extern int eay_cast_weakkey __P((vchar_t *));
+extern int eay_cast_keylen __P((int));
+
+/* AES(RIJNDAEL) */
+extern vchar_t *eay_aes_encrypt __P((vchar_t *, vchar_t *, vchar_t *));
+extern vchar_t *eay_aes_decrypt __P((vchar_t *, vchar_t *, vchar_t *));
+extern int eay_aes_weakkey __P((vchar_t *));
+extern int eay_aes_keylen __P((int));
+
+#if defined(HAVE_OPENSSL_CAMELLIA_H)
+/* Camellia */
+extern vchar_t *eay_camellia_encrypt __P((vchar_t *, vchar_t *, vchar_t *));
+extern vchar_t *eay_camellia_decrypt __P((vchar_t *, vchar_t *, vchar_t *));
+extern int eay_camellia_weakkey __P((vchar_t *));
+extern int eay_camellia_keylen __P((int));
+#endif
+
+/* misc */
+extern int eay_null_keylen __P((int));
+extern int eay_null_hashlen __P((void));
+extern int eay_kpdk_hashlen __P((void));
+extern int eay_twofish_keylen __P((int));
+
+/* hash */
+#if defined(WITH_SHA2)
+/* HMAC SHA2 */
+extern vchar_t *eay_hmacsha2_512_one __P((vchar_t *, vchar_t *));
+extern caddr_t eay_hmacsha2_512_init __P((vchar_t *));
+extern void eay_hmacsha2_512_update __P((caddr_t, vchar_t *));
+extern vchar_t *eay_hmacsha2_512_final __P((caddr_t));
+extern vchar_t *eay_hmacsha2_384_one __P((vchar_t *, vchar_t *));
+extern caddr_t eay_hmacsha2_384_init __P((vchar_t *));
+extern void eay_hmacsha2_384_update __P((caddr_t, vchar_t *));
+extern vchar_t *eay_hmacsha2_384_final __P((caddr_t));
+extern vchar_t *eay_hmacsha2_256_one __P((vchar_t *, vchar_t *));
+extern caddr_t eay_hmacsha2_256_init __P((vchar_t *));
+extern void eay_hmacsha2_256_update __P((caddr_t, vchar_t *));
+extern vchar_t *eay_hmacsha2_256_final __P((caddr_t));
+#endif
+/* HMAC SHA1 */
+extern vchar_t *eay_hmacsha1_one __P((vchar_t *, vchar_t *));
+extern caddr_t eay_hmacsha1_init __P((vchar_t *));
+extern void eay_hmacsha1_update __P((caddr_t, vchar_t *));
+extern vchar_t *eay_hmacsha1_final __P((caddr_t));
+/* HMAC MD5 */
+extern vchar_t *eay_hmacmd5_one __P((vchar_t *, vchar_t *));
+extern caddr_t eay_hmacmd5_init __P((vchar_t *));
+extern void eay_hmacmd5_update __P((caddr_t, vchar_t *));
+extern vchar_t *eay_hmacmd5_final __P((caddr_t));
+
+#if defined(WITH_SHA2)
+/* SHA2 functions */
+extern caddr_t eay_sha2_512_init __P((void));
+extern void eay_sha2_512_update __P((caddr_t, vchar_t *));
+extern vchar_t *eay_sha2_512_final __P((caddr_t));
+extern vchar_t *eay_sha2_512_one __P((vchar_t *));
+#endif
+extern int eay_sha2_512_hashlen __P((void));
+
+#if defined(WITH_SHA2)
+extern caddr_t eay_sha2_384_init __P((void));
+extern void eay_sha2_384_update __P((caddr_t, vchar_t *));
+extern vchar_t *eay_sha2_384_final __P((caddr_t));
+extern vchar_t *eay_sha2_384_one __P((vchar_t *));
+#endif
+extern int eay_sha2_384_hashlen __P((void));
+
+#if defined(WITH_SHA2)
+extern caddr_t eay_sha2_256_init __P((void));
+extern void eay_sha2_256_update __P((caddr_t, vchar_t *));
+extern vchar_t *eay_sha2_256_final __P((caddr_t));
+extern vchar_t *eay_sha2_256_one __P((vchar_t *));
+#endif
+extern int eay_sha2_256_hashlen __P((void));
+
+/* SHA functions */
+extern caddr_t eay_sha1_init __P((void));
+extern void eay_sha1_update __P((caddr_t, vchar_t *));
+extern vchar_t *eay_sha1_final __P((caddr_t));
+extern vchar_t *eay_sha1_one __P((vchar_t *));
+extern int eay_sha1_hashlen __P((void));
+
+/* MD5 functions */
+extern caddr_t eay_md5_init __P((void));
+extern void eay_md5_update __P((caddr_t, vchar_t *));
+extern vchar_t *eay_md5_final __P((caddr_t));
+extern vchar_t *eay_md5_one __P((vchar_t *));
+extern int eay_md5_hashlen __P((void));
+
+/* RNG */
+extern vchar_t *eay_set_random __P((u_int32_t));
+extern u_int32_t eay_random __P((void));
+
+/* DH */
+extern int eay_dh_generate __P((vchar_t *, u_int32_t, u_int, vchar_t **, vchar_t **));
+extern int eay_dh_compute __P((vchar_t *, u_int32_t, vchar_t *, vchar_t *, vchar_t *, vchar_t **));
+
+/* Base 64 */
+vchar_t *base64_encode(char *in, long inlen);
+vchar_t *base64_decode(char *in, long inlen);
+
+RSA *base64_pubkey2rsa(char *in);
+RSA *bignum_pubkey2rsa(BIGNUM *in);
+
+/* misc */
+extern int eay_revbnl __P((vchar_t *));
+#include <openssl/bn.h>
+extern int eay_v2bn __P((BIGNUM **, vchar_t *));
+extern int eay_bn2v __P((vchar_t **, BIGNUM *));
+
+extern const char *eay_version __P((void));
+
+#define CBC_BLOCKLEN 8
+#define IPSEC_ENCRYPTKEYLEN 8
+
+#endif /* _CRYPTO_OPENSSL_H */
diff --git a/src/racoon/debug.h b/src/racoon/debug.h
new file mode 100644
index 0000000..47c2641
--- /dev/null
+++ b/src/racoon/debug.h
@@ -0,0 +1,41 @@
+/*	$NetBSD: debug.h,v 1.4 2006/09/09 16:22:09 manu Exp $	*/
+
+/* Id: debug.h,v 1.3 2004/06/11 16:00:16 ludvigm Exp */
+
+/*
+ * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _DEBUG_H
+#define _DEBUG_H
+
+/* define by main.c */
+extern int f_local;
+extern int vflag;
+
+#endif /* _DEBUG_H */
diff --git a/src/racoon/debugrm.h b/src/racoon/debugrm.h
new file mode 100644
index 0000000..6a2f411
--- /dev/null
+++ b/src/racoon/debugrm.h
@@ -0,0 +1,102 @@
+/*	$NetBSD: debugrm.h,v 1.4 2006/09/09 16:22:09 manu Exp $	*/
+
+/* Id: debugrm.h,v 1.4 2006/04/06 14:00:06 manubsd Exp */
+
+/*
+ * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _DEBUGRM_H
+#define _DEBUGRM_H
+
+#define DRMDUMPFILE	"/var/tmp/debugrm.dump"
+
+#ifdef NONEED_DRM
+#ifndef racoon_malloc
+#define	racoon_malloc(sz)	malloc((sz))
+#endif
+#ifndef racoon_calloc
+#define	racoon_calloc(cnt, sz)	calloc((cnt), (sz))
+#endif
+#ifndef racoon_realloc
+#define	racoon_realloc(old, sz)	realloc((old), (sz))
+#endif
+#ifndef racoon_free
+#define	racoon_free(p)		free((p))
+#endif
+#ifndef racoon_strdup
+#define	racoon_strdup(p)	strdup((p))
+#endif
+#else /*!NONEED_DRM*/
+#ifndef racoon_malloc
+#define	racoon_malloc(sz)	\
+	DRM_malloc(__FILE__, __LINE__, __func__, (sz))
+#endif
+#ifndef racoon_calloc
+#define	racoon_calloc(cnt, sz)	\
+	DRM_calloc(__FILE__, __LINE__, __func__, (cnt), (sz))
+#endif
+#ifndef racoon_realloc
+#define	racoon_realloc(old, sz)	\
+	DRM_realloc(__FILE__, __LINE__, __func__, (old), (sz))
+#endif
+#ifndef racoon_free
+#define	racoon_free(p)		\
+	DRM_free(__FILE__, __LINE__, __func__, (p))
+#endif
+#ifndef racoon_strdup
+#define	racoon_strdup(p)	\
+	DRM_strdup(__FILE__, __LINE__, __func__, (p))
+#endif
+#endif /*NONEED_DRM*/
+
+extern void DRM_init __P((void));
+extern void DRM_dump __P((void));
+extern void *DRM_malloc __P((char *, int, char *, size_t));
+extern void *DRM_calloc __P((char *, int, char *, size_t, size_t));
+extern void *DRM_realloc __P((char *, int, char *, void *, size_t));
+extern void DRM_free __P((char *, int, char *, void *));
+extern char *DRM_strdup __P((char *, int, char *, const char *));
+
+#ifndef NONEED_DRM
+#define	vmalloc(sz)	\
+	DRM_vmalloc(__FILE__, __LINE__, __func__, (sz))
+#define	vdup(old)	\
+	DRM_vdup(__FILE__, __LINE__, __func__, (old))
+#define	vrealloc(old, sz)	\
+	DRM_vrealloc(__FILE__, __LINE__, __func__, (old), (sz))
+#define	vfree(p)		\
+	DRM_vfree(__FILE__, __LINE__, __func__, (p))
+#endif
+
+extern void *DRM_vmalloc __P((char *, int, char *, size_t));
+extern void *DRM_vrealloc __P((char *, int, char *, void *, size_t));
+extern void DRM_vfree __P((char *, int, char *, void *));
+extern void *DRM_vdup __P((char *, int, char *, void *));
+
+#endif /* _DEBUGRM_H */
diff --git a/src/racoon/dhgroup.h b/src/racoon/dhgroup.h
new file mode 100644
index 0000000..54d7eeb
--- /dev/null
+++ b/src/racoon/dhgroup.h
@@ -0,0 +1,205 @@
+/*	$NetBSD: dhgroup.h,v 1.4 2006/09/09 16:22:09 manu Exp $	*/
+
+/* Id: dhgroup.h,v 1.3 2004/06/11 16:00:16 ludvigm Exp */
+
+/*
+ * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _DHGROUP_H
+#define _DHGROUP_H
+
+#define OAKLEY_PRIME_MODP768 \
+	"FFFFFFFF FFFFFFFF C90FDAA2 2168C234 C4C6628B 80DC1CD1" \
+	"29024E08 8A67CC74 020BBEA6 3B139B22 514A0879 8E3404DD" \
+	"EF9519B3 CD3A431B 302B0A6D F25F1437 4FE1356D 6D51C245" \
+	"E485B576 625E7EC6 F44C42E9 A63A3620 FFFFFFFF FFFFFFFF"
+
+#define OAKLEY_PRIME_MODP1024 \
+	"FFFFFFFF FFFFFFFF C90FDAA2 2168C234 C4C6628B 80DC1CD1" \
+	"29024E08 8A67CC74 020BBEA6 3B139B22 514A0879 8E3404DD" \
+	"EF9519B3 CD3A431B 302B0A6D F25F1437 4FE1356D 6D51C245" \
+	"E485B576 625E7EC6 F44C42E9 A637ED6B 0BFF5CB6 F406B7ED" \
+	"EE386BFB 5A899FA5 AE9F2411 7C4B1FE6 49286651 ECE65381" \
+	"FFFFFFFF FFFFFFFF"
+
+#define OAKLEY_PRIME_MODP1536 \
+	"FFFFFFFF FFFFFFFF C90FDAA2 2168C234 C4C6628B 80DC1CD1" \
+	"29024E08 8A67CC74 020BBEA6 3B139B22 514A0879 8E3404DD" \
+	"EF9519B3 CD3A431B 302B0A6D F25F1437 4FE1356D 6D51C245" \
+	"E485B576 625E7EC6 F44C42E9 A637ED6B 0BFF5CB6 F406B7ED" \
+	"EE386BFB 5A899FA5 AE9F2411 7C4B1FE6 49286651 ECE45B3D" \
+	"C2007CB8 A163BF05 98DA4836 1C55D39A 69163FA8 FD24CF5F" \
+	"83655D23 DCA3AD96 1C62F356 208552BB 9ED52907 7096966D" \
+	"670C354E 4ABC9804 F1746C08 CA237327 FFFFFFFF FFFFFFFF"
+
+/* RFC 3526 */
+#define OAKLEY_PRIME_MODP2048 \
+	"FFFFFFFF FFFFFFFF C90FDAA2 2168C234 C4C6628B 80DC1CD1" \
+	"29024E08 8A67CC74 020BBEA6 3B139B22 514A0879 8E3404DD" \
+	"EF9519B3 CD3A431B 302B0A6D F25F1437 4FE1356D 6D51C245" \
+	"E485B576 625E7EC6 F44C42E9 A637ED6B 0BFF5CB6 F406B7ED" \
+	"EE386BFB 5A899FA5 AE9F2411 7C4B1FE6 49286651 ECE45B3D" \
+	"C2007CB8 A163BF05 98DA4836 1C55D39A 69163FA8 FD24CF5F" \
+	"83655D23 DCA3AD96 1C62F356 208552BB 9ED52907 7096966D" \
+	"670C354E 4ABC9804 F1746C08 CA18217C 32905E46 2E36CE3B" \
+	"E39E772C 180E8603 9B2783A2 EC07A28F B5C55DF0 6F4C52C9" \
+	"DE2BCBF6 95581718 3995497C EA956AE5 15D22618 98FA0510" \
+	"15728E5A 8AACAA68 FFFFFFFF FFFFFFFF"
+
+#define OAKLEY_PRIME_MODP3072 \
+	"FFFFFFFF FFFFFFFF C90FDAA2 2168C234 C4C6628B 80DC1CD1" \
+	"29024E08 8A67CC74 020BBEA6 3B139B22 514A0879 8E3404DD" \
+	"EF9519B3 CD3A431B 302B0A6D F25F1437 4FE1356D 6D51C245" \
+	"E485B576 625E7EC6 F44C42E9 A637ED6B 0BFF5CB6 F406B7ED" \
+	"EE386BFB 5A899FA5 AE9F2411 7C4B1FE6 49286651 ECE45B3D" \
+	"C2007CB8 A163BF05 98DA4836 1C55D39A 69163FA8 FD24CF5F" \
+	"83655D23 DCA3AD96 1C62F356 208552BB 9ED52907 7096966D" \
+	"670C354E 4ABC9804 F1746C08 CA18217C 32905E46 2E36CE3B" \
+	"E39E772C 180E8603 9B2783A2 EC07A28F B5C55DF0 6F4C52C9" \
+	"DE2BCBF6 95581718 3995497C EA956AE5 15D22618 98FA0510" \
+	"15728E5A 8AAAC42D AD33170D 04507A33 A85521AB DF1CBA64" \
+	"ECFB8504 58DBEF0A 8AEA7157 5D060C7D B3970F85 A6E1E4C7" \
+	"ABF5AE8C DB0933D7 1E8C94E0 4A25619D CEE3D226 1AD2EE6B" \
+	"F12FFA06 D98A0864 D8760273 3EC86A64 521F2B18 177B200C" \
+	"BBE11757 7A615D6C 770988C0 BAD946E2 08E24FA0 74E5AB31" \
+	"43DB5BFC E0FD108E 4B82D120 A93AD2CA FFFFFFFF FFFFFFFF"
+
+#define OAKLEY_PRIME_MODP4096 \
+	"FFFFFFFF FFFFFFFF C90FDAA2 2168C234 C4C6628B 80DC1CD1" \
+	"29024E08 8A67CC74 020BBEA6 3B139B22 514A0879 8E3404DD" \
+	"EF9519B3 CD3A431B 302B0A6D F25F1437 4FE1356D 6D51C245" \
+	"E485B576 625E7EC6 F44C42E9 A637ED6B 0BFF5CB6 F406B7ED" \
+	"EE386BFB 5A899FA5 AE9F2411 7C4B1FE6 49286651 ECE45B3D" \
+	"C2007CB8 A163BF05 98DA4836 1C55D39A 69163FA8 FD24CF5F" \
+	"83655D23 DCA3AD96 1C62F356 208552BB 9ED52907 7096966D" \
+	"670C354E 4ABC9804 F1746C08 CA18217C 32905E46 2E36CE3B" \
+	"E39E772C 180E8603 9B2783A2 EC07A28F B5C55DF0 6F4C52C9" \
+	"DE2BCBF6 95581718 3995497C EA956AE5 15D22618 98FA0510" \
+	"15728E5A 8AAAC42D AD33170D 04507A33 A85521AB DF1CBA64" \
+	"ECFB8504 58DBEF0A 8AEA7157 5D060C7D B3970F85 A6E1E4C7" \
+	"ABF5AE8C DB0933D7 1E8C94E0 4A25619D CEE3D226 1AD2EE6B" \
+	"F12FFA06 D98A0864 D8760273 3EC86A64 521F2B18 177B200C" \
+	"BBE11757 7A615D6C 770988C0 BAD946E2 08E24FA0 74E5AB31" \
+	"43DB5BFC E0FD108E 4B82D120 A9210801 1A723C12 A787E6D7" \
+	"88719A10 BDBA5B26 99C32718 6AF4E23C 1A946834 B6150BDA" \
+	"2583E9CA 2AD44CE8 DBBBC2DB 04DE8EF9 2E8EFC14 1FBECAA6" \
+	"287C5947 4E6BC05D 99B2964F A090C3A2 233BA186 515BE7ED" \
+	"1F612970 CEE2D7AF B81BDD76 2170481C D0069127 D5B05AA9" \
+	"93B4EA98 8D8FDDC1 86FFB7DC 90A6C08F 4DF435C9 34063199" \
+	"FFFFFFFF FFFFFFFF"
+
+#define OAKLEY_PRIME_MODP6144 \
+	"FFFFFFFF FFFFFFFF C90FDAA2 2168C234 C4C6628B 80DC1CD1" \
+	"29024E08 8A67CC74 020BBEA6 3B139B22 514A0879 8E3404DD" \
+	"EF9519B3 CD3A431B 302B0A6D F25F1437 4FE1356D 6D51C245" \
+	"E485B576 625E7EC6 F44C42E9 A637ED6B 0BFF5CB6 F406B7ED" \
+	"EE386BFB 5A899FA5 AE9F2411 7C4B1FE6 49286651 ECE45B3D" \
+	"C2007CB8 A163BF05 98DA4836 1C55D39A 69163FA8 FD24CF5F" \
+	"83655D23 DCA3AD96 1C62F356 208552BB 9ED52907 7096966D" \
+	"670C354E 4ABC9804 F1746C08 CA18217C 32905E46 2E36CE3B" \
+	"E39E772C 180E8603 9B2783A2 EC07A28F B5C55DF0 6F4C52C9" \
+	"DE2BCBF6 95581718 3995497C EA956AE5 15D22618 98FA0510" \
+	"15728E5A 8AAAC42D AD33170D 04507A33 A85521AB DF1CBA64" \
+	"ECFB8504 58DBEF0A 8AEA7157 5D060C7D B3970F85 A6E1E4C7" \
+	"ABF5AE8C DB0933D7 1E8C94E0 4A25619D CEE3D226 1AD2EE6B" \
+	"F12FFA06 D98A0864 D8760273 3EC86A64 521F2B18 177B200C" \
+	"BBE11757 7A615D6C 770988C0 BAD946E2 08E24FA0 74E5AB31" \
+	"43DB5BFC E0FD108E 4B82D120 A9210801 1A723C12 A787E6D7" \
+	"88719A10 BDBA5B26 99C32718 6AF4E23C 1A946834 B6150BDA" \
+	"2583E9CA 2AD44CE8 DBBBC2DB 04DE8EF9 2E8EFC14 1FBECAA6" \
+	"287C5947 4E6BC05D 99B2964F A090C3A2 233BA186 515BE7ED" \
+	"1F612970 CEE2D7AF B81BDD76 2170481C D0069127 D5B05AA9" \
+	"93B4EA98 8D8FDDC1 86FFB7DC 90A6C08F 4DF435C9 34028492" \
+	"36C3FAB4 D27C7026 C1D4DCB2 602646DE C9751E76 3DBA37BD" \
+	"F8FF9406 AD9E530E E5DB382F 413001AE B06A53ED 9027D831" \
+	"179727B0 865A8918 DA3EDBEB CF9B14ED 44CE6CBA CED4BB1B" \
+	"DB7F1447 E6CC254B 33205151 2BD7AF42 6FB8F401 378CD2BF" \
+	"5983CA01 C64B92EC F032EA15 D1721D03 F482D7CE 6E74FEF6" \
+	"D55E702F 46980C82 B5A84031 900B1C9E 59E7C97F BEC7E8F3" \
+	"23A97A7E 36CC88BE 0F1D45B7 FF585AC5 4BD407B2 2B4154AA" \
+	"CC8F6D7E BF48E1D8 14CC5ED2 0F8037E0 A79715EE F29BE328" \
+	"06A1D58B B7C5DA76 F550AA3D 8A1FBFF0 EB19CCB1 A313D55C" \
+	"DA56C9EC 2EF29632 387FE8D7 6E3C0468 043E8F66 3F4860EE" \
+	"12BF2D5B 0B7474D6 E694F91E 6DCC4024 FFFFFFFF FFFFFFFF"
+
+#define OAKLEY_PRIME_MODP8192 \
+	"FFFFFFFF FFFFFFFF C90FDAA2 2168C234 C4C6628B 80DC1CD1" \
+	"29024E08 8A67CC74 020BBEA6 3B139B22 514A0879 8E3404DD" \
+	"EF9519B3 CD3A431B 302B0A6D F25F1437 4FE1356D 6D51C245" \
+	"E485B576 625E7EC6 F44C42E9 A637ED6B 0BFF5CB6 F406B7ED" \
+	"EE386BFB 5A899FA5 AE9F2411 7C4B1FE6 49286651 ECE45B3D" \
+	"C2007CB8 A163BF05 98DA4836 1C55D39A 69163FA8 FD24CF5F" \
+	"83655D23 DCA3AD96 1C62F356 208552BB 9ED52907 7096966D" \
+	"670C354E 4ABC9804 F1746C08 CA18217C 32905E46 2E36CE3B" \
+	"E39E772C 180E8603 9B2783A2 EC07A28F B5C55DF0 6F4C52C9" \
+	"DE2BCBF6 95581718 3995497C EA956AE5 15D22618 98FA0510" \
+	"15728E5A 8AAAC42D AD33170D 04507A33 A85521AB DF1CBA64" \
+	"ECFB8504 58DBEF0A 8AEA7157 5D060C7D B3970F85 A6E1E4C7" \
+	"ABF5AE8C DB0933D7 1E8C94E0 4A25619D CEE3D226 1AD2EE6B" \
+	"F12FFA06 D98A0864 D8760273 3EC86A64 521F2B18 177B200C" \
+	"BBE11757 7A615D6C 770988C0 BAD946E2 08E24FA0 74E5AB31" \
+	"43DB5BFC E0FD108E 4B82D120 A9210801 1A723C12 A787E6D7" \
+	"88719A10 BDBA5B26 99C32718 6AF4E23C 1A946834 B6150BDA" \
+	"2583E9CA 2AD44CE8 DBBBC2DB 04DE8EF9 2E8EFC14 1FBECAA6" \
+	"287C5947 4E6BC05D 99B2964F A090C3A2 233BA186 515BE7ED" \
+	"1F612970 CEE2D7AF B81BDD76 2170481C D0069127 D5B05AA9" \
+	"93B4EA98 8D8FDDC1 86FFB7DC 90A6C08F 4DF435C9 34028492" \
+	"36C3FAB4 D27C7026 C1D4DCB2 602646DE C9751E76 3DBA37BD" \
+	"F8FF9406 AD9E530E E5DB382F 413001AE B06A53ED 9027D831" \
+	"179727B0 865A8918 DA3EDBEB CF9B14ED 44CE6CBA CED4BB1B" \
+	"DB7F1447 E6CC254B 33205151 2BD7AF42 6FB8F401 378CD2BF" \
+	"5983CA01 C64B92EC F032EA15 D1721D03 F482D7CE 6E74FEF6" \
+	"D55E702F 46980C82 B5A84031 900B1C9E 59E7C97F BEC7E8F3" \
+	"23A97A7E 36CC88BE 0F1D45B7 FF585AC5 4BD407B2 2B4154AA" \
+	"CC8F6D7E BF48E1D8 14CC5ED2 0F8037E0 A79715EE F29BE328" \
+	"06A1D58B B7C5DA76 F550AA3D 8A1FBFF0 EB19CCB1 A313D55C" \
+	"DA56C9EC 2EF29632 387FE8D7 6E3C0468 043E8F66 3F4860EE" \
+	"12BF2D5B 0B7474D6 E694F91E 6DBE1159 74A3926F 12FEE5E4" \
+	"38777CB6 A932DF8C D8BEC4D0 73B931BA 3BC832B6 8D9DD300" \
+	"741FA7BF 8AFC47ED 2576F693 6BA42466 3AAB639C 5AE4F568" \
+	"3423B474 2BF1C978 238F16CB E39D652D E3FDB8BE FC848AD9" \
+	"22222E04 A4037C07 13EB57A8 1A23F0C7 3473FC64 6CEA306B" \
+	"4BCBC886 2F8385DD FA9D4B7F A2C087E8 79683303 ED5BDD3A" \
+	"062B3CF5 B3A278A6 6D2A13F8 3F44F82D DF310EE0 74AB6A36" \
+	"4597E899 A0255DC1 64F31CC5 0846851D F9AB4819 5DED7EA1" \
+	"B1D510BD 7EE74D73 FAF36BC3 1ECFA268 359046F4 EB879F92" \
+	"4009438B 481C6CD7 889A002E D5EE382B C9190DA6 FC026E47" \
+	"9558E447 5677E9AA 9E3050E2 765694DF C81F56E8 80B96E71" \
+	"60C980DD 98EDD3DF FFFFFFFF FFFFFFFF"
+
+extern struct dhgroup dh_modp768;
+extern struct dhgroup dh_modp1024;
+extern struct dhgroup dh_modp1536;
+extern struct dhgroup dh_modp2048;
+extern struct dhgroup dh_modp3072;
+extern struct dhgroup dh_modp4096;
+extern struct dhgroup dh_modp6144;
+extern struct dhgroup dh_modp8192;
+
+#endif /* _DHGROUP_H */
diff --git a/src/racoon/dnssec.c b/src/racoon/dnssec.c
new file mode 100644
index 0000000..1fc0bd1
--- /dev/null
+++ b/src/racoon/dnssec.c
@@ -0,0 +1,154 @@
+/*	$NetBSD: dnssec.c,v 1.4 2006/09/09 16:22:09 manu Exp $	*/
+
+/*	$KAME: dnssec.c,v 1.2 2001/08/05 18:46:07 itojun Exp $	*/
+
+/*
+ * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "var.h"
+#include "vmbuf.h"
+#include "misc.h"
+#include "plog.h"
+#include "debug.h"
+
+#include "isakmp_var.h"
+#include "isakmp.h"
+#include "ipsec_doi.h"
+#include "oakley.h"
+#include "netdb_dnssec.h"
+#include "strnames.h"
+#include "dnssec.h"
+#include "gcmalloc.h"
+
+extern int h_errno;
+
+cert_t *
+dnssec_getcert(id)
+	vchar_t *id;
+{
+	cert_t *cert = NULL;
+	struct certinfo *res = NULL;
+	struct ipsecdoi_id_b *id_b;
+	int type;
+	char *name = NULL;
+	int namelen;
+	int error;
+
+	id_b = (struct ipsecdoi_id_b *)id->v;
+
+	namelen = id->l - sizeof(*id_b);
+	name = racoon_malloc(namelen + 1);
+	if (!name) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"failed to get buffer.\n");
+		return NULL;
+	}
+	memcpy(name, id_b + 1, namelen);
+	name[namelen] = '\0';
+
+	switch (id_b->type) {
+	case IPSECDOI_ID_FQDN:
+		error = getcertsbyname(name, &res);
+		if (error != 0) {
+			plog(LLV_ERROR, LOCATION, NULL,
+				"getcertsbyname(\"%s\") failed.\n", name);
+			goto err;
+		}
+		break;
+	case IPSECDOI_ID_IPV4_ADDR:
+	case IPSECDOI_ID_IPV6_ADDR:
+		/* XXX should be processed to query PTR ? */
+	default:
+		plog(LLV_ERROR, LOCATION, NULL,
+			"inpropper ID type passed %s "
+			"though getcert method is dnssec.\n",
+			s_ipsecdoi_ident(id_b->type));
+		goto err;
+	}
+
+	/* check response */
+	if (res->ci_next != NULL) {
+		plog(LLV_WARNING, LOCATION, NULL,
+			"not supported multiple CERT RR.\n");
+	}
+	switch (res->ci_type) {
+	case DNSSEC_TYPE_PKIX:
+		/* XXX is it enough condition to set this type ? */
+		type = ISAKMP_CERT_X509SIGN;
+		break;
+	default:
+		plog(LLV_ERROR, LOCATION, NULL,
+			"not supported CERT RR type %d.\n", res->ci_type);
+		goto err;
+	}
+
+	/* create cert holder */
+	cert = oakley_newcert();
+	if (cert == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"failed to get cert buffer.\n");
+		goto err;
+	}
+	cert->pl = vmalloc(res->ci_certlen + 1);
+	if (cert->pl == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"failed to get cert buffer.\n");
+		goto err;
+	}
+	memcpy(cert->pl->v + 1, res->ci_cert, res->ci_certlen);
+	cert->pl->v[0] = type;
+	cert->cert.v = cert->pl->v + 1;
+	cert->cert.l = cert->pl->l - 1;
+
+	plog(LLV_DEBUG, LOCATION, NULL, "created CERT payload:\n");
+	plogdump(LLV_DEBUG, cert->pl->v, cert->pl->l);
+
+end:
+	if (res)
+		freecertinfo(res);
+
+	return cert;
+
+err:
+	if (name)
+		racoon_free(name);
+	if (cert) {
+		oakley_delcert(cert);
+		cert = NULL;
+	}
+
+	goto end;
+}
diff --git a/src/racoon/dnssec.h b/src/racoon/dnssec.h
new file mode 100644
index 0000000..fb1c931
--- /dev/null
+++ b/src/racoon/dnssec.h
@@ -0,0 +1,39 @@
+/*	$NetBSD: dnssec.h,v 1.4 2006/09/09 16:22:09 manu Exp $	*/
+
+/* Id: dnssec.h,v 1.3 2004/06/11 16:00:16 ludvigm Exp */
+
+/*
+ * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _DNSSEC_H
+#define _DNSSEC_H
+
+extern cert_t *dnssec_getcert __P((vchar_t *));
+
+#endif /* _DNSSEC_H */
diff --git a/src/racoon/doc/FAQ b/src/racoon/doc/FAQ
new file mode 100644
index 0000000..0ab49f0
--- /dev/null
+++ b/src/racoon/doc/FAQ
@@ -0,0 +1,114 @@
+This document is derived from the KAME racoon FAQ. Some answers do not
+apply to ipsec-tools (they are obsolete or not up to date). They are
+tagged [KAME]
+
+Q: With what other IKE/IPsec implementation racoon is known to be interoperable?
+
+A: [KAME]
+	See "IMPLEMENTATION" document supplied with KAME kit, or:
+	http://www.kame.net/dev/cvsweb.cgi/kame/IMPLEMENTATION
+	As we have tested/got test reports in the past, and our end and
+	the other end may have changed their implemenations, we are not sure
+	if we can interoperate with them today (we hope them to interoperate,
+	but we are not sure).
+	Also note that, IKE interoperability highly depends on configuration
+	on both ends.  You must configure both ends exactly the same.
+
+Q: How can I make racoon interoperate with <IKE/IPsec implementation>?
+
+A:
+	Configure both ends exactly the same.  With just a tiny little
+	differnce, you will be in trouble.
+
+Q: How to build racoon on my platform?
+
+A: 
+	As usual: configure && make && make install
+	ipsec-tools is also available as a package in the NetBSD pkgsrc
+
+Q: Describe me the options to "configure".
+
+A:
+	--enable-adminport:
+		Lets racoon to listen to racoon admin port, which is to
+		be contacted by racoonctl(8).
+	--enable-natt:
+		Enable NAT-Traversal. This needs kernel support, which is
+		available on Linux. On NetBSD, NAT-Traversal kernel support
+		has not been integrated yet, you can get it from here:
+		http://ipsec-tools.sourceforge.net/netbsd_nat-t.diff
+		If you live in a country where software patents are legal,
+		using NAT-Traversal might infringe a patent. 
+	--enable-broken-natt:
+		When ipsec-tools is built with --enable-natt, racoon 
+		sets IKE ports in SAD and SPD so that the kernel is 
+		able to ditinguish peers hidden behind the same NAT.
+		Some kernel will not cope with that ports. Use that
+		option to force the ports to 0 in SAD ans SPD. Of 
+		course this means that you cannot have multiple peers
+		behind the same NAT.
+	--enable-frag:
+		Enable IKE fragmentation, which is a workaround for 
+		broken routers that drop fragmented packets
+	--enable-hybrid:
+		Enable hybrid authentication, and ISAKMP mode config and
+		Xauth as well. Note that plain Xauth (without hybrid auth)
+		is not implemented.
+	--with-libradius:
+		Enable the use of RADIUS with hybrid authentication on the
+		server side. RADIUS is used for authentication, configuration
+		and accounting.
+	--with-libpam:
+		Enable the use of PAM with hybrid authentication on the 
+		server side. PAM can be used for authentication and accounting.
+	--enable-gssapi:
+		Enable GSS-API, for Kerberos V support.
+	--enable-stats:	
+		Enable statistics logging function.
+	--enable-samode-unspec:	
+		Enable to use unspecified a mode of SA.
+	--enable-ipv6:
+		Enable IPv6 support.
+	--with-kernel-headers:
+		Supply the location of Linux kernel headers.
+	--with-readline:
+		Support readline input (yes by default).
+	--with-openssl:
+		Specify OpenSSL directory.
+	--sysconfdir:
+		Where racoon config file goes. Default is /etc, which means
+		that racoon will look for /etc/racoon.conf
+	--localstatedir:
+		Where is the directory where racoon stores the control socket
+		(when using --enable-adminport). Default is /var, which 
+		means racoon will use /var/racoon/racoon.sock
+	--prefix:
+		Where racoon gets installed. 
+
+Q: How can I get help?
+
+A: 
+	Always identify your operating system platforms, the versions you are
+	using (like "ipsec-tools-0.5"), and information to repeat the
+	problem.  The more revelant information you supply, the better your 
+	chances of getting help are. Useful informations include, depending
+	of the problem: 
+	- version identification
+	- trace from racoon, taken by "racoon -d 0xffffffff"
+		(maximum debug level)
+	- configuration file you are using
+	- probabaly, tcpdump trace
+	http://orange.kame.net/dev/send-pr.html has the guideline.
+
+	If your question is not confidential, send your questions to:
+	<ipsec-tools-devel@lists.sourceforge.net>
+
+	If your question is confidential, send your questions to:
+	<ipsec-tools-core@lists.sourceforge.net>
+
+Q: Other documents to look at?
+
+A:
+	http://www.netbsd.org/Documentation/network/ipsec/
+	http://www.kame.net/
+	http://www.kame.net/newsletter/
diff --git a/src/racoon/doc/README.certificate b/src/racoon/doc/README.certificate
new file mode 100644
index 0000000..a8bbfa2
--- /dev/null
+++ b/src/racoon/doc/README.certificate
@@ -0,0 +1 @@
+See http://www.kame.net/newsletter/20001119b/
diff --git a/src/racoon/doc/README.gssapi b/src/racoon/doc/README.gssapi
new file mode 100644
index 0000000..9cb3fbb
--- /dev/null
+++ b/src/racoon/doc/README.gssapi
@@ -0,0 +1,106 @@
+The gss-api authentication mechanism implementation for racoon was
+based on the ietf draft draft-ietf-ipsec-isakmp-gss-auth-06.txt.
+
+The implementation uses the Heimdal gss-api library, i.e. gss-api
+on top of Kerberos 5. The Heimdal gss-api library had to be modified
+to meet the requirements of using gss-api in a daemon. More specifically,
+the gss_acquire_cred() call did not work for other cases than
+GSS_C_NO_CREDENTIAL ("use default creds"). Daemons are often started
+as root, and have no Kerberos 5 credentials, so racoon explicitly
+needs to acquire its credentials. The usual method (already used
+by login authentication daemons) in these situations is to add
+a set of special credentials to be used. For example, authentication
+by daemons concerned with login credentials, uses 'host/fqdn' as
+its credential, where fqdn is the hostname on the interface that
+is being used. These special credentials need to be extracted into
+a local keytab from the kdc. The default value used in racoon
+is 'ike/fqdn', but it can be overridden in the racoon config file.
+
+The modification to the Heimdal gss-api library implements the
+mechanism above. If a credential other than GSS_C_NO_CREDENTIAL
+is specified to gss_acquire_cred(), it first looks in the default
+credential cache if it its principal matches the desired credential.
+If not, it extracts it from the default keytab file, and stores
+it in a memory-based credential cache, part of the gss credential
+structure.
+
+
+
+The modifcations to racoon itself are as follows:
+
+	* The racoon.conf config file accepts a new keyword, "gssapi_id",
+	  to be used inside a proposal specification. It specifies
+	  a string (a Kerberos 5 principal in this case), specifying the
+	  credential that racoon will try to acquire. The default value
+	  is 'ike/fqdn', where fqdn is the hostname for the interface
+	  being used for the exchange. If the id is not specified, no
+	  GSS endpoint attribute will be specified in the first SA sent.
+	  However, if the initiator does specify a GSS endpoint attribute,
+	  racoon will always respond with its own GSS endpoint name
+	  in the SA (the default one if not specified by this option).
+
+	* The racoon.conf file accepts "gssapi_krb" as authentication
+	  method inside a proposal specification. The number used
+	  for this method is 65001, which is a temporary number as
+	  specified in the draft.
+
+	* The cftoken.l and cfparse.y source files were modified to
+	  pick up the configuration options. The original sources
+	  stored algorithms in bitmask, which unfortunately meant
+	  that the maximum value was 32, clearly not enough for 65001.
+	  After consulting with the author (sakane@kame.net), it turned
+	  out that method was a leftover, and no longer needed. I replaced
+	  it with plain integers.
+
+	* The gss-api specific code was concentrated as much as possible
+	  in gssapi.c and gssapi.h. The code to call functions defined
+	  in these files is conditional on HAVE_GSSAPI, except for the
+	  config scan code. Specifying this flag on the compiler commandline
+	  is conditional on the --enable-gssapi option to the configure
+	  script.
+
+	* Racoon seems to want to send accepted SA proposals back to
+	  the initiator in a verbatim fashion, leaving no room to
+	  insert the (variable-length) GSS endpoint name attribute.
+	  I worked around this by re-assembling the extracted SA
+	  into a new SA if the gssapi_krb method is used, and the
+	  initiator sent the name attribute. This scheme should
+	  possibly be re-examined by the racoon maintainers, storing
+	  the SAs (the transformations, to be more precise) in a different
+	  fashion to allow for variable-length attributes to be
+	  re-inserted would be a good change, but I considered it to be
+	  beyond the scope of this project.
+
+	* The various state functions for aggressive and main mode
+	  (in isakmp_agg.c and isakmp_ident.c respectively) were
+	  changed to conditionally change their behavior if the
+	  gssapi_krb method is specified.
+
+
+This implementation tried to follow the specification in the ietf draft
+as close as possible. However, it has not been tested against other
+IKE daemon implementations. The only other one I know of is Windows 2000,
+and it has some caveats. I attempted to be Windows 2000 compatible.
+Should racoon be tried against Windows 2000, the gssapi_id option in
+the config file must be used, as Windows 2000 expects the GSS endpoint
+name to be sent at all times. I have my doubts as to the W2K compatibility,
+because the spec describes the GSS endpoint name sent by W2K as
+an unicode string 'xxx@domain', which doesn't seem to match the
+required standard for gss-api + kerberos 5 (i.e. I am fairly certain
+that such a string will be rejected by the Heimdal gss-api library, as it
+is not a valid Kerberos 5 principal).
+
+With the Heimdal gss-api implementation, the gssapi_krb authentication
+method will only work in main mode. Aggressive mode does not allow
+for the extra round-trips needed by gss_init_sec_context and
+gss_accept_sec_context when mutual authentication is requested.
+The draft specifies that the a fallback should be done to main mode,
+through the return of INVALID-EXCHANGE-TYPE if it turns out that
+the gss-api mechanisms needs more roundtrips. This is implemented.
+Unfortunately, racoon does not seem to properly fall back to
+its next mode, and this is not specific to the gssapi_krb method.
+So, to avoid problems, only specify main mode in the config file.
+
+
+	-- Frank van der Linden <fvdl@wasabisystems.com>
+
diff --git a/src/racoon/doc/README.plainrsa b/src/racoon/doc/README.plainrsa
new file mode 100644
index 0000000..36de09c
--- /dev/null
+++ b/src/racoon/doc/README.plainrsa
@@ -0,0 +1,109 @@
+HOW-TO use plainrsa auth, contributed by Simon Chang <simonychang@gmail.com>
+
+Before you begin, you should understand that the RSA authentication
+mechanism hinges upon the idea of a split cryptographic key:  one used
+by the public, the other readable only to you.  Any data that is
+encrypted by a public key can be decrypted only by the corresponding
+private key, so that the private key user can be assured that the
+content of the transmission has not been examined by unauthorized
+parties.  Similarly, any data encrypted by the private key can be
+decrypted by the public key so that the public knows that this
+transmission came from this user and nobody else (this idea is called
+non-repudiation).  Also, the longer the key length, the more difficult
+it would be for potential attacker to conduct brute-force discovery of
+the keys.  So, what all this means for the security administrator is
+that the setup needs a pair of reasonably long keys for each host that
+wishes to authenticate in this manner.
+
+With this in mind, it should be relatively straightforward to set up
+RSA authentication.  For the purpose of this document, we assume that
+we are setting up RSA authentication between two networked hosts
+called Boston and Chicago.  Unless otherwise noted, all steps should
+be performed on both hosts with corresponding key names.  Here are the
+steps:
+
+1)  Included in each default installation of ipsec-tools is a binary
+called plainrsa-gen.  This executable is used to generate a pair of
+RSA keys for the host.  There are only two parameters that you should
+be concerned about: -b, which sets the number of bits for the keys,
+and -f, which specifies the output file for plainrsa-gen to send the
+results.  On an ordinary Pentium-II with 128 MB of RAM, it takes only
+seconds to generate keys that are 2048 bits long, and only slightly
+longer to generate 4096-bit keys.  Either key length should be
+sufficient; any longer key length actually reduces performance and
+does not increase security significantly.  You should therefore run it
+as:
+
+	plainrsa-gen -b 2048 -f /var/tmp/boston.keys
+
+2)  When the process completes, you should have a text file that
+includes both public and private keys.  GUARD THIS FILE CAREFULLY,
+because once a private key is compromised it is no longer any good,
+and you must generate a new pair from scratch.  Reading the file
+itself, you should see several very long lines of alphanumeric data.
+The only line you should be concerned with is the line towards the top
+of the output file that begins with "# pubkey=0sAQPAmBdT/" or
+something to that effect.  This line is your public key, which should
+be made available to the other host that you are setting up.  Copy
+this line to a separate file called "boston.pub" and change the
+beginning of the line so that it reads ": PUB 0sAQPAmBdT/".
+Alternatively, you can also grab the first line of the boston.keys
+file and uncomment the line so that it reads the same as above.  Now
+rename the file you generated initially to "boston.priv".
+
+3)  You should now have two files, boston.priv and boston.pub
+(chicago.priv and chicago.pub on Chicago).  The first file contains
+your private key and the second file your public key.  Next you should
+find a way to get the public key over to the other host involved.
+Boston should have (1) its own key pair, and (2) Chicago's public key
+ONLY.  Do not copy Chicago's private key over to Boston, because (a)
+it is not necessary, and (b) you would now have two potential places
+for losing control of your private key.
+
+4)  You should now configure the racoon.conf configuration file for
+each host to (a) turn on RSA authentication, and (b) designate each
+host's private key and the remote host(s)'s public key(s).  Take all
+your keys and place it in one directory and use the global directive
+"path certificate" to specify the location of the keys.  This step is
+especially important if you are running racoon with privilege
+separation, because if racoon cannot find the keys inside the
+directory you have just specified it will fail the authentication
+process.  So, write the directive like the following:
+
+	path certificate "/etc/racoon";
+
+Next, you need to specify the host's own private key and the public
+keys of all the remote peers involved. For your local private key and 
+remote public key(s), you should use the following directives:
+
+	certificate_type plain_rsa "/etc/racoon/boston.priv";
+	peers_certfile plain_rsa "/etc/racoon/chicago.pub";
+
+Notice the option "plain_rsa" for both directives.
+
+Finally, under the "proposal" statement section, you should specify
+the "rsasig" option for "authentication_method".
+
+5)  You have finished configuring the host for RSA authentication.
+Now use racoonctl to reload the configuration or simply restart the
+machine and you should be all set.
+
+TROUBLESHOOTING
+
+In the event that the hosts fail to communicate, first go back to the
+instructions above and make sure that:
+
+1)  You have placed all the keys in the directory that is specified by
+the "path certificate" directive.  Keep in mind that privilege
+separation will force racoon to look into that directory and nowhere
+else.
+2)  You have specified correctly the host's own private key and the
+remote peer's public key.
+3)  You have specified the "rsasig" method for authentication in the
+proposal statement.
+
+If you run into any further problems, you should try to use "racoon
+-v" to debug the setup, and send a copy of the debug messages to the
+mailing list so that we can help you determine what the problem is.
+
+Last modified: $Date: 2006/12/10 05:51:14 $
diff --git a/src/racoon/dump.h b/src/racoon/dump.h
new file mode 100644
index 0000000..3e8a5df
--- /dev/null
+++ b/src/racoon/dump.h
@@ -0,0 +1,41 @@
+/*	$NetBSD: dump.h,v 1.4 2006/09/09 16:22:09 manu Exp $	*/
+
+/* Id: dump.h,v 1.3 2004/06/11 16:00:16 ludvigm Exp */
+
+/*
+ * Copyright (C) 2000 WIDE Project.
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _DUMP_H
+#define _DUMP_H
+
+extern int isakmp_dump_open __P((char *));
+extern int isakmp_dump_close __P((void));
+extern int isakmp_dump __P((vchar_t *, struct sockaddr *, struct sockaddr *));
+
+#endif /* _DUMP_H */
diff --git a/src/racoon/eaytest.c b/src/racoon/eaytest.c
new file mode 100644
index 0000000..323ecef
--- /dev/null
+++ b/src/racoon/eaytest.c
@@ -0,0 +1,1068 @@
+/*	$NetBSD: eaytest.c,v 1.7.6.2 2008/07/15 00:55:48 mgrooms Exp $	*/
+
+/* Id: eaytest.c,v 1.22 2005/06/19 18:02:54 manubsd Exp */
+
+/*
+ * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
+
+#include <netinet/in.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <limits.h>
+#include <dirent.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <err.h>
+
+#include <openssl/bio.h>
+#include <openssl/pem.h>
+
+#include "var.h"
+#include "vmbuf.h"
+#include "misc.h"
+#include "debug.h"
+#include "str2val.h"
+#include "plog.h"
+
+#include "oakley.h"
+#include "dhgroup.h"
+#include "crypto_openssl.h"
+#include "gnuc.h"
+
+#include "package_version.h"
+
+#define PVDUMP(var) racoon_hexdump((var)->v, (var)->l)
+
+/*#define CERTTEST_BROKEN */
+
+/* prototype */
+
+static vchar_t *pem_read_buf __P((char *));
+void Usage __P((void));
+
+int rsatest __P((int, char **));
+int ciphertest __P((int, char **));
+int hmactest __P((int, char **));
+int sha1test __P((int, char **));
+int md5test __P((int, char **));
+int dhtest __P((int, char **));
+int bntest __P((int, char **));
+#ifndef CERTTEST_BROKEN
+static char **getcerts __P((char *));
+int certtest __P((int, char **));
+#endif
+
+/* test */
+
+static int
+rsa_verify_with_pubkey(src, sig, pubkey_txt)
+	vchar_t *src, *sig;
+	char *pubkey_txt;
+{
+	BIO *bio;
+	EVP_PKEY *evp;
+	int error;
+
+	bio = BIO_new_mem_buf(pubkey_txt, strlen(pubkey_txt));
+	evp = PEM_read_bio_PUBKEY(bio, NULL, NULL, NULL);
+	if (! evp) {
+		printf ("PEM_read_PUBKEY(): %s\n", eay_strerror());
+		return -1;
+	}
+	error = eay_check_rsasign(src, sig, evp->pkey.rsa);
+
+	return error;
+}
+
+int
+rsatest(ac, av)
+	int ac;
+	char **av;
+{
+	char *text = "this is test.";
+	vchar_t src;
+	vchar_t *priv, *sig;
+	int loglevel_saved;
+
+	char *pkcs1 =
+"-----BEGIN RSA PRIVATE KEY-----\n"
+"MIICXQIBAAKBgQChe5/Fzk9SA0vCKBOcu9jBcLb9oLv50PeuEfQojhakY+OH8A3Q\n"
+"M8A0qIDG6uhTNGPvzCWb/+mKeOB48n5HJpLxlDFyP3kyd2yXHIZ/MN8g1nh4FsB0\n"
+"iTkk8QUCJkkan6FCOBrIeLEsGA5AdodzuR+khnCMt8vO+NFHZYKAQeynyQIDAQAB\n"
+"AoGAOfDcnCHxjhDGrwyoNNWl6Yqi7hAtQm67YAbrH14UO7nnmxAENM9MyNgpFLaW\n"
+"07v5m8IZQIcradcDXAJOUwNBN8E06UflwEYCaScIwndvr5UpVlN3e2NC6Wyg2yC7\n"
+"GarxQput3zj35XNR5bK42UneU0H6zDxpHWqI1SwE+ToAHu0CQQDNl9gUJTpg0L09\n"
+"HkbE5jeb8bA5I20nKqBOBP0v5tnzpwu41umQwk9I7Ru0ucD7j+DW4k8otadW+FnI\n"
+"G1M1MpSjAkEAyRMt4bN8otfpOpsOQWzw4jQtouohOxRFCrQTntHhU20PrQnQLZWs\n"
+"pOVzqCjRytYtkPEUA1z8QK5gGcVPcOQsowJBALmt2rwPB1NrEo5Bat7noO+Zb3Ob\n"
+"WDiYWeE8xkHd95gDlSWiC53ur9aINo6ZeP556jGIgL+el/yHHecJLrQL84sCQH48\n"
+"zUxq/C/cb++8UzneJGlPqusiJNTLiAENR1gpmlZfHT1c8Nb9phMsfu0vG29GAfuC\n"
+"bzchVLljALCNQK+2gRMCQQCNIgN+R9mRWZhFAcC1sq++YnuSBlw4VwdL/fd1Yg9e\n"
+"Ul+U98yPl/NXt8Rs4TRBFcOZjkFI8xv0hQtevTgTmgz+\n"
+"-----END RSA PRIVATE KEY-----\n\n";
+	char *pubkey =
+"-----BEGIN PUBLIC KEY-----\n"
+"MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQChe5/Fzk9SA0vCKBOcu9jBcLb9\n"
+"oLv50PeuEfQojhakY+OH8A3QM8A0qIDG6uhTNGPvzCWb/+mKeOB48n5HJpLxlDFy\n"
+"P3kyd2yXHIZ/MN8g1nh4FsB0iTkk8QUCJkkan6FCOBrIeLEsGA5AdodzuR+khnCM\n"
+"t8vO+NFHZYKAQeynyQIDAQAB\n"
+"-----END PUBLIC KEY-----\n\n";
+	char *pubkey_wrong = 
+"-----BEGIN PUBLIC KEY-----\n"
+"MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwDncG2tSokRBhK8la1mO\n"
+"QnUpxg6KvpoFUjEyRiIE1GRap5V6jCCEOmA9ZAz4Oa/97oxewwMWtchIxSBZVCia\n"
+"H9oGasbOFzrtSR+MKl6Cb/Ow3Fu+PKbHTsnfTk/nOOWyaQh91PRD7fdwHe8L9P7w\n"
+"2kFPmDW6+RNKIR4OErhXf1O0eSShPe0TO3vx43O7dWqhmh3Kgr4Jq7zAGqHtwu0B\n"
+"RFZnmsocOnVZb2yAHndp51/Mk1H37ThHwN7qMx7RqrS3ru3XtchpJd9IQJPBIRfY\n"
+"VYQ68u5ix/Z80Y6VkRf0qnAvel8B6D3N3Zyq5u7G60PfvvtCybeMn7nVrSMxqMW/\n"
+"xwIDAQAB\n"
+"-----END PUBLIC KEY-----\n\n";
+
+	printf ("%s", pkcs1);
+	printf ("%s", pubkey);
+	priv = pem_read_buf(pkcs1);
+
+	src.v = text;
+	src.l = strlen(text);
+
+	/* sign */
+	sig = eay_get_x509sign(&src, priv);
+	if (sig == NULL) {
+		printf("sign failed. %s\n", eay_strerror());
+		return -1;
+	}
+
+	printf("RSA signed data.\n");
+	PVDUMP(sig);
+
+	printf("Verification with correct pubkey: ");
+	if (rsa_verify_with_pubkey (&src, sig, pubkey) != 0) {
+		printf ("Failed.\n");
+		return -1;
+	}
+	else
+		printf ("Verified. Good.\n");
+
+	loglevel_saved = loglevel;
+	loglevel = 0;
+	printf("Verification with wrong pubkey: ");
+	if (rsa_verify_with_pubkey (&src, sig, pubkey_wrong) != 0)
+		printf ("Not verified. Good.\n");
+	else {
+		printf ("Verified. This is bad...\n");
+		loglevel = loglevel_saved;
+		return -1;
+	}
+	loglevel = loglevel_saved;
+
+	return 0;
+}
+
+static vchar_t *
+pem_read_buf(buf)
+	char *buf;
+{
+	BIO *bio;
+	char *nm = NULL, *header = NULL;
+	unsigned char *data = NULL;
+	long len;
+	vchar_t *ret;
+	int error;
+
+	bio = BIO_new_mem_buf(buf, strlen(buf));
+	error = PEM_read_bio(bio, &nm, &header, &data, &len);
+	if (error == 0)
+		errx(1, "%s", eay_strerror());
+	ret = vmalloc(len);
+	if (ret == NULL)
+		err(1, "vmalloc");
+	memcpy(ret->v, data, len);
+
+	return ret;
+}
+
+#ifndef CERTTEST_BROKEN
+int
+certtest(ac, av)
+	int ac;
+	char **av;
+{
+	char *certpath;
+	char **certs;
+	int type;
+	int error;
+
+	printf("\n**Test for Certificate.**\n");
+
+    {
+	vchar_t *asn1dn = NULL, asn1dn0;
+#ifdef ORIG_DN
+	char dnstr[] = "C=JP, ST=Kanagawa, L=Fujisawa, O=WIDE Project, OU=KAME Project, CN=Shoichi Sakane/Email=sakane@kame.net";
+	char *dnstr_w1 = NULL;
+	char *dnstr_w2 = NULL;
+	char dn0[] = {
+		0x30,0x81,0x9a,0x31,0x0b,0x30,0x09,0x06,
+		0x03,0x55,0x04,0x06,0x13,0x02,0x4a,0x50,
+		0x31,0x11,0x30,0x0f,0x06,0x03,0x55,0x04,
+		0x08,0x13,0x08,0x4b,0x61,0x6e,0x61,0x67,
+		0x61,0x77,0x61,0x31,0x11,0x30,0x0f,0x06,
+		0x03,0x55,0x04,0x07,0x13,0x08,0x46,0x75,
+		0x6a,0x69,0x73,0x61,0x77,0x61,0x31,0x15,
+		0x30,0x13,0x06,0x03,0x55,0x04,0x0a,0x13,
+		0x0c,0x57,0x49,0x44,0x45,0x20,0x50,0x72,
+		0x6f,0x6a,0x65,0x63,0x74,0x31,0x15,0x30,
+		0x13,0x06,0x03,0x55,0x04,0x0b,0x13,0x0c,
+		0x4b,0x41,0x4d,0x45,0x20,0x50,0x72,0x6f,
+		0x6a,0x65,0x63,0x74,0x31,0x17,0x30,0x15,
+		0x06,0x03,0x55,0x04,0x03,0x13,0x0e,0x53,
+		0x68,0x6f,0x69,0x63,0x68,0x69,0x20,0x53,
+		0x61,0x6b,0x61,0x6e,0x65,0x31,0x1e,0x30,
+		0x1c,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,
+		0x0d,0x01,0x09,0x01,
+		0x0c,	/* <== XXX */
+		0x0f,0x73,0x61,
+		0x6b,0x61,0x6e,0x65,0x40,0x6b,0x61,0x6d,
+		0x65,0x2e,0x6e,0x65,0x74,
+	};
+#else /* not ORIG_DN */
+	char dnstr[] = "C=JP, ST=Kanagawa, L=Fujisawa, O=WIDE Project, OU=KAME Project, CN=Shoichi Sakane";
+	char dnstr_w1[] = "C=JP, ST=Kanagawa, L=Fujisawa, O=WIDE Project, OU=*, CN=Shoichi Sakane";
+	char dnstr_w2[] = "C=JP, ST=Kanagawa, L=Fujisawa, O=WIDE Project, OU=KAME Project, CN=*";
+	char dn0[] = {
+		0x30,0x7a,0x31,0x0b,0x30,0x09,0x06,0x03,
+		0x55,0x04,0x06,0x13,0x02,0x4a,0x50,0x31,
+		0x11,0x30,0x0f,0x06,0x03,0x55,0x04,0x08,
+		0x13,0x08,0x4b,0x61,0x6e,0x61,0x67,0x61,
+		0x77,0x61,0x31,0x11,0x30,0x0f,0x06,0x03,
+		0x55,0x04,0x07,0x13,0x08,0x46,0x75,0x6a,
+		0x69,0x73,0x61,0x77,0x61,0x31,0x15,0x30,
+		0x13,0x06,0x03,0x55,0x04,0x0a,0x13,0x0c,
+		0x57,0x49,0x44,0x45,0x20,0x50,0x72,0x6f,
+		0x6a,0x65,0x63,0x74,0x31,0x15,0x30,0x13,
+		0x06,0x03,0x55,0x04,0x0b,0x13,0x0c,0x4b,
+		0x41,0x4d,0x45,0x20,0x50,0x72,0x6f,0x6a,
+		0x65,0x63,0x74,0x31,0x17,0x30,0x15,0x06,
+		0x03,0x55,0x04,0x03,0x13,0x0e,0x53,0x68,
+		0x6f,0x69,0x63,0x68,0x69,0x20,0x53,0x61,
+		0x6b,0x61,0x6e,0x65,
+	};
+#endif /* ORIG_DN */
+
+	printf("check to convert the string into subjectName.\n");
+	printf("%s\n", dnstr);
+
+	asn1dn0.v = dn0;
+	asn1dn0.l = sizeof(dn0);
+
+	asn1dn = eay_str2asn1dn(dnstr, strlen(dnstr));
+	if (asn1dn == NULL || asn1dn->l != asn1dn0.l)
+#ifdef OUTPUT_VALID_ASN1DN
+	{
+		unsigned char *cp; int  i;
+		printf("asn1dn length mismatched (%zu != %zu).\n", asn1dn ? asn1dn->l : -1, asn1dn0.l);
+		for (cp = asn1dn->v, i = 0; i < asn1dn->l; i++)
+		    printf ("0x%02x,", *cp++);
+		exit (1);
+	}
+#else
+		errx(1, "asn1dn length mismatched (%zu != %zu).\n", asn1dn ? asn1dn->l : -1, asn1dn0.l);
+#endif
+
+	/*
+	 * NOTE: The value pointed by "<==" above is different from the
+	 * return of eay_str2asn1dn().  but eay_cmp_asn1dn() can distinguish
+	 * both of the names are same name.
+	 */
+	if (eay_cmp_asn1dn(&asn1dn0,  asn1dn))
+		errx(1, "asn1dn mismatched.\n");
+	vfree(asn1dn);
+
+	printf("exact match: succeed.\n");
+
+	if (dnstr_w1 != NULL) {
+		asn1dn = eay_str2asn1dn(dnstr_w1, strlen(dnstr_w1));
+		if (asn1dn == NULL || asn1dn->l == asn1dn0.l)
+			errx(1, "asn1dn length wrong for wildcard 1\n");
+		if (eay_cmp_asn1dn(&asn1dn0,  asn1dn))
+			errx(1, "asn1dn mismatched for wildcard 1.\n");
+		vfree(asn1dn);
+		printf("wildcard 1 match: succeed.\n");
+	}
+
+	if (dnstr_w1 != NULL) {
+		asn1dn = eay_str2asn1dn(dnstr_w2, strlen(dnstr_w2));
+		if (asn1dn == NULL || asn1dn->l == asn1dn0.l)
+			errx(1, "asn1dn length wrong for wildcard 2\n");
+		if (eay_cmp_asn1dn(&asn1dn0,  asn1dn))
+			errx(1, "asn1dn mismatched for wildcard 2.\n");
+		vfree(asn1dn);
+		printf("wildcard 2 match: succeed.\n");
+	}
+
+    }
+	eay_init();
+
+	/* get certs */
+	if (ac > 1) {
+		certpath = *(av + 1);
+		certs = getcerts(certpath);
+	} else {
+#ifdef ORIG_DN
+		printf("\nCAUTION: These certificates are probably invalid "
+			"on your environment because you don't have their "
+			"issuer's certs in your environment.\n\n");
+
+		certpath = "/usr/local/openssl/certs";
+		certs = getcerts(NULL);
+#else
+		printf("\nWARNING: The main certificates are probably invalid "
+			"on your environment\nbecause you don't have their "
+			"issuer's certs in your environment\nso not doing "
+			"this test.\n\n");
+		return (0);
+#endif
+	}
+
+	while (*certs != NULL) {
+
+		vchar_t c;
+		char *str;
+		vchar_t *vstr;
+
+		printf("===CERT===\n");
+
+		c.v = *certs;
+		c.l = strlen(*certs);
+
+		/* print text */
+		str = eay_get_x509text(&c);
+		printf("%s", str);
+		racoon_free(str);
+
+		/* print ASN.1 of subject name */
+		vstr = eay_get_x509asn1subjectname(&c);
+		if (!vstr)
+			return 0;
+		PVDUMP(vstr);
+		printf("\n");
+		vfree(vstr);
+
+		/* print subject alt name */
+	    {
+		int pos;
+		for (pos = 1; ; pos++) {
+			error = eay_get_x509subjectaltname(&c, &str, &type, pos);
+			if (error) {
+				printf("no subjectaltname found.\n");
+				break;
+			}
+			if (!str)
+				break;
+			printf("SubjectAltName: %d: %s\n", type, str);
+			racoon_free(str);
+		}
+	    }
+
+		/* NULL => name of the certificate file */
+		error = eay_check_x509cert(&c, certpath, NULL, 1);
+		if (error)
+			printf("ERROR: cert is invalid.\n");
+		printf("\n");
+
+		certs++;
+	}
+	return 0;
+}
+
+static char **
+getcerts(path)
+	char *path;
+{
+	char **certs = NULL, **p;
+	DIR *dirp;
+	struct dirent *dp;
+	struct stat sb;
+	char buf[512];
+	int len;
+	int n;
+	int fd;
+
+	static char *samplecerts[] = {
+/* self signed */
+"-----BEGIN CERTIFICATE-----\n"
+"MIICpTCCAg4CAQAwDQYJKoZIhvcNAQEEBQAwgZoxCzAJBgNVBAYTAkpQMREwDwYD\n"
+"VQQIEwhLYW5hZ2F3YTERMA8GA1UEBxMIRnVqaXNhd2ExFTATBgNVBAoTDFdJREUg\n"
+"UHJvamVjdDEVMBMGA1UECxMMS0FNRSBQcm9qZWN0MRcwFQYDVQQDEw5TaG9pY2hp\n"
+"IFNha2FuZTEeMBwGCSqGSIb3DQEJARYPc2FrYW5lQGthbWUubmV0MB4XDTAwMDgy\n"
+"NDAxMzc0NFoXDTAwMDkyMzAxMzc0NFowgZoxCzAJBgNVBAYTAkpQMREwDwYDVQQI\n"
+"EwhLYW5hZ2F3YTERMA8GA1UEBxMIRnVqaXNhd2ExFTATBgNVBAoTDFdJREUgUHJv\n"
+"amVjdDEVMBMGA1UECxMMS0FNRSBQcm9qZWN0MRcwFQYDVQQDEw5TaG9pY2hpIFNh\n"
+"a2FuZTEeMBwGCSqGSIb3DQEJARYPc2FrYW5lQGthbWUubmV0MIGfMA0GCSqGSIb3\n"
+"DQEBAQUAA4GNADCBiQKBgQCpIQG/H3zn4czAmPBcbkDrYxE1A9vcpghpib3Of0Op\n"
+"SsiWIBOyIMiVAzK/I/JotWp3Vdn5fzGp/7DGAbWXAALas2xHkNmTMPpu6qhmNQ57\n"
+"kJHZHal24mgc1hwbrI9fb5olvIexx9a1riNPnKMRVHzXYizsyMbf+lJJmZ8QFhWN\n"
+"twIDAQABMA0GCSqGSIb3DQEBBAUAA4GBACKs6X/BYycuHI3iop403R3XWMHHnNBN\n"
+"5XTHVWiWgR1cMWkq/dp51gn+nPftpdAaYGpqGkiHGhZcXLoBaX9uON3p+7av+sQN\n"
+"plXwnvUf2Zsgu+fojskS0gKcDlYiq1O8TOaBgJouFZgr1q6PiYjVEJGogAP28+HN\n"
+"M4o+GBFbFoqK\n"
+"-----END CERTIFICATE-----\n\n",
+/* signed by SSH testing CA + CA1 + CA2 */
+"-----BEGIN X509 CERTIFICATE-----\n"
+"MIICtTCCAj+gAwIBAgIEOaR8NjANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJG\n"
+"STEkMCIGA1UEChMbU1NIIENvbW11bmljYXRpb25zIFNlY3VyaXR5MREwDwYDVQQL\n"
+"EwhXZWIgdGVzdDEbMBkGA1UEAxMSVGVzdCBDQSAxIHN1YiBjYSAyMB4XDTAwMDgy\n"
+"NDAwMDAwMFoXDTAwMTAwMTAwMDAwMFowgZoxCzAJBgNVBAYTAkpQMREwDwYDVQQI\n"
+"EwhLYW5hZ2F3YTERMA8GA1UEBxMIRnVqaXNhd2ExFTATBgNVBAoTDFdJREUgUHJv\n"
+"amVjdDEVMBMGA1UECxMMS0FNRSBQcm9qZWN0MRcwFQYDVQQDEw5TaG9pY2hpIFNh\n"
+"a2FuZTEeMBwGCSqGSIb3DQEJAQwPc2FrYW5lQGthbWUubmV0MIGfMA0GCSqGSIb3\n"
+"DQEBAQUAA4GNADCBiQKBgQCpIQG/H3zn4czAmPBcbkDrYxE1A9vcpghpib3Of0Op\n"
+"SsiWIBOyIMiVAzK/I/JotWp3Vdn5fzGp/7DGAbWXAALas2xHkNmTMPpu6qhmNQ57\n"
+"kJHZHal24mgc1hwbrI9fb5olvIexx9a1riNPnKMRVHzXYizsyMbf+lJJmZ8QFhWN\n"
+"twIDAQABo18wXTALBgNVHQ8EBAMCBaAwGgYDVR0RBBMwEYEPc2FrYW5lQGthbWUu\n"
+"bmV0MDIGA1UdHwQrMCkwJ6AloCOGIWh0dHA6Ly9sZGFwLnNzaC5maS9jcmxzL2Nh\n"
+"MS0yLmNybDANBgkqhkiG9w0BAQUFAANhADtaqual41OWshF/rwCTuR6zySBJysGp\n"
+"+qjkp5efCiYKhAu1L4WXlMsV/SNdzspui5tHasPBvUw8gzFsU/VW/B2zuQZkimf1\n"
+"u6ZPjUb/vt8vLOPScP5MeH7xrTk9iigsqQ==\n"
+"-----END X509 CERTIFICATE-----\n\n",
+/* VP100 */
+"-----BEGIN CERTIFICATE-----\n"
+"MIICXzCCAcigAwIBAgIEOXGBIzANBgkqhkiG9w0BAQUFADBaMQswCQYDVQQGEwJG\n"
+"STEkMCIGA1UEChMbU1NIIENvbW11bmljYXRpb25zIFNlY3VyaXR5MREwDwYDVQQL\n"
+"EwhXZWIgdGVzdDESMBAGA1UEAxMJVGVzdCBDQSAxMB4XDTAwMDcxNjAwMDAwMFoX\n"
+"DTAwMDkwMTAwMDAwMFowNTELMAkGA1UEBhMCanAxETAPBgNVBAoTCHRhaGl0ZXN0\n"
+"MRMwEQYDVQQDEwpmdXJ1a2F3YS0xMIGdMA0GCSqGSIb3DQEBAQUAA4GLADCBhwKB\n"
+"gQDUmI2RaAuoLvtRDbASwRhbkj/Oq0BBIKgAqbFknc/EanJSQwZQu82gD88nf7gG\n"
+"VEioWmKPLDuEjz5JCuM+k5f7HYHI1wWmz1KFr7UA+avZm4Kp6YKnhuH7soZp7kBL\n"
+"hTiZEpL0jdmCWLW3ZXoro55rmPrBsCd+bt8VU6tRZm5dUwIBKaNZMFcwCwYDVR0P\n"
+"BAQDAgWgMBYGA1UdEQQPMA2CBVZQMTAwhwQKFIaFMDAGA1UdHwQpMCcwJaAjoCGG\n"
+"H2h0dHA6Ly9sZGFwLnNzaC5maS9jcmxzL2NhMS5jcmwwDQYJKoZIhvcNAQEFBQAD\n"
+"gYEAKJ/2Co/KYW65mwpGG3CBvsoRL8xyUMHGt6gQpFLHiiHuAdix1ADTL6uoFuYi\n"
+"4sE5omQm1wKVv2ZhS03zDtUfKoVEv0HZ7IY3AU/FZT/M5gQvbt43Dki/ma3ock2I\n"
+"PPhbLsvXm+GCVh3jvkYGk1zr7VERVeTPtmT+hW63lcxfFp4=\n"
+"-----END CERTIFICATE-----\n\n",
+/* IKED */
+"-----BEGIN CERTIFICATE-----\n"
+"MIIEFTCCA7+gAwIBAgIKYU5X6AAAAAAACTANBgkqhkiG9w0BAQUFADCBljEpMCcG\n"
+"CSqGSIb3DQEJARYaeS13YXRhbmFAc2RsLmhpdGFjaGkuY28uanAxCzAJBgNVBAYT\n"
+"AkpQMREwDwYDVQQIEwhLQU5BR0FXQTERMA8GA1UEBxMIWW9rb2hhbWExEDAOBgNV\n"
+"BAoTB0hJVEFDSEkxDDAKBgNVBAsTA1NETDEWMBQGA1UEAxMNSVBzZWMgVGVzdCBD\n"
+"QTAeFw0wMDA3MTUwMjUxNDdaFw0wMTA3MTUwMzAxNDdaMEUxCzAJBgNVBAYTAkpQ\n"
+"MREwDwYDVQQIEwhLQU5BR0FXQTEQMA4GA1UEChMHSElUQUNISTERMA8GA1UEAxMI\n"
+"V0FUQU5BQkUwXDANBgkqhkiG9w0BAQEFAANLADBIAkEA6Wja5A7Ldzrtx+rMWHEB\n"
+"Cyt+/ZoG0qdFQbuuUiU1vOSq+1f+ZSCYAdTq13Lrr6Xfz3jDVFEZLPID9PSTFwq+\n"
+"yQIDAQABo4ICPTCCAjkwDgYDVR0PAQH/BAQDAgTwMBMGA1UdJQQMMAoGCCsGAQUF\n"
+"CAICMB0GA1UdDgQWBBTkv7/MH5Ra+S1zBAmnUIH5w8ZTUTCB0gYDVR0jBIHKMIHH\n"
+"gBQsF2qoaTl5F3GFLKrttaxPJ8j4faGBnKSBmTCBljEpMCcGCSqGSIb3DQEJARYa\n"
+"eS13YXRhbmFAc2RsLmhpdGFjaGkuY28uanAxCzAJBgNVBAYTAkpQMREwDwYDVQQI\n"
+"EwhLQU5BR0FXQTERMA8GA1UEBxMIWW9rb2hhbWExEDAOBgNVBAoTB0hJVEFDSEkx\n"
+"DDAKBgNVBAsTA1NETDEWMBQGA1UEAxMNSVBzZWMgVGVzdCBDQYIQeccIf4GYDIBA\n"
+"rS6HSUt8XjB7BgNVHR8EdDByMDagNKAyhjBodHRwOi8vZmxvcmEyMjAvQ2VydEVu\n"
+"cm9sbC9JUHNlYyUyMFRlc3QlMjBDQS5jcmwwOKA2oDSGMmZpbGU6Ly9cXGZsb3Jh\n"
+"MjIwXENlcnRFbnJvbGxcSVBzZWMlMjBUZXN0JTIwQ0EuY3JsMIGgBggrBgEFBQcB\n"
+"AQSBkzCBkDBFBggrBgEFBQcwAoY5aHR0cDovL2Zsb3JhMjIwL0NlcnRFbnJvbGwv\n"
+"ZmxvcmEyMjBfSVBzZWMlMjBUZXN0JTIwQ0EuY3J0MEcGCCsGAQUFBzAChjtmaWxl\n"
+"Oi8vXFxmbG9yYTIyMFxDZXJ0RW5yb2xsXGZsb3JhMjIwX0lQc2VjJTIwVGVzdCUy\n"
+"MENBLmNydDANBgkqhkiG9w0BAQUFAANBAG8yZAWHb6g3zba453Hw5loojVDZO6fD\n"
+"9lCsyaxeo9/+7x1JEEcdZ6qL7KKqe7ZBwza+hIN0ITkp2WEWo22gTz4=\n"
+"-----END CERTIFICATE-----\n\n",
+/* From Entrust */
+"-----BEGIN CERTIFICATE-----\n"
+"MIIDXTCCAsagAwIBAgIEOb6khTANBgkqhkiG9w0BAQUFADA4MQswCQYDVQQGEwJV\n"
+"UzEQMA4GA1UEChMHRW50cnVzdDEXMBUGA1UECxMOVlBOIEludGVyb3AgUk8wHhcN\n"
+"MDAwOTE4MjMwMDM3WhcNMDMwOTE4MjMzMDM3WjBTMQswCQYDVQQGEwJVUzEQMA4G\n"
+"A1UEChMHRW50cnVzdDEXMBUGA1UECxMOVlBOIEludGVyb3AgUk8xGTAXBgNVBAMT\n"
+"EFNob2ljaGkgU2FrYW5lIDIwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAKj3\n"
+"eXSt1qXxFXzpa265B/NQYk5BZN7pNJg0tlTKBTVV3UgpQ92Bx5DoNfZh11oIv0Sw\n"
+"6YnG5p9F9ma36U9HDoD3hVTjAvQKy4ssCsnU1y6v5XOU1QvYQo6UTzgsXUTaIau4\n"
+"Lrccl+nyoiNzy3lG51tLR8CxuA+3OOAK9xPjszClAgMBAAGjggFXMIIBUzBABgNV\n"
+"HREEOTA3gQ9zYWthbmVAa2FtZS5uZXSHBM6vIHWCHjIwNi0xNzUtMzItMTE3LnZw\n"
+"bndvcmtzaG9wLmNvbTATBgNVHSUEDDAKBggrBgEFBQgCAjALBgNVHQ8EBAMCAKAw\n"
+"KwYDVR0QBCQwIoAPMjAwMDA5MTgyMzAwMzdagQ8yMDAyMTAyNTExMzAzN1owWgYD\n"
+"VR0fBFMwUTBPoE2gS6RJMEcxCzAJBgNVBAYTAlVTMRAwDgYDVQQKEwdFbnRydXN0\n"
+"MRcwFQYDVQQLEw5WUE4gSW50ZXJvcCBSTzENMAsGA1UEAxMEQ1JMMTAfBgNVHSME\n"
+"GDAWgBTzVmhu0tBoWKwkZE5mXpooE9630DAdBgNVHQ4EFgQUEgBHPtXggJqei5Xz\n"
+"92CrWXTJxfAwCQYDVR0TBAIwADAZBgkqhkiG9n0HQQAEDDAKGwRWNS4wAwIEsDAN\n"
+"BgkqhkiG9w0BAQUFAAOBgQCIFriNGMUE8GH5LuDrTJfA8uGx8vLy2seljuo694TR\n"
+"et/ojp9QnfOJ1PF9iAdGaEaSLfkwhY4fZNZzxic5HBoHLeo9BXLP7i7FByXjvOZC\n"
+"Y8++0dC8NVvendIILcJBM5nbDq1TqIbb8K3SP80XhO5JLVJkoZiQftAMjo0peZPO\n"
+"EQ==\n"
+"-----END CERTIFICATE-----\n\n",
+	NULL,
+	};
+
+	if (path == NULL)
+		return (char **)&samplecerts;
+
+	stat(path, &sb);
+	if (!(sb.st_mode & S_IFDIR)) {
+		printf("ERROR: %s is not directory.\n", path);
+		exit(0);
+	}
+
+	dirp = opendir(path);
+	if (dirp == NULL) {
+		printf("opendir failed.\n");
+		exit(0);
+	}
+
+	n = 0;
+	while ((dp = readdir(dirp)) != NULL) {
+		if (dp->d_type != DT_REG)
+			continue;
+		if (strcmp(dp->d_name + strlen(dp->d_name) - 4, "cert"))
+			continue;
+		snprintf(buf, sizeof(buf), "%s/%s", path, dp->d_name);
+		stat(buf, &sb);
+
+		p = (char **)realloc(certs, (n + 1) * sizeof(certs));
+		if (p == NULL)
+			err(1, "realloc");
+		certs = p;
+
+		certs[n] = malloc(sb.st_size + 1);
+		if (certs[n] == NULL)
+			err(1, "malloc");
+
+		fd = open(buf, O_RDONLY);
+		if (fd == -1)
+			err(1, "open");
+		len = read(fd, certs[n], sb.st_size);
+		if (len == -1)
+			err(1, "read");
+		if (len != sb.st_size)
+			errx(1, "read: length mismatch");
+		certs[n][sb.st_size] = '\0';
+		close(fd);
+
+		printf("%s: %d\n", dp->d_name, (int)sb.st_size);
+
+		n++;
+	}
+
+	p = (char **)realloc(certs, (n + 1) * sizeof(certs));
+	if (p == NULL)
+		err(1, "realloc");
+	certs = p;
+	certs[n] = NULL;
+
+	return certs;
+}
+#endif /* CERTTEST_BROKEN */
+
+typedef vchar_t* (eay_func) (vchar_t *, vchar_t *, vchar_t *);
+
+static int 
+ciphertest_1 (const char *name,
+	      vchar_t *data,
+	      size_t data_align,
+	      vchar_t *key,
+	      size_t min_keysize,
+	      vchar_t *iv0,
+	      size_t iv_length,
+	      eay_func encrypt,
+	      eay_func decrypt)
+{
+	int padlen;
+	vchar_t *buf, *iv, *res1, *res2;
+	iv = vmalloc(iv_length);
+	
+	printf("Test for cipher %s\n", name);
+	printf("data:\n");
+	PVDUMP(data);
+
+	if (data_align <= 1 || (data->l % data_align) == 0)
+	  padlen = 0;
+	else
+	  padlen = data_align - data->l % data_align;
+
+	buf = vmalloc(data->l + padlen);
+	memcpy(buf->v, data->v, data->l);
+
+	memcpy(iv->v, iv0->v, iv_length);
+	res1 = (encrypt)(buf, key, iv);
+	if (res1 == NULL) {
+		printf("%s encryption failed.\n", name);
+		return -1;
+	}
+	printf("encrypted:\n");
+	PVDUMP(res1);
+
+	memcpy(iv->v, iv0->v, iv_length);
+	res2 = (decrypt)(res1, key, iv);
+	if (res2 == NULL) {
+		printf("%s decryption failed.\n", name);
+		return -1;
+	}
+	printf("decrypted:\n");
+	PVDUMP(res2);
+
+	if (memcmp(data->v, res2->v, data->l)) {
+		printf("XXXX NG (%s) XXXX\n", name);
+		return -1;
+	}
+	else
+		printf("%s cipher verified.\n", name);
+	vfree(res1);
+	vfree(res2);
+	vfree(buf);
+	vfree(iv);
+
+	return 0;
+}
+
+int
+ciphertest(ac, av)
+	int ac;
+	char **av;
+{
+	vchar_t data;
+	vchar_t key;
+	vchar_t iv0;
+
+	printf("\n**Testing CIPHERS**\n");
+
+	data.v = str2val("\
+06000017 03000000 73616b61 6e65406b 616d652e 6e657409 0002c104 308202b8 \
+04f05a90 \
+	", 16, &data.l);
+	key.v = str2val("f59bd70f 81b9b9cc 2a32c7fd 229a4b37", 16, &key.l);
+	iv0.v = str2val("26b68c90 9467b4ab 7ec29fa0 0b696b55", 16, &iv0.l);
+
+	if (ciphertest_1 ("DES", 
+			  &data, 8, 
+			  &key, 8, 
+			  &iv0, 8, 
+			  eay_des_encrypt, eay_des_decrypt) < 0)
+	  return -1;
+	
+	if (ciphertest_1 ("3DES",
+			  &data, 8,
+			  &key, 24,
+			  &iv0, 8,
+			  eay_3des_encrypt, eay_3des_decrypt) < 0)
+	  return -1;
+	
+	if (ciphertest_1 ("AES",
+			  &data, 16,
+			  &key, key.l,
+			  &iv0, 16,
+			  eay_aes_encrypt, eay_aes_decrypt) < 0)
+	  return -1;
+
+	if (ciphertest_1 ("BLOWFISH",
+			  &data, 8,
+			  &key, key.l,
+			  &iv0, 8,
+			  eay_bf_encrypt, eay_bf_decrypt) < 0)
+	  return -1;
+
+	if (ciphertest_1 ("CAST",
+			  &data, 8,
+			  &key, key.l,
+			  &iv0, 8,
+			  eay_cast_encrypt, eay_cast_decrypt) < 0)
+	  return -1;
+	
+#ifdef HAVE_OPENSSL_IDEA_H
+	if (ciphertest_1 ("IDEA",
+			  &data, 8,
+			  &key, key.l,
+			  &iv0, 8,
+			  eay_idea_encrypt, eay_idea_decrypt) < 0)
+	  return -1;
+#endif
+
+#ifdef HAVE_OPENSSL_RC5_H
+	if (ciphertest_1 ("RC5",
+			  &data, 8,
+			  &key, key.l,
+			  &iv0, 8,
+			  eay_rc5_encrypt, eay_rc5_decrypt) < 0)
+	  return -1;
+#endif
+#if defined(HAVE_OPENSSL_CAMELLIA_H)
+	if (ciphertest_1 ("CAMELLIA",
+			  &data, 16,
+			  &key, key.l,
+			  &iv0, 16,
+			  eay_camellia_encrypt, eay_camellia_decrypt) < 0)
+	  return -1;
+#endif
+	return 0;
+}
+
+int
+hmactest(ac, av)
+	int ac;
+	char **av;
+{
+	char *keyword = "hehehe test secret!";
+	char *object  = "d7e6a6c1876ef0488bb74958b9fee94e";
+	char *object1 = "d7e6a6c1876ef048";
+	char *object2 =                 "8bb74958b9fee94e";
+	char *r_hmd5  = "5702d7d1 fd1bfc7e 210fc9fa cda7d02c";
+	char *r_hsha1 = "309999aa 9779a43e ebdea839 1b4e7ee1 d8646874";
+#ifdef WITH_SHA2
+	char *r_hsha2 = "d47262d8 a5b6f39d d8686939 411b3e79 ed2e27f9 2c4ea89f dd0a06ae 0c0aa396";
+#endif
+	vchar_t *key, *data, *data1, *data2, *res;
+	vchar_t mod;
+	caddr_t ctx;
+
+#ifdef WITH_SHA2
+	printf("\n**Test for HMAC MD5, SHA1, and SHA256.**\n");
+#else
+	printf("\n**Test for HMAC MD5 & SHA1.**\n");
+#endif
+
+	key = vmalloc(strlen(keyword));
+	memcpy(key->v, keyword, key->l);
+
+	data = vmalloc(strlen(object));
+	data1 = vmalloc(strlen(object1));
+	data2 = vmalloc(strlen(object2));
+	memcpy(data->v, object, data->l);
+	memcpy(data1->v, object1, data1->l);
+	memcpy(data2->v, object2, data2->l);
+
+	/* HMAC MD5 */
+	printf("HMAC MD5 by eay_hmacmd5_one()\n");
+	res = eay_hmacmd5_one(key, data);
+	PVDUMP(res);
+	mod.v = str2val(r_hmd5, 16, &mod.l);
+	if (memcmp(res->v, mod.v, mod.l)) {
+		printf(" XXX NG XXX\n");
+		return -1;
+	}
+	free(mod.v);
+	vfree(res);
+
+	/* HMAC MD5 */
+	printf("HMAC MD5 by eay_hmacmd5_xxx()\n");
+	ctx = eay_hmacmd5_init(key);
+	eay_hmacmd5_update(ctx, data1);
+	eay_hmacmd5_update(ctx, data2);
+	res = eay_hmacmd5_final(ctx);
+	PVDUMP(res);
+	mod.v = str2val(r_hmd5, 16, &mod.l);
+	if (memcmp(res->v, mod.v, mod.l)) {
+		printf(" XXX NG XXX\n");
+		return -1;
+	}
+	free(mod.v);
+	vfree(res);
+
+	/* HMAC SHA1 */
+	printf("HMAC SHA1 by eay_hmacsha1_one()\n");
+	res = eay_hmacsha1_one(key, data);
+	PVDUMP(res);
+	mod.v = str2val(r_hsha1, 16, &mod.l);
+	if (memcmp(res->v, mod.v, mod.l)) {
+		printf(" XXX NG XXX\n");
+		return -1;
+	}
+	free(mod.v);
+	vfree(res);
+
+	/* HMAC SHA1 */
+	printf("HMAC SHA1 by eay_hmacsha1_xxx()\n");
+	ctx = eay_hmacsha1_init(key);
+	eay_hmacsha1_update(ctx, data1);
+	eay_hmacsha1_update(ctx, data2);
+	res = eay_hmacsha1_final(ctx);
+	PVDUMP(res);
+	mod.v = str2val(r_hsha1, 16, &mod.l);
+	if (memcmp(res->v, mod.v, mod.l)) {
+		printf(" XXX NG XXX\n");
+		return -1;
+	}
+	free(mod.v);
+	vfree(res);
+
+#ifdef WITH_SHA2
+	/* HMAC SHA2 */
+	printf("HMAC SHA2 by eay_hmacsha2_256_one()\n");
+	res = eay_hmacsha2_256_one(key, data);
+	PVDUMP(res);
+	mod.v = str2val(r_hsha2, 16, &mod.l);
+	if (memcmp(res->v, mod.v, mod.l)) {
+		printf(" XXX NG XXX\n");
+		return -1;
+	}
+	free(mod.v);
+	vfree(res);
+#endif
+
+	vfree(data);
+	vfree(data1);
+	vfree(data2);
+	vfree(key);
+
+	return 0;
+}
+
+int
+sha1test(ac, av)
+	int ac;
+	char **av;
+{
+	char *word1 = "1234567890", *word2 = "12345678901234567890";
+	caddr_t ctx;
+	vchar_t *buf, *res;
+
+	printf("\n**Test for SHA1.**\n");
+
+	ctx = eay_sha1_init();
+	buf = vmalloc(strlen(word1));
+	memcpy(buf->v, word1, buf->l);
+	eay_sha1_update(ctx, buf);
+	eay_sha1_update(ctx, buf);
+	res = eay_sha1_final(ctx);
+	PVDUMP(res);
+	vfree(res);
+	vfree(buf);
+
+	ctx = eay_sha1_init();
+	buf = vmalloc(strlen(word2));
+	memcpy(buf->v, word2, buf->l);
+	eay_sha1_update(ctx, buf);
+	res = eay_sha1_final(ctx);
+	PVDUMP(res);
+	vfree(res);
+
+	res = eay_sha1_one(buf);
+	PVDUMP(res);
+	vfree(res);
+	vfree(buf);
+
+	return 0;
+}
+
+int
+md5test(ac, av)
+	int ac;
+	char **av;
+{
+	char *word1 = "1234567890", *word2 = "12345678901234567890";
+	caddr_t ctx;
+	vchar_t *buf, *res;
+
+	printf("\n**Test for MD5.**\n");
+
+	ctx = eay_md5_init();
+	buf = vmalloc(strlen(word1));
+	memcpy(buf->v, word1, buf->l);
+	eay_md5_update(ctx, buf);
+	eay_md5_update(ctx, buf);
+	res = eay_md5_final(ctx);
+	PVDUMP(res);
+	vfree(res);
+	vfree(buf);
+
+	ctx = eay_md5_init();
+	buf = vmalloc(strlen(word2));
+	memcpy(buf->v, word2, buf->l);
+	eay_md5_update(ctx, buf);
+	res = eay_md5_final(ctx);
+	PVDUMP(res);
+	vfree(res);
+
+	res = eay_md5_one(buf);
+	PVDUMP(res);
+	vfree(res);
+	vfree(buf);
+
+	return 0;
+}
+
+int
+dhtest(ac, av)
+	int ac;
+	char **av;
+{
+	static struct {
+		char *name;
+		char *p;
+	} px[] = {
+		{ "modp768",	OAKLEY_PRIME_MODP768, },
+		{ "modp1024",	OAKLEY_PRIME_MODP1024, },
+		{ "modp1536",	OAKLEY_PRIME_MODP1536, },
+		{ "modp2048",	OAKLEY_PRIME_MODP2048, },
+		{ "modp3072",	OAKLEY_PRIME_MODP3072, },
+		{ "modp4096",	OAKLEY_PRIME_MODP4096, },
+		{ "modp6144",	OAKLEY_PRIME_MODP6144, },
+		{ "modp8192",	OAKLEY_PRIME_MODP8192, },
+	};
+	vchar_t p1, *pub1, *priv1, *gxy1;
+	vchar_t p2, *pub2, *priv2, *gxy2;
+	int i;
+
+	printf("\n**Test for DH.**\n");
+
+	for (i = 0; i < sizeof(px)/sizeof(px[0]); i++) {
+		printf("\n**Test for DH %s.**\n", px[i].name);
+
+		p1.v = str2val(px[i].p, 16, &p1.l);
+		p2.v = str2val(px[i].p, 16, &p2.l);
+		printf("prime number = \n"); PVDUMP(&p1);
+
+		if (eay_dh_generate(&p1, 2, 96, &pub1, &priv1) < 0) {
+			printf("error\n");
+			return -1;
+		}
+		printf("private key for user 1 = \n"); PVDUMP(priv1);
+		printf("public key for user 1  = \n"); PVDUMP(pub1);
+
+		if (eay_dh_generate(&p2, 2, 96, &pub2, &priv2) < 0) {
+			printf("error\n");
+			return -1;
+		}
+		printf("private key for user 2 = \n"); PVDUMP(priv2);
+		printf("public key for user 2  = \n"); PVDUMP(pub2);
+
+		/* process to generate key for user 1 */
+		gxy1 = vmalloc(p1.l);
+		memset(gxy1->v, 0, gxy1->l);
+		eay_dh_compute(&p1, 2, pub1, priv1, pub2, &gxy1);
+		printf("sharing gxy1 of user 1 = \n"); PVDUMP(gxy1);
+
+		/* process to generate key for user 2 */
+		gxy2 = vmalloc(p1.l);
+		memset(gxy2->v, 0, gxy2->l);
+		eay_dh_compute(&p2, 2, pub2, priv2, pub1, &gxy2);
+		printf("sharing gxy2 of user 2 = \n"); PVDUMP(gxy2);
+
+		if (memcmp(gxy1->v, gxy2->v, gxy1->l)) {
+			printf("ERROR: sharing gxy mismatched.\n");
+			return -1;
+		}
+
+		vfree(pub1);
+		vfree(pub2);
+		vfree(priv1);
+		vfree(priv2);
+		vfree(gxy1);
+		vfree(gxy2);
+	}
+
+	return 0;
+}
+
+int
+bntest(ac, av)
+	int ac;
+	char **av;
+{
+	vchar_t *rn;
+
+	printf("\n**Test for generate a random number.**\n");
+
+	rn = eay_set_random((u_int32_t)96);
+	PVDUMP(rn);
+	vfree(rn);
+
+	return 0;
+}
+
+struct {
+	char *name;
+	int (*func) __P((int, char **));
+} func[] = {
+	{ "random", bntest, },
+	{ "dh", dhtest, },
+	{ "md5", md5test, },
+	{ "sha1", sha1test, },
+	{ "hmac", hmactest, },
+	{ "cipher", ciphertest, },
+#ifndef CERTTEST_BROKEN
+	{ "cert", certtest, },
+#endif
+	{ "rsa", rsatest, },
+};
+
+int
+main(ac, av)
+	int ac;
+	char **av;
+{
+	int i;
+	int len = sizeof(func)/sizeof(func[0]);
+
+	f_foreground = 1;
+	ploginit();
+
+	printf ("\nTestsuite of the %s\nlinked with %s\n\n", TOP_PACKAGE_STRING, eay_version());
+
+	if (strcmp(*av, "-h") == 0)
+		Usage();
+
+	ac--;
+	av++;
+
+	for (i = 0; i < len; i++) {
+		if ((ac == 0) || (strcmp(*av, func[i].name) == 0)) {
+			if ((func[i].func)(ac, av) != 0) {
+				printf ("\n!!!!! Test '%s' failed. !!!!!\n\n", func[i].name);
+				exit(1);
+			}
+			if (ac)
+				break;
+		}
+	}
+	if (ac && i == len)
+		Usage();
+
+	printf ("\n===== All tests passed =====\n\n");
+	exit(0);
+}
+
+void
+Usage()
+{
+	int i;
+	int len = sizeof(func)/sizeof(func[0]);
+
+	printf("Usage: eaytest [");
+	for (i = 0; i < len; i++)
+		printf("%s%s", func[i].name, (i<len-1)?"|":"");
+	printf("]\n");
+#ifndef CERTTEST_BROKEN
+	printf("       eaytest cert [cert_directory]\n");
+#endif
+	exit(1);
+}
+
diff --git a/src/racoon/evt.c b/src/racoon/evt.c
new file mode 100644
index 0000000..fc65b20
--- /dev/null
+++ b/src/racoon/evt.c
@@ -0,0 +1,158 @@
+/*	$NetBSD: evt.c,v 1.5 2006/09/09 16:22:09 manu Exp $	*/
+
+/* Id: evt.c,v 1.5 2006/06/22 20:11:35 manubsd Exp */
+
+/*
+ * Copyright (C) 2004 Emmanuel Dreyfus
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include <errno.h>
+#include <string.h>
+#include <stdio.h>
+#include <time.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <sys/queue.h>
+#include <sys/socket.h>
+
+#include "vmbuf.h"
+#include "plog.h"
+#include "misc.h"
+#include "admin.h"
+#include "gcmalloc.h"
+#include "evt.h"
+
+#ifdef ENABLE_ADMINPORT
+struct evtlist evtlist = TAILQ_HEAD_INITIALIZER(evtlist);
+int evtlist_len = 0;
+
+void
+evt_push(src, dst, type, optdata)
+	struct sockaddr *src;
+	struct sockaddr *dst;
+	int type;
+	vchar_t *optdata;
+{
+	struct evtdump *evtdump;
+	struct evt *evt;
+	size_t len;
+
+	/* If admin socket is disabled, silently discard anything */
+	if (adminsock_path == NULL)
+		return;
+
+	/* If we are above the limit, don't record anything */
+	if (evtlist_len > EVTLIST_MAX) {
+		plog(LLV_DEBUG, LOCATION, NULL, 
+		    "Cannot record event: event queue overflowed\n");
+		return;
+	}
+
+	/* If we hit the limit, record an overflow event instead */
+	if (evtlist_len == EVTLIST_MAX) {
+		plog(LLV_ERROR, LOCATION, NULL, 
+		    "Cannot record event: event queue overflow\n");
+		src = NULL;
+		dst = NULL;
+		type = EVTT_OVERFLOW;
+		optdata = NULL;
+	}
+
+	len = sizeof(*evtdump);
+	if (optdata)
+		len += optdata->l;
+
+	if ((evtdump = racoon_malloc(len)) == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL, "Cannot record event: %s\n",
+		    strerror(errno));
+		return;
+	}
+
+	if ((evt = racoon_malloc(sizeof(*evt))) == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL, "Cannot record event: %s\n",
+		    strerror(errno));
+		racoon_free(evtdump);
+		return;
+	}
+
+	if (src)
+		memcpy(&evtdump->src, src, sysdep_sa_len(src));
+	if (dst)
+		memcpy(&evtdump->dst, dst, sysdep_sa_len(dst));
+	evtdump->len = len;
+	evtdump->type = type;
+	time(&evtdump->timestamp);
+
+	if (optdata)
+		memcpy(evtdump + 1, optdata->v, optdata->l);
+
+	evt->dump = evtdump;
+	TAILQ_INSERT_TAIL(&evtlist, evt, next);
+
+	evtlist_len++;
+
+	return;
+}
+
+struct evtdump *
+evt_pop(void) {
+	struct evtdump *evtdump;
+	struct evt *evt;
+
+	if ((evt = TAILQ_FIRST(&evtlist)) == NULL)
+		return NULL;
+
+	evtdump = evt->dump;
+	TAILQ_REMOVE(&evtlist, evt, next);
+	racoon_free(evt);
+	evtlist_len--;
+
+	return evtdump;
+}
+
+vchar_t *
+evt_dump(void) {
+	struct evtdump *evtdump;
+	vchar_t *buf = NULL;
+
+	if ((evtdump = evt_pop()) != NULL) {
+		if ((buf = vmalloc(evtdump->len)) == NULL) {
+			plog(LLV_ERROR, LOCATION, NULL, 
+			    "evt_dump failed: %s\n", strerror(errno));
+			return NULL;
+		}
+		memcpy(buf->v, evtdump, evtdump->len);	
+		racoon_free(evtdump);
+	}
+
+	return buf;
+}
+
+#endif /* ENABLE_ADMINPORT */
diff --git a/src/racoon/evt.h b/src/racoon/evt.h
new file mode 100644
index 0000000..88ee366
--- /dev/null
+++ b/src/racoon/evt.h
@@ -0,0 +1,88 @@
+/*	$NetBSD: evt.h,v 1.4 2006/09/09 16:22:09 manu Exp $	*/
+
+/* Id: evt.h,v 1.5 2006/01/19 10:24:09 fredsen Exp */
+
+/*
+ * Copyright (C) 2004 Emmanuel Dreyfus
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _EVT_H
+#define _EVT_H
+
+struct evtdump {
+	size_t len;	
+	struct sockaddr_storage src;
+	struct sockaddr_storage dst;
+	time_t timestamp;
+	int type;
+	/* 
+	 * Optionnal list of struct isakmp_data 
+	 * for type EVTT_ISAKMP_CFG_DONE
+	 */
+};
+
+/* type */
+#define EVTT_UNSEPC		0
+#define EVTT_PHASE1_UP		1
+#define EVTT_PHASE1_DOWN	2
+#define EVTT_XAUTH_SUCCESS	3
+#define EVTT_ISAKMP_CFG_DONE	4
+#define EVTT_PHASE2_UP		5
+#define EVTT_PHASE2_DOWN	6
+#define EVTT_DPD_TIMEOUT	7
+#define EVTT_PEER_NO_RESPONSE	8
+#define EVTT_PEER_DELETE	9
+#define EVTT_RACOON_QUIT	10
+#define EVTT_XAUTH_FAILED	11
+#define EVTT_OVERFLOW		12	/* Event queue overflowed */
+#define EVTT_PEERPH1AUTH_FAILED	13
+#define EVTT_PEERPH1_NOPROP	14	/* NO_PROPOSAL_CHOSEN & friends */
+#define EVTT_NO_ISAKMP_CFG	15	/* no need to wait for mode_cfg */
+
+struct evt {
+	struct evtdump *dump;
+	TAILQ_ENTRY(evt) next;
+};
+
+TAILQ_HEAD(evtlist, evt);
+
+#define EVTLIST_MAX	32
+
+#ifdef ENABLE_ADMINPORT
+struct evtdump *evt_pop(void);
+vchar_t *evt_dump(void);
+void evt_push(struct sockaddr *, struct sockaddr *, int, vchar_t *);
+#endif
+
+#ifdef ENABLE_ADMINPORT
+#define EVT_PUSH(src, dst, type, optdata) evt_push(src, dst, type, optdata);
+#else
+#define EVT_PUSH(src, dst, type, optdata) ;
+#endif
+
+#endif /* _EVT_H */
diff --git a/src/racoon/gcmalloc.h b/src/racoon/gcmalloc.h
new file mode 100644
index 0000000..acdf7fa
--- /dev/null
+++ b/src/racoon/gcmalloc.h
@@ -0,0 +1,127 @@
+/*	$NetBSD: gcmalloc.h,v 1.4 2006/09/09 16:22:09 manu Exp $	*/
+
+/*	$KAME: gcmalloc.h,v 1.4 2001/11/16 04:34:57 sakane Exp $	*/
+
+/*
+ * Copyright (C) 2000, 2001 WIDE Project.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Debugging malloc glue for Racoon.
+ */
+
+#ifndef _GCMALLOC_H_DEFINED
+#define _GCMALLOC_H_DEFINED
+
+/* ElectricFence needs no special handling. */
+
+/*
+ * Boehm-GC provides GC_malloc(), GC_realloc(), GC_free() functions,
+ * but not the traditional entry points.  So what we do is provide  
+ * malloc(), calloc(), realloc(), and free() entry points in the main
+ * program and letting the linker do the rest.
+ */
+#ifdef GC
+#define GC_DEBUG
+#include <gc.h>
+
+#ifdef RACOON_MAIN_PROGRAM
+void *
+malloc(size_t size)
+{
+
+	return (GC_MALLOC(size));
+}
+
+void *
+calloc(size_t number, size_t size)
+{
+
+	/* GC_malloc() clears the storage. */
+	return (GC_MALLOC(number * size));
+}
+
+void *
+realloc(void *ptr, size_t size)
+{
+
+	return (GC_REALLOC(ptr, size));
+}
+
+void
+free(void *ptr)
+{
+
+	GC_FREE(ptr);
+}
+
+char *
+strdup(const char *str)
+{
+
+	return (GC_STRDUP(str));
+}
+#endif /* RACOON_MAIN_PROGRAM */
+
+#define	racoon_malloc(sz)	GC_debug_malloc(sz, GC_EXTRAS)
+#define	racoon_calloc(cnt, sz)	GC_debug_malloc(cnt * sz, GC_EXTRAS)
+#define	racoon_realloc(old, sz)	GC_debug_realloc(old, sz, GC_EXTRAS)
+#define	racoon_free(p)		GC_debug_free(p)
+#define	racoon_strdup(str)	GC_debug_strdup(str)
+
+#endif /* GC */
+
+/*
+ * Dmalloc only requires that you pull in a header file and link
+ * against libdmalloc.
+ */
+#ifdef DMALLOC
+#include <dmalloc.h>
+#endif /* DMALLOC */
+
+#ifdef DEBUG_RECORD_MALLOCATION
+#include <debugrm.h>
+#else
+#ifndef racoon_malloc
+#define	racoon_malloc(sz)	malloc((sz))
+#endif
+#ifndef racoon_calloc
+#define	racoon_calloc(cnt, sz)	calloc((cnt), (sz))
+#endif
+#ifndef racoon_realloc
+#define	racoon_realloc(old, sz)	realloc((old), (sz))
+#endif
+#ifndef racoon_free
+#define	racoon_free(p)		free((p))
+#endif
+#ifndef racoon_strdup
+#define	racoon_strdup(s)	strdup((s))
+#endif
+#endif /* DEBUG_RECORD_MALLOCATION */
+
+#endif /* _GCMALLOC_H_DEFINED */
diff --git a/src/racoon/genlist.c b/src/racoon/genlist.c
new file mode 100644
index 0000000..b5204c0
--- /dev/null
+++ b/src/racoon/genlist.c
@@ -0,0 +1,174 @@
+/*	$NetBSD: genlist.c,v 1.4 2006/09/09 16:22:09 manu Exp $	*/
+
+/* Id: genlist.c,v 1.2 2004/07/12 20:43:50 ludvigm Exp */
+
+/*
+ * Copyright (C) 2004 SuSE Linux AG, Nuernberg, Germany.
+ * Contributed by: Michal Ludvig <mludvig@suse.cz>, SUSE Labs
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/queue.h>
+
+#include "genlist.h"
+
+struct genlist *
+genlist_init (void)
+{
+	struct genlist *new = calloc(sizeof(struct genlist), 1);
+	TAILQ_INIT(new);
+	return new;
+}
+
+struct genlist_entry *
+genlist_insert (struct genlist *head, void *data)
+{
+	struct genlist_entry *entry = calloc(sizeof(struct genlist_entry), 1);
+	entry->data = data;
+	TAILQ_INSERT_HEAD(head, entry, chain);
+	return entry;
+}
+
+struct genlist_entry *
+genlist_append (struct genlist *head, void *data)
+{
+	struct genlist_entry *entry = calloc(sizeof(struct genlist_entry), 1);
+	entry->data = data;
+	TAILQ_INSERT_TAIL(head, entry, chain);
+	return entry;
+}
+
+void *
+genlist_foreach (struct genlist *head, genlist_func_t func, void *arg)
+{
+	struct genlist_entry *p;
+	void *ret = NULL;
+	TAILQ_FOREACH(p, head, chain) {
+		ret = (*func)(p->data, arg);
+		if (ret)
+			break;
+	}
+
+	return ret;
+}
+
+void *
+genlist_next (struct genlist *head, struct genlist_entry **buf)
+{
+	struct genlist_entry *p;
+
+	if (head)
+		p = TAILQ_FIRST(head);
+	else
+		p = (buf && *buf) ? TAILQ_NEXT(*buf, chain) : NULL;
+	if (buf)
+		*buf = p;
+	return (p ? p->data : NULL);
+}
+
+void
+genlist_free (struct genlist *head, genlist_freedata_t func)
+{
+	struct genlist_entry *p;
+
+	while ((p = TAILQ_LAST(head, genlist)) != NULL) {
+		TAILQ_REMOVE(head, p, chain);
+		if (func)
+			func(p->data);
+		free(p);
+	}
+	free(head);
+}
+
+
+#if 0
+/* Here comes the example... */
+struct conf {
+	struct genlist	*l1, *l2;
+};
+
+void *
+print_entry(void *entry, void *arg)
+{
+	if (!entry)
+		return NULL;
+	printf("%s\n", (char *)entry);
+	return NULL;
+}
+
+void
+dump_list(struct genlist *head)
+{
+	genlist_foreach(head, print_entry, NULL);
+}
+
+void
+free_data(void *data)
+{
+	printf ("removing %s\n", (char *)data);
+}
+
+int main()
+{
+	struct conf *cf;
+	char *cp;
+	struct genlist_entry *gpb;
+
+	cf = calloc(sizeof(struct conf), 1);
+	cf->l1 = genlist_init();
+	cf->l2 = genlist_init();
+	
+	genlist_insert(cf->l1, "Ahoj");
+	genlist_insert(cf->l1, "Cau");
+	genlist_insert(cf->l1, "Nazdar");
+	genlist_insert(cf->l1, "Te buch");
+
+	genlist_append(cf->l2, "Curak");
+	genlist_append(cf->l2, "Kozy");
+	genlist_append(cf->l2, "Pica");
+	genlist_append(cf->l2, "Prdel");
+
+	printf("List 2\n");
+	dump_list(cf->l2);
+	printf("\nList 1\n");
+	dump_list(cf->l1);
+
+	printf("\nList 2 - using genlist_next()\n");
+	for (cp = genlist_next (cf->l2, &gpb); cp; cp = genlist_next (0, &gpb))
+	    printf("%s\n", cp);
+
+	printf("\nFreeing List 1\n");
+	/* the data here isn't actually alloc'd so we would really call
+	 * genlist_free (cf->l1, 0);    but to illustrate the idea */
+	genlist_free (cf->l1, free_data);
+	cf->l1 = 0;
+
+	return 0;
+}
+#endif
diff --git a/src/racoon/genlist.h b/src/racoon/genlist.h
new file mode 100644
index 0000000..ee15392
--- /dev/null
+++ b/src/racoon/genlist.h
@@ -0,0 +1,82 @@
+/*	$NetBSD: genlist.h,v 1.4 2006/09/09 16:22:09 manu Exp $	*/
+
+/* Id: genlist.h,v 1.2 2004/07/12 20:43:50 ludvigm Exp */
+
+/*
+ * Copyright (C) 2004 SuSE Linux AG, Nuernberg, Germany.
+ * Contributed by: Michal Ludvig <mludvig@suse.cz>, SUSE Labs
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _GENLIST_H
+#define _GENLIST_H
+
+#include <sys/queue.h>
+
+/* See the bottom of genlist.c for example use. */
+
+/* This declares 'struct genlist' */
+TAILQ_HEAD(genlist, genlist_entry);
+
+/* This is where the data are actually stored. */
+struct genlist_entry {
+	void *data;
+	TAILQ_ENTRY(genlist_entry) chain;
+};
+
+/* This function returns an initialized list head. */
+struct genlist *genlist_init (void);
+
+/* Insert an entry at the beginning/end og the list. */
+struct genlist_entry *genlist_insert (struct genlist *head, void *data);
+struct genlist_entry *genlist_append (struct genlist *head, void *data);
+
+/* Create a function with this prototype for use with genlist_foreach().
+ * See genlist_foreach() description below for details. */
+typedef void *(genlist_func_t)(void *entry, void *arg);
+
+/* Traverse the list and call 'func' for each entry.  As long as func() returns
+ * NULL the list traversal continues, once it returns non-NULL (usually the
+ * 'entry' arg), the list traversal exits and the return value is returned
+ * further from genlist_foreach(). Optional 'arg' may be passed to func(), e.g.
+ * for some lookup purposes, etc. */
+void *genlist_foreach (struct genlist *head, genlist_func_t func, void *arg);
+
+/* Get first entry in list if head is not NULL, otherwise get next
+ * entry based on saved position in list from previous call as stored in buf.
+ * If buf is NULL no position is saved */
+void *genlist_next (struct genlist *head, struct genlist_entry **buf);
+
+/* Create a function with this prototype for use with genlist_free()
+ * to free any storage associated with genlist_entry.data */
+typedef void (genlist_freedata_t)(void *entry);
+
+/* Free all storage associated with list at head using func to free any
+ * alloc()d data in data field of genlist_entry */
+void genlist_free (struct genlist *head, genlist_freedata_t func);
+
+#endif /* _GENLIST_H */
diff --git a/src/racoon/getcertsbyname.c b/src/racoon/getcertsbyname.c
new file mode 100644
index 0000000..8c83ae7
--- /dev/null
+++ b/src/racoon/getcertsbyname.c
@@ -0,0 +1,423 @@
+/*	$NetBSD: getcertsbyname.c,v 1.4 2006/09/09 16:22:09 manu Exp $	*/
+
+/*	$KAME: getcertsbyname.c,v 1.7 2001/11/16 04:12:59 sakane Exp $	*/
+
+/*
+ * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#if (defined(__APPLE__) && defined(__MACH__))
+# include <nameser8_compat.h>
+#endif
+#include <resolv.h>
+#ifdef HAVE_LWRES_GETRRSETBYNAME
+#include <lwres/netdb.h>
+#include <lwres/lwres.h>
+#else
+#include <netdb.h>
+#endif
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#ifdef DNSSEC_DEBUG
+#include <stdio.h>
+#include <strings.h>
+#endif
+
+#ifdef ANDROID_CHANGES
+#include <arpa/inet.h>
+#include <arpa_nameser.h>
+#endif
+
+#include "netdb_dnssec.h"
+
+/* XXX should it use ci_errno to hold errno instead of h_errno ? */
+extern int h_errno;
+
+static struct certinfo *getnewci __P((int, int, int, int, int, 
+			unsigned char *));
+
+static struct certinfo *
+getnewci(qtype, keytag, algorithm, flags, certlen, cert)
+	int qtype, keytag, algorithm, flags, certlen;
+	unsigned char *cert;
+{
+	struct certinfo *res;
+
+	res = malloc(sizeof(*res));
+	if (!res)
+		return NULL;
+
+	memset(res, 0, sizeof(*res));
+	res->ci_type = qtype;
+	res->ci_keytag = keytag;
+	res->ci_algorithm = algorithm;
+	res->ci_flags = flags;
+	res->ci_certlen = certlen;
+	res->ci_cert = malloc(certlen);
+	if (!res->ci_cert) {
+		free(res);
+		return NULL;
+	}
+	memcpy(res->ci_cert, cert, certlen);
+
+	return res;
+}
+
+void
+freecertinfo(ci)
+	struct certinfo *ci;
+{
+	struct certinfo *next;
+
+	do {
+		next = ci->ci_next;
+		if (ci->ci_cert)
+			free(ci->ci_cert);
+		free(ci);
+		ci = next;
+	} while (ci);
+}
+
+/*
+ * get CERT RR by FQDN and create certinfo structure chain.
+ */
+#ifdef HAVE_LWRES_GETRRSETBYNAME
+#define getrrsetbyname lwres_getrrsetbyname
+#define freerrset lwres_freerrset
+#define hstrerror lwres_hstrerror
+#endif
+#if defined(HAVE_LWRES_GETRRSETBYNAME) || defined(AHVE_GETRRSETBYNAME)
+int
+getcertsbyname(name, res)
+	char *name;
+	struct certinfo **res;
+{
+	int rdlength;
+	char *cp;
+	int type, keytag, algorithm;
+	struct certinfo head, *cur;
+	struct rrsetinfo *rr = NULL;
+	int i;
+	int error = -1;
+
+	/* initialize res */
+	*res = NULL;
+
+	memset(&head, 0, sizeof(head));
+	cur = &head;
+
+	error = getrrsetbyname(name, C_IN, T_CERT, 0, &rr);
+	if (error) {
+#ifdef DNSSEC_DEBUG
+		printf("getrrsetbyname: %s\n", hstrerror(error));
+#endif
+		h_errno = NO_RECOVERY;
+		goto end;
+	}
+
+	if (rr->rri_rdclass != C_IN
+	 || rr->rri_rdtype != T_CERT
+	 || rr->rri_nrdatas == 0) {
+#ifdef DNSSEC_DEBUG
+		printf("getrrsetbyname: %s", hstrerror(error));
+#endif
+		h_errno = NO_RECOVERY;
+		goto end;
+	}
+#ifdef DNSSEC_DEBUG
+	if (!(rr->rri_flags & LWRDATA_VALIDATED))
+		printf("rr is not valid");
+#endif
+
+	for (i = 0; i < rr->rri_nrdatas; i++) {
+		rdlength = rr->rri_rdatas[i].rdi_length;
+		cp = rr->rri_rdatas[i].rdi_data;
+
+		GETSHORT(type, cp);	/* type */
+		rdlength -= INT16SZ;
+		GETSHORT(keytag, cp);	/* key tag */
+		rdlength -= INT16SZ;
+		algorithm = *cp++;	/* algorithm */
+		rdlength -= 1;
+
+#ifdef DNSSEC_DEBUG
+		printf("type=%d keytag=%d alg=%d len=%d\n",
+			type, keytag, algorithm, rdlength);
+#endif
+
+		/* create new certinfo */
+		cur->ci_next = getnewci(type, keytag, algorithm,
+					rr->rri_flags, rdlength, cp);
+		if (!cur->ci_next) {
+#ifdef DNSSEC_DEBUG
+			printf("getnewci: %s", strerror(errno));
+#endif
+			h_errno = NO_RECOVERY;
+			goto end;
+		}
+		cur = cur->ci_next;
+	}
+
+	*res = head.ci_next;
+	error = 0;
+
+end:
+	if (rr)
+		freerrset(rr);
+	if (error && head.ci_next)
+		freecertinfo(head.ci_next);
+
+	return error;
+}
+#else	/*!HAVE_LWRES_GETRRSETBYNAME*/
+int
+getcertsbyname(name, res)
+	char *name;
+	struct certinfo **res;
+{
+	unsigned char *answer = NULL, *p;
+	int buflen, anslen, len;
+	HEADER *hp;
+	int qdcount, ancount, rdlength;
+	unsigned char *cp, *eom;
+	char hostbuf[1024];	/* XXX */
+	int qtype, qclass, keytag, algorithm;
+	struct certinfo head, *cur;
+	int error = -1;
+
+	/* initialize res */
+	*res = NULL;
+
+	memset(&head, 0, sizeof(head));
+	cur = &head;
+
+	/* get CERT RR */
+	buflen = 512;
+	do {
+
+		buflen *= 2;
+		p = realloc(answer, buflen);
+		if (!p) {
+#ifdef DNSSEC_DEBUG
+			printf("realloc: %s", strerror(errno));
+#endif
+			h_errno = NO_RECOVERY;
+			goto end;
+		}
+		answer = p;
+
+		anslen = res_query(name,  C_IN, T_CERT, answer, buflen);
+		if (anslen == -1)
+			goto end;
+
+	} while (buflen < anslen);
+
+#ifdef DNSSEC_DEBUG
+	printf("get a DNS packet len=%d\n", anslen);
+#endif
+
+	/* parse CERT RR */
+	eom = answer + anslen;
+
+	hp = (HEADER *)answer;
+	qdcount = ntohs(hp->qdcount);
+	ancount = ntohs(hp->ancount);
+
+	/* question section */
+	if (qdcount != 1) {
+#ifdef DNSSEC_DEBUG
+		printf("query count is not 1.\n");
+#endif
+		h_errno = NO_RECOVERY;
+		goto end;
+	}
+	cp = (unsigned char *)(hp + 1);
+	len = dn_expand(answer, eom, cp, hostbuf, sizeof(hostbuf));
+	if (len < 0) {
+#ifdef DNSSEC_DEBUG
+		printf("dn_expand failed.\n");
+#endif
+		goto end;
+	}
+	cp += len;
+	GETSHORT(qtype, cp);		/* QTYPE */
+	GETSHORT(qclass, cp);		/* QCLASS */
+
+	/* answer section */
+	while (ancount-- && cp < eom) {
+		len = dn_expand(answer, eom, cp, hostbuf, sizeof(hostbuf));
+		if (len < 0) {
+#ifdef DNSSEC_DEBUG
+			printf("dn_expand failed.\n");
+#endif
+			goto end;
+		}
+		cp += len;
+		GETSHORT(qtype, cp);	/* TYPE */
+		GETSHORT(qclass, cp);	/* CLASS */
+		cp += INT32SZ;		/* TTL */
+		GETSHORT(rdlength, cp);	/* RDLENGTH */
+
+		/* CERT RR */
+		if (qtype != T_CERT) {
+#ifdef DNSSEC_DEBUG
+			printf("not T_CERT\n");
+#endif
+			h_errno = NO_RECOVERY;
+			goto end;
+		}
+		GETSHORT(qtype, cp);	/* type */
+		rdlength -= INT16SZ;
+		GETSHORT(keytag, cp);	/* key tag */
+		rdlength -= INT16SZ;
+		algorithm = *cp++;	/* algorithm */
+		rdlength -= 1;
+		if (cp + rdlength > eom) {
+#ifdef DNSSEC_DEBUG
+			printf("rdlength is too long.\n");
+#endif
+			h_errno = NO_RECOVERY;
+			goto end;
+		}
+#ifdef DNSSEC_DEBUG
+		printf("type=%d keytag=%d alg=%d len=%d\n",
+			qtype, keytag, algorithm, rdlength);
+#endif
+
+		/* create new certinfo */
+		cur->ci_next = getnewci(qtype, keytag, algorithm,
+					0, rdlength, cp);
+		if (!cur->ci_next) {
+#ifdef DNSSEC_DEBUG
+			printf("getnewci: %s", strerror(errno));
+#endif
+			h_errno = NO_RECOVERY;
+			goto end;
+		}
+		cur = cur->ci_next;
+
+		cp += rdlength;
+	}
+
+	*res = head.ci_next;
+	error = 0;
+
+end:
+	if (answer)
+		free(answer);
+	if (error && head.ci_next)
+		freecertinfo(head.ci_next);
+
+	return error;
+}
+#endif
+
+#ifdef DNSSEC_DEBUG
+int
+b64encode(p, len)
+	char *p;
+	int len;
+{
+	static const char b64t[] =
+		"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+		"abcdefghijklmnopqrstuvwxyz"
+		"0123456789+/=";
+
+	while (len > 2) {
+                printf("%c", b64t[(p[0] >> 2) & 0x3f]);
+                printf("%c", b64t[((p[0] << 4) & 0x30) | ((p[1] >> 4) & 0x0f)]);
+                printf("%c", b64t[((p[1] << 2) & 0x3c) | ((p[2] >> 6) & 0x03)]);
+                printf("%c", b64t[p[2] & 0x3f]);
+		len -= 3;
+		p += 3;
+	}
+
+	if (len == 2) {
+                printf("%c", b64t[(p[0] >> 2) & 0x3f]);
+                printf("%c", b64t[((p[0] << 4) & 0x30)| ((p[1] >> 4) & 0x0f)]);
+                printf("%c", b64t[((p[1] << 2) & 0x3c)]);
+                printf("%c", '=');
+        } else if (len == 1) {
+                printf("%c", b64t[(p[0] >> 2) & 0x3f]);
+                printf("%c", b64t[((p[0] << 4) & 0x30)]);
+                printf("%c", '=');
+                printf("%c", '=');
+	}
+
+	return 0;
+}
+
+int
+main(ac, av)
+	int ac;
+	char **av;
+{
+	struct certinfo *res, *p;
+	int i;
+
+	if (ac < 2) {
+		printf("Usage: a.out (FQDN)\n");
+		exit(1);
+	}
+
+	i = getcertsbyname(*(av + 1), &res);
+	if (i != 0) {
+		herror("getcertsbyname");
+		exit(1);
+	}
+	printf("getcertsbyname succeeded.\n");
+
+	i = 0;
+	for (p = res; p; p = p->ci_next) {
+		printf("certinfo[%d]:\n", i);
+		printf("\tci_type=%d\n", p->ci_type);
+		printf("\tci_keytag=%d\n", p->ci_keytag);
+		printf("\tci_algorithm=%d\n", p->ci_algorithm);
+		printf("\tci_flags=%d\n", p->ci_flags);
+		printf("\tci_certlen=%d\n", p->ci_certlen);
+		printf("\tci_cert: ");
+		b64encode(p->ci_cert, p->ci_certlen);
+		printf("\n");
+		i++;
+	}
+
+	freecertinfo(res);
+
+	exit(0);
+}
+#endif
diff --git a/src/racoon/gnuc.h b/src/racoon/gnuc.h
new file mode 100644
index 0000000..8537ad2
--- /dev/null
+++ b/src/racoon/gnuc.h
@@ -0,0 +1,46 @@
+/*	$NetBSD: gnuc.h,v 1.4 2006/09/09 16:22:09 manu Exp $	*/
+
+/* Id: gnuc.h,v 1.4 2004/11/18 15:14:44 ludvigm Exp */
+
+/* Define __P() macro, if necessary */
+#undef __P
+#ifndef __P
+#if __STDC__
+#define __P(protos) protos
+#else
+#define __P(protos) ()
+#endif
+#endif
+
+/* inline foo */
+#ifdef __GNUC__
+#define inline __inline
+#else
+#define inline
+#endif
+
+/*
+ * Handle new and old "dead" routine prototypes
+ *
+ * For example:
+ *
+ *	__dead void foo(void) __attribute__((volatile));
+ *
+ */
+#ifdef __GNUC__
+#ifndef __dead
+#define __dead volatile
+#endif
+#if __GNUC__ < 2  || (__GNUC__ == 2 && __GNUC_MINOR__ < 5)
+#ifndef __attribute__
+#define __attribute__(args)
+#endif
+#endif
+#else
+#ifndef __dead
+#define __dead
+#endif
+#ifndef __attribute__
+#define __attribute__(args)
+#endif
+#endif
diff --git a/src/racoon/grabmyaddr.c b/src/racoon/grabmyaddr.c
new file mode 100644
index 0000000..00a8e9b
--- /dev/null
+++ b/src/racoon/grabmyaddr.c
@@ -0,0 +1,922 @@
+/*	$NetBSD: grabmyaddr.c,v 1.4.6.3 2008/06/18 07:30:18 mgrooms Exp $	*/
+
+/* Id: grabmyaddr.c,v 1.27 2006/04/06 16:27:05 manubsd Exp */
+
+/*
+ * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+
+#include <net/if.h>
+#if defined(__FreeBSD__) && __FreeBSD__ >= 3
+#include <net/if_var.h>
+#endif
+#if defined(__NetBSD__) || defined(__FreeBSD__) ||	\
+  (defined(__APPLE__) && defined(__MACH__))
+#include <netinet/in.h>
+#include <netinet6/in6_var.h>
+#endif
+#include <net/route.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <netdb.h>
+#ifdef HAVE_GETIFADDRS
+#include <ifaddrs.h>
+#include <net/if.h>
+#endif 
+
+#include "var.h"
+#include "misc.h"
+#include "vmbuf.h"
+#include "plog.h"
+#include "sockmisc.h"
+#include "debug.h"
+
+#include "localconf.h"
+#include "handler.h"
+#include "grabmyaddr.h"
+#include "sockmisc.h"
+#include "isakmp_var.h"
+#include "gcmalloc.h"
+#include "nattraversal.h"
+
+#ifdef __linux__
+#include <linux/types.h>
+#include <linux/rtnetlink.h>
+#ifndef HAVE_GETIFADDRS
+#define HAVE_GETIFADDRS
+#define NEED_LINUX_GETIFADDRS
+#endif
+#endif
+
+#ifdef ANDROID_CHANGES
+#include <arpa/inet.h>
+#include <arpa_nameser.h>
+#endif
+
+#ifndef HAVE_GETIFADDRS
+static unsigned int if_maxindex __P((void));
+#endif
+static struct myaddrs *find_myaddr __P((struct myaddrs *, struct myaddrs *));
+static int suitable_ifaddr __P((const char *, const struct sockaddr *));
+#ifdef INET6
+static int suitable_ifaddr6 __P((const char *, const struct sockaddr *));
+#endif
+
+#ifdef NEED_LINUX_GETIFADDRS
+
+/* We could do this _much_ better. kame racoon in its current form
+ * will esentially die at frequent changes of address configuration.
+ */
+
+struct ifaddrs
+{
+	struct ifaddrs *ifa_next;
+	char		ifa_name[16];
+	int		ifa_ifindex;
+	struct sockaddr *ifa_addr;
+	struct sockaddr_storage ifa_addrbuf;
+};
+
+static int parse_rtattr(struct rtattr *tb[], int max, struct rtattr *rta, int len)
+{
+	while (RTA_OK(rta, len)) {
+		if (rta->rta_type <= max)
+			tb[rta->rta_type] = rta;
+		rta = RTA_NEXT(rta,len);
+	}
+	return 0;
+}
+
+static void recvaddrs(int fd, struct ifaddrs **ifa, __u32 seq)
+{
+	char	buf[8192];
+	struct sockaddr_nl nladdr;
+	struct iovec iov = { buf, sizeof(buf) };
+	struct ifaddrmsg *m;
+	struct rtattr * rta_tb[IFA_MAX+1];
+	struct ifaddrs *I;
+
+	while (1) {
+		int status;
+		struct nlmsghdr *h;
+
+		struct msghdr msg = {
+			(void*)&nladdr, sizeof(nladdr),
+			&iov,	1,
+			NULL,	0,
+			0
+		};
+
+		status = recvmsg(fd, &msg, 0);
+
+		if (status < 0)
+			continue;
+
+		if (status == 0)
+			return;
+
+		if (nladdr.nl_pid) /* Message not from kernel */
+			continue;
+
+		h = (struct nlmsghdr*)buf;
+		while (NLMSG_OK(h, status)) {
+			if (h->nlmsg_seq != seq)
+				goto skip_it;
+
+			if (h->nlmsg_type == NLMSG_DONE)
+				return;
+
+			if (h->nlmsg_type == NLMSG_ERROR)
+				return;
+
+			if (h->nlmsg_type != RTM_NEWADDR)
+				goto skip_it;
+
+			m = NLMSG_DATA(h);
+
+			if (m->ifa_family != AF_INET &&
+			    m->ifa_family != AF_INET6)
+				goto skip_it;
+
+			if (m->ifa_flags&IFA_F_TENTATIVE)
+				goto skip_it;
+
+			memset(rta_tb, 0, sizeof(rta_tb));
+			parse_rtattr(rta_tb, IFA_MAX, IFA_RTA(m), h->nlmsg_len - NLMSG_LENGTH(sizeof(*m)));
+
+			if (rta_tb[IFA_LOCAL] == NULL)
+				rta_tb[IFA_LOCAL] = rta_tb[IFA_ADDRESS];
+			if (rta_tb[IFA_LOCAL] == NULL)
+				goto skip_it;
+			
+			I = malloc(sizeof(struct ifaddrs));
+			if (!I)
+				return;
+			memset(I, 0, sizeof(*I));
+
+			I->ifa_ifindex = m->ifa_index;
+			I->ifa_addr = (struct sockaddr*)&I->ifa_addrbuf;
+			I->ifa_addr->sa_family = m->ifa_family;
+			if (m->ifa_family == AF_INET) {
+				struct sockaddr_in *sin = (void*)I->ifa_addr;
+				memcpy(&sin->sin_addr, RTA_DATA(rta_tb[IFA_LOCAL]), 4);
+			} else {
+				struct sockaddr_in6 *sin = (void*)I->ifa_addr;
+				memcpy(&sin->sin6_addr, RTA_DATA(rta_tb[IFA_LOCAL]), 16);
+				if (IN6_IS_ADDR_LINKLOCAL(&sin->sin6_addr))
+					sin->sin6_scope_id = I->ifa_ifindex;
+			}
+			I->ifa_next = *ifa;
+			*ifa = I;
+
+skip_it:
+			h = NLMSG_NEXT(h, status);
+		}
+		if (msg.msg_flags & MSG_TRUNC)
+			continue;
+	}
+	return;
+}
+
+static int getifaddrs(struct ifaddrs **ifa0)
+{
+	struct {
+		struct nlmsghdr nlh;
+		struct rtgenmsg g;
+	} req;
+	struct sockaddr_nl nladdr;
+	static __u32 seq;
+	struct ifaddrs *i;
+	int fd;
+
+	fd = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
+	if (fd < 0)
+		return -1;
+
+	memset(&nladdr, 0, sizeof(nladdr));
+	nladdr.nl_family = AF_NETLINK;
+
+	req.nlh.nlmsg_len = sizeof(req);
+	req.nlh.nlmsg_type = RTM_GETADDR;
+	req.nlh.nlmsg_flags = NLM_F_ROOT|NLM_F_MATCH|NLM_F_REQUEST;
+	req.nlh.nlmsg_pid = 0;
+	req.nlh.nlmsg_seq = ++seq;
+	req.g.rtgen_family = AF_UNSPEC;
+
+	if (sendto(fd, (void*)&req, sizeof(req), 0, (struct sockaddr*)&nladdr, sizeof(nladdr)) < 0) {
+		close(fd);
+		return -1;
+	}
+
+	*ifa0 = NULL;
+
+	recvaddrs(fd, ifa0, seq);
+
+	close(fd);
+
+	fd = socket(AF_INET, SOCK_DGRAM, 0);
+
+	for (i=*ifa0; i; i = i->ifa_next) {
+		struct ifreq ifr;
+		ifr.ifr_ifindex = i->ifa_ifindex;
+		ioctl(fd, SIOCGIFNAME, (void*)&ifr);
+		memcpy(i->ifa_name, ifr.ifr_name, 16);
+	}
+	close(fd);
+
+	return 0;
+}
+
+static void freeifaddrs(struct ifaddrs *ifa0)
+{
+        struct ifaddrs *i;
+
+        while (ifa0) {
+                i = ifa0;
+                ifa0 = i->ifa_next;
+                free(i);
+        }
+}
+
+#endif
+
+#ifndef HAVE_GETIFADDRS
+static unsigned int
+if_maxindex()
+{
+	struct if_nameindex *p, *p0;
+	unsigned int max = 0;
+
+	p0 = if_nameindex();
+	for (p = p0; p && p->if_index && p->if_name; p++) {
+		if (max < p->if_index)
+			max = p->if_index;
+	}
+	if_freenameindex(p0);
+	return max;
+}
+#endif
+
+void
+clear_myaddr(db)
+	struct myaddrs **db;
+{
+	struct myaddrs *p;
+
+	while (*db) {
+		p = (*db)->next;
+		delmyaddr(*db);
+		*db = p;
+	}
+}
+  
+static struct myaddrs *
+find_myaddr(db, p)
+	struct myaddrs *db;
+	struct myaddrs *p;
+{
+	struct myaddrs *q;
+	char h1[NI_MAXHOST], h2[NI_MAXHOST];
+
+	if (getnameinfo(p->addr, sysdep_sa_len(p->addr), h1, sizeof(h1), NULL, 0,
+	    NI_NUMERICHOST | niflags) != 0)
+		return NULL;
+
+	for (q = db; q; q = q->next) {
+		if (p->addr->sa_family != q->addr->sa_family)
+			continue;
+		if (getnameinfo(q->addr, sysdep_sa_len(q->addr), h2, sizeof(h2),
+		    NULL, 0, NI_NUMERICHOST | niflags) != 0)
+			return NULL;
+		if (strcmp(h1, h2) == 0)
+			return q;
+	}
+
+	return NULL;
+}
+
+void
+grab_myaddrs()
+{
+#ifdef HAVE_GETIFADDRS
+	struct myaddrs *p, *q, *old;
+	struct ifaddrs *ifa0, *ifap;
+#ifdef INET6
+	struct sockaddr_in6 *sin6;
+#endif
+
+	char addr1[NI_MAXHOST];
+
+	if (getifaddrs(&ifa0)) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"getifaddrs failed: %s\n", strerror(errno));
+		exit(1);
+		/*NOTREACHED*/
+	}
+
+	old = lcconf->myaddrs;
+
+	for (ifap = ifa0; ifap; ifap = ifap->ifa_next) {
+		if (! ifap->ifa_addr)
+			continue;
+
+		if (ifap->ifa_addr->sa_family != AF_INET
+#ifdef INET6
+		 && ifap->ifa_addr->sa_family != AF_INET6
+#endif
+		)
+			continue;
+
+		if (!suitable_ifaddr(ifap->ifa_name, ifap->ifa_addr)) {
+			plog(LLV_ERROR, LOCATION, NULL,
+				"unsuitable address: %s %s\n",
+				ifap->ifa_name,
+				saddrwop2str(ifap->ifa_addr));
+			continue;
+		}
+
+		p = newmyaddr();
+		if (p == NULL) {
+			exit(1);
+			/*NOTREACHED*/
+		}
+		p->addr = dupsaddr(ifap->ifa_addr);
+		if (p->addr == NULL) {
+			exit(1);
+			/*NOTREACHED*/
+		}
+#ifdef INET6
+#ifdef __KAME__
+		if (ifap->ifa_addr->sa_family == AF_INET6) {
+			sin6 = (struct sockaddr_in6 *)p->addr;
+			if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)
+			 || IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr)) {
+				sin6->sin6_scope_id =
+					ntohs(*(u_int16_t *)&sin6->sin6_addr.s6_addr[2]);
+				sin6->sin6_addr.s6_addr[2] = 0;
+				sin6->sin6_addr.s6_addr[3] = 0;
+			}
+		}
+#else /* !__KAME__ */
+		if (ifap->ifa_addr->sa_family == AF_INET6) {
+			sin6 = (struct sockaddr_in6 *)p->addr;
+			if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)
+			 || IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr)) {
+				sin6->sin6_scope_id =
+					if_nametoindex(ifap->ifa_name);
+			}
+		}
+				
+#endif
+#endif
+		if (getnameinfo(p->addr, sysdep_sa_len(p->addr),
+				addr1, sizeof(addr1),
+				NULL, 0,
+				NI_NUMERICHOST | niflags))
+		strlcpy(addr1, "(invalid)", sizeof(addr1));
+		plog(LLV_DEBUG, LOCATION, NULL,
+			"my interface: %s (%s)\n",
+			addr1, ifap->ifa_name);
+		q = find_myaddr(old, p);
+		if (q)
+			p->sock = q->sock;
+		else
+			p->sock = -1;
+		p->next = lcconf->myaddrs;
+		lcconf->myaddrs = p;
+	}
+
+	freeifaddrs(ifa0);
+
+	clear_myaddr(&old);
+
+#else /*!HAVE_GETIFADDRS*/
+	int s;
+	unsigned int maxif;
+	int len;
+	struct ifreq *iflist;
+	struct ifconf ifconf;
+	struct ifreq *ifr, *ifr_end;
+	struct myaddrs *p, *q, *old;
+#ifdef INET6
+#ifdef __KAME__
+	struct sockaddr_in6 *sin6;
+#endif
+#endif
+
+	char addr1[NI_MAXHOST];
+
+	maxif = if_maxindex() + 1;
+	len = maxif * sizeof(struct sockaddr_storage) * 4; /* guess guess */
+
+	iflist = (struct ifreq *)racoon_malloc(len);
+	if (!iflist) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"failed to allocate buffer\n");
+		exit(1);
+		/*NOTREACHED*/
+	}
+
+	if ((s = socket(PF_INET, SOCK_DGRAM, 0)) < 0) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"socket(SOCK_DGRAM) failed: %s\n",
+			strerror(errno));
+		exit(1);
+		/*NOTREACHED*/
+	}
+	memset(&ifconf, 0, sizeof(ifconf));
+	ifconf.ifc_req = iflist;
+	ifconf.ifc_len = len;
+	if (ioctl(s, SIOCGIFCONF, &ifconf) < 0) {
+		close(s);
+		plog(LLV_ERROR, LOCATION, NULL,
+			"ioctl(SIOCGIFCONF) failed: %s\n",
+			strerror(errno));
+		exit(1);
+		/*NOTREACHED*/
+	}
+	close(s);
+
+	old = lcconf->myaddrs;
+
+	/* Look for this interface in the list */
+	ifr_end = (struct ifreq *) (ifconf.ifc_buf + ifconf.ifc_len);
+
+#define _IFREQ_LEN(p) \
+  (sizeof((p)->ifr_name) + sysdep_sa_len(&(p)->ifr_addr) > sizeof(struct ifreq) \
+    ? sizeof((p)->ifr_name) + sysdep_sa_len(&(p)->ifr_addr) : sizeof(struct ifreq))
+
+	for (ifr = ifconf.ifc_req;
+	     ifr < ifr_end;
+	     ifr = (struct ifreq *)((caddr_t)ifr + _IFREQ_LEN(ifr))) {
+
+		switch (ifr->ifr_addr.sa_family) {
+		case AF_INET:
+#ifdef INET6
+		case AF_INET6:
+#endif
+			if (!suitable_ifaddr(ifr->ifr_name, &ifr->ifr_addr)) {
+				plog(LLV_ERROR, LOCATION, NULL,
+					"unsuitable address: %s %s\n",
+					ifr->ifr_name,
+					saddrwop2str(&ifr->ifr_addr));
+				continue;
+			}
+
+			p = newmyaddr();
+			if (p == NULL) {
+				exit(1);
+				/*NOTREACHED*/
+			}
+			p->addr = dupsaddr(&ifr->ifr_addr);
+			if (p->addr == NULL) {
+				exit(1);
+				/*NOTREACHED*/
+			}
+#ifdef INET6
+#ifdef __KAME__
+			sin6 = (struct sockaddr_in6 *)p->addr;
+			if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)
+			 || IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr)) {
+				sin6->sin6_scope_id =
+					ntohs(*(u_int16_t *)&sin6->sin6_addr.s6_addr[2]);
+				sin6->sin6_addr.s6_addr[2] = 0;
+				sin6->sin6_addr.s6_addr[3] = 0;
+			}
+#endif
+#endif
+			if (getnameinfo(p->addr, sysdep_sa_len(p->addr),
+					addr1, sizeof(addr1),
+					NULL, 0,
+					NI_NUMERICHOST | niflags))
+			strlcpy(addr1, "(invalid)", sizeof(addr1));
+			plog(LLV_DEBUG, LOCATION, NULL,
+				"my interface: %s (%s)\n",
+				addr1, ifr->ifr_name);
+			q = find_myaddr(old, p);
+			if (q)
+				p->sock = q->sock;
+			else
+				p->sock = -1;
+			p->next = lcconf->myaddrs;
+			lcconf->myaddrs = p;
+			break;
+		default:
+			break;
+		}
+	}
+
+	clear_myaddr(&old);
+
+	racoon_free(iflist);
+#endif /*HAVE_GETIFADDRS*/
+}
+
+/*
+ * check the interface is suitable or not
+ */
+static int
+suitable_ifaddr(ifname, ifaddr)
+	const char *ifname;
+	const struct sockaddr *ifaddr;
+{
+#ifdef ENABLE_HYBRID
+	/* Exclude any address we got through ISAKMP mode config */
+	if (exclude_cfg_addr(ifaddr) == 0)
+		return 0;
+#endif
+	switch(ifaddr->sa_family) {
+	case AF_INET:
+		return 1;
+#ifdef INET6
+	case AF_INET6:
+		return suitable_ifaddr6(ifname, ifaddr);
+#endif
+	default:
+		return 0;
+	}
+	/*NOTREACHED*/
+}
+
+#ifdef INET6
+static int
+suitable_ifaddr6(ifname, ifaddr)
+	const char *ifname;
+	const struct sockaddr *ifaddr;
+{
+#ifndef __linux__
+	struct in6_ifreq ifr6;
+	int s;
+#endif
+
+	if (ifaddr->sa_family != AF_INET6)
+		return 0;
+
+#ifndef __linux__
+	s = socket(PF_INET6, SOCK_DGRAM, 0);
+	if (s == -1) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"socket(SOCK_DGRAM) failed:%s\n", strerror(errno));
+		return 0;
+	}
+
+	memset(&ifr6, 0, sizeof(ifr6));
+	strncpy(ifr6.ifr_name, ifname, strlen(ifname));
+
+	ifr6.ifr_addr = *(const struct sockaddr_in6 *)ifaddr;
+
+	if (ioctl(s, SIOCGIFAFLAG_IN6, &ifr6) < 0) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"ioctl(SIOCGIFAFLAG_IN6) failed:%s\n", strerror(errno));
+		close(s);
+		return 0;
+	}
+
+	close(s);
+
+	if (ifr6.ifr_ifru.ifru_flags6 & IN6_IFF_DUPLICATED
+	 || ifr6.ifr_ifru.ifru_flags6 & IN6_IFF_DETACHED
+	 || ifr6.ifr_ifru.ifru_flags6 & IN6_IFF_ANYCAST)
+		return 0;
+#endif
+
+	/* suitable */
+	return 1;
+}
+#endif
+
+int
+update_myaddrs()
+{
+#ifdef __linux__
+	char msg[BUFSIZ];
+	int len;
+	struct nlmsghdr *h = (void*)msg;
+	len = read(lcconf->rtsock, msg, sizeof(msg));
+	if (len < 0)
+		return errno == ENOBUFS;
+	if (len < sizeof(*h))
+		return 0;
+	if (h->nlmsg_pid) /* not from kernel! */
+		return 0;
+	if (h->nlmsg_type == RTM_NEWLINK)
+		return 0;
+	plog(LLV_DEBUG, LOCATION, NULL,
+		"netlink signals update interface address list\n");
+	return 1;
+#else
+	char msg[BUFSIZ];
+	int len;
+	struct rt_msghdr *rtm;
+
+	len = read(lcconf->rtsock, msg, sizeof(msg));
+	if (len < 0) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"read(PF_ROUTE) failed: %s\n",
+			strerror(errno));
+		return 0;
+	}
+	rtm = (struct rt_msghdr *)msg;
+	if (len < rtm->rtm_msglen) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"read(PF_ROUTE) short read\n");
+		return 0;
+	}
+	if (rtm->rtm_version != RTM_VERSION) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"routing socket version mismatch\n");
+		close(lcconf->rtsock);
+		lcconf->rtsock = -1;
+		return 0;
+	}
+	switch (rtm->rtm_type) {
+	case RTM_NEWADDR:
+	case RTM_DELADDR:
+	case RTM_DELETE:
+	case RTM_IFINFO:
+		break;
+	case RTM_MISS:
+		/* ignore this message silently */
+		return 0;
+	default:
+		plog(LLV_DEBUG, LOCATION, NULL,
+			"msg %d not interesting\n", rtm->rtm_type);
+		return 0;
+	}
+	/* XXX more filters here? */
+
+	plog(LLV_DEBUG, LOCATION, NULL,
+		"caught rtm:%d, need update interface address list\n",
+		rtm->rtm_type);
+	return 1;
+#endif /* __linux__ */
+}
+
+/*
+ * initialize default port for ISAKMP to send, if no "listen"
+ * directive is specified in config file.
+ *
+ * DO NOT listen to wildcard addresses.  if you receive packets to
+ * wildcard address, you'll be in trouble (DoS attack possible by
+ * broadcast storm).
+ */
+int
+autoconf_myaddrsport()
+{
+	struct myaddrs *p;
+	int n;
+
+	plog(LLV_DEBUG, LOCATION, NULL,
+		"configuring default isakmp port.\n");
+
+#ifdef ENABLE_NATT
+	if (natt_enabled_in_rmconf ()) {
+		plog(LLV_NOTIFY, LOCATION, NULL, "NAT-T is enabled, autoconfiguring ports\n");
+		for (p = lcconf->myaddrs; p; p = p->next) {
+			struct myaddrs *new;
+			if (! p->udp_encap) {
+				new = dupmyaddr(p);
+				new->udp_encap = 1;
+			}
+		}
+	}
+#endif
+
+	for (p = lcconf->myaddrs, n = 0; p; p = p->next, n++) {
+		set_port (p->addr, p->udp_encap ? lcconf->port_isakmp_natt : lcconf->port_isakmp);
+	}
+	plog(LLV_DEBUG, LOCATION, NULL,
+		"%d addrs are configured successfully\n", n);
+
+	return 0;
+}
+
+/*
+ * get a port number to which racoon binded.
+ */
+u_short
+getmyaddrsport(local)
+	struct sockaddr *local;
+{
+	struct myaddrs *p, *bestmatch = NULL;
+	u_short bestmatch_port = PORT_ISAKMP;
+
+	/* get a relative port */
+	for (p = lcconf->myaddrs; p; p = p->next) {
+		if (!p->addr)
+			continue;
+		if (cmpsaddrwop(local, p->addr))
+			continue;
+
+		/* use first matching address regardless of port */
+		if (!bestmatch) {
+			bestmatch = p;
+			continue;
+		}
+
+		/* matching address with port PORT_ISAKMP */
+		if (extract_port(p->addr) == PORT_ISAKMP) {
+			bestmatch = p;
+			bestmatch_port = PORT_ISAKMP;
+		}
+	}
+
+	return bestmatch_port;
+}
+
+struct myaddrs *
+newmyaddr()
+{
+	struct myaddrs *new;
+
+	new = racoon_calloc(1, sizeof(*new));
+	if (new == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"failed to allocate buffer for myaddrs.\n");
+		return NULL;
+	}
+
+	new->next = NULL;
+	new->addr = NULL;
+
+	return new;
+}
+
+struct myaddrs *
+dupmyaddr(struct myaddrs *old)
+{
+	struct myaddrs *new;
+
+	new = racoon_calloc(1, sizeof(*new));
+	if (new == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"failed to allocate buffer for myaddrs.\n");
+		return NULL;
+	}
+
+	/* Copy the whole structure and set the differences.  */
+	memcpy (new, old, sizeof (*new));
+	new->addr = dupsaddr (old->addr);
+	if (new->addr == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"failed to allocate buffer for myaddrs.\n");
+		racoon_free(new);
+		return NULL;
+	}
+	new->next = old->next;
+	old->next = new;
+
+	return new;
+}
+
+void
+insmyaddr(new, head)
+	struct myaddrs *new;
+	struct myaddrs **head;
+{
+	new->next = *head;
+	*head = new;
+}
+
+void
+delmyaddr(myaddr)
+	struct myaddrs *myaddr;
+{
+	if (myaddr->addr)
+		racoon_free(myaddr->addr);
+	racoon_free(myaddr);
+}
+
+int
+initmyaddr()
+{
+	/* initialize routing socket */
+	lcconf->rtsock = socket(PF_ROUTE, SOCK_RAW, PF_UNSPEC);
+	if (lcconf->rtsock < 0) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"socket(PF_ROUTE) failed: %s",
+			strerror(errno));
+		return -1;
+	}
+
+#ifdef __linux__
+   {
+	struct sockaddr_nl nl;
+	u_int addr_len;
+
+	memset(&nl, 0, sizeof(nl));
+	nl.nl_family = AF_NETLINK;
+	nl.nl_groups = RTMGRP_IPV4_IFADDR|RTMGRP_LINK|RTMGRP_IPV6_IFADDR;
+
+	if (bind(lcconf->rtsock, (struct sockaddr*)&nl, sizeof(nl)) < 0) {
+		plog(LLV_ERROR, LOCATION, NULL,
+		     "bind(PF_NETLINK) failed: %s\n",
+		     strerror(errno));
+		return -1;
+	}
+	addr_len = sizeof(nl);
+	if (getsockname(lcconf->rtsock, (struct sockaddr*)&nl, &addr_len) < 0) {
+		plog(LLV_ERROR, LOCATION, NULL,
+		     "getsockname(PF_NETLINK) failed: %s\n",
+		     strerror(errno));
+		return -1;
+	}
+   }
+#endif
+
+	if (lcconf->myaddrs == NULL && lcconf->autograbaddr == 1) {
+		grab_myaddrs();
+
+		if (autoconf_myaddrsport() < 0)
+			return -1;
+	}
+
+	return 0;
+}
+
+/* select the socket to be sent */
+/* should implement other method. */
+int
+getsockmyaddr(my)
+	struct sockaddr *my;
+{
+	struct myaddrs *p, *lastresort = NULL;
+#if defined(INET6) && defined(__linux__)
+	struct myaddrs *match_wo_scope_id = NULL;
+	int check_wo_scope_id = (my->sa_family == AF_INET6) && 
+		IN6_IS_ADDR_LINKLOCAL(&((struct sockaddr_in6 *)my)->sin6_addr);
+#endif
+
+	for (p = lcconf->myaddrs; p; p = p->next) {
+		if (p->addr == NULL)
+			continue;
+		if (my->sa_family == p->addr->sa_family) {
+			lastresort = p;
+		} else continue;
+		if (sysdep_sa_len(my) == sysdep_sa_len(p->addr)
+		 && memcmp(my, p->addr, sysdep_sa_len(my)) == 0) {
+			break;
+		}
+#if defined(INET6) && defined(__linux__)
+		if (check_wo_scope_id && IN6_IS_ADDR_LINKLOCAL(&((struct sockaddr_in6 *)p->addr)->sin6_addr) &&
+			/* XXX: this depends on sin6_scope_id to be last
+			 * item in struct sockaddr_in6 */
+			memcmp(my, p->addr, 
+				sysdep_sa_len(my) - sizeof(uint32_t)) == 0) {
+			match_wo_scope_id = p;
+		}
+#endif
+	}
+#if defined(INET6) && defined(__linux__)
+	if (!p)
+		p = match_wo_scope_id;
+#endif
+	if (!p)
+		p = lastresort;
+	if (!p) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"no socket matches address family %d\n",
+			my->sa_family);
+		return -1;
+	}
+
+	return p->sock;
+}
diff --git a/src/racoon/grabmyaddr.h b/src/racoon/grabmyaddr.h
new file mode 100644
index 0000000..ac74b46
--- /dev/null
+++ b/src/racoon/grabmyaddr.h
@@ -0,0 +1,56 @@
+/*	$NetBSD: grabmyaddr.h,v 1.4 2006/09/09 16:22:09 manu Exp $	*/
+
+/* Id: grabmyaddr.h,v 1.5 2004/06/11 16:00:16 ludvigm Exp */
+
+/*
+ * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _GRABMYADDR_H
+#define _GRABMYADDR_H
+
+struct myaddrs {
+	struct myaddrs *next;
+	struct sockaddr *addr;
+	int sock;
+	int udp_encap;
+};
+
+extern void clear_myaddr __P((struct myaddrs **));
+extern void grab_myaddrs __P((void));
+extern int update_myaddrs __P((void));
+extern int autoconf_myaddrsport __P((void));
+extern u_short getmyaddrsport __P((struct sockaddr *));
+extern struct myaddrs *newmyaddr __P((void));
+extern struct myaddrs *dupmyaddr __P((struct myaddrs *));
+extern void insmyaddr __P((struct myaddrs *, struct myaddrs **));
+extern void delmyaddr __P((struct myaddrs *));
+extern int initmyaddr __P((void));
+extern int getsockmyaddr __P((struct sockaddr *));
+
+#endif /* _GRABMYADDR_H */
diff --git a/src/racoon/gssapi.c b/src/racoon/gssapi.c
new file mode 100644
index 0000000..e64b201
--- /dev/null
+++ b/src/racoon/gssapi.c
@@ -0,0 +1,749 @@
+/*	$NetBSD: gssapi.c,v 1.4 2006/09/09 16:22:09 manu Exp $	*/
+
+/*	$KAME: gssapi.c,v 1.19 2001/04/03 15:51:55 thorpej Exp $	*/
+
+/*
+ * Copyright 2000 Wasabi Systems, Inc.
+ * All rights reserved.
+ *
+ * This software was written by Frank van der Linden of Wasabi Systems
+ * for Zembu Labs, Inc. http://www.zembu.com/
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of Wasabi Systems, Inc. may not be used to endorse
+ *    or promote products derived from this software without specific prior
+ *    written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL WASABI SYSTEMS, INC
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#ifdef HAVE_GSSAPI
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/socket.h>
+#include <netdb.h>
+#include <unistd.h>
+
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#include "var.h"
+#include "misc.h"
+#include "vmbuf.h"
+#include "plog.h"
+#include "sockmisc.h"
+#include "schedule.h"
+#include "debug.h"
+
+#include "localconf.h"
+#include "remoteconf.h"
+#include "isakmp_var.h"
+#include "isakmp.h"
+#include "oakley.h"
+#include "handler.h"
+#include "ipsec_doi.h"
+#include "crypto_openssl.h"
+#include "pfkey.h"
+#include "isakmp_ident.h"
+#include "isakmp_inf.h"
+#include "vendorid.h"
+#include "gcmalloc.h"
+
+#include "gssapi.h"
+
+static void
+gssapi_error(OM_uint32 status_code, const char *where,
+	     const char *fmt, ...)
+{
+	OM_uint32 message_context, maj_stat, min_stat;
+	gss_buffer_desc status_string;
+	va_list ap;
+
+	va_start(ap, fmt);
+	plogv(LLV_ERROR, where, NULL, fmt, ap);
+	va_end(ap);
+
+	message_context = 0;
+
+	do {
+		maj_stat = gss_display_status(&min_stat, status_code,
+		    GSS_C_MECH_CODE, GSS_C_NO_OID, &message_context,
+		    &status_string);
+		if (GSS_ERROR(maj_stat))
+			plog(LLV_ERROR, LOCATION, NULL,
+			    "UNABLE TO GET GSSAPI ERROR CODE\n");
+		else {
+			plog(LLV_ERROR, where, NULL,
+			    "%s\n", (char *)status_string.value);
+			gss_release_buffer(&min_stat, &status_string);
+		}
+	} while (message_context != 0);
+}
+
+/*
+ * vmbufs and gss_buffer_descs are really just the same on NetBSD, but
+ * this is to be portable.
+ */
+static int
+gssapi_vm2gssbuf(vchar_t *vmbuf, gss_buffer_t gsstoken)
+{
+
+	gsstoken->value = racoon_malloc(vmbuf->l);
+	if (gsstoken->value == NULL)
+		return -1;
+	memcpy(gsstoken->value, vmbuf->v, vmbuf->l);
+	gsstoken->length = vmbuf->l;
+
+	return 0;
+}
+
+static int
+gssapi_gss2vmbuf(gss_buffer_t gsstoken, vchar_t **vmbuf)
+{
+
+	*vmbuf = vmalloc(gsstoken->length);
+	if (*vmbuf == NULL)
+		return -1;
+	memcpy((*vmbuf)->v, gsstoken->value, gsstoken->length);
+	(*vmbuf)->l = gsstoken->length;
+
+	return 0;
+}
+
+vchar_t *
+gssapi_get_default_gss_id(void)
+{
+	char name[NI_MAXHOST];
+	vchar_t *gssid;
+
+	if (gethostname(name, sizeof(name)) != 0) {
+		plog(LLV_ERROR, LOCATION, NULL, "gethostname failed: %s\n",
+		    strerror(errno));
+		return (NULL);
+	}
+	name[sizeof(name) - 1] = '\0';
+
+	gssid = racoon_malloc(sizeof(*gssid));
+	gssid->l = asprintf(&gssid->v, "%s/%s", GSSAPI_DEF_NAME, name);
+
+	return (gssid);
+}
+
+static int
+gssapi_get_default_name(struct ph1handle *iph1, int remote, gss_name_t *service)
+{
+	char name[NI_MAXHOST];
+	struct sockaddr *sa;
+	char* buf = NULL;
+	gss_buffer_desc name_token;
+	OM_uint32 min_stat, maj_stat;
+
+	sa = remote ? iph1->remote : iph1->local;
+
+	if (getnameinfo(sa, sysdep_sa_len(sa), name, NI_MAXHOST, NULL, 0, 0) != 0)
+		return -1;
+
+	name_token.length = asprintf(&buf, "%s@%s", GSSAPI_DEF_NAME, name);
+	name_token.value = buf;
+
+	maj_stat = gss_import_name(&min_stat, &name_token,
+	    GSS_C_NT_HOSTBASED_SERVICE, service);
+	if (GSS_ERROR(maj_stat)) {
+		gssapi_error(min_stat, LOCATION, "import name\n");
+		maj_stat = gss_release_buffer(&min_stat, &name_token);
+		if (GSS_ERROR(maj_stat))
+			gssapi_error(min_stat, LOCATION, "release name_token");
+		return -1;
+	}
+	maj_stat = gss_release_buffer(&min_stat, &name_token);
+	if (GSS_ERROR(maj_stat))
+		gssapi_error(min_stat, LOCATION, "release name_token");
+
+	return 0;
+}
+
+static int
+gssapi_init(struct ph1handle *iph1)
+{
+	struct gssapi_ph1_state *gps;
+	gss_buffer_desc id_token, cred_token;
+	gss_buffer_t cred = &cred_token;
+	gss_name_t princ, canon_princ;
+	OM_uint32 maj_stat, min_stat;
+
+	gps = racoon_calloc(1, sizeof (struct gssapi_ph1_state));
+	if (gps == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL, "racoon_calloc failed\n");
+		return -1;
+	}
+	gps->gss_context = GSS_C_NO_CONTEXT;
+	gps->gss_cred = GSS_C_NO_CREDENTIAL;
+
+	gssapi_set_state(iph1, gps);
+
+	if (iph1->rmconf->proposal->gssid != NULL) {
+		id_token.length = iph1->rmconf->proposal->gssid->l;
+		id_token.value = iph1->rmconf->proposal->gssid->v;
+		maj_stat = gss_import_name(&min_stat, &id_token, GSS_C_NO_OID,
+		    &princ);
+		if (GSS_ERROR(maj_stat)) {
+			gssapi_error(min_stat, LOCATION, "import name\n");
+			gssapi_free_state(iph1);
+			return -1;
+		}
+	} else
+		gssapi_get_default_name(iph1, 0, &princ);
+
+	maj_stat = gss_canonicalize_name(&min_stat, princ, GSS_C_NO_OID,
+	    &canon_princ);
+	if (GSS_ERROR(maj_stat)) {
+		gssapi_error(min_stat, LOCATION, "canonicalize name\n");
+		maj_stat = gss_release_name(&min_stat, &princ);
+		if (GSS_ERROR(maj_stat))
+			gssapi_error(min_stat, LOCATION, "release princ\n");
+		gssapi_free_state(iph1);
+		return -1;
+	}
+	maj_stat = gss_release_name(&min_stat, &princ);
+	if (GSS_ERROR(maj_stat))
+		gssapi_error(min_stat, LOCATION, "release princ\n");
+
+	maj_stat = gss_export_name(&min_stat, canon_princ, cred);
+	if (GSS_ERROR(maj_stat)) {
+		gssapi_error(min_stat, LOCATION, "export name\n");
+		maj_stat = gss_release_name(&min_stat, &canon_princ);
+		if (GSS_ERROR(maj_stat))
+			gssapi_error(min_stat, LOCATION,
+			    "release canon_princ\n");
+		gssapi_free_state(iph1);
+		return -1;
+	}
+
+#if 0
+	/*
+	 * XXXJRT Did this debug message ever work?  This is a GSS name
+	 * blob at this point.
+	 */
+	plog(LLV_DEBUG, LOCATION, NULL, "will try to acquire '%.*s' creds\n",
+	    cred->length, cred->value);
+#endif
+
+	maj_stat = gss_release_buffer(&min_stat, cred);
+	if (GSS_ERROR(maj_stat))
+		gssapi_error(min_stat, LOCATION, "release cred buffer\n");
+
+	maj_stat = gss_acquire_cred(&min_stat, canon_princ, GSS_C_INDEFINITE,
+	    GSS_C_NO_OID_SET, GSS_C_BOTH, &gps->gss_cred, NULL, NULL);
+	if (GSS_ERROR(maj_stat)) {
+		gssapi_error(min_stat, LOCATION, "acquire cred\n");
+		maj_stat = gss_release_name(&min_stat, &canon_princ);
+		if (GSS_ERROR(maj_stat))
+			gssapi_error(min_stat, LOCATION,
+			    "release canon_princ\n");
+		gssapi_free_state(iph1);
+		return -1;
+	}
+	maj_stat = gss_release_name(&min_stat, &canon_princ);
+	if (GSS_ERROR(maj_stat))
+		gssapi_error(min_stat, LOCATION, "release canon_princ\n");
+
+	return 0;
+}
+
+int
+gssapi_get_itoken(struct ph1handle *iph1, int *lenp)
+{
+	struct gssapi_ph1_state *gps;
+	gss_buffer_desc empty, name_token;
+	gss_buffer_t itoken, rtoken, dummy;
+	OM_uint32 maj_stat, min_stat;
+	gss_name_t partner;
+
+	if (gssapi_get_state(iph1) == NULL && gssapi_init(iph1) < 0)
+		return -1;
+
+	gps = gssapi_get_state(iph1);
+
+	empty.length = 0;
+	empty.value = NULL;
+	dummy = &empty;
+
+	if (iph1->approval != NULL && iph1->approval->gssid != NULL) {
+		plog(LLV_DEBUG, LOCATION, NULL,
+		    "using provided service '%.*s'\n",
+		    (int)iph1->approval->gssid->l, iph1->approval->gssid->v);
+		name_token.length = iph1->approval->gssid->l;
+		name_token.value = iph1->approval->gssid->v;
+		maj_stat = gss_import_name(&min_stat, &name_token,
+		    GSS_C_NO_OID, &partner);
+		if (GSS_ERROR(maj_stat)) {
+			gssapi_error(min_stat, LOCATION, "import of %.*s\n",
+			    name_token.length, name_token.value);
+			return -1;
+		}
+	} else
+		if (gssapi_get_default_name(iph1, 1, &partner) < 0)
+			return -1;
+
+	rtoken = gps->gsscnt_p == 0 ? dummy : &gps->gss_p[gps->gsscnt_p - 1];
+	itoken = &gps->gss[gps->gsscnt];
+
+	gps->gss_status = gss_init_sec_context(&min_stat, gps->gss_cred,
+	    &gps->gss_context, partner, GSS_C_NO_OID,
+	    GSS_C_MUTUAL_FLAG | GSS_C_SEQUENCE_FLAG |
+		GSS_C_CONF_FLAG | GSS_C_INTEG_FLAG,
+	    0, GSS_C_NO_CHANNEL_BINDINGS, rtoken, NULL,
+	    itoken, NULL, NULL);
+
+	if (GSS_ERROR(gps->gss_status)) {
+		gssapi_error(min_stat, LOCATION, "init_sec_context\n");
+		maj_stat = gss_release_name(&min_stat, &partner);
+		if (GSS_ERROR(maj_stat))
+			gssapi_error(min_stat, LOCATION, "release name\n");
+		return -1;
+	}
+	maj_stat = gss_release_name(&min_stat, &partner);
+	if (GSS_ERROR(maj_stat))
+		gssapi_error(min_stat, LOCATION, "release name\n");
+
+	plog(LLV_DEBUG, LOCATION, NULL, "gss_init_sec_context status %x\n",
+	    gps->gss_status);
+
+	if (lenp)
+		*lenp = itoken->length;
+
+	if (itoken->length != 0)
+		gps->gsscnt++;
+
+	return 0;
+}
+
+/*
+ * Call gss_accept_context, with token just read from the wire.
+ */
+int
+gssapi_get_rtoken(struct ph1handle *iph1, int *lenp)
+{
+	struct gssapi_ph1_state *gps;
+	gss_buffer_desc name_token;
+	gss_buffer_t itoken, rtoken;
+	OM_uint32 min_stat, maj_stat;
+	gss_name_t client_name;
+
+	if (gssapi_get_state(iph1) == NULL && gssapi_init(iph1) < 0)
+		return -1;
+
+	gps = gssapi_get_state(iph1);
+
+	rtoken = &gps->gss_p[gps->gsscnt_p - 1];
+	itoken = &gps->gss[gps->gsscnt];
+
+	gps->gss_status = gss_accept_sec_context(&min_stat, &gps->gss_context,
+	    gps->gss_cred, rtoken, GSS_C_NO_CHANNEL_BINDINGS, &client_name,
+	    NULL, itoken, NULL, NULL, NULL);
+
+	if (GSS_ERROR(gps->gss_status)) {
+		gssapi_error(min_stat, LOCATION, "accept_sec_context\n");
+		return -1;
+	}
+
+	maj_stat = gss_display_name(&min_stat, client_name, &name_token, NULL);
+	if (GSS_ERROR(maj_stat)) {
+		gssapi_error(min_stat, LOCATION, "gss_display_name\n");
+		maj_stat = gss_release_name(&min_stat, &client_name);
+		if (GSS_ERROR(maj_stat))
+			gssapi_error(min_stat, LOCATION,
+			    "release client_name\n");
+		return -1;
+	}
+	maj_stat = gss_release_name(&min_stat, &client_name);
+	if (GSS_ERROR(maj_stat))
+		gssapi_error(min_stat, LOCATION, "release client_name\n");
+
+	plog(LLV_DEBUG, LOCATION, NULL,
+		"gss_accept_sec_context: other side is %s\n",
+		(char *)name_token.value);
+	maj_stat = gss_release_buffer(&min_stat, &name_token);
+	if (GSS_ERROR(maj_stat))
+		gssapi_error(min_stat, LOCATION, "release name buffer\n");
+
+	if (itoken->length != 0)
+		gps->gsscnt++;
+
+	if (lenp)
+		*lenp = itoken->length;
+
+	return 0;
+}
+
+int
+gssapi_save_received_token(struct ph1handle *iph1, vchar_t *token)
+{
+	struct gssapi_ph1_state *gps;
+	gss_buffer_t gsstoken;
+	int ret;
+
+	if (gssapi_get_state(iph1) == NULL && gssapi_init(iph1) < 0)
+		return -1;
+
+	gps = gssapi_get_state(iph1);
+
+	gsstoken = &gps->gss_p[gps->gsscnt_p];
+
+	ret = gssapi_vm2gssbuf(token, gsstoken);
+	if (ret < 0)
+		return ret;
+	gps->gsscnt_p++;
+
+	return 0;
+}
+
+int
+gssapi_get_token_to_send(struct ph1handle *iph1, vchar_t **token)
+{
+	struct gssapi_ph1_state *gps;
+	gss_buffer_t gsstoken;
+	int ret;
+
+	gps = gssapi_get_state(iph1);
+	if (gps == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL,
+		    "gssapi not yet initialized?\n");
+		return -1;
+	}
+	gsstoken = &gps->gss[gps->gsscnt - 1];
+	ret = gssapi_gss2vmbuf(gsstoken, token);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+int
+gssapi_get_itokens(struct ph1handle *iph1, vchar_t **tokens)
+{
+	struct gssapi_ph1_state *gps;
+	int len, i;
+	vchar_t *toks;
+	char *p;
+
+	gps = gssapi_get_state(iph1);
+	if (gps == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL,
+		    "gssapi not yet initialized?\n");
+		return -1;
+	}
+
+	for (i = len = 0; i < gps->gsscnt; i++)
+		len += gps->gss[i].length;
+
+	toks = vmalloc(len);
+	if (toks == 0)
+		return -1;
+	p = (char *)toks->v;
+	for (i = 0; i < gps->gsscnt; i++) {
+		memcpy(p, gps->gss[i].value, gps->gss[i].length);
+		p += gps->gss[i].length;
+	}
+
+	*tokens = toks;
+
+	plog(LLV_DEBUG, LOCATION, NULL,
+		"%d itokens of length %zu\n", gps->gsscnt, (*tokens)->l);
+
+	return 0;
+}
+
+int
+gssapi_get_rtokens(struct ph1handle *iph1, vchar_t **tokens)
+{
+	struct gssapi_ph1_state *gps;
+	int len, i;
+	vchar_t *toks;
+	char *p;
+
+	gps = gssapi_get_state(iph1);
+	if (gps == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL,
+		    "gssapi not yet initialized?\n");
+		return -1;
+	}
+
+	if (gssapi_more_tokens(iph1)) {
+		plog(LLV_ERROR, LOCATION, NULL,
+		    "gssapi roundtrips not complete\n");
+		return -1;
+	}
+
+	for (i = len = 0; i < gps->gsscnt_p; i++)
+		len += gps->gss_p[i].length;
+
+	toks = vmalloc(len);
+	if (toks == 0)
+		return -1;
+	p = (char *)toks->v;
+	for (i = 0; i < gps->gsscnt_p; i++) {
+		memcpy(p, gps->gss_p[i].value, gps->gss_p[i].length);
+		p += gps->gss_p[i].length;
+	}
+
+	*tokens = toks;
+
+	return 0;
+}
+
+vchar_t *
+gssapi_wraphash(struct ph1handle *iph1)
+{
+	struct gssapi_ph1_state *gps;
+	OM_uint32 maj_stat, min_stat;
+	gss_buffer_desc hash_in_buf, hash_out_buf;
+	gss_buffer_t hash_in = &hash_in_buf, hash_out = &hash_out_buf;
+	vchar_t *outbuf;
+
+	gps = gssapi_get_state(iph1);
+	if (gps == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL,
+		    "gssapi not yet initialized?\n");
+		return NULL;
+	}
+
+	if (gssapi_more_tokens(iph1)) {
+		plog(LLV_ERROR, LOCATION, NULL,
+		    "gssapi roundtrips not complete\n");
+		return NULL;
+	}
+
+	if (gssapi_vm2gssbuf(iph1->hash, hash_in) < 0) {
+		plog(LLV_ERROR, LOCATION, NULL, "vm2gssbuf failed\n");
+		return NULL;
+	}
+
+	maj_stat = gss_wrap(&min_stat, gps->gss_context, 1, GSS_C_QOP_DEFAULT,
+	    hash_in, NULL, hash_out);
+	if (GSS_ERROR(maj_stat)) {
+		gssapi_error(min_stat, LOCATION, "wrapping hash value\n");
+		maj_stat = gss_release_buffer(&min_stat, hash_in);
+		if (GSS_ERROR(maj_stat))
+			gssapi_error(min_stat, LOCATION,
+			    "release hash_in buffer\n");
+		return NULL;
+	}
+
+	plog(LLV_DEBUG, LOCATION, NULL, "wrapped HASH, ilen %zu olen %zu\n",
+	    hash_in->length, hash_out->length);
+
+	maj_stat = gss_release_buffer(&min_stat, hash_in);
+	if (GSS_ERROR(maj_stat))
+		gssapi_error(min_stat, LOCATION, "release hash_in buffer\n");
+
+	if (gssapi_gss2vmbuf(hash_out, &outbuf) < 0) {
+		plog(LLV_ERROR, LOCATION, NULL, "gss2vmbuf failed\n");
+		maj_stat = gss_release_buffer(&min_stat, hash_out);
+		if (GSS_ERROR(maj_stat))
+			gssapi_error(min_stat, LOCATION,
+			    "release hash_out buffer\n");
+		return NULL;
+	}
+	maj_stat = gss_release_buffer(&min_stat, hash_out);
+	if (GSS_ERROR(maj_stat))
+		gssapi_error(min_stat, LOCATION, "release hash_out buffer\n");
+
+	return outbuf;
+}
+
+vchar_t *
+gssapi_unwraphash(struct ph1handle *iph1)
+{
+	struct gssapi_ph1_state *gps;
+	OM_uint32 maj_stat, min_stat;
+	gss_buffer_desc hashbuf, hash_outbuf;
+	gss_buffer_t hash_in = &hashbuf, hash_out = &hash_outbuf;
+	vchar_t *outbuf;
+
+	gps = gssapi_get_state(iph1);
+	if (gps == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL,
+		    "gssapi not yet initialized?\n");
+		return NULL;
+	}
+
+
+	hashbuf.length = ntohs(iph1->pl_hash->h.len) - sizeof(*iph1->pl_hash);
+	hashbuf.value = (char *)(iph1->pl_hash + 1);
+
+	plog(LLV_DEBUG, LOCATION, NULL, "unwrapping HASH of len %zu\n",
+	    hashbuf.length);
+
+	maj_stat = gss_unwrap(&min_stat, gps->gss_context, hash_in, hash_out,
+	    NULL, NULL);
+	if (GSS_ERROR(maj_stat)) {
+		gssapi_error(min_stat, LOCATION, "unwrapping hash value\n");
+		return NULL;
+	}
+
+	if (gssapi_gss2vmbuf(hash_out, &outbuf) < 0) {
+		plog(LLV_ERROR, LOCATION, NULL, "gss2vmbuf failed\n");
+		maj_stat = gss_release_buffer(&min_stat, hash_out);
+		if (GSS_ERROR(maj_stat))
+			gssapi_error(min_stat, LOCATION,
+			    "release hash_out buffer\n");
+		return NULL;
+	}
+	maj_stat = gss_release_buffer(&min_stat, hash_out);
+	if (GSS_ERROR(maj_stat))
+		gssapi_error(min_stat, LOCATION, "release hash_out buffer\n");
+
+	return outbuf;
+}
+
+void
+gssapi_set_id_sent(struct ph1handle *iph1)
+{
+	struct gssapi_ph1_state *gps;
+
+	gps = gssapi_get_state(iph1);
+
+	gps->gss_flags |= GSSFLAG_ID_SENT;
+}
+
+int
+gssapi_id_sent(struct ph1handle *iph1)
+{
+	struct gssapi_ph1_state *gps;
+
+	gps = gssapi_get_state(iph1);
+
+	return (gps->gss_flags & GSSFLAG_ID_SENT) != 0;
+}
+
+void
+gssapi_set_id_rcvd(struct ph1handle *iph1)
+{
+	struct gssapi_ph1_state *gps;
+
+	gps = gssapi_get_state(iph1);
+
+	gps->gss_flags |= GSSFLAG_ID_RCVD;
+}
+
+int
+gssapi_id_rcvd(struct ph1handle *iph1)
+{
+	struct gssapi_ph1_state *gps;
+
+	gps = gssapi_get_state(iph1);
+
+	return (gps->gss_flags & GSSFLAG_ID_RCVD) != 0;
+}
+
+void
+gssapi_free_state(struct ph1handle *iph1)
+{
+	struct gssapi_ph1_state *gps;
+	OM_uint32 maj_stat, min_stat;
+
+	gps = gssapi_get_state(iph1);
+
+	if (gps == NULL)
+		return;
+
+	gssapi_set_state(iph1, NULL);
+
+	if (gps->gss_cred != GSS_C_NO_CREDENTIAL) {
+		maj_stat = gss_release_cred(&min_stat, &gps->gss_cred);
+		if (GSS_ERROR(maj_stat))
+			gssapi_error(min_stat, LOCATION,
+			    "releasing credentials\n");
+	}
+	racoon_free(gps);
+}
+
+vchar_t *
+gssapi_get_id(struct ph1handle *iph1)
+{
+	gss_buffer_desc id_buffer;
+	gss_buffer_t id = &id_buffer;
+	gss_name_t defname, canon_name;
+	OM_uint32 min_stat, maj_stat;
+	vchar_t *vmbuf;
+
+	if (iph1->rmconf->proposal->gssid != NULL)
+		return (vdup(iph1->rmconf->proposal->gssid));
+
+	if (gssapi_get_default_name(iph1, 0, &defname) < 0)
+		return NULL;
+
+	maj_stat = gss_canonicalize_name(&min_stat, defname, GSS_C_NO_OID,
+	    &canon_name);
+	if (GSS_ERROR(maj_stat)) {
+		gssapi_error(min_stat, LOCATION, "canonicalize name\n");
+		maj_stat = gss_release_name(&min_stat, &defname);
+		if (GSS_ERROR(maj_stat))
+			gssapi_error(min_stat, LOCATION,
+			    "release default name\n");
+		return NULL;
+	}
+	maj_stat = gss_release_name(&min_stat, &defname);
+	if (GSS_ERROR(maj_stat))
+		gssapi_error(min_stat, LOCATION, "release default name\n");
+
+	maj_stat = gss_export_name(&min_stat, canon_name, id);
+	if (GSS_ERROR(maj_stat)) {
+		gssapi_error(min_stat, LOCATION, "export name\n");
+		maj_stat = gss_release_name(&min_stat, &canon_name);
+		if (GSS_ERROR(maj_stat))
+			gssapi_error(min_stat, LOCATION,
+			    "release canonical name\n");
+		return NULL;
+	}
+	maj_stat = gss_release_name(&min_stat, &canon_name);
+	if (GSS_ERROR(maj_stat))
+		gssapi_error(min_stat, LOCATION, "release canonical name\n");
+
+#if 0
+	/*
+	 * XXXJRT Did this debug message ever work?  This is a GSS name
+	 * blob at this point.
+	 */
+	plog(LLV_DEBUG, LOCATION, NULL, "will try to acquire '%.*s' creds\n",
+	    id->length, id->value);
+#endif
+
+	if (gssapi_gss2vmbuf(id, &vmbuf) < 0) {
+		plog(LLV_ERROR, LOCATION, NULL, "gss2vmbuf failed\n");
+		maj_stat = gss_release_buffer(&min_stat, id);
+		if (GSS_ERROR(maj_stat))
+			gssapi_error(min_stat, LOCATION, "release id buffer\n");
+		return NULL;
+	}
+	maj_stat = gss_release_buffer(&min_stat, id);
+	if (GSS_ERROR(maj_stat))
+		gssapi_error(min_stat, LOCATION, "release id buffer\n");
+
+	return vmbuf;
+}
+#else
+int __gssapi_dUmMy;
+#endif
diff --git a/src/racoon/gssapi.h b/src/racoon/gssapi.h
new file mode 100644
index 0000000..25c6c48
--- /dev/null
+++ b/src/racoon/gssapi.h
@@ -0,0 +1,91 @@
+/*	$NetBSD: gssapi.h,v 1.4 2006/09/09 16:22:09 manu Exp $	*/
+
+/* Id: gssapi.h,v 1.5 2005/02/11 06:59:01 manubsd Exp */
+
+/*
+ * Copyright 2000 Wasabi Systems, Inc.
+ * All rights reserved.
+ *
+ * This software was written by Frank van der Linden of Wasabi Systems
+ * for Zembu Labs, Inc. http://www.zembu.com/
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of Wasabi Systems, Inc. may not be used to endorse
+ *    or promote products derived from this software without specific prior
+ *    written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL WASABI SYSTEMS, INC
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifdef __FreeBSD__
+#include "/usr/include/gssapi.h"
+#else
+#include <gssapi/gssapi.h>
+#endif
+
+#define GSSAPI_DEF_NAME         "host"
+
+struct ph1handle;
+struct isakmpsa;
+
+struct gssapi_ph1_state {
+	int gsscnt;			/* # of token we're working on */
+	int gsscnt_p;			/* # of token we're working on */
+
+	gss_buffer_desc gss[3];		/* gss-api tokens. */
+					/* NOTE: XXX this restricts the max # */
+					/* to 3. More should never happen */
+
+	gss_buffer_desc gss_p[3];
+
+	gss_ctx_id_t gss_context;	/* context for gss_init_sec_context */
+
+	OM_uint32 gss_status;		/* retval from gss_init_sec_context */
+	gss_cred_id_t gss_cred;		/* acquired credentials */
+
+	int gss_flags;
+#define GSSFLAG_ID_SENT		0x0001
+#define GSSFLAG_ID_RCVD		0x0001
+};
+
+#define	gssapi_get_state(ph)						\
+	((struct gssapi_ph1_state *)((ph)->gssapi_state))
+
+#define	gssapi_set_state(ph, st)					\
+	(ph)->gssapi_state = (st)
+
+#define	gssapi_more_tokens(ph)						\
+	((gssapi_get_state(ph)->gss_status & GSS_S_CONTINUE_NEEDED) != 0)
+
+int gssapi_get_itoken __P((struct ph1handle *, int *));
+int gssapi_get_rtoken __P((struct ph1handle *, int *));
+int gssapi_save_received_token __P((struct ph1handle *, vchar_t *));
+int gssapi_get_token_to_send __P((struct ph1handle *, vchar_t **));
+int gssapi_get_itokens __P((struct ph1handle *, vchar_t **));
+int gssapi_get_rtokens __P((struct ph1handle *, vchar_t **));
+vchar_t *gssapi_wraphash __P((struct ph1handle *));
+vchar_t *gssapi_unwraphash __P((struct ph1handle *));
+void gssapi_set_id_sent __P((struct ph1handle *));
+int gssapi_id_sent __P((struct ph1handle *));
+void gssapi_set_id_rcvd __P((struct ph1handle *));
+int gssapi_id_rcvd __P((struct ph1handle *));
+void gssapi_free_state __P((struct ph1handle *));
+vchar_t *gssapi_get_id __P((struct ph1handle *));
+vchar_t *gssapi_get_default_gss_id __P((void));
diff --git a/src/racoon/handler.c b/src/racoon/handler.c
new file mode 100644
index 0000000..d75768d
--- /dev/null
+++ b/src/racoon/handler.c
@@ -0,0 +1,1571 @@
+/*	$NetBSD: handler.c,v 1.9.6.7 2008/01/11 14:12:00 vanhu Exp $	*/
+
+/* Id: handler.c,v 1.28 2006/05/26 12:17:29 manubsd Exp */
+
+/*
+ * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <time.h>
+#include <errno.h>
+
+#include "var.h"
+#include "misc.h"
+#include "vmbuf.h"
+#include "plog.h"
+#include "sockmisc.h"
+#include "debug.h"
+
+#ifdef ENABLE_HYBRID
+#include <resolv.h>
+#endif
+
+#include "schedule.h"
+#include "grabmyaddr.h"
+#include "algorithm.h"
+#include "crypto_openssl.h"
+#include "policy.h"
+#include "proposal.h"
+#include "isakmp_var.h"
+#include "evt.h"
+#include "isakmp.h"
+#ifdef ENABLE_HYBRID
+#include "isakmp_xauth.h"  
+#include "isakmp_cfg.h"
+#endif
+#include "isakmp_inf.h"
+#include "oakley.h"
+#include "remoteconf.h"
+#include "localconf.h"
+#include "handler.h"
+#include "gcmalloc.h"
+#include "nattraversal.h"
+
+#include "sainfo.h"
+
+#ifdef HAVE_GSSAPI
+#include "gssapi.h"
+#endif
+
+static LIST_HEAD(_ph1tree_, ph1handle) ph1tree;
+static LIST_HEAD(_ph2tree_, ph2handle) ph2tree;
+static LIST_HEAD(_ctdtree_, contacted) ctdtree;
+static LIST_HEAD(_rcptree_, recvdpkt) rcptree;
+
+static void del_recvdpkt __P((struct recvdpkt *));
+static void rem_recvdpkt __P((struct recvdpkt *));
+static void sweep_recvdpkt __P((void *));
+
+/*
+ * functions about management of the isakmp status table
+ */
+/* %%% management phase 1 handler */
+/*
+ * search for isakmpsa handler with isakmp index.
+ */
+
+extern caddr_t val2str(const char *, size_t);
+
+struct ph1handle *
+getph1byindex(index)
+	isakmp_index *index;
+{
+	struct ph1handle *p;
+
+	LIST_FOREACH(p, &ph1tree, chain) {
+		if (p->status == PHASE1ST_EXPIRED)
+			continue;
+		if (memcmp(&p->index, index, sizeof(*index)) == 0)
+			return p;
+	}
+
+	return NULL;
+}
+
+
+/*
+ * search for isakmp handler by i_ck in index.
+ */
+struct ph1handle *
+getph1byindex0(index)
+	isakmp_index *index;
+{
+	struct ph1handle *p;
+
+	LIST_FOREACH(p, &ph1tree, chain) {
+		if (p->status == PHASE1ST_EXPIRED)
+			continue;
+		if (memcmp(&p->index, index, sizeof(cookie_t)) == 0)
+			return p;
+	}
+
+	return NULL;
+}
+
+/*
+ * search for isakmpsa handler by source and remote address.
+ * don't use port number to search because this function search
+ * with phase 2's destinaion.
+ */
+struct ph1handle *
+getph1byaddr(local, remote, established)
+	struct sockaddr *local, *remote;
+	int established;
+{
+	struct ph1handle *p;
+
+	plog(LLV_DEBUG2, LOCATION, NULL, "getph1byaddr: start\n");
+	plog(LLV_DEBUG2, LOCATION, NULL, "local: %s\n", saddr2str(local));
+	plog(LLV_DEBUG2, LOCATION, NULL, "remote: %s\n", saddr2str(remote));
+
+	LIST_FOREACH(p, &ph1tree, chain) {
+		if (p->status == PHASE1ST_EXPIRED)
+			continue;
+		plog(LLV_DEBUG2, LOCATION, NULL, "p->local: %s\n", saddr2str(p->local));
+		plog(LLV_DEBUG2, LOCATION, NULL, "p->remote: %s\n", saddr2str(p->remote));
+
+		if(established && p->status != PHASE1ST_ESTABLISHED){
+			plog(LLV_DEBUG2, LOCATION, NULL, "status %d, skipping\n", p->status);
+			continue;
+		}
+		if (CMPSADDR(local, p->local) == 0
+			&& CMPSADDR(remote, p->remote) == 0){
+			plog(LLV_DEBUG2, LOCATION, NULL, "matched\n");
+			return p;
+		}
+	}
+
+	plog(LLV_DEBUG2, LOCATION, NULL, "no match\n");
+
+	return NULL;
+}
+
+struct ph1handle *
+getph1byaddrwop(local, remote)
+	struct sockaddr *local, *remote;
+{
+	struct ph1handle *p;
+
+	LIST_FOREACH(p, &ph1tree, chain) {
+		if (p->status == PHASE1ST_EXPIRED)
+			continue;
+		if (cmpsaddrwop(local, p->local) == 0
+		 && cmpsaddrwop(remote, p->remote) == 0)
+			return p;
+	}
+
+	return NULL;
+}
+
+/*
+ * search for isakmpsa handler by remote address.
+ * don't use port number to search because this function search
+ * with phase 2's destinaion.
+ */
+struct ph1handle *
+getph1bydstaddrwop(remote)
+	struct sockaddr *remote;
+{
+	struct ph1handle *p;
+
+	LIST_FOREACH(p, &ph1tree, chain) {
+		if (p->status == PHASE1ST_EXPIRED)
+			continue;
+		if (cmpsaddrwop(remote, p->remote) == 0)
+			return p;
+	}
+
+	return NULL;
+}
+
+/*
+ * dump isakmp-sa
+ */
+vchar_t *
+dumpph1()
+{
+	struct ph1handle *iph1;
+	struct ph1dump *pd;
+	int cnt = 0;
+	vchar_t *buf;
+
+	/* get length of buffer */
+	LIST_FOREACH(iph1, &ph1tree, chain)
+		cnt++;
+
+	buf = vmalloc(cnt * sizeof(struct ph1dump));
+	if (buf == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"failed to get buffer\n");
+		return NULL;
+	}
+	pd = (struct ph1dump *)buf->v;
+
+	LIST_FOREACH(iph1, &ph1tree, chain) {
+		memcpy(&pd->index, &iph1->index, sizeof(iph1->index));
+		pd->status = iph1->status;
+		pd->side = iph1->side;
+		memcpy(&pd->remote, iph1->remote, sysdep_sa_len(iph1->remote));
+		memcpy(&pd->local, iph1->local, sysdep_sa_len(iph1->local));
+		pd->version = iph1->version;
+		pd->etype = iph1->etype;
+		pd->created = iph1->created;
+		pd->ph2cnt = iph1->ph2cnt;
+		pd++;
+	}
+
+	return buf;
+}
+
+/*
+ * create new isakmp Phase 1 status record to handle isakmp in Phase1
+ */
+struct ph1handle *
+newph1()
+{
+	struct ph1handle *iph1;
+
+	/* create new iph1 */
+	iph1 = racoon_calloc(1, sizeof(*iph1));
+	if (iph1 == NULL)
+		return NULL;
+
+	iph1->status = PHASE1ST_SPAWN;
+
+#ifdef ENABLE_DPD
+	iph1->dpd_support = 0;
+	iph1->dpd_lastack = 0;
+	iph1->dpd_seq = 0;
+	iph1->dpd_fails = 0;
+	iph1->dpd_r_u = NULL;
+#endif
+
+	return iph1;
+}
+
+/*
+ * delete new isakmp Phase 1 status record to handle isakmp in Phase1
+ */
+void
+delph1(iph1)
+	struct ph1handle *iph1;
+{
+	if (iph1 == NULL)
+		return;
+
+	/* SA down shell script hook */
+	script_hook(iph1, SCRIPT_PHASE1_DOWN);
+
+	EVT_PUSH(iph1->local, iph1->remote, EVTT_PHASE1_DOWN, NULL);
+
+#ifdef ENABLE_NATT
+	if (iph1->natt_flags & NAT_KA_QUEUED)
+		natt_keepalive_remove (iph1->local, iph1->remote);
+
+	if (iph1->natt_options) {
+		racoon_free(iph1->natt_options);
+		iph1->natt_options = NULL;
+	}
+#endif
+
+#ifdef ENABLE_HYBRID
+	if (iph1->mode_cfg)
+		isakmp_cfg_rmstate(iph1);
+#endif
+
+#ifdef ENABLE_DPD
+	SCHED_KILL(iph1->dpd_r_u);
+#endif
+
+	if (iph1->remote) {
+		racoon_free(iph1->remote);
+		iph1->remote = NULL;
+	}
+	if (iph1->local) {
+		racoon_free(iph1->local);
+		iph1->local = NULL;
+	}
+	if (iph1->approval) {
+		delisakmpsa(iph1->approval);
+		iph1->approval = NULL;
+	}
+
+	VPTRINIT(iph1->authstr);
+
+	sched_scrub_param(iph1);
+	iph1->sce = NULL;
+	iph1->scr = NULL;
+
+	VPTRINIT(iph1->sendbuf);
+
+	VPTRINIT(iph1->dhpriv);
+	VPTRINIT(iph1->dhpub);
+	VPTRINIT(iph1->dhpub_p);
+	VPTRINIT(iph1->dhgxy);
+	VPTRINIT(iph1->nonce);
+	VPTRINIT(iph1->nonce_p);
+	VPTRINIT(iph1->skeyid);
+	VPTRINIT(iph1->skeyid_d);
+	VPTRINIT(iph1->skeyid_a);
+	VPTRINIT(iph1->skeyid_e);
+	VPTRINIT(iph1->key);
+	VPTRINIT(iph1->hash);
+	VPTRINIT(iph1->sig);
+	VPTRINIT(iph1->sig_p);
+	oakley_delcert(iph1->cert);
+	iph1->cert = NULL;
+	oakley_delcert(iph1->cert_p);
+	iph1->cert_p = NULL;
+	oakley_delcert(iph1->crl_p);
+	iph1->crl_p = NULL;
+	oakley_delcert(iph1->cr_p);
+	iph1->cr_p = NULL;
+	VPTRINIT(iph1->id);
+	VPTRINIT(iph1->id_p);
+
+	if(iph1->approval != NULL)
+		delisakmpsa(iph1->approval);
+
+	if (iph1->ivm) {
+		oakley_delivm(iph1->ivm);
+		iph1->ivm = NULL;
+	}
+
+	VPTRINIT(iph1->sa);
+	VPTRINIT(iph1->sa_ret);
+
+#ifdef HAVE_GSSAPI
+	VPTRINIT(iph1->gi_i);
+	VPTRINIT(iph1->gi_r);
+
+	gssapi_free_state(iph1);
+#endif
+
+	racoon_free(iph1);
+}
+
+/*
+ * create new isakmp Phase 1 status record to handle isakmp in Phase1
+ */
+int
+insph1(iph1)
+	struct ph1handle *iph1;
+{
+	/* validity check */
+	if (iph1->remote == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"invalid isakmp SA handler. no remote address.\n");
+		return -1;
+	}
+	LIST_INSERT_HEAD(&ph1tree, iph1, chain);
+
+	return 0;
+}
+
+void
+remph1(iph1)
+	struct ph1handle *iph1;
+{
+	LIST_REMOVE(iph1, chain);
+}
+
+/*
+ * flush isakmp-sa
+ */
+void
+flushph1()
+{
+	struct ph1handle *p, *next;
+
+	for (p = LIST_FIRST(&ph1tree); p; p = next) {
+		next = LIST_NEXT(p, chain);
+
+		/* send delete information */
+		if (p->status == PHASE1ST_ESTABLISHED) 
+			isakmp_info_send_d1(p);
+
+		remph1(p);
+		delph1(p);
+	}
+}
+
+void
+initph1tree()
+{
+	LIST_INIT(&ph1tree);
+}
+
+/* %%% management phase 2 handler */
+/*
+ * search ph2handle with policy id.
+ */
+struct ph2handle *
+getph2byspid(spid)
+      u_int32_t spid;
+{
+	struct ph2handle *p;
+
+	LIST_FOREACH(p, &ph2tree, chain) {
+		/*
+		 * there are ph2handle independent on policy
+		 * such like informational exchange.
+		 */
+		if (p->spid == spid)
+			return p;
+	}
+
+	return NULL;
+}
+
+/*
+ * search ph2handle with sequence number.
+ */
+struct ph2handle *
+getph2byseq(seq)
+	u_int32_t seq;
+{
+	struct ph2handle *p;
+
+	LIST_FOREACH(p, &ph2tree, chain) {
+		if (p->seq == seq)
+			return p;
+	}
+
+	return NULL;
+}
+
+/*
+ * search ph2handle with message id.
+ */
+struct ph2handle *
+getph2bymsgid(iph1, msgid)
+	struct ph1handle *iph1;
+	u_int32_t msgid;
+{
+	struct ph2handle *p;
+
+	LIST_FOREACH(p, &ph2tree, chain) {
+		if (p->msgid == msgid)
+			return p;
+	}
+
+	return NULL;
+}
+
+struct ph2handle *
+getph2byid(src, dst, spid)
+	struct sockaddr *src, *dst;
+	u_int32_t spid;
+{
+	struct ph2handle *p;
+
+	LIST_FOREACH(p, &ph2tree, chain) {
+		if (spid == p->spid &&
+		    CMPSADDR(src, p->src) == 0 &&
+		    CMPSADDR(dst, p->dst) == 0){
+			/* Sanity check to detect zombie handlers
+			 * XXX Sould be done "somewhere" more interesting,
+			 * because we have lots of getph2byxxxx(), but this one
+			 * is called by pk_recvacquire(), so is the most important.
+			 */
+			if(p->status < PHASE2ST_ESTABLISHED &&
+			   p->retry_counter == 0
+			   && p->sce == NULL && p->scr == NULL){
+				plog(LLV_DEBUG, LOCATION, NULL,
+					 "Zombie ph2 found, expiring it\n");
+				isakmp_ph2expire(p);
+			}else
+				return p;
+		}
+	}
+
+	return NULL;
+}
+
+struct ph2handle *
+getph2bysaddr(src, dst)
+	struct sockaddr *src, *dst;
+{
+	struct ph2handle *p;
+
+	LIST_FOREACH(p, &ph2tree, chain) {
+		if (cmpsaddrstrict(src, p->src) == 0 &&
+		    cmpsaddrstrict(dst, p->dst) == 0)
+			return p;
+	}
+
+	return NULL;
+}
+
+/*
+ * call by pk_recvexpire().
+ */
+struct ph2handle *
+getph2bysaidx(src, dst, proto_id, spi)
+	struct sockaddr *src, *dst;
+	u_int proto_id;
+	u_int32_t spi;
+{
+	struct ph2handle *iph2;
+	struct saproto *pr;
+
+	LIST_FOREACH(iph2, &ph2tree, chain) {
+		if (iph2->proposal == NULL && iph2->approval == NULL)
+			continue;
+		if (iph2->approval != NULL) {
+			for (pr = iph2->approval->head; pr != NULL;
+			     pr = pr->next) {
+				if (proto_id != pr->proto_id)
+					break;
+				if (spi == pr->spi || spi == pr->spi_p)
+					return iph2;
+			}
+		} else if (iph2->proposal != NULL) {
+			for (pr = iph2->proposal->head; pr != NULL;
+			     pr = pr->next) {
+				if (proto_id != pr->proto_id)
+					break;
+				if (spi == pr->spi)
+					return iph2;
+			}
+		}
+	}
+
+	return NULL;
+}
+
+/*
+ * create new isakmp Phase 2 status record to handle isakmp in Phase2
+ */
+struct ph2handle *
+newph2()
+{
+	struct ph2handle *iph2 = NULL;
+
+	/* create new iph2 */
+	iph2 = racoon_calloc(1, sizeof(*iph2));
+	if (iph2 == NULL)
+		return NULL;
+
+	iph2->status = PHASE1ST_SPAWN;
+
+	return iph2;
+}
+
+/*
+ * initialize ph2handle
+ * NOTE: don't initialize src/dst.
+ *       SPI in the proposal is cleared.
+ */
+void
+initph2(iph2)
+	struct ph2handle *iph2;
+{
+	sched_scrub_param(iph2);
+	iph2->sce = NULL;
+	iph2->scr = NULL;
+
+	VPTRINIT(iph2->sendbuf);
+	VPTRINIT(iph2->msg1);
+
+	/* clear spi, keep variables in the proposal */
+	if (iph2->proposal) {
+		struct saproto *pr;
+		for (pr = iph2->proposal->head; pr != NULL; pr = pr->next)
+			pr->spi = 0;
+	}
+
+	/* clear approval */
+	if (iph2->approval) {
+		flushsaprop(iph2->approval);
+		iph2->approval = NULL;
+	}
+
+	/* clear the generated policy */
+	if (iph2->spidx_gen) {
+		delsp_bothdir((struct policyindex *)iph2->spidx_gen);
+		racoon_free(iph2->spidx_gen);
+		iph2->spidx_gen = NULL;
+	}
+
+	if (iph2->pfsgrp) {
+		oakley_dhgrp_free(iph2->pfsgrp);
+		iph2->pfsgrp = NULL;
+	}
+
+	VPTRINIT(iph2->dhpriv);
+	VPTRINIT(iph2->dhpub);
+	VPTRINIT(iph2->dhpub_p);
+	VPTRINIT(iph2->dhgxy);
+	VPTRINIT(iph2->id);
+	VPTRINIT(iph2->id_p);
+	VPTRINIT(iph2->nonce);
+	VPTRINIT(iph2->nonce_p);
+	VPTRINIT(iph2->sa);
+	VPTRINIT(iph2->sa_ret);
+
+	if (iph2->ivm) {
+		oakley_delivm(iph2->ivm);
+		iph2->ivm = NULL;
+	}
+}
+
+/*
+ * delete new isakmp Phase 2 status record to handle isakmp in Phase2
+ */
+void
+delph2(iph2)
+	struct ph2handle *iph2;
+{
+	initph2(iph2);
+
+	if (iph2->src) {
+		racoon_free(iph2->src);
+		iph2->src = NULL;
+	}
+	if (iph2->dst) {
+		racoon_free(iph2->dst);
+		iph2->dst = NULL;
+	}
+	if (iph2->src_id) {
+	      racoon_free(iph2->src_id);
+	      iph2->src_id = NULL;
+	}
+	if (iph2->dst_id) {
+	      racoon_free(iph2->dst_id);
+	      iph2->dst_id = NULL;
+	}
+
+	if (iph2->proposal) {
+		flushsaprop(iph2->proposal);
+		iph2->proposal = NULL;
+	}
+
+	racoon_free(iph2);
+}
+
+/*
+ * create new isakmp Phase 2 status record to handle isakmp in Phase2
+ */
+int
+insph2(iph2)
+	struct ph2handle *iph2;
+{
+	LIST_INSERT_HEAD(&ph2tree, iph2, chain);
+
+	return 0;
+}
+
+void
+remph2(iph2)
+	struct ph2handle *iph2;
+{
+	LIST_REMOVE(iph2, chain);
+}
+
+void
+initph2tree()
+{
+	LIST_INIT(&ph2tree);
+}
+
+void
+flushph2()
+{
+	struct ph2handle *p, *next;
+
+	plog(LLV_DEBUG2, LOCATION, NULL,
+		 "flushing all ph2 handlers...\n");
+
+	for (p = LIST_FIRST(&ph2tree); p; p = next) {
+		next = LIST_NEXT(p, chain);
+
+		/* send delete information */
+		if (p->status == PHASE2ST_ESTABLISHED){
+			plog(LLV_DEBUG2, LOCATION, NULL,
+				 "got a ph2 handler to flush...\n");
+			isakmp_info_send_d2(p);
+		}else{
+			plog(LLV_DEBUG2, LOCATION, NULL,
+				 "skipping ph2 handler (state %d)\n", p->status);
+		}
+
+		delete_spd(p, 0);
+		unbindph12(p);
+		remph2(p);
+		delph2(p);
+	}
+}
+
+/*
+ * Delete all Phase 2 handlers for this src/dst/proto.  This
+ * is used during INITIAL-CONTACT processing (so no need to
+ * send a message to the peer).
+ */
+void
+deleteallph2(src, dst, proto_id)
+	struct sockaddr *src, *dst;
+	u_int proto_id;
+{
+	struct ph2handle *iph2, *next;
+	struct saproto *pr;
+
+	for (iph2 = LIST_FIRST(&ph2tree); iph2 != NULL; iph2 = next) {
+		next = LIST_NEXT(iph2, chain);
+		if (iph2->proposal == NULL && iph2->approval == NULL)
+			continue;
+		if (iph2->approval != NULL) {
+			for (pr = iph2->approval->head; pr != NULL;
+			     pr = pr->next) {
+				if (proto_id == pr->proto_id)
+					goto zap_it;
+			}
+		} else if (iph2->proposal != NULL) {
+			for (pr = iph2->proposal->head; pr != NULL;
+			     pr = pr->next) {
+				if (proto_id == pr->proto_id)
+					goto zap_it;
+			}
+		}
+		continue;
+ zap_it:
+		unbindph12(iph2);
+		remph2(iph2);
+		delph2(iph2);
+	}
+}
+
+/* %%% */
+void
+bindph12(iph1, iph2)
+	struct ph1handle *iph1;
+	struct ph2handle *iph2;
+{
+	iph2->ph1 = iph1;
+	LIST_INSERT_HEAD(&iph1->ph2tree, iph2, ph1bind);
+}
+
+void
+unbindph12(iph2)
+	struct ph2handle *iph2;
+{
+	if (iph2->ph1 != NULL) {
+		iph2->ph1 = NULL;
+		LIST_REMOVE(iph2, ph1bind);
+	}
+}
+
+/* %%% management contacted list */
+/*
+ * search contacted list.
+ */
+struct contacted *
+getcontacted(remote)
+	struct sockaddr *remote;
+{
+	struct contacted *p;
+
+	LIST_FOREACH(p, &ctdtree, chain) {
+		if (cmpsaddrstrict(remote, p->remote) == 0)
+			return p;
+	}
+
+	return NULL;
+}
+
+/*
+ * create new isakmp Phase 2 status record to handle isakmp in Phase2
+ */
+int
+inscontacted(remote)
+	struct sockaddr *remote;
+{
+	struct contacted *new;
+
+	/* create new iph2 */
+	new = racoon_calloc(1, sizeof(*new));
+	if (new == NULL)
+		return -1;
+
+	new->remote = dupsaddr(remote);
+	if (new->remote == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"failed to allocate buffer.\n");
+		racoon_free(new);
+		return -1;
+	}
+
+	LIST_INSERT_HEAD(&ctdtree, new, chain);
+
+	return 0;
+}
+
+void
+initctdtree()
+{
+	LIST_INIT(&ctdtree);
+}
+
+/*
+ * check the response has been sent to the peer.  when not, simply reply
+ * the buffered packet to the peer.
+ * OUT:
+ *	 0:	the packet is received at the first time.
+ *	 1:	the packet was processed before.
+ *	 2:	the packet was processed before, but the address mismatches.
+ *	-1:	error happened.
+ */
+int
+check_recvdpkt(remote, local, rbuf)
+	struct sockaddr *remote, *local;
+	vchar_t *rbuf;
+{
+	vchar_t *hash;
+	struct recvdpkt *r;
+	time_t t;
+	int len, s;
+
+	/* set current time */
+	t = time(NULL);
+
+	hash = eay_md5_one(rbuf);
+	if (!hash) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"failed to allocate buffer.\n");
+		return -1;
+	}
+
+	LIST_FOREACH(r, &rcptree, chain) {
+		if (memcmp(hash->v, r->hash->v, r->hash->l) == 0)
+			break;
+	}
+	vfree(hash);
+
+	/* this is the first time to receive the packet */
+	if (r == NULL)
+		return 0;
+
+	/*
+	 * the packet was processed before, but the remote address mismatches.
+	 */
+	if (cmpsaddrstrict(remote, r->remote) != 0)
+		return 2;
+
+	/*
+	 * it should not check the local address because the packet
+	 * may arrive at other interface.
+	 */
+
+	/* check the previous time to send */
+	if (t - r->time_send < 1) {
+		plog(LLV_WARNING, LOCATION, NULL,
+			"the packet retransmitted in a short time from %s\n",
+			saddr2str(remote));
+		/*XXX should it be error ? */
+	}
+
+	/* select the socket to be sent */
+	s = getsockmyaddr(r->local);
+	if (s == -1)
+		return -1;
+
+	/* resend the packet if needed */
+	len = sendfromto(s, r->sendbuf->v, r->sendbuf->l,
+			r->local, r->remote, lcconf->count_persend);
+	if (len == -1) {
+		plog(LLV_ERROR, LOCATION, NULL, "sendfromto failed\n");
+		return -1;
+	}
+
+	/* check the retry counter */
+	r->retry_counter--;
+	if (r->retry_counter <= 0) {
+		rem_recvdpkt(r);
+		del_recvdpkt(r);
+		plog(LLV_DEBUG, LOCATION, NULL,
+			"deleted the retransmission packet to %s.\n",
+			saddr2str(remote));
+	} else
+		r->time_send = t;
+
+	return 1;
+}
+
+/*
+ * adding a hash of received packet into the received list.
+ */
+int
+add_recvdpkt(remote, local, sbuf, rbuf)
+	struct sockaddr *remote, *local;
+	vchar_t *sbuf, *rbuf;
+{
+	struct recvdpkt *new = NULL;
+
+	if (lcconf->retry_counter == 0) {
+		/* no need to add it */
+		return 0;
+	}
+
+	new = racoon_calloc(1, sizeof(*new));
+	if (!new) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"failed to allocate buffer.\n");
+		return -1;
+	}
+
+	new->hash = eay_md5_one(rbuf);
+	if (!new->hash) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"failed to allocate buffer.\n");
+		del_recvdpkt(new);
+		return -1;
+	}
+	new->remote = dupsaddr(remote);
+	if (new->remote == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"failed to allocate buffer.\n");
+		del_recvdpkt(new);
+		return -1;
+	}
+	new->local = dupsaddr(local);
+	if (new->local == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"failed to allocate buffer.\n");
+		del_recvdpkt(new);
+		return -1;
+	}
+	new->sendbuf = vdup(sbuf);
+	if (new->sendbuf == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"failed to allocate buffer.\n");
+		del_recvdpkt(new);
+		return -1;
+	}
+
+	new->retry_counter = lcconf->retry_counter;
+	new->time_send = 0;
+	new->created = time(NULL);
+
+	LIST_INSERT_HEAD(&rcptree, new, chain);
+
+	return 0;
+}
+
+void
+del_recvdpkt(r)
+	struct recvdpkt *r;
+{
+	if (r->remote)
+		racoon_free(r->remote);
+	if (r->local)
+		racoon_free(r->local);
+	if (r->hash)
+		vfree(r->hash);
+	if (r->sendbuf)
+		vfree(r->sendbuf);
+	racoon_free(r);
+}
+
+void
+rem_recvdpkt(r)
+	struct recvdpkt *r;
+{
+	LIST_REMOVE(r, chain);
+}
+
+void
+sweep_recvdpkt(dummy)
+	void *dummy;
+{
+	struct recvdpkt *r, *next;
+	time_t t, lt;
+
+	/* set current time */
+	t = time(NULL);
+
+	/* set the lifetime of the retransmission */
+	lt = lcconf->retry_counter * lcconf->retry_interval;
+
+	for (r = LIST_FIRST(&rcptree); r; r = next) {
+		next = LIST_NEXT(r, chain);
+
+		if (t - r->created > lt) {
+			rem_recvdpkt(r);
+			del_recvdpkt(r);
+		}
+	}
+
+	sched_new(lt, sweep_recvdpkt, NULL);
+}
+
+void
+init_recvdpkt()
+{
+	time_t lt = lcconf->retry_counter * lcconf->retry_interval;
+
+	LIST_INIT(&rcptree);
+
+	sched_new(lt, sweep_recvdpkt, NULL);
+}
+
+#ifdef ENABLE_HYBRID
+/* 
+ * Retruns 0 if the address was obtained by ISAKMP mode config, 1 otherwise
+ * This should be in isakmp_cfg.c but ph1tree being private, it must be there
+ */
+int
+exclude_cfg_addr(addr)
+	const struct sockaddr *addr;
+{
+	struct ph1handle *p;
+	struct sockaddr_in *sin;
+
+	LIST_FOREACH(p, &ph1tree, chain) {
+		if ((p->mode_cfg != NULL) &&
+		    (p->mode_cfg->flags & ISAKMP_CFG_GOT_ADDR4) &&
+		    (addr->sa_family == AF_INET)) {
+			sin = (struct sockaddr_in *)addr;
+			if (sin->sin_addr.s_addr == p->mode_cfg->addr4.s_addr)
+				return 0;
+		}
+	}
+
+	return 1;
+}
+#endif
+
+
+
+/* 
+ * Reload conf code
+ */
+static int revalidate_ph2(struct ph2handle *iph2){
+	struct sainfoalg *alg;
+	int found, check_level;
+	struct sainfo *sainfo;
+	struct saprop *approval;
+	struct ph1handle *iph1;
+
+	/* 
+	 * Get the new sainfo using values of the old one
+	 */
+	if (iph2->sainfo != NULL) {
+		iph2->sainfo = getsainfo(iph2->sainfo->idsrc, 
+					  iph2->sainfo->iddst, iph2->sainfo->id_i,
+					  iph2->sainfo->remoteid);
+	}
+	approval = iph2->approval;
+	sainfo = iph2->sainfo;
+
+	if (sainfo == NULL) {
+		/* 
+		 * Sainfo has been removed
+		 */
+		plog(LLV_DEBUG, LOCATION, NULL,
+			 "Reload: No sainfo for ph2\n");
+		return 0;
+	}
+
+	if (approval == NULL) {
+		/*
+		 * XXX why do we have a NULL approval sometimes ???
+		 */
+		plog(LLV_DEBUG, LOCATION, NULL,
+			 "No approval found !\n");
+		return 0;
+	}	
+
+	/*
+	 * Don't care about proposals, should we do something ?
+	 * We have to keep iph2->proposal valid at least for initiator,
+	 * for pk_sendgetspi()
+	 */
+
+	plog(LLV_DEBUG, LOCATION, NULL, "active single bundle:\n");
+	printsaprop0(LLV_DEBUG, approval);
+
+	/*
+	 * Validate approval against sainfo
+	 * Note: we must have an updated ph1->rmconf before doing that,
+	 * we'll set check_level to EXACT if we don't have a ph1
+	 * XXX try tu find the new remote section to get the new check level ?
+	 * XXX lifebyte
+	 */
+	if (iph2->ph1 != NULL)
+		iph1=iph2->ph1;
+	else
+		iph1=getph1byaddr(iph2->src, iph2->dst, 0);
+
+	if(iph1 != NULL && iph1->rmconf != NULL) {
+		check_level = iph1->rmconf->pcheck_level;
+	} else {
+		if(iph1 != NULL)
+			plog(LLV_DEBUG, LOCATION, NULL, "No phase1 rmconf found !\n");
+		else
+			plog(LLV_DEBUG, LOCATION, NULL, "No phase1 found !\n");
+		check_level = PROP_CHECK_EXACT;
+	}
+
+	switch (check_level) {
+	case PROP_CHECK_OBEY:
+		plog(LLV_DEBUG, LOCATION, NULL,
+			 "Reload: OBEY for ph2, ok\n");
+		return 1;
+		break;
+
+	case PROP_CHECK_STRICT:
+		/* FALLTHROUGH */
+	case PROP_CHECK_CLAIM:
+		if (sainfo->lifetime < approval->lifetime) {
+			plog(LLV_DEBUG, LOCATION, NULL,
+				 "Reload: lifetime mismatch\n");
+			return 0;
+		}
+
+#if 0
+		/* Lifebyte is deprecated, just ignore it
+		 */
+		if (sainfo->lifebyte < approval->lifebyte) {
+			plog(LLV_DEBUG, LOCATION, NULL,
+				 "Reload: lifebyte mismatch\n");
+			return 0;
+		}
+#endif
+
+		if (sainfo->pfs_group &&
+		   sainfo->pfs_group != approval->pfs_group) {
+			plog(LLV_DEBUG, LOCATION, NULL,
+				 "Reload: PFS group mismatch\n");
+			return 0;
+		}
+		break;
+
+	case PROP_CHECK_EXACT:
+		if (sainfo->lifetime != approval->lifetime ||
+#if 0
+			/* Lifebyte is deprecated, just ignore it
+			 */
+		    sainfo->lifebyte != approval->lifebyte ||
+#endif
+		    sainfo->pfs_group != iph2->approval->pfs_group) {
+			plog(LLV_DEBUG, LOCATION, NULL,
+			    "Reload: lifetime | pfs mismatch\n");
+			return 0;
+		}
+		break;
+
+	default:
+		plog(LLV_DEBUG, LOCATION, NULL,
+			 "Reload: Shouldn't be here !\n");
+		return 0;
+		break;
+	}
+
+	for (alg = sainfo->algs[algclass_ipsec_auth]; alg; alg = alg->next) {
+		if (alg->alg == approval->head->head->authtype)
+			break;
+	}
+	if (alg == NULL) {
+		plog(LLV_DEBUG, LOCATION, NULL,
+			 "Reload: alg == NULL (auth)\n");
+		return 0;
+	}
+
+	found = 0;
+	for (alg = sainfo->algs[algclass_ipsec_enc]; 
+	    (found == 0 && alg != NULL); alg = alg->next) {
+		plog(LLV_DEBUG, LOCATION, NULL,
+			 "Reload: next ph2 enc alg...\n");
+
+		if (alg->alg != approval->head->head->trns_id){
+			plog(LLV_DEBUG, LOCATION, NULL,
+				 "Reload: encmode mismatch (%d / %d)\n",
+				 alg->alg, approval->head->head->trns_id);
+			continue;
+		}
+
+		switch (check_level){
+		/* PROP_CHECK_STRICT cannot happen here */
+		case PROP_CHECK_EXACT:
+			if (alg->encklen != approval->head->head->encklen) {
+				plog(LLV_DEBUG, LOCATION, NULL,
+					 "Reload: enclen mismatch\n");
+				continue;
+			}
+			break;
+
+		case PROP_CHECK_CLAIM:
+			/* FALLTHROUGH */
+		case PROP_CHECK_STRICT:
+			if (alg->encklen > approval->head->head->encklen) {
+				plog(LLV_DEBUG, LOCATION, NULL,
+					 "Reload: enclen mismatch\n");
+				continue;
+			}
+			break;
+
+		default:
+			plog(LLV_ERROR, LOCATION, NULL, 
+			    "unexpected check_level\n");
+			continue;
+			break;
+		}
+		found = 1;
+	}
+
+	if (!found){
+		plog(LLV_DEBUG, LOCATION, NULL,
+			 "Reload: No valid enc\n");
+		return 0;
+	}
+
+	/*
+	 * XXX comp
+	 */
+	plog(LLV_DEBUG, LOCATION, NULL,
+		 "Reload: ph2 check ok\n");
+
+	return 1;
+}
+
+
+static void 
+remove_ph2(struct ph2handle *iph2)
+{
+	u_int32_t spis[2];
+
+	if(iph2 == NULL)
+		return;
+
+	plog(LLV_DEBUG, LOCATION, NULL,
+		 "Deleting a Ph2...\n");
+
+	if (iph2->status == PHASE2ST_ESTABLISHED)
+		isakmp_info_send_d2(iph2);
+
+	if(iph2->approval != NULL && iph2->approval->head != NULL){
+		spis[0]=iph2->approval->head->spi;
+		spis[1]=iph2->approval->head->spi_p;
+
+		/* purge_ipsec_spi() will do all the work:
+		 * - delete SPIs in kernel
+		 * - delete generated SPD
+		 * - unbind / rem / del ph2
+		 */
+		purge_ipsec_spi(iph2->dst, iph2->approval->head->proto_id,
+						spis, 2);
+	}else{
+		unbindph12(iph2);
+		remph2(iph2);
+		delph2(iph2);
+	}
+}
+
+static void remove_ph1(struct ph1handle *iph1){
+	struct ph2handle *iph2, *iph2_next;
+
+	if(iph1 == NULL)
+		return;
+
+	plog(LLV_DEBUG, LOCATION, NULL,
+		 "Removing PH1...\n");
+
+	if (iph1->status == PHASE1ST_ESTABLISHED){
+		for (iph2 = LIST_FIRST(&iph1->ph2tree); iph2; iph2 = iph2_next) {
+			iph2_next = LIST_NEXT(iph2, chain);
+			remove_ph2(iph2);
+		}
+		isakmp_info_send_d1(iph1);
+	}
+	iph1->status = PHASE1ST_EXPIRED;
+	iph1->sce = sched_new(1, isakmp_ph1delete_stub, iph1);
+}
+
+
+static int revalidate_ph1tree_rmconf(void){
+	struct ph1handle *p, *next;
+	struct remoteconf *newrmconf;
+
+	for (p = LIST_FIRST(&ph1tree); p; p = next) {
+		next = LIST_NEXT(p, chain);
+
+		if (p->status == PHASE1ST_EXPIRED)
+			continue;
+
+		newrmconf=getrmconf(p->remote);
+		if(newrmconf == NULL){
+			p->rmconf = NULL;
+			remove_ph1(p);
+		}else{
+			/* Do not free old rmconf, it is just a pointer to an entry in rmtree
+			 */
+			p->rmconf=newrmconf;
+			if(p->approval != NULL){
+				struct isakmpsa *tmpsa;
+
+				tmpsa=dupisakmpsa(p->approval);
+				if(tmpsa != NULL){
+					delisakmpsa(p->approval);
+					p->approval=tmpsa;
+					p->approval->rmconf=newrmconf;
+				}
+			}
+		}
+	}
+
+	return 1;
+}
+
+
+/* rmconf is already updated here
+ */
+static int revalidate_ph1(struct ph1handle *iph1){
+	struct isakmpsa *p, *approval;
+	struct etypes *e;
+
+	if(iph1 == NULL ||
+	   iph1->approval == NULL ||
+		iph1->rmconf == NULL)
+		return 0;
+
+	approval=iph1->approval;
+
+	for (e = iph1->rmconf->etypes; e != NULL; e = e->next){
+		if (iph1->etype == e->type)
+			break;
+	}
+
+	if (e == NULL){
+		plog(LLV_DEBUG, LOCATION, NULL,
+			 "Reload: Exchange type mismatch\n");
+		return 0;
+	}
+
+	if (iph1->etype == ISAKMP_ETYPE_AGG &&
+	   approval->dh_group != iph1->rmconf->dh_group){
+		plog(LLV_DEBUG, LOCATION, NULL,
+			 "Reload: DH mismatch\n");
+		return 0;
+	}
+
+	for (p=iph1->rmconf->proposal; p != NULL; p=p->next){
+		plog(LLV_DEBUG, LOCATION, NULL,
+			 "Reload: Trying next proposal...\n");
+
+		if(approval->authmethod != p->authmethod){
+			plog(LLV_DEBUG, LOCATION, NULL,
+				 "Reload: Authmethod mismatch\n");
+			continue;
+		}
+
+		if(approval->enctype != p->enctype){
+			plog(LLV_DEBUG, LOCATION, NULL,
+				 "Reload: enctype mismatch\n");
+			continue;
+		}
+
+		switch (iph1->rmconf->pcheck_level) {
+		case PROP_CHECK_OBEY:
+			plog(LLV_DEBUG, LOCATION, NULL,
+				 "Reload: OBEY pcheck level, ok...\n");
+			return 1;
+			break;
+
+		case PROP_CHECK_CLAIM:
+			/* FALLTHROUGH */
+		case PROP_CHECK_STRICT:
+			if (approval->encklen < p->encklen) {
+				plog(LLV_DEBUG, LOCATION, NULL,
+					 "Reload: encklen mismatch\n");
+				continue;
+			}
+
+			if (approval->lifetime > p->lifetime) {
+				plog(LLV_DEBUG, LOCATION, NULL,
+					 "Reload: lifetime mismatch\n");
+				continue;
+			}
+
+#if 0
+			/* Lifebyte is deprecated, just ignore it
+			 */
+			if (approval->lifebyte > p->lifebyte) {
+				plog(LLV_DEBUG, LOCATION, NULL,
+					 "Reload: lifebyte mismatch\n");
+				continue;
+			}
+#endif
+			break;
+
+		case PROP_CHECK_EXACT:
+			if (approval->encklen != p->encklen) {
+				plog(LLV_DEBUG, LOCATION, NULL,
+					 "Reload: encklen mismatch\n");
+				continue;
+			}
+
+			if (approval->lifetime != p->lifetime) {
+				plog(LLV_DEBUG, LOCATION, NULL,
+					 "Reload: lifetime mismatch\n");
+				continue;
+			}
+
+#if 0
+			/* Lifebyte is deprecated, just ignore it
+			 */
+			if (approval->lifebyte != p->lifebyte) {
+				plog(LLV_DEBUG, LOCATION, NULL,
+					 "Reload: lifebyte mismatch\n");
+				continue;
+			}
+#endif
+			break;
+
+		default:
+			plog(LLV_ERROR, LOCATION, NULL, 
+			    "unexpected check_level\n");
+			continue;
+			break;
+		}
+
+		if (approval->hashtype != p->hashtype) {
+			plog(LLV_DEBUG, LOCATION, NULL,
+				 "Reload: hashtype mismatch\n");
+			continue;
+		}
+
+		if (iph1->etype != ISAKMP_ETYPE_AGG &&
+		    approval->dh_group != p->dh_group) {
+			plog(LLV_DEBUG, LOCATION, NULL,
+				 "Reload: dhgroup mismatch\n");
+			continue;
+		}
+
+		plog(LLV_DEBUG, LOCATION, NULL, "Reload: Conf ok\n");
+		return 1;
+	}
+
+	plog(LLV_DEBUG, LOCATION, NULL, "Reload: No valid conf found\n");
+	return 0;
+}
+
+
+static int revalidate_ph1tree(void){
+	struct ph1handle *p, *next;
+
+	for (p = LIST_FIRST(&ph1tree); p; p = next) {
+		next = LIST_NEXT(p, chain);
+
+		if (p->status == PHASE1ST_EXPIRED)
+			continue;
+
+		if(!revalidate_ph1(p))
+			remove_ph1(p);
+	}
+
+	return 1;
+}
+
+static int revalidate_ph2tree(void){
+	struct ph2handle *p, *next;
+
+	for (p = LIST_FIRST(&ph2tree); p; p = next) {
+		next = LIST_NEXT(p, chain);
+
+		if (p->status == PHASE2ST_EXPIRED)
+			continue;
+
+		if(!revalidate_ph2(p)){
+			plog(LLV_DEBUG, LOCATION, NULL,
+				 "PH2 not validated, removing it\n");
+			remove_ph2(p);
+		}
+	}
+
+	return 1;
+}
+
+int 
+revalidate_ph12(void)
+{
+
+	revalidate_ph1tree_rmconf();
+
+	revalidate_ph2tree();
+	revalidate_ph1tree();
+
+	return 1;
+}
+
+#ifdef ENABLE_HYBRID
+struct ph1handle *
+getph1bylogin(login)
+	char *login;
+{
+	struct ph1handle *p;
+
+	LIST_FOREACH(p, &ph1tree, chain) {
+		if (p->mode_cfg == NULL)
+			continue;
+		if (strncmp(p->mode_cfg->login, login, LOGINLEN) == 0)
+			return p;
+	}
+
+	return NULL;
+}
+
+int
+purgeph1bylogin(login)
+	char *login;
+{
+	struct ph1handle *p;
+	int found = 0;
+
+	LIST_FOREACH(p, &ph1tree, chain) {
+		if (p->mode_cfg == NULL)
+			continue;
+		if (strncmp(p->mode_cfg->login, login, LOGINLEN) == 0) {
+			if (p->status == PHASE1ST_ESTABLISHED)
+				isakmp_info_send_d1(p);
+			purge_remote(p);
+			found++;
+		}
+	}
+
+	return found;
+}
+#endif
diff --git a/src/racoon/handler.h b/src/racoon/handler.h
new file mode 100644
index 0000000..a52dc6c
--- /dev/null
+++ b/src/racoon/handler.h
@@ -0,0 +1,483 @@
+/*	$NetBSD: handler.h,v 1.9.6.1 2008/01/11 14:12:01 vanhu Exp $	*/
+
+/* Id: handler.h,v 1.19 2006/02/25 08:25:12 manubsd Exp */
+
+/*
+ * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _HANDLER_H
+#define _HANDLER_H
+
+#include <sys/queue.h>
+#include <openssl/rsa.h>
+
+#include <sys/time.h>
+
+#include "isakmp_var.h"
+#include "oakley.h"
+
+/* Phase 1 handler */
+/*
+ * main mode:
+ *      initiator               responder
+ *  0   (---)                   (---)
+ *  1   start                   start (1st msg received)
+ *  2   (---)                   1st valid msg received
+ *  3   1st msg sent	        1st msg sent
+ *  4   1st valid msg received  2st valid msg received
+ *  5   2nd msg sent            2nd msg sent
+ *  6   2nd valid msg received  3rd valid msg received
+ *  7   3rd msg sent            3rd msg sent
+ *  8   3rd valid msg received  (---)
+ *  9   SA established          SA established
+ *
+ * aggressive mode:
+ *      initiator               responder
+ *  0   (---)                   (---)
+ *  1   start                   start (1st msg received)
+ *  2   (---)                   1st valid msg received
+ *  3   1st msg sent	        1st msg sent
+ *  4   1st valid msg received  2st valid msg received
+ *  5   (---)                   (---)
+ *  6   (---)                   (---)
+ *  7   (---)                   (---)
+ *  8   (---)                   (---)
+ *  9   SA established          SA established
+ *
+ * base mode:
+ *      initiator               responder
+ *  0   (---)                   (---)
+ *  1   start                   start (1st msg received)
+ *  2   (---)                   1st valid msg received
+ *  3   1st msg sent	        1st msg sent
+ *  4   1st valid msg received  2st valid msg received
+ *  5   2nd msg sent            (---)
+ *  6   (---)                   (---)
+ *  7   (---)                   (---)
+ *  8   (---)                   (---)
+ *  9   SA established          SA established
+ */
+#define PHASE1ST_SPAWN			0
+#define PHASE1ST_START			1
+#define PHASE1ST_MSG1RECEIVED		2
+#define PHASE1ST_MSG1SENT		3
+#define PHASE1ST_MSG2RECEIVED		4
+#define PHASE1ST_MSG2SENT		5
+#define PHASE1ST_MSG3RECEIVED		6
+#define PHASE1ST_MSG3SENT		7
+#define PHASE1ST_MSG4RECEIVED		8
+#define PHASE1ST_ESTABLISHED		9
+#define PHASE1ST_EXPIRED		10
+#define PHASE1ST_MAX			11
+
+/* About address semantics in each case.
+ *			initiator(addr=I)	responder(addr=R)
+ *			src	dst		src	dst
+ *			(local)	(remote)	(local)	(remote)
+ * phase 1 handler	I	R		R	I
+ * phase 2 handler	I	R		R	I
+ * getspi msg		R	I		I	R
+ * acquire msg		I	R
+ * ID payload		I	R		I	R
+ */
+#ifdef ENABLE_HYBRID
+struct isakmp_cfg_state;
+#endif
+struct ph1handle {
+	isakmp_index index;
+
+	int status;			/* status of this SA */
+	int side;			/* INITIATOR or RESPONDER */
+
+	struct sockaddr *remote;	/* remote address to negosiate ph1 */
+	struct sockaddr *local;		/* local address to negosiate ph1 */
+			/* XXX copy from rmconf due to anonymous configuration.
+			 * If anonymous will be forbidden, we do delete them. */
+
+	struct remoteconf *rmconf;	/* pointer to remote configuration */
+
+	struct isakmpsa *approval;	/* pointer to SA(s) approved. */
+	vchar_t *authstr;		/* place holder of string for auth. */
+					/* for example pre-shared key */
+
+	u_int8_t version;		/* ISAKMP version */
+	u_int8_t etype;			/* Exchange type actually for use */
+	u_int8_t flags;			/* Flags */
+	u_int32_t msgid;		/* message id */
+
+#ifdef ENABLE_NATT
+	struct ph1natt_options *natt_options;	/* Selected NAT-T IKE version */
+	u_int32_t natt_flags;		/* NAT-T related flags */
+#endif
+#ifdef ENABLE_FRAG
+	int frag;			/* IKE phase 1 fragmentation */
+	struct isakmp_frag_item *frag_chain;	/* Received fragments */
+#endif
+
+	struct sched *sce;		/* schedule for expire */
+
+	struct sched *scr;		/* schedule for resend */
+	int retry_counter;		/* for resend. */
+	vchar_t *sendbuf;		/* buffer for re-sending */
+
+	vchar_t *dhpriv;		/* DH; private value */
+	vchar_t *dhpub;			/* DH; public value */
+	vchar_t *dhpub_p;		/* DH; partner's public value */
+	vchar_t *dhgxy;			/* DH; shared secret */
+	vchar_t *nonce;			/* nonce value */
+	vchar_t *nonce_p;		/* partner's nonce value */
+	vchar_t *skeyid;		/* SKEYID */
+	vchar_t *skeyid_d;		/* SKEYID_d */
+	vchar_t *skeyid_a;		/* SKEYID_a, i.e. hash */
+	vchar_t *skeyid_e;		/* SKEYID_e, i.e. encryption */
+	vchar_t *key;			/* cipher key */
+	vchar_t *hash;			/* HASH minus general header */
+	vchar_t *sig;			/* SIG minus general header */
+	vchar_t *sig_p;			/* peer's SIG minus general header */
+	cert_t *cert;			/* CERT minus general header */
+	cert_t *cert_p;			/* peer's CERT minus general header */
+	cert_t *crl_p;			/* peer's CRL minus general header */
+	cert_t *cr_p;			/* peer's CR not including general */
+	RSA *rsa;			/* my RSA key */
+	RSA *rsa_p;			/* peer's RSA key */
+	struct genlist *rsa_candidates;	/* possible candidates for peer's RSA key */
+	vchar_t *id;			/* ID minus gen header */
+	vchar_t *id_p;			/* partner's ID minus general header */
+					/* i.e. struct ipsecdoi_id_b*. */
+	struct isakmp_ivm *ivm;		/* IVs */
+
+	vchar_t *sa;			/* whole SA payload to send/to be sent*/
+					/* to calculate HASH */
+					/* NOT INCLUDING general header. */
+
+	vchar_t *sa_ret;		/* SA payload to reply/to be replyed */
+					/* NOT INCLUDING general header. */
+					/* NOTE: Should be release after use. */
+
+#ifdef HAVE_GSSAPI
+	void *gssapi_state;		/* GSS-API specific state. */
+					/* Allocated when needed */
+	vchar_t *gi_i;			/* optional initiator GSS id */
+	vchar_t *gi_r;			/* optional responder GSS id */
+#endif
+
+	struct isakmp_pl_hash *pl_hash;	/* pointer to hash payload */
+
+	time_t created;			/* timestamp for establish */
+#ifdef ENABLE_STATS
+	struct timeval start;
+	struct timeval end;
+#endif
+
+#ifdef ENABLE_DPD
+	int		dpd_support;	/* Does remote supports DPD ? */
+	time_t		dpd_lastack;	/* Last ack received */
+	u_int16_t	dpd_seq;		/* DPD seq number to receive */
+	u_int8_t	dpd_fails;		/* number of failures */
+	struct sched	*dpd_r_u;
+#endif
+
+	u_int32_t msgid2;		/* msgid counter for Phase 2 */
+	int ph2cnt;	/* the number which is negotiated by this phase 1 */
+	LIST_HEAD(_ph2ofph1_, ph2handle) ph2tree;
+
+	LIST_ENTRY(ph1handle) chain;
+#ifdef ENABLE_HYBRID
+	struct isakmp_cfg_state *mode_cfg;	/* ISAKMP mode config state */
+#endif       
+
+};
+
+/* Phase 2 handler */
+/* allocated per a SA or SA bundles of a pair of peer's IP addresses. */
+/*
+ *      initiator               responder
+ *  0   (---)                   (---)
+ *  1   start                   start (1st msg received)
+ *  2   acquire msg get         1st valid msg received
+ *  3   getspi request sent     getspi request sent
+ *  4   getspi done             getspi done
+ *  5   1st msg sent            1st msg sent
+ *  6   1st valid msg received  2nd valid msg received
+ *  7   (commit bit)            (commit bit)
+ *  8   SAs added               SAs added
+ *  9   SAs established         SAs established
+ * 10   SAs expired             SAs expired
+ */
+#define PHASE2ST_SPAWN		0
+#define PHASE2ST_START		1
+#define PHASE2ST_STATUS2	2
+#define PHASE2ST_GETSPISENT	3
+#define PHASE2ST_GETSPIDONE	4
+#define PHASE2ST_MSG1SENT	5
+#define PHASE2ST_STATUS6	6
+#define PHASE2ST_COMMIT		7
+#define PHASE2ST_ADDSA		8
+#define PHASE2ST_ESTABLISHED	9
+#define PHASE2ST_EXPIRED	10
+#define PHASE2ST_MAX		11
+
+struct ph2handle {
+	struct sockaddr *src;		/* my address of SA. */
+	struct sockaddr *dst;		/* peer's address of SA. */
+
+		/*
+		 * copy ip address from ID payloads when ID type is ip address.
+		 * In other case, they must be null.
+		 */
+	struct sockaddr *src_id;
+	struct sockaddr *dst_id;
+
+	u_int32_t spid;			/* policy id by kernel */
+
+	int status;			/* ipsec sa status */
+	u_int8_t side;			/* INITIATOR or RESPONDER */
+
+	struct sched *sce;		/* schedule for expire */
+	struct sched *scr;		/* schedule for resend */
+	int retry_counter;		/* for resend. */
+	vchar_t *sendbuf;		/* buffer for re-sending */
+	vchar_t *msg1;			/* buffer for re-sending */
+				/* used for responder's first message */
+
+	int retry_checkph1;		/* counter to wait phase 1 finished. */
+					/* NOTE: actually it's timer. */
+
+	u_int32_t seq;			/* sequence number used by PF_KEY */
+			/*
+			 * NOTE: In responder side, we can't identify each SAs
+			 * with same destination address for example, when
+			 * socket based SA is required.  So we set a identifier
+			 * number to "seq", and sent kernel by pfkey.
+			 */
+	u_int8_t satype;		/* satype in PF_KEY */
+			/*
+			 * saved satype in the original PF_KEY request from
+			 * the kernel in order to reply a error.
+			 */
+
+	u_int8_t flags;			/* Flags for phase 2 */
+	u_int32_t msgid;		/* msgid for phase 2 */
+
+	struct sainfo *sainfo;		/* place holder of sainfo */
+	struct saprop *proposal;	/* SA(s) proposal. */
+	struct saprop *approval;	/* SA(s) approved. */
+	caddr_t spidx_gen;		/* policy from peer's proposal */
+
+	struct dhgroup *pfsgrp;		/* DH; prime number */
+	vchar_t *dhpriv;		/* DH; private value */
+	vchar_t *dhpub;			/* DH; public value */
+	vchar_t *dhpub_p;		/* DH; partner's public value */
+	vchar_t *dhgxy;			/* DH; shared secret */
+	vchar_t *id;			/* ID minus gen header */
+	vchar_t *id_p;			/* peer's ID minus general header */
+	vchar_t *nonce;			/* nonce value in phase 2 */
+	vchar_t *nonce_p;		/* partner's nonce value in phase 2 */
+
+	vchar_t *sa;			/* whole SA payload to send/to be sent*/
+					/* to calculate HASH */
+					/* NOT INCLUDING general header. */
+
+	vchar_t *sa_ret;		/* SA payload to reply/to be replyed */
+					/* NOT INCLUDING general header. */
+					/* NOTE: Should be release after use. */
+
+	struct isakmp_ivm *ivm;		/* IVs */
+
+	int generated_spidx;	/* mark handlers whith generated policy */
+
+#ifdef ENABLE_STATS
+	struct timeval start;
+	struct timeval end;
+#endif
+	struct ph1handle *ph1;	/* back pointer to isakmp status */
+
+	LIST_ENTRY(ph2handle) chain;
+	LIST_ENTRY(ph2handle) ph1bind;	/* chain to ph1handle */
+};
+
+/*
+ * for handling initial contact.
+ */
+struct contacted {
+	struct sockaddr *remote;	/* remote address to negosiate ph1 */
+	LIST_ENTRY(contacted) chain;
+};
+
+/*
+ * for checking a packet retransmited.
+ */
+struct recvdpkt {
+	struct sockaddr *remote;	/* the remote address */
+	struct sockaddr *local;		/* the local address */
+	vchar_t *hash;			/* hash of the received packet */
+	vchar_t *sendbuf;		/* buffer for the response */
+	int retry_counter;		/* how many times to send */
+	time_t time_send;		/* timestamp to send a packet */
+	time_t created;			/* timestamp to create a queue */
+
+	struct sched *scr;		/* schedule for resend, may not used */
+
+	LIST_ENTRY(recvdpkt) chain;
+};
+
+/* for parsing ISAKMP header. */
+struct isakmp_parse_t {
+	u_char type;		/* payload type of mine */
+	int len;		/* ntohs(ptr->len) */
+	struct isakmp_gen *ptr;
+};
+
+/*
+ * for IV management.
+ *
+ * - normal case
+ * initiator                                     responder
+ * -------------------------                     --------------------------
+ * initialize iv(A), ive(A).                     initialize iv(A), ive(A).
+ * encode by ive(A).
+ * save to iv(B).            ---[packet(B)]-->   save to ive(B).
+ *                                               decode by iv(A).
+ *                                               packet consistency.
+ *                                               sync iv(B) with ive(B).
+ *                                               check auth, integrity.
+ *                                               encode by ive(B).
+ * save to ive(C).          <--[packet(C)]---    save to iv(C).
+ * decoded by iv(B).
+ *      :
+ *
+ * - In the case that a error is found while cipher processing,
+ * initiator                                     responder
+ * -------------------------                     --------------------------
+ * initialize iv(A), ive(A).                     initialize iv(A), ive(A).
+ * encode by ive(A).
+ * save to iv(B).            ---[packet(B)]-->   save to ive(B).
+ *                                               decode by iv(A).
+ *                                               packet consistency.
+ *                                               sync iv(B) with ive(B).
+ *                                               check auth, integrity.
+ *                                               error found.
+ *                                               create notify.
+ *                                               get ive2(X) from iv(B).
+ *                                               encode by ive2(X).
+ * get iv2(X) from iv(B).   <--[packet(Y)]---    save to iv2(Y).
+ * save to ive2(Y).
+ * decoded by iv2(X).
+ *      :
+ *
+ * The reason why the responder synchronizes iv with ive after checking the
+ * packet consistency is that it is required to leave the IV for decoding
+ * packet.  Because there is a potential of error while checking the packet
+ * consistency.  Also the reason why that is before authentication and
+ * integirty check is that the IV for informational exchange has to be made
+ * by the IV which is after packet decoded and checking the packet consistency.
+ * Otherwise IV mismatched happens between the intitiator and the responder.
+ */
+struct isakmp_ivm {
+	vchar_t *iv;	/* for decoding packet */
+			/* if phase 1, it's for computing phase2 iv */
+	vchar_t *ive;	/* for encoding packet */
+};
+
+/* for dumping */
+struct ph1dump {
+	isakmp_index index;
+	int status;
+	int side;
+	struct sockaddr_storage remote;
+	struct sockaddr_storage local;
+	u_int8_t version;
+	u_int8_t etype;	
+	time_t created;
+	int ph2cnt;
+};
+
+struct sockaddr;
+struct ph1handle;
+struct ph2handle;
+struct policyindex;
+
+extern struct ph1handle *getph1byindex __P((isakmp_index *));
+extern struct ph1handle *getph1byindex0 __P((isakmp_index *));
+extern struct ph1handle *getph1byaddr __P((struct sockaddr *,
+										   struct sockaddr *, int));
+extern struct ph1handle *getph1byaddrwop __P((struct sockaddr *,
+	struct sockaddr *));
+extern struct ph1handle *getph1bydstaddrwop __P((struct sockaddr *));
+#ifdef ENABLE_HYBRID
+struct ph1handle *getph1bylogin __P((char *));
+int purgeph1bylogin __P((char *));
+#endif
+extern vchar_t *dumpph1 __P((void));
+extern struct ph1handle *newph1 __P((void));
+extern void delph1 __P((struct ph1handle *));
+extern int insph1 __P((struct ph1handle *));
+extern void remph1 __P((struct ph1handle *));
+extern void flushph1 __P((void));
+extern void initph1tree __P((void));
+
+extern struct ph2handle *getph2byspidx __P((struct policyindex *));
+extern struct ph2handle *getph2byspid __P((u_int32_t));
+extern struct ph2handle *getph2byseq __P((u_int32_t));
+extern struct ph2handle *getph2bysaddr __P((struct sockaddr *,
+	struct sockaddr *));
+extern struct ph2handle *getph2bymsgid __P((struct ph1handle *, u_int32_t));
+extern struct ph2handle *getph2byid __P((struct sockaddr *,
+	struct sockaddr *, u_int32_t));
+extern struct ph2handle *getph2bysaidx __P((struct sockaddr *,
+	struct sockaddr *, u_int, u_int32_t));
+extern struct ph2handle *newph2 __P((void));
+extern void initph2 __P((struct ph2handle *));
+extern void delph2 __P((struct ph2handle *));
+extern int insph2 __P((struct ph2handle *));
+extern void remph2 __P((struct ph2handle *));
+extern void flushph2 __P((void));
+extern void deleteallph2 __P((struct sockaddr *, struct sockaddr *, u_int));
+extern void initph2tree __P((void));
+
+extern void bindph12 __P((struct ph1handle *, struct ph2handle *));
+extern void unbindph12 __P((struct ph2handle *));
+
+extern struct contacted *getcontacted __P((struct sockaddr *));
+extern int inscontacted __P((struct sockaddr *));
+extern void initctdtree __P((void));
+
+extern int check_recvdpkt __P((struct sockaddr *,
+	struct sockaddr *, vchar_t *));
+extern int add_recvdpkt __P((struct sockaddr *, struct sockaddr *,
+	vchar_t *, vchar_t *));
+extern void init_recvdpkt __P((void));
+
+#ifdef ENABLE_HYBRID
+extern int exclude_cfg_addr __P((const struct sockaddr *));
+#endif
+
+extern int revalidate_ph12(void);
+
+#endif /* _HANDLER_H */
diff --git a/src/racoon/ipsec_doi.c b/src/racoon/ipsec_doi.c
new file mode 100644
index 0000000..cc326e0
--- /dev/null
+++ b/src/racoon/ipsec_doi.c
@@ -0,0 +1,4915 @@
+/*	$NetBSD: ipsec_doi.c,v 1.23.4.9 2008/06/18 07:30:19 mgrooms Exp $	*/
+
+/* Id: ipsec_doi.c,v 1.55 2006/08/17 09:20:41 vanhu Exp */
+
+/*
+ * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+
+#include <netinet/in.h>
+
+#include PATH_IPSEC_H
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <netdb.h>
+#if TIME_WITH_SYS_TIME
+# include <sys/time.h>
+# include <time.h>
+#else
+# if HAVE_SYS_TIME_H
+#  include <sys/time.h>
+# else
+#  include <time.h>
+# endif
+#endif
+
+#include "var.h"
+#include "vmbuf.h"
+#include "misc.h"
+#include "plog.h"
+#include "debug.h"
+
+#include "cfparse_proto.h"
+#include "isakmp_var.h"
+#include "isakmp.h"
+#include "ipsec_doi.h"
+#include "oakley.h"
+#include "remoteconf.h"
+#include "localconf.h"
+#include "sockmisc.h"
+#include "handler.h"
+#include "policy.h"
+#include "algorithm.h"
+#include "sainfo.h"
+#include "proposal.h"
+#include "crypto_openssl.h"
+#include "strnames.h"
+#include "gcmalloc.h"
+
+#ifdef ENABLE_NATT
+#include "nattraversal.h"
+#endif
+#ifdef ENABLE_HYBRID
+static int switch_authmethod(int);
+#endif
+
+#ifdef HAVE_GSSAPI
+#include <iconv.h>
+#include "gssapi.h"
+#ifdef HAVE_ICONV_2ND_CONST
+#define __iconv_const const
+#else
+#define __iconv_const
+#endif
+#endif
+
+int verbose_proposal_check = 1;
+
+static vchar_t *get_ph1approval __P((struct ph1handle *, struct prop_pair **));
+static struct isakmpsa *get_ph1approvalx __P((struct prop_pair *,
+	struct isakmpsa *, struct isakmpsa *, int));
+static void print_ph1mismatched __P((struct prop_pair *, struct isakmpsa *));
+static int t2isakmpsa __P((struct isakmp_pl_t *, struct isakmpsa *));
+static int cmp_aproppair_i __P((struct prop_pair *, struct prop_pair *));
+static struct prop_pair *get_ph2approval __P((struct ph2handle *,
+	struct prop_pair **));
+static struct prop_pair *get_ph2approvalx __P((struct ph2handle *,
+	struct prop_pair *));
+static void free_proppair0 __P((struct prop_pair *));
+
+static int get_transform
+	__P((struct isakmp_pl_p *, struct prop_pair **, int *));
+static u_int32_t ipsecdoi_set_ld __P((vchar_t *));
+
+static int check_doi __P((u_int32_t));
+static int check_situation __P((u_int32_t));
+
+static int check_prot_main __P((int));
+static int check_prot_quick __P((int));
+static int (*check_protocol[]) __P((int)) = {
+	check_prot_main,	/* IPSECDOI_TYPE_PH1 */
+	check_prot_quick,	/* IPSECDOI_TYPE_PH2 */
+};
+
+static int check_spi_size __P((int, int));
+
+static int check_trns_isakmp __P((int));
+static int check_trns_ah __P((int));
+static int check_trns_esp __P((int));
+static int check_trns_ipcomp __P((int));
+static int (*check_transform[]) __P((int)) = {
+	0,
+	check_trns_isakmp,	/* IPSECDOI_PROTO_ISAKMP */
+	check_trns_ah,		/* IPSECDOI_PROTO_IPSEC_AH */
+	check_trns_esp,		/* IPSECDOI_PROTO_IPSEC_ESP */
+	check_trns_ipcomp,	/* IPSECDOI_PROTO_IPCOMP */
+};
+
+static int check_attr_isakmp __P((struct isakmp_pl_t *));
+static int check_attr_ah __P((struct isakmp_pl_t *));
+static int check_attr_esp __P((struct isakmp_pl_t *));
+static int check_attr_ipsec __P((int, struct isakmp_pl_t *));
+static int check_attr_ipcomp __P((struct isakmp_pl_t *));
+static int (*check_attributes[]) __P((struct isakmp_pl_t *)) = {
+	0,
+	check_attr_isakmp,	/* IPSECDOI_PROTO_ISAKMP */
+	check_attr_ah,		/* IPSECDOI_PROTO_IPSEC_AH */
+	check_attr_esp,		/* IPSECDOI_PROTO_IPSEC_ESP */
+	check_attr_ipcomp,	/* IPSECDOI_PROTO_IPCOMP */
+};
+
+static int setph1prop __P((struct isakmpsa *, caddr_t));
+static int setph1trns __P((struct isakmpsa *, caddr_t));
+static int setph1attr __P((struct isakmpsa *, caddr_t));
+static vchar_t *setph2proposal0 __P((const struct ph2handle *,
+	const struct saprop *, const struct saproto *));
+
+static vchar_t *getidval __P((int, vchar_t *));
+
+#ifdef HAVE_GSSAPI
+static struct isakmpsa *fixup_initiator_sa __P((struct isakmpsa *,
+	struct isakmpsa *));
+#endif
+
+/*%%%*/
+/*
+ * check phase 1 SA payload.
+ * make new SA payload to be replyed not including general header.
+ * the pointer to one of isakmpsa in proposal is set into iph1->approval.
+ * OUT:
+ *	positive: the pointer to new buffer of SA payload.
+ *		  network byte order.
+ *	NULL	: error occurd.
+ */
+int
+ipsecdoi_checkph1proposal(sa, iph1)
+	vchar_t *sa;
+	struct ph1handle *iph1;
+{
+	vchar_t *newsa;		/* new SA payload approved. */
+	struct prop_pair **pair;
+
+	/* get proposal pair */
+	pair = get_proppair(sa, IPSECDOI_TYPE_PH1);
+	if (pair == NULL)
+		return -1;
+
+	/* check and get one SA for use */
+	newsa = get_ph1approval(iph1, pair);
+	
+	free_proppair(pair);
+
+	if (newsa == NULL)
+		return -1;
+
+	iph1->sa_ret = newsa;
+
+	return 0;
+}
+
+/*
+ * acceptable check for remote configuration.
+ * return a new SA payload to be reply to peer.
+ */
+static vchar_t *
+get_ph1approval(iph1, pair)
+	struct ph1handle *iph1;
+	struct prop_pair **pair;
+{
+	vchar_t *newsa;
+	struct isakmpsa *sa, tsa;
+	struct prop_pair *s, *p;
+	int prophlen;
+	int i;
+
+	if (iph1->approval) {
+		delisakmpsa(iph1->approval);
+		iph1->approval = NULL;
+	}
+
+	for (i = 0; i < MAXPROPPAIRLEN; i++) {
+		if (pair[i] == NULL)
+			continue;
+		for (s = pair[i]; s; s = s->next) {
+			prophlen = 
+			    sizeof(struct isakmp_pl_p) + s->prop->spi_size;
+
+			/* compare proposal and select one */
+			for (p = s; p; p = p->tnext) {
+				if ((sa = get_ph1approvalx(p, 
+				    iph1->rmconf->proposal, &tsa, 
+				    iph1->rmconf->pcheck_level)) != NULL)
+					goto found;
+			}
+		}
+	}
+
+	/*
+	 * if there is no suitable proposal, racoon complains about all of
+	 * mismatched items in those proposal.
+	 */
+	if (verbose_proposal_check) {
+		for (i = 0; i < MAXPROPPAIRLEN; i++) {
+			if (pair[i] == NULL)
+				continue;
+			for (s = pair[i]; s; s = s->next) {
+				prophlen = sizeof(struct isakmp_pl_p)
+						+ s->prop->spi_size;
+				for (p = s; p; p = p->tnext) {
+					print_ph1mismatched(p,
+						iph1->rmconf->proposal);
+				}
+			}
+		}
+	}
+	plog(LLV_ERROR, LOCATION, NULL, "no suitable proposal found.\n");
+
+	return NULL;
+
+found:
+	plog(LLV_DEBUG, LOCATION, NULL, "an acceptable proposal found.\n");
+
+	/* check DH group settings */
+	if (sa->dhgrp) {
+		if (sa->dhgrp->prime && sa->dhgrp->gen1) {
+			/* it's ok */
+			goto saok;
+		}
+		plog(LLV_WARNING, LOCATION, NULL,
+			"invalid DH parameter found, use default.\n");
+		oakley_dhgrp_free(sa->dhgrp);
+		sa->dhgrp=NULL;
+	}
+
+	if (oakley_setdhgroup(sa->dh_group, &sa->dhgrp) == -1) {
+		sa->dhgrp = NULL;
+		racoon_free(sa);
+		return NULL;
+	}
+
+saok:
+#ifdef HAVE_GSSAPI
+	if (sa->gssid != NULL)
+		plog(LLV_DEBUG, LOCATION, NULL, "gss id in new sa '%.*s'\n",
+		    (int)sa->gssid->l, sa->gssid->v);
+	if (iph1-> side == INITIATOR) {
+		if (iph1->rmconf->proposal->gssid != NULL)
+			iph1->gi_i = vdup(iph1->rmconf->proposal->gssid);
+		if (tsa.gssid != NULL)
+			iph1->gi_r = vdup(tsa.gssid);
+		iph1->approval = fixup_initiator_sa(sa, &tsa);
+	} else {
+		if (tsa.gssid != NULL) {
+			iph1->gi_r = vdup(tsa.gssid);
+			iph1->gi_i = gssapi_get_id(iph1);
+			if (sa->gssid == NULL && iph1->gi_i != NULL)
+				sa->gssid = vdup(iph1->gi_i);
+		}
+		iph1->approval = sa;
+	}
+	if (iph1->gi_i != NULL)
+		plog(LLV_DEBUG, LOCATION, NULL, "GIi is %.*s\n",
+		    (int)iph1->gi_i->l, iph1->gi_i->v);
+	if (iph1->gi_r != NULL)
+		plog(LLV_DEBUG, LOCATION, NULL, "GIr is %.*s\n",
+		    (int)iph1->gi_r->l, iph1->gi_r->v);
+#else
+	iph1->approval = sa;
+#endif
+	if(iph1->approval) {
+		plog(LLV_DEBUG, LOCATION, NULL, "agreed on %s auth.\n",
+		    s_oakley_attr_method(iph1->approval->authmethod));
+	}
+
+	newsa = get_sabyproppair(p, iph1);
+	if (newsa == NULL){
+		delisakmpsa(iph1->approval);
+		iph1->approval = NULL;
+	}
+
+	return newsa;
+}
+
+/*
+ * compare peer's single proposal and all of my proposal.
+ * and select one if suiatable.
+ * p       : one of peer's proposal.
+ * proposal: my proposals.
+ */
+static struct isakmpsa *
+get_ph1approvalx(p, proposal, sap, check_level)
+	struct prop_pair *p;
+	struct isakmpsa *proposal, *sap;
+	int check_level;
+{
+	struct isakmp_pl_p *prop = p->prop;
+	struct isakmp_pl_t *trns = p->trns;
+	struct isakmpsa sa, *s, *tsap;
+	int authmethod;
+
+	plog(LLV_DEBUG, LOCATION, NULL,
+       		"prop#=%d, prot-id=%s, spi-size=%d, #trns=%d\n",
+		prop->p_no, s_ipsecdoi_proto(prop->proto_id),
+		prop->spi_size, prop->num_t);
+
+	plog(LLV_DEBUG, LOCATION, NULL,
+		"trns#=%d, trns-id=%s\n",
+		trns->t_no,
+		s_ipsecdoi_trns(prop->proto_id, trns->t_id));
+
+	tsap = sap != NULL ? sap : &sa;
+
+	memset(tsap, 0, sizeof(*tsap));
+	if (t2isakmpsa(trns, tsap) < 0)
+		return NULL;
+	for (s = proposal; s != NULL; s = s->next) {
+#ifdef ENABLE_HYBRID
+		authmethod = switch_authmethod(s->authmethod);
+#else
+		authmethod = s->authmethod;
+#endif
+		plog(LLV_DEBUG, LOCATION, NULL, "Compared: DB:Peer\n");
+		plog(LLV_DEBUG, LOCATION, NULL, "(lifetime = %ld:%ld)\n",
+			(long)s->lifetime, (long)tsap->lifetime);
+		plog(LLV_DEBUG, LOCATION, NULL, "(lifebyte = %zu:%zu)\n",
+			s->lifebyte, tsap->lifebyte);
+		plog(LLV_DEBUG, LOCATION, NULL, "enctype = %s:%s\n",
+			s_oakley_attr_v(OAKLEY_ATTR_ENC_ALG,
+					s->enctype),
+			s_oakley_attr_v(OAKLEY_ATTR_ENC_ALG,
+					tsap->enctype));
+		plog(LLV_DEBUG, LOCATION, NULL, "(encklen = %d:%d)\n",
+			s->encklen, tsap->encklen);
+		plog(LLV_DEBUG, LOCATION, NULL, "hashtype = %s:%s\n",
+			s_oakley_attr_v(OAKLEY_ATTR_HASH_ALG,
+					s->hashtype),
+			s_oakley_attr_v(OAKLEY_ATTR_HASH_ALG,
+					tsap->hashtype));
+		plog(LLV_DEBUG, LOCATION, NULL, "authmethod = %s:%s\n",
+			s_oakley_attr_v(OAKLEY_ATTR_AUTH_METHOD,
+					s->authmethod),
+			s_oakley_attr_v(OAKLEY_ATTR_AUTH_METHOD,
+					tsap->authmethod));
+		plog(LLV_DEBUG, LOCATION, NULL, "dh_group = %s:%s\n",
+			s_oakley_attr_v(OAKLEY_ATTR_GRP_DESC,
+					s->dh_group),
+			s_oakley_attr_v(OAKLEY_ATTR_GRP_DESC,
+					tsap->dh_group));
+#if 0
+		/* XXX to be considered ? */
+		if (tsap->lifebyte > s->lifebyte) ;
+#endif
+		/*
+		 * if responder side and peer's key length in proposal
+		 * is bigger than mine, it might be accepted.
+		 */
+		if(tsap->enctype == s->enctype &&
+		    tsap->authmethod == authmethod &&
+		    tsap->hashtype == s->hashtype &&
+		    tsap->dh_group == s->dh_group &&
+		    tsap->encklen == s->encklen) {
+			switch(check_level) {
+			case PROP_CHECK_OBEY:
+				goto found;
+				break;
+
+			case PROP_CHECK_STRICT:
+				if ((tsap->lifetime > s->lifetime) ||
+				    (tsap->lifebyte > s->lifebyte))
+					continue;
+				goto found;
+				break;
+
+			case PROP_CHECK_CLAIM:
+				if (tsap->lifetime < s->lifetime)
+					s->lifetime = tsap->lifetime;
+				if (tsap->lifebyte < s->lifebyte)
+					s->lifebyte = tsap->lifebyte;
+				goto found;
+				break;
+
+			case PROP_CHECK_EXACT:
+				if ((tsap->lifetime != s->lifetime) ||
+				    (tsap->lifebyte != s->lifebyte))
+					continue;
+				goto found;
+				break;
+
+			default:
+				plog(LLV_ERROR, LOCATION, NULL, 
+				    "Unexpected proposal_check value\n");
+				continue;
+				break;
+			}
+		}
+	}
+
+found:
+	if (tsap->dhgrp != NULL){
+		oakley_dhgrp_free(tsap->dhgrp);
+		tsap->dhgrp = NULL;
+	}
+
+	if ((s = dupisakmpsa(s)) != NULL) {
+		switch(check_level) {
+		case PROP_CHECK_OBEY:
+			s->lifetime = tsap->lifetime;
+			s->lifebyte = tsap->lifebyte;
+			break;
+
+		case PROP_CHECK_STRICT:
+			s->lifetime = tsap->lifetime;
+			s->lifebyte = tsap->lifebyte;
+			break;
+
+		case PROP_CHECK_CLAIM:
+			if (tsap->lifetime < s->lifetime)
+				s->lifetime = tsap->lifetime;
+			if (tsap->lifebyte < s->lifebyte)
+				s->lifebyte = tsap->lifebyte;
+			break;
+
+		default:
+			break;
+		}
+	}
+	return s;
+}
+
+/*
+ * print all of items in peer's proposal which are mismatched to my proposal.
+ * p       : one of peer's proposal.
+ * proposal: my proposals.
+ */
+static void
+print_ph1mismatched(p, proposal)
+	struct prop_pair *p;
+	struct isakmpsa *proposal;
+{
+	struct isakmpsa sa, *s;
+
+	memset(&sa, 0, sizeof(sa));
+	if (t2isakmpsa(p->trns, &sa) < 0)
+		return;
+	for (s = proposal; s ; s = s->next) {
+		if (sa.enctype != s->enctype) {
+			plog(LLV_ERROR, LOCATION, NULL,
+				"rejected enctype: "
+				"DB(prop#%d:trns#%d):Peer(prop#%d:trns#%d) = "
+				"%s:%s\n",
+				s->prop_no, s->trns_no,
+				p->prop->p_no, p->trns->t_no,
+				s_oakley_attr_v(OAKLEY_ATTR_ENC_ALG,
+					s->enctype),
+				s_oakley_attr_v(OAKLEY_ATTR_ENC_ALG,
+					sa.enctype));
+		}
+		if (sa.authmethod != s->authmethod) {
+			plog(LLV_ERROR, LOCATION, NULL,
+				"rejected authmethod: "
+				"DB(prop#%d:trns#%d):Peer(prop#%d:trns#%d) = "
+				"%s:%s\n",
+				s->prop_no, s->trns_no,
+				p->prop->p_no, p->trns->t_no,
+				s_oakley_attr_v(OAKLEY_ATTR_AUTH_METHOD,
+					s->authmethod),
+				s_oakley_attr_v(OAKLEY_ATTR_AUTH_METHOD,
+					sa.authmethod));
+		}
+		if (sa.hashtype != s->hashtype) {
+			plog(LLV_ERROR, LOCATION, NULL,
+				"rejected hashtype: "
+				"DB(prop#%d:trns#%d):Peer(prop#%d:trns#%d) = "
+				"%s:%s\n",
+				s->prop_no, s->trns_no,
+				p->prop->p_no, p->trns->t_no,
+				s_oakley_attr_v(OAKLEY_ATTR_HASH_ALG,
+					s->hashtype),
+				s_oakley_attr_v(OAKLEY_ATTR_HASH_ALG,
+					sa.hashtype));
+		}
+		if (sa.dh_group != s->dh_group) {
+			plog(LLV_ERROR, LOCATION, NULL,
+				"rejected dh_group: "
+				"DB(prop#%d:trns#%d):Peer(prop#%d:trns#%d) = "
+				"%s:%s\n",
+				s->prop_no, s->trns_no,
+				p->prop->p_no, p->trns->t_no,
+				s_oakley_attr_v(OAKLEY_ATTR_GRP_DESC,
+					s->dh_group),
+				s_oakley_attr_v(OAKLEY_ATTR_GRP_DESC,
+					sa.dh_group));
+		}
+	}
+
+	if (sa.dhgrp != NULL){
+		oakley_dhgrp_free(sa.dhgrp);
+		sa.dhgrp=NULL;
+	}
+}
+
+/*
+ * get ISAKMP data attributes
+ */
+static int
+t2isakmpsa(trns, sa)
+	struct isakmp_pl_t *trns;
+	struct isakmpsa *sa;
+{
+	struct isakmp_data *d, *prev;
+	int flag, type;
+	int error = -1;
+	int life_t;
+	int keylen = 0;
+	vchar_t *val = NULL;
+	int len, tlen;
+	u_char *p;
+
+	tlen = ntohs(trns->h.len) - sizeof(*trns);
+	prev = (struct isakmp_data *)NULL;
+	d = (struct isakmp_data *)(trns + 1);
+
+	/* default */
+	life_t = OAKLEY_ATTR_SA_LD_TYPE_DEFAULT;
+	sa->lifetime = OAKLEY_ATTR_SA_LD_SEC_DEFAULT;
+	sa->lifebyte = 0;
+	sa->dhgrp = racoon_calloc(1, sizeof(struct dhgroup));
+	if (!sa->dhgrp)
+		goto err;
+
+	while (tlen > 0) {
+
+		type = ntohs(d->type) & ~ISAKMP_GEN_MASK;
+		flag = ntohs(d->type) & ISAKMP_GEN_MASK;
+
+		plog(LLV_DEBUG, LOCATION, NULL,
+			"type=%s, flag=0x%04x, lorv=%s\n",
+			s_oakley_attr(type), flag,
+			s_oakley_attr_v(type, ntohs(d->lorv)));
+
+		/* get variable-sized item */
+		switch (type) {
+		case OAKLEY_ATTR_GRP_PI:
+		case OAKLEY_ATTR_GRP_GEN_ONE:
+		case OAKLEY_ATTR_GRP_GEN_TWO:
+		case OAKLEY_ATTR_GRP_CURVE_A:
+		case OAKLEY_ATTR_GRP_CURVE_B:
+		case OAKLEY_ATTR_SA_LD:
+		case OAKLEY_ATTR_GRP_ORDER:
+			if (flag) {	/*TV*/
+				len = 2;
+				p = (u_char *)&d->lorv;
+			} else {	/*TLV*/
+				len = ntohs(d->lorv);
+				p = (u_char *)(d + 1);
+			}
+			val = vmalloc(len);
+			if (!val)
+				return -1;
+			memcpy(val->v, p, len);
+			break;
+
+		default:
+			break;
+		}
+
+		switch (type) {
+		case OAKLEY_ATTR_ENC_ALG:
+			sa->enctype = (u_int16_t)ntohs(d->lorv);
+			break;
+
+		case OAKLEY_ATTR_HASH_ALG:
+			sa->hashtype = (u_int16_t)ntohs(d->lorv);
+			break;
+
+		case OAKLEY_ATTR_AUTH_METHOD:
+			sa->authmethod = ntohs(d->lorv);
+			break;
+
+		case OAKLEY_ATTR_GRP_DESC:
+			sa->dh_group = (u_int16_t)ntohs(d->lorv);
+			break;
+
+		case OAKLEY_ATTR_GRP_TYPE:
+		{
+			int type = (int)ntohs(d->lorv);
+			if (type == OAKLEY_ATTR_GRP_TYPE_MODP)
+				sa->dhgrp->type = type;
+			else
+				return -1;
+			break;
+		}
+		case OAKLEY_ATTR_GRP_PI:
+			sa->dhgrp->prime = val;
+			break;
+
+		case OAKLEY_ATTR_GRP_GEN_ONE:
+			vfree(val);
+			if (!flag)
+				sa->dhgrp->gen1 = ntohs(d->lorv);
+			else {
+				int len = ntohs(d->lorv);
+				sa->dhgrp->gen1 = 0;
+				if (len > 4)
+					return -1;
+				memcpy(&sa->dhgrp->gen1, d + 1, len);
+				sa->dhgrp->gen1 = ntohl(sa->dhgrp->gen1);
+			}
+			break;
+
+		case OAKLEY_ATTR_GRP_GEN_TWO:
+			vfree(val);
+			if (!flag)
+				sa->dhgrp->gen2 = ntohs(d->lorv);
+			else {
+				int len = ntohs(d->lorv);
+				sa->dhgrp->gen2 = 0;
+				if (len > 4)
+					return -1;
+				memcpy(&sa->dhgrp->gen2, d + 1, len);
+				sa->dhgrp->gen2 = ntohl(sa->dhgrp->gen2);
+			}
+			break;
+
+		case OAKLEY_ATTR_GRP_CURVE_A:
+			sa->dhgrp->curve_a = val;
+			break;
+
+		case OAKLEY_ATTR_GRP_CURVE_B:
+			sa->dhgrp->curve_b = val;
+			break;
+
+		case OAKLEY_ATTR_SA_LD_TYPE:
+		{
+			int type = (int)ntohs(d->lorv);
+			switch (type) {
+			case OAKLEY_ATTR_SA_LD_TYPE_SEC:
+			case OAKLEY_ATTR_SA_LD_TYPE_KB:
+				life_t = type;
+				break;
+			default:
+				life_t = OAKLEY_ATTR_SA_LD_TYPE_DEFAULT;
+				break;
+			}
+			break;
+		}
+		case OAKLEY_ATTR_SA_LD:
+			if (!prev
+			 || (ntohs(prev->type) & ~ISAKMP_GEN_MASK) !=
+					OAKLEY_ATTR_SA_LD_TYPE) {
+				plog(LLV_ERROR, LOCATION, NULL,
+				    "life duration must follow ltype\n");
+				break;
+			}
+
+			switch (life_t) {
+			case IPSECDOI_ATTR_SA_LD_TYPE_SEC:
+				sa->lifetime = ipsecdoi_set_ld(val);
+				vfree(val);
+				if (sa->lifetime == 0) {
+					plog(LLV_ERROR, LOCATION, NULL,
+						"invalid life duration.\n");
+					goto err;
+				}
+				break;
+			case IPSECDOI_ATTR_SA_LD_TYPE_KB:
+				sa->lifebyte = ipsecdoi_set_ld(val);
+				vfree(val);
+				if (sa->lifebyte == 0) {
+					plog(LLV_ERROR, LOCATION, NULL,
+						"invalid life duration.\n");
+					goto err;
+				}
+				break;
+			default:
+				vfree(val);
+				plog(LLV_ERROR, LOCATION, NULL,
+					"invalid life type: %d\n", life_t);
+				goto err;
+			}
+			break;
+
+		case OAKLEY_ATTR_KEY_LEN:
+		{
+			int len = ntohs(d->lorv);
+			if (len % 8 != 0) {
+				plog(LLV_ERROR, LOCATION, NULL,
+					"keylen %d: not multiple of 8\n",
+					len);
+				goto err;
+			}
+			sa->encklen = (u_int16_t)len;
+			keylen++;
+			break;
+		}
+		case OAKLEY_ATTR_PRF:
+		case OAKLEY_ATTR_FIELD_SIZE:
+			/* unsupported */
+			break;
+
+		case OAKLEY_ATTR_GRP_ORDER:
+			sa->dhgrp->order = val;
+			break;
+#ifdef HAVE_GSSAPI
+		case OAKLEY_ATTR_GSS_ID:
+		{
+			int error = -1;
+			iconv_t cd = (iconv_t) -1;
+			size_t srcleft, dstleft, rv;
+			__iconv_const char *src;
+			char *dst;
+			int len = ntohs(d->lorv);
+
+			/*
+			 * Older verions of racoon just placed the
+			 * ISO-Latin-1 string on the wire directly.
+			 * Check to see if we are configured to be
+			 * compatible with this behavior.
+			 */
+			if (lcconf->gss_id_enc == LC_GSSENC_LATIN1) {
+				if ((sa->gssid = vmalloc(len)) == NULL) {
+					plog(LLV_ERROR, LOCATION, NULL,
+					    "failed to allocate memory\n");
+					goto out;
+				}
+				memcpy(sa->gssid->v, d + 1, len);
+				plog(LLV_DEBUG, LOCATION, NULL,
+				    "received old-style gss "
+				    "id '%.*s' (len %zu)\n",
+				    (int)sa->gssid->l, sa->gssid->v, 
+				    sa->gssid->l);
+				error = 0;
+				goto out;
+			}
+
+			/*
+			 * For Windows 2000 compatibility, we expect
+			 * the GSS ID attribute on the wire to be
+			 * encoded in UTF-16LE.  Internally, we work
+			 * in ISO-Latin-1.  Therefore, we should need
+			 * 1/2 the specified length, which should always
+			 * be a multiple of 2 octets.
+			 */
+			cd = iconv_open("latin1", "utf-16le");
+			if (cd == (iconv_t) -1) {
+				plog(LLV_ERROR, LOCATION, NULL,
+				    "unable to initialize utf-16le -> latin1 "
+				    "conversion descriptor: %s\n",
+				    strerror(errno));
+				goto out;
+			}
+
+			if ((sa->gssid = vmalloc(len / 2)) == NULL) {
+				plog(LLV_ERROR, LOCATION, NULL,
+				    "failed to allocate memory\n");
+				goto out;
+			}
+
+			src = (__iconv_const char *)(d + 1);
+			srcleft = len;
+
+			dst = sa->gssid->v;
+			dstleft = len / 2;
+
+			rv = iconv(cd, (__iconv_const char **)&src, &srcleft, 
+				   &dst, &dstleft);
+			if (rv != 0) {
+				if (rv == -1) {
+					plog(LLV_ERROR, LOCATION, NULL,
+					    "unable to convert GSS ID from "
+					    "utf-16le -> latin1: %s\n",
+					    strerror(errno));
+				} else {
+					plog(LLV_ERROR, LOCATION, NULL,
+					    "%zd character%s in GSS ID cannot "
+					    "be represented in latin1\n",
+					    rv, rv == 1 ? "" : "s");
+				}
+				goto out;
+			}
+
+			/* XXX dstleft should always be 0; assert it? */
+			sa->gssid->l = (len / 2) - dstleft;
+
+			plog(LLV_DEBUG, LOCATION, NULL,
+			    "received gss id '%.*s' (len %zu)\n",
+			    (int)sa->gssid->l, sa->gssid->v, sa->gssid->l);
+
+			error = 0;
+out:
+			if (cd != (iconv_t)-1)
+				(void)iconv_close(cd);
+
+			if ((error != 0) && (sa->gssid != NULL)) {
+				vfree(sa->gssid);
+				sa->gssid = NULL;
+			}
+			break;
+		}
+#endif /* HAVE_GSSAPI */
+
+		default:
+			break;
+		}
+
+		prev = d;
+		if (flag) {
+			tlen -= sizeof(*d);
+			d = (struct isakmp_data *)((char *)d + sizeof(*d));
+		} else {
+			tlen -= (sizeof(*d) + ntohs(d->lorv));
+			d = (struct isakmp_data *)((char *)d + sizeof(*d) + ntohs(d->lorv));
+		}
+	}
+
+	/* key length must not be specified on some algorithms */
+	if (keylen) {
+		if (sa->enctype == OAKLEY_ATTR_ENC_ALG_DES
+#ifdef HAVE_OPENSSL_IDEA_H
+		 || sa->enctype == OAKLEY_ATTR_ENC_ALG_IDEA
+#endif
+		 || sa->enctype == OAKLEY_ATTR_ENC_ALG_3DES) {
+			plog(LLV_ERROR, LOCATION, NULL,
+				"keylen must not be specified "
+				"for encryption algorithm %d\n",
+				sa->enctype);
+			return -1;
+		}
+	}
+
+	return 0;
+err:
+	return error;
+}
+
+/*%%%*/
+/*
+ * check phase 2 SA payload and select single proposal.
+ * make new SA payload to be replyed not including general header.
+ * This function is called by responder only.
+ * OUT:
+ *	0: succeed.
+ *	-1: error occured.
+ */
+int
+ipsecdoi_selectph2proposal(iph2)
+	struct ph2handle *iph2;
+{
+	struct prop_pair **pair;
+	struct prop_pair *ret;
+
+	/* get proposal pair */
+	pair = get_proppair(iph2->sa, IPSECDOI_TYPE_PH2);
+	if (pair == NULL)
+		return -1;
+
+	/* check and select a proposal. */
+	ret = get_ph2approval(iph2, pair);
+	free_proppair(pair);
+	if (ret == NULL)
+		return -1;
+
+	/* make a SA to be replayed. */
+	/* SPI must be updated later. */
+	iph2->sa_ret = get_sabyproppair(ret, iph2->ph1);
+	free_proppair0(ret);
+	if (iph2->sa_ret == NULL)
+		return -1;
+
+	return 0;
+}
+
+/*
+ * check phase 2 SA payload returned from responder.
+ * This function is called by initiator only.
+ * OUT:
+ *	0: valid.
+ *	-1: invalid.
+ */
+int
+ipsecdoi_checkph2proposal(iph2)
+	struct ph2handle *iph2;
+{
+	struct prop_pair **rpair = NULL, **spair = NULL;
+	struct prop_pair *p;
+	int i, n, num;
+	int error = -1;
+	vchar_t *sa_ret = NULL;
+
+	/* get proposal pair of SA sent. */
+	spair = get_proppair(iph2->sa, IPSECDOI_TYPE_PH2);
+	if (spair == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"failed to get prop pair.\n");
+		goto end;
+	}
+
+	/* XXX should check the number of transform */
+
+	/* get proposal pair of SA replayed */
+	rpair = get_proppair(iph2->sa_ret, IPSECDOI_TYPE_PH2);
+	if (rpair == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"failed to get prop pair.\n");
+		goto end;
+	}
+
+	/* check proposal is only one ? */
+	n = 0;
+	num = 0;
+	for (i = 0; i < MAXPROPPAIRLEN; i++) {
+		if (rpair[i]) {
+			n = i;
+			num++;
+		}
+	}
+	if (num == 0) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"no proposal received.\n");
+		goto end;
+	}
+	if (num != 1) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"some proposals received.\n");
+		goto end;
+	}
+
+	if (spair[n] == NULL) {
+		plog(LLV_WARNING, LOCATION, NULL,
+			"invalid proposal number:%d received.\n", i);
+	}
+	
+
+	if (rpair[n]->tnext != NULL) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"multi transforms replyed.\n");
+		goto end;
+	}
+
+	if (cmp_aproppair_i(rpair[n], spair[n])) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"proposal mismathed.\n");
+		goto end;
+	}
+
+	/*
+	 * check and select a proposal.
+	 * ensure that there is no modification of the proposal by
+	 * cmp_aproppair_i()
+	 */
+	p = get_ph2approval(iph2, rpair);
+	if (p == NULL)
+		goto end;
+
+	/* make a SA to be replayed. */
+	sa_ret = iph2->sa_ret;
+	iph2->sa_ret = get_sabyproppair(p, iph2->ph1);
+	free_proppair0(p);
+	if (iph2->sa_ret == NULL)
+		goto end;
+
+	error = 0;
+
+end:
+	if (rpair)
+		free_proppair(rpair);
+	if (spair)
+		free_proppair(spair);
+	if (sa_ret)
+		vfree(sa_ret);
+
+	return error;
+}
+
+/*
+ * compare two prop_pair which is assumed to have same proposal number.
+ * the case of bundle or single SA, NOT multi transforms.
+ * a: a proposal that is multi protocols and single transform, usually replyed.
+ * b: a proposal that is multi protocols and multi transform, usually sent.
+ * NOTE: this function is for initiator.
+ * OUT
+ *	0: equal
+ *	1: not equal
+ * XXX cannot understand the comment!
+ */
+static int
+cmp_aproppair_i(a, b)
+	struct prop_pair *a, *b;
+{
+	struct prop_pair *p, *q, *r;
+	int len;
+
+	for (p = a, q = b; p && q; p = p->next, q = q->next) {
+		for (r = q; r; r = r->tnext) {
+			/* compare trns */
+			if (p->trns->t_no == r->trns->t_no)
+				break;
+		}
+		if (!r) {
+			/* no suitable transform found */
+			plog(LLV_ERROR, LOCATION, NULL,
+				"no suitable transform found.\n");
+			return -1;
+		}
+
+		/* compare prop */
+		if (p->prop->p_no != r->prop->p_no) {
+			plog(LLV_WARNING, LOCATION, NULL,
+				"proposal #%d mismatched, "
+				"expected #%d.\n",
+				r->prop->p_no, p->prop->p_no);
+			/*FALLTHROUGH*/
+		}
+
+		if (p->prop->proto_id != r->prop->proto_id) {
+			plog(LLV_ERROR, LOCATION, NULL,
+				"proto_id mismathed: my:%d peer:%d\n",
+				r->prop->proto_id, p->prop->proto_id);
+			return -1;
+		}
+
+		if (p->prop->spi_size != r->prop->spi_size) {
+			plog(LLV_ERROR, LOCATION, NULL,
+				"invalid spi size: %d.\n",
+				p->prop->spi_size);
+			return -1;
+		}
+
+		/* check #of transforms */
+		if (p->prop->num_t != 1) {
+			plog(LLV_WARNING, LOCATION, NULL,
+				"#of transform is %d, "
+				"but expected 1.\n", p->prop->num_t);
+			/*FALLTHROUGH*/
+		}
+
+		if (p->trns->t_id != r->trns->t_id) {
+			plog(LLV_WARNING, LOCATION, NULL,
+				"transform number has been modified.\n");
+			/*FALLTHROUGH*/
+		}
+		if (p->trns->reserved != r->trns->reserved) {
+			plog(LLV_WARNING, LOCATION, NULL,
+				"reserved field should be zero.\n");
+			/*FALLTHROUGH*/
+		}
+
+		/* compare attribute */
+		len = ntohs(r->trns->h.len) - sizeof(*p->trns);
+		if (memcmp(p->trns + 1, r->trns + 1, len) != 0) {
+			plog(LLV_WARNING, LOCATION, NULL,
+				"attribute has been modified.\n");
+			/*FALLTHROUGH*/
+		}
+	}
+	if ((p && !q) || (!p && q)) {
+		/* # of protocols mismatched */
+		plog(LLV_ERROR, LOCATION, NULL,
+			"#of protocols mismatched.\n");
+		return -1;
+	}
+
+	return 0;
+}
+
+/*
+ * acceptable check for policy configuration.
+ * return a new SA payload to be reply to peer.
+ */
+static struct prop_pair *
+get_ph2approval(iph2, pair)
+	struct ph2handle *iph2;
+	struct prop_pair **pair;
+{
+	struct prop_pair *ret;
+	int i;
+
+	iph2->approval = NULL;
+
+	plog(LLV_DEBUG, LOCATION, NULL,
+		"begin compare proposals.\n");
+
+	for (i = 0; i < MAXPROPPAIRLEN; i++) {
+		if (pair[i] == NULL)
+			continue;
+		plog(LLV_DEBUG, LOCATION, NULL,
+			"pair[%d]: %p\n", i, pair[i]);
+		print_proppair(LLV_DEBUG, pair[i]);;
+
+		/* compare proposal and select one */
+		ret = get_ph2approvalx(iph2, pair[i]);
+		if (ret != NULL) {
+			/* found */
+			return ret;
+		}
+	}
+
+	plog(LLV_ERROR, LOCATION, NULL, "no suitable policy found.\n");
+
+	return NULL;
+}
+
+/*
+ * compare my proposal and peers just one proposal.
+ * set a approval.
+ */
+static struct prop_pair *
+get_ph2approvalx(iph2, pp)
+	struct ph2handle *iph2;
+	struct prop_pair *pp;
+{
+	struct prop_pair *ret = NULL;
+	struct saprop *pr0, *pr = NULL;
+	struct saprop *q1, *q2;
+
+	pr0 = aproppair2saprop(pp);
+	if (pr0 == NULL)
+		return NULL;
+
+	for (q1 = pr0; q1; q1 = q1->next) {
+		for (q2 = iph2->proposal; q2; q2 = q2->next) {
+			plog(LLV_DEBUG, LOCATION, NULL,
+				"peer's single bundle:\n");
+			printsaprop0(LLV_DEBUG, q1);
+			plog(LLV_DEBUG, LOCATION, NULL,
+				"my single bundle:\n");
+			printsaprop0(LLV_DEBUG, q2);
+
+			pr = cmpsaprop_alloc(iph2->ph1, q1, q2, iph2->side);
+			if (pr != NULL)
+				goto found;
+
+			plog(LLV_ERROR, LOCATION, NULL,
+				"not matched\n");
+		}
+	}
+	/* no proposal matching */
+err:
+	flushsaprop(pr0);
+	return NULL;
+
+found:
+	flushsaprop(pr0);
+	plog(LLV_DEBUG, LOCATION, NULL, "matched\n");
+	iph2->approval = pr;
+
+    {
+	struct saproto *sp;
+	struct prop_pair *p, *x;
+	struct prop_pair *n = NULL;
+
+	ret = NULL;
+
+	for (p = pp; p; p = p->next) {
+		/*
+		 * find a proposal with matching proto_id.
+		 * we have analyzed validity already, in cmpsaprop_alloc().
+		 */
+		for (sp = pr->head; sp; sp = sp->next) {
+			if (sp->proto_id == p->prop->proto_id)
+				break;
+		}
+		if (!sp)
+			goto err;
+		if (sp->head->next)
+			goto err;	/* XXX */
+
+		for (x = p; x; x = x->tnext)
+			if (sp->head->trns_no == x->trns->t_no)
+				break;
+		if (!x)
+			goto err;	/* XXX */
+
+		n = racoon_calloc(1, sizeof(struct prop_pair));
+		if (n == NULL) {
+			plog(LLV_ERROR, LOCATION, NULL,
+				"failed to get buffer.\n");
+			goto err;
+		}
+
+		n->prop = x->prop;
+		n->trns = x->trns;
+
+		/* need to preserve the order */
+		for (x = ret; x && x->next; x = x->next)
+			;
+		if (x && x->prop == n->prop) {
+			for (/*nothing*/; x && x->tnext; x = x->tnext)
+				;
+			x->tnext = n;
+		} else {
+			if (x)
+				x->next = n;
+			else {
+				ret = n;
+			}
+		}
+
+		/* #of transforms should be updated ? */
+	}
+    }
+
+	return ret;
+}
+
+void
+free_proppair(pair)
+	struct prop_pair **pair;
+{
+	int i;
+
+	for (i = 0; i < MAXPROPPAIRLEN; i++) {
+		free_proppair0(pair[i]);
+		pair[i] = NULL;
+	}
+	racoon_free(pair);
+}
+
+static void
+free_proppair0(pair)
+	struct prop_pair *pair;
+{
+	struct prop_pair *p, *q, *r, *s;
+
+	p = pair;
+	while (p) {
+		q = p->next;
+		r = p;
+		while (r) {
+			s = r->tnext;
+			racoon_free(r);
+			r = s;
+		}
+		p = q;
+	}
+}
+
+/*
+ * get proposal pairs from SA payload.
+ * tiny check for proposal payload.
+ */
+struct prop_pair **
+get_proppair(sa, mode)
+	vchar_t *sa;
+	int mode;
+{
+	struct prop_pair **pair = NULL;
+	int num_p = 0;			/* number of proposal for use */
+	int tlen;
+	caddr_t bp;
+	int i;
+	struct ipsecdoi_sa_b *sab = (struct ipsecdoi_sa_b *)sa->v;
+
+	plog(LLV_DEBUG, LOCATION, NULL, "total SA len=%zu\n", sa->l);
+	plogdump(LLV_DEBUG, sa->v, sa->l);
+
+	/* check SA payload size */
+	if (sa->l < sizeof(*sab)) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"Invalid SA length = %zu.\n", sa->l);
+		goto bad;
+	}
+
+	/* check DOI */
+	if (check_doi(ntohl(sab->doi)) < 0)
+		goto bad;
+
+	/* check SITUATION */
+	if (check_situation(ntohl(sab->sit)) < 0)
+		goto bad;
+
+	pair = racoon_calloc(1, MAXPROPPAIRLEN * sizeof(*pair));
+	if (pair == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"failed to get buffer.\n");
+		goto bad;
+	}
+	memset(pair, 0, sizeof(pair));
+
+	bp = (caddr_t)(sab + 1);
+	tlen = sa->l - sizeof(*sab);
+
+    {
+	struct isakmp_pl_p *prop;
+	int proplen;
+	vchar_t *pbuf = NULL;
+	struct isakmp_parse_t *pa;
+
+	pbuf = isakmp_parsewoh(ISAKMP_NPTYPE_P, (struct isakmp_gen *)bp, tlen);
+	if (pbuf == NULL)
+		goto bad;
+
+	for (pa = (struct isakmp_parse_t *)pbuf->v;
+	     pa->type != ISAKMP_NPTYPE_NONE;
+	     pa++) {
+		/* check the value of next payload */
+		if (pa->type != ISAKMP_NPTYPE_P) {
+			plog(LLV_ERROR, LOCATION, NULL,
+				"Invalid payload type=%u\n", pa->type);
+			vfree(pbuf);
+			goto bad;
+		}
+
+		prop = (struct isakmp_pl_p *)pa->ptr;
+		proplen = pa->len;
+
+		plog(LLV_DEBUG, LOCATION, NULL,
+			"proposal #%u len=%d\n", prop->p_no, proplen);
+
+		if (proplen == 0) {
+			plog(LLV_ERROR, LOCATION, NULL,
+				"invalid proposal with length %d\n", proplen);
+			vfree(pbuf);
+			goto bad;
+		}
+
+		/* check Protocol ID */
+		if (!check_protocol[mode]) {
+			plog(LLV_ERROR, LOCATION, NULL,
+				"unsupported mode %d\n", mode);
+			continue;
+		}
+
+		if (check_protocol[mode](prop->proto_id) < 0)
+			continue;
+
+		/* check SPI length when IKE. */
+		if (check_spi_size(prop->proto_id, prop->spi_size) < 0)
+			continue;
+
+		/* get transform */
+		if (get_transform(prop, pair, &num_p) < 0) {
+			vfree(pbuf);
+			goto bad;
+		}
+	}
+	vfree(pbuf);
+	pbuf = NULL;
+    }
+
+    {
+	int notrans, nprop;
+	struct prop_pair *p, *q;
+
+	/* check for proposals with no transforms */
+	for (i = 0; i < MAXPROPPAIRLEN; i++) {
+		if (!pair[i])
+			continue;
+
+		plog(LLV_DEBUG, LOCATION, NULL, "pair %d:\n", i);
+		print_proppair(LLV_DEBUG, pair[i]);
+
+		notrans = nprop = 0;
+		for (p = pair[i]; p; p = p->next) {
+			if (p->trns == NULL) {
+				notrans++;
+				break;
+			}
+			for (q = p; q; q = q->tnext)
+				nprop++;
+		}
+
+#if 0
+		/*
+		 * XXX at this moment, we cannot accept proposal group
+		 * with multiple proposals.  this should be fixed.
+		 */
+		if (pair[i]->next) {
+			plog(LLV_WARNING, LOCATION, NULL,
+				"proposal #%u ignored "
+				"(multiple proposal not supported)\n",
+				pair[i]->prop->p_no);
+			notrans++;
+		}
+#endif
+
+		if (notrans) {
+			for (p = pair[i]; p; p = q) {
+				q = p->next;
+				racoon_free(p);
+			}
+			pair[i] = NULL;
+			num_p--;
+		} else {
+			plog(LLV_DEBUG, LOCATION, NULL,
+				"proposal #%u: %d transform\n",
+				pair[i]->prop->p_no, nprop);
+		}
+	}
+    }
+
+	/* bark if no proposal is found. */
+	if (num_p <= 0) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"no Proposal found.\n");
+		goto bad;
+	}
+
+	return pair;
+bad:
+	if (pair != NULL)
+		racoon_free(pair);
+	return NULL;
+}
+
+/*
+ * check transform payload.
+ * OUT:
+ *	positive: return the pointer to the payload of valid transform.
+ *	0	: No valid transform found.
+ */
+static int
+get_transform(prop, pair, num_p)
+	struct isakmp_pl_p *prop;
+	struct prop_pair **pair;
+	int *num_p;
+{
+	int tlen; /* total length of all transform in a proposal */
+	caddr_t bp;
+	struct isakmp_pl_t *trns;
+	int trnslen;
+	vchar_t *pbuf = NULL;
+	struct isakmp_parse_t *pa;
+	struct prop_pair *p = NULL, *q;
+	int num_t;
+
+	bp = (caddr_t)prop + sizeof(struct isakmp_pl_p) + prop->spi_size;
+	tlen = ntohs(prop->h.len)
+		- (sizeof(struct isakmp_pl_p) + prop->spi_size);
+	pbuf = isakmp_parsewoh(ISAKMP_NPTYPE_T, (struct isakmp_gen *)bp, tlen);
+	if (pbuf == NULL)
+		return -1;
+
+	/* check and get transform for use */
+	num_t = 0;
+	for (pa = (struct isakmp_parse_t *)pbuf->v;
+	     pa->type != ISAKMP_NPTYPE_NONE;
+	     pa++) {
+
+		num_t++;
+
+		/* check the value of next payload */
+		if (pa->type != ISAKMP_NPTYPE_T) {
+			plog(LLV_ERROR, LOCATION, NULL,
+				"Invalid payload type=%u\n", pa->type);
+			break;
+		}
+
+		trns = (struct isakmp_pl_t *)pa->ptr;
+		trnslen = pa->len;
+
+		plog(LLV_DEBUG, LOCATION, NULL,
+			"transform #%u len=%u\n", trns->t_no, trnslen);
+
+		/* check transform ID */
+		if (prop->proto_id >= ARRAYLEN(check_transform)) {
+			plog(LLV_WARNING, LOCATION, NULL,
+				"unsupported proto_id %u\n",
+				prop->proto_id);
+			continue;
+		}
+		if (prop->proto_id >= ARRAYLEN(check_attributes)) {
+			plog(LLV_WARNING, LOCATION, NULL,
+				"unsupported proto_id %u\n",
+				prop->proto_id);
+			continue;
+		}
+
+		if (!check_transform[prop->proto_id]
+		 || !check_attributes[prop->proto_id]) {
+			plog(LLV_WARNING, LOCATION, NULL,
+				"unsupported proto_id %u\n",
+				prop->proto_id);
+			continue;
+		}
+		if (check_transform[prop->proto_id](trns->t_id) < 0)
+			continue;
+
+		/* check data attributes */
+		if (check_attributes[prop->proto_id](trns) != 0)
+			continue;
+
+		p = racoon_calloc(1, sizeof(*p));
+		if (p == NULL) {
+			plog(LLV_ERROR, LOCATION, NULL,
+				"failed to get buffer.\n");
+			vfree(pbuf);
+			return -1;
+		}
+		p->prop = prop;
+		p->trns = trns;
+
+		/* need to preserve the order */
+		for (q = pair[prop->p_no]; q && q->next; q = q->next)
+			;
+		if (q && q->prop == p->prop) {
+			for (/*nothing*/; q && q->tnext; q = q->tnext)
+				;
+			q->tnext = p;
+		} else {
+			if (q)
+				q->next = p;
+			else {
+				pair[prop->p_no] = p;
+				(*num_p)++;
+			}
+		}
+	}
+
+	vfree(pbuf);
+
+	return 0;
+}
+
+/*
+ * make a new SA payload from prop_pair.
+ * NOTE: this function make spi value clear.
+ */
+vchar_t *
+get_sabyproppair(pair, iph1)
+	struct prop_pair *pair;
+	struct ph1handle *iph1;
+{
+	vchar_t *newsa;
+	int newtlen;
+	u_int8_t *np_p = NULL;
+	struct prop_pair *p;
+	int prophlen, trnslen;
+	caddr_t bp;
+
+	newtlen = sizeof(struct ipsecdoi_sa_b);
+	for (p = pair; p; p = p->next) {
+		newtlen += sizeof(struct isakmp_pl_p);
+		newtlen += p->prop->spi_size;
+		newtlen += ntohs(p->trns->h.len);
+	}
+
+	newsa = vmalloc(newtlen);
+	if (newsa == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL, "failed to get newsa.\n");
+		return NULL;
+	}
+	bp = newsa->v;
+
+	((struct isakmp_gen *)bp)->len = htons(newtlen);
+
+	/* update some of values in SA header */
+	((struct ipsecdoi_sa_b *)bp)->doi = htonl(iph1->rmconf->doitype);
+	((struct ipsecdoi_sa_b *)bp)->sit = htonl(iph1->rmconf->sittype);
+	bp += sizeof(struct ipsecdoi_sa_b);
+
+	/* create proposal payloads */
+	for (p = pair; p; p = p->next) {
+		prophlen = sizeof(struct isakmp_pl_p)
+				+ p->prop->spi_size;
+		trnslen = ntohs(p->trns->h.len);
+
+		if (np_p)
+			*np_p = ISAKMP_NPTYPE_P;
+
+		/* create proposal */
+
+		memcpy(bp, p->prop, prophlen);
+		((struct isakmp_pl_p *)bp)->h.np = ISAKMP_NPTYPE_NONE;
+		((struct isakmp_pl_p *)bp)->h.len = htons(prophlen + trnslen);
+		((struct isakmp_pl_p *)bp)->num_t = 1;
+		np_p = &((struct isakmp_pl_p *)bp)->h.np;
+		memset(bp + sizeof(struct isakmp_pl_p), 0, p->prop->spi_size);
+		bp += prophlen;
+
+		/* create transform */
+		memcpy(bp, p->trns, trnslen);
+		((struct isakmp_pl_t *)bp)->h.np = ISAKMP_NPTYPE_NONE;
+		((struct isakmp_pl_t *)bp)->h.len = htons(trnslen);
+		bp += trnslen;
+	}
+
+	return newsa;
+}
+
+/*
+ * update responder's spi
+ */
+int
+ipsecdoi_updatespi(iph2)
+	struct ph2handle *iph2;
+{
+	struct prop_pair **pair, *p;
+	struct saprop *pp;
+	struct saproto *pr;
+	int i;
+	int error = -1;
+	u_int8_t *spi;
+
+	pair = get_proppair(iph2->sa_ret, IPSECDOI_TYPE_PH2);
+	if (pair == NULL)
+		return -1;
+	for (i = 0; i < MAXPROPPAIRLEN; i++) {
+		if (pair[i])
+			break;
+	}
+	if (i == MAXPROPPAIRLEN || pair[i]->tnext) {
+		/* multiple transform must be filtered by selectph2proposal.*/
+		goto end;
+	}
+
+	pp = iph2->approval;
+
+	/* create proposal payloads */
+	for (p = pair[i]; p; p = p->next) {
+		/*
+		 * find a proposal/transform with matching proto_id/t_id.
+		 * we have analyzed validity already, in cmpsaprop_alloc().
+		 */
+		for (pr = pp->head; pr; pr = pr->next) {
+			if (p->prop->proto_id == pr->proto_id &&
+			    p->trns->t_id == pr->head->trns_id) {
+				break;
+			}
+		}
+		if (!pr)
+			goto end;
+
+		/*
+		 * XXX SPI bits are left-filled, for use with IPComp.
+		 * we should be switching to variable-length spi field...
+		 */
+		spi = (u_int8_t *)&pr->spi;
+		spi += sizeof(pr->spi);
+		spi -= pr->spisize;
+		memcpy((caddr_t)p->prop + sizeof(*p->prop), spi, pr->spisize);
+	}
+
+	error = 0;
+end:
+	free_proppair(pair);
+	return error;
+}
+
+/*
+ * make a new SA payload from prop_pair.
+ */
+vchar_t *
+get_sabysaprop(pp0, sa0)
+	struct saprop *pp0;
+	vchar_t *sa0;
+{
+	struct prop_pair **pair = NULL;
+	vchar_t *newsa = NULL;
+	int newtlen;
+	u_int8_t *np_p = NULL;
+	struct prop_pair *p = NULL;
+	struct saprop *pp;
+	struct saproto *pr;
+	struct satrns *tr;
+	int prophlen, trnslen;
+	caddr_t bp;
+	int error = -1;
+
+	/* get proposal pair */
+	pair = get_proppair(sa0, IPSECDOI_TYPE_PH2);
+	if (pair == NULL)
+		goto out;
+
+	newtlen = sizeof(struct ipsecdoi_sa_b);
+	for (pp = pp0; pp; pp = pp->next) {
+
+		if (pair[pp->prop_no] == NULL)
+			goto out;
+
+		for (pr = pp->head; pr; pr = pr->next) {
+			newtlen += (sizeof(struct isakmp_pl_p)
+				+ pr->spisize);
+
+			for (tr = pr->head; tr; tr = tr->next) {
+				for (p = pair[pp->prop_no]; p; p = p->tnext) {
+					if (tr->trns_no == p->trns->t_no)
+						break;
+				}
+				if (p == NULL)
+					goto out;
+
+				newtlen += ntohs(p->trns->h.len);
+			}
+		}
+	}
+
+	newsa = vmalloc(newtlen);
+	if (newsa == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL, "failed to get newsa.\n");
+		goto out;
+	}
+	bp = newsa->v;
+
+	/* some of values of SA must be updated in the out of this function */
+	((struct isakmp_gen *)bp)->len = htons(newtlen);
+	bp += sizeof(struct ipsecdoi_sa_b);
+
+	/* create proposal payloads */
+	for (pp = pp0; pp; pp = pp->next) {
+
+		for (pr = pp->head; pr; pr = pr->next) {
+			prophlen = sizeof(struct isakmp_pl_p)
+					+ p->prop->spi_size;
+
+			for (tr = pr->head; tr; tr = tr->next) {
+				for (p = pair[pp->prop_no]; p; p = p->tnext) {
+					if (tr->trns_no == p->trns->t_no)
+						break;
+				}
+				if (p == NULL)
+					goto out;
+
+				trnslen = ntohs(p->trns->h.len);
+
+				if (np_p)
+					*np_p = ISAKMP_NPTYPE_P;
+
+				/* create proposal */
+
+				memcpy(bp, p->prop, prophlen);
+				((struct isakmp_pl_p *)bp)->h.np = ISAKMP_NPTYPE_NONE;
+				((struct isakmp_pl_p *)bp)->h.len = htons(prophlen + trnslen);
+				((struct isakmp_pl_p *)bp)->num_t = 1;
+				np_p = &((struct isakmp_pl_p *)bp)->h.np;
+				bp += prophlen;
+
+				/* create transform */
+				memcpy(bp, p->trns, trnslen);
+				((struct isakmp_pl_t *)bp)->h.np = ISAKMP_NPTYPE_NONE;
+				((struct isakmp_pl_t *)bp)->h.len = htons(trnslen);
+				bp += trnslen;
+			}
+		}
+	}
+
+	error = 0;
+out:
+	if (pair != NULL)
+		racoon_free(pair);
+
+	if (error != 0) {
+		if (newsa != NULL) {
+			vfree(newsa);
+			newsa = NULL;
+		}
+	}
+
+	return newsa;
+}
+
+/*
+ * If some error happens then return 0.  Although 0 means that lifetime is zero,
+ * such a value should not be accepted.
+ * Also 0 of lifebyte should not be included in a packet although 0 means not
+ * to care of it.
+ */
+static u_int32_t
+ipsecdoi_set_ld(buf)
+	vchar_t *buf;
+{
+	u_int32_t ld;
+
+	if (buf == 0)
+		return 0;
+
+	switch (buf->l) {
+	case 2:
+		ld = ntohs(*(u_int16_t *)buf->v);
+		break;
+	case 4:
+		ld = ntohl(*(u_int32_t *)buf->v);
+		break;
+	default:
+		plog(LLV_ERROR, LOCATION, NULL,
+			"length %zu of life duration "
+			"isn't supported.\n", buf->l);
+		return 0;
+	}
+
+	return ld;
+}
+
+/*%%%*/
+/*
+ * check DOI
+ */
+static int
+check_doi(doi)
+	u_int32_t doi;
+{
+	switch (doi) {
+	case IPSEC_DOI:
+		return 0;
+	default:
+		plog(LLV_ERROR, LOCATION, NULL,
+			"invalid value of DOI 0x%08x.\n", doi);
+		return -1;
+	}
+	/* NOT REACHED */
+}
+
+/*
+ * check situation
+ */
+static int
+check_situation(sit)
+	u_int32_t sit;
+{
+	switch (sit) {
+	case IPSECDOI_SIT_IDENTITY_ONLY:
+		return 0;
+
+	case IPSECDOI_SIT_SECRECY:
+	case IPSECDOI_SIT_INTEGRITY:
+		plog(LLV_ERROR, LOCATION, NULL,
+			"situation 0x%08x unsupported yet.\n", sit);
+		return -1;
+
+	default:
+		plog(LLV_ERROR, LOCATION, NULL,
+			"invalid situation 0x%08x.\n", sit);
+		return -1;
+	}
+	/* NOT REACHED */
+}
+
+/*
+ * check protocol id in main mode
+ */
+static int
+check_prot_main(proto_id)
+	int proto_id;
+{
+	switch (proto_id) {
+	case IPSECDOI_PROTO_ISAKMP:
+		return 0;
+
+	default:
+		plog(LLV_ERROR, LOCATION, NULL,
+			"Illegal protocol id=%u.\n", proto_id);
+		return -1;
+	}
+	/* NOT REACHED */
+}
+
+/*
+ * check protocol id in quick mode
+ */
+static int
+check_prot_quick(proto_id)
+	int proto_id;
+{
+	switch (proto_id) {
+	case IPSECDOI_PROTO_IPSEC_AH:
+	case IPSECDOI_PROTO_IPSEC_ESP:
+		return 0;
+
+	case IPSECDOI_PROTO_IPCOMP:
+		return 0;
+
+	default:
+		plog(LLV_ERROR, LOCATION, NULL,
+			"invalid protocol id %d.\n", proto_id);
+		return -1;
+	}
+	/* NOT REACHED */
+}
+
+static int
+check_spi_size(proto_id, size)
+	int proto_id, size;
+{
+	switch (proto_id) {
+	case IPSECDOI_PROTO_ISAKMP:
+		if (size != 0) {
+			/* WARNING */
+			plog(LLV_WARNING, LOCATION, NULL,
+				"SPI size isn't zero, but IKE proposal.\n");
+		}
+		return 0;
+
+	case IPSECDOI_PROTO_IPSEC_AH:
+	case IPSECDOI_PROTO_IPSEC_ESP:
+		if (size != 4) {
+			plog(LLV_ERROR, LOCATION, NULL,
+				"invalid SPI size=%d for IPSEC proposal.\n",
+				size);
+			return -1;
+		}
+		return 0;
+
+	case IPSECDOI_PROTO_IPCOMP:
+		if (size != 2 && size != 4) {
+			plog(LLV_ERROR, LOCATION, NULL,
+				"invalid SPI size=%d for IPCOMP proposal.\n",
+				size);
+			return -1;
+		}
+		return 0;
+
+	default:
+		/* ??? */
+		return -1;
+	}
+	/* NOT REACHED */
+}
+
+/*
+ * check transform ID in ISAKMP.
+ */
+static int
+check_trns_isakmp(t_id)
+	int t_id;
+{
+	switch (t_id) {
+	case IPSECDOI_KEY_IKE:
+		return 0;
+	default:
+		plog(LLV_ERROR, LOCATION, NULL,
+			"invalid transform-id=%u in proto_id=%u.\n",
+			t_id, IPSECDOI_KEY_IKE);
+		return -1;
+	}
+	/* NOT REACHED */
+}
+
+/*
+ * check transform ID in AH.
+ */
+static int
+check_trns_ah(t_id)
+	int t_id;
+{
+	switch (t_id) {
+	case IPSECDOI_AH_MD5:
+	case IPSECDOI_AH_SHA:
+	case IPSECDOI_AH_SHA256:
+	case IPSECDOI_AH_SHA384:
+	case IPSECDOI_AH_SHA512:
+		return 0;
+	case IPSECDOI_AH_DES:
+		plog(LLV_ERROR, LOCATION, NULL,
+			"not support transform-id=%u in AH.\n", t_id);
+		return -1;
+	default:
+		plog(LLV_ERROR, LOCATION, NULL,
+			"invalid transform-id=%u in AH.\n", t_id);
+		return -1;
+	}
+	/* NOT REACHED */
+}
+
+/*
+ * check transform ID in ESP.
+ */
+static int
+check_trns_esp(t_id)
+	int t_id;
+{
+	switch (t_id) {
+	case IPSECDOI_ESP_DES:
+	case IPSECDOI_ESP_3DES:
+	case IPSECDOI_ESP_NULL:
+	case IPSECDOI_ESP_RC5:
+	case IPSECDOI_ESP_CAST:
+	case IPSECDOI_ESP_BLOWFISH:
+	case IPSECDOI_ESP_AES:
+	case IPSECDOI_ESP_TWOFISH:
+	case IPSECDOI_ESP_CAMELLIA:
+		return 0;
+	case IPSECDOI_ESP_DES_IV32:
+	case IPSECDOI_ESP_DES_IV64:
+	case IPSECDOI_ESP_IDEA:
+	case IPSECDOI_ESP_3IDEA:
+	case IPSECDOI_ESP_RC4:
+		plog(LLV_ERROR, LOCATION, NULL,
+			"not support transform-id=%u in ESP.\n", t_id);
+		return -1;
+	default:
+		plog(LLV_ERROR, LOCATION, NULL,
+			"invalid transform-id=%u in ESP.\n", t_id);
+		return -1;
+	}
+	/* NOT REACHED */
+}
+
+/*
+ * check transform ID in IPCOMP.
+ */
+static int
+check_trns_ipcomp(t_id)
+	int t_id;
+{
+	switch (t_id) {
+	case IPSECDOI_IPCOMP_OUI:
+	case IPSECDOI_IPCOMP_DEFLATE:
+	case IPSECDOI_IPCOMP_LZS:
+		return 0;
+	default:
+		plog(LLV_ERROR, LOCATION, NULL,
+			"invalid transform-id=%u in IPCOMP.\n", t_id);
+		return -1;
+	}
+	/* NOT REACHED */
+}
+
+/*
+ * check data attributes in IKE.
+ */
+static int
+check_attr_isakmp(trns)
+	struct isakmp_pl_t *trns;
+{
+	struct isakmp_data *d;
+	int tlen;
+	int flag, type;
+	u_int16_t lorv;
+
+	tlen = ntohs(trns->h.len) - sizeof(struct isakmp_pl_t);
+	d = (struct isakmp_data *)((caddr_t)trns + sizeof(struct isakmp_pl_t));
+
+	while (tlen > 0) {
+		type = ntohs(d->type) & ~ISAKMP_GEN_MASK;
+		flag = ntohs(d->type) & ISAKMP_GEN_MASK;
+		lorv = ntohs(d->lorv);
+
+		plog(LLV_DEBUG, LOCATION, NULL,
+			"type=%s, flag=0x%04x, lorv=%s\n",
+			s_oakley_attr(type), flag,
+			s_oakley_attr_v(type, lorv));
+
+		/*
+		 * some of the attributes must be encoded in TV.
+		 * see RFC2409 Appendix A "Attribute Classes".
+		 */
+		switch (type) {
+		case OAKLEY_ATTR_ENC_ALG:
+		case OAKLEY_ATTR_HASH_ALG:
+		case OAKLEY_ATTR_AUTH_METHOD:
+		case OAKLEY_ATTR_GRP_DESC:
+		case OAKLEY_ATTR_GRP_TYPE:
+		case OAKLEY_ATTR_SA_LD_TYPE:
+		case OAKLEY_ATTR_PRF:
+		case OAKLEY_ATTR_KEY_LEN:
+		case OAKLEY_ATTR_FIELD_SIZE:
+			if (!flag) {	/* TLV*/
+				plog(LLV_ERROR, LOCATION, NULL,
+					"oakley attribute %d must be TV.\n",
+					type);
+				return -1;
+			}
+			break;
+		}
+
+		/* sanity check for TLV.  length must be specified. */
+		if (!flag && lorv == 0) {	/*TLV*/
+			plog(LLV_ERROR, LOCATION, NULL,
+				"invalid length %d for TLV attribute %d.\n",
+				lorv, type);
+			return -1;
+		}
+
+		switch (type) {
+		case OAKLEY_ATTR_ENC_ALG:
+			if (!alg_oakley_encdef_ok(lorv)) {
+				plog(LLV_ERROR, LOCATION, NULL,
+					"invalied encryption algorithm=%d.\n",
+					lorv);
+				return -1;
+			}
+			break;
+
+		case OAKLEY_ATTR_HASH_ALG:
+			if (!alg_oakley_hashdef_ok(lorv)) {
+				plog(LLV_ERROR, LOCATION, NULL,
+					"invalied hash algorithm=%d.\n",
+					lorv);
+				return -1;
+			}
+			break;
+
+		case OAKLEY_ATTR_AUTH_METHOD:
+			switch (lorv) {
+			case OAKLEY_ATTR_AUTH_METHOD_PSKEY:
+			case OAKLEY_ATTR_AUTH_METHOD_RSASIG:
+#ifdef ENABLE_HYBRID
+			case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_I:
+			case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_I:
+#if 0 /* Clashes with OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB */
+			case OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_I:
+#endif
+#endif
+			case OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB:
+				break;
+			case OAKLEY_ATTR_AUTH_METHOD_DSSSIG:
+#ifdef ENABLE_HYBRID
+			case OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_R:
+			case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_R:
+			case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_R:
+			case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_I:
+			case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_R:
+			case OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_I:
+			case OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_R:
+			case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAENC_I:
+			case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAENC_R:
+			case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAREV_I:
+			case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAREV_R:
+#endif
+			case OAKLEY_ATTR_AUTH_METHOD_RSAENC:
+			case OAKLEY_ATTR_AUTH_METHOD_RSAREV:
+				plog(LLV_ERROR, LOCATION, NULL,
+					"auth method %s isn't supported.\n",
+					s_oakley_attr_method(lorv));
+				return -1;
+			default:
+				plog(LLV_ERROR, LOCATION, NULL,
+					"invalid auth method %d.\n",
+					lorv);
+				return -1;
+			}
+			break;
+
+		case OAKLEY_ATTR_GRP_DESC:
+			if (!alg_oakley_dhdef_ok(lorv)) {
+				plog(LLV_ERROR, LOCATION, NULL,
+					"invalid DH group %d.\n",
+					lorv);
+				return -1;
+			}
+			break;
+
+		case OAKLEY_ATTR_GRP_TYPE:
+			switch (lorv) {
+			case OAKLEY_ATTR_GRP_TYPE_MODP:
+				break;
+			default:
+				plog(LLV_ERROR, LOCATION, NULL,
+					"unsupported DH group type %d.\n",
+					lorv);
+				return -1;
+			}
+			break;
+
+		case OAKLEY_ATTR_GRP_PI:
+		case OAKLEY_ATTR_GRP_GEN_ONE:
+			/* sanity checks? */
+			break;
+
+		case OAKLEY_ATTR_GRP_GEN_TWO:
+		case OAKLEY_ATTR_GRP_CURVE_A:
+		case OAKLEY_ATTR_GRP_CURVE_B:
+			plog(LLV_ERROR, LOCATION, NULL,
+				"attr type=%u isn't supported.\n", type);
+			return -1;
+
+		case OAKLEY_ATTR_SA_LD_TYPE:
+			switch (lorv) {
+			case OAKLEY_ATTR_SA_LD_TYPE_SEC:
+			case OAKLEY_ATTR_SA_LD_TYPE_KB:
+				break;
+			default:
+				plog(LLV_ERROR, LOCATION, NULL,
+					"invalid life type %d.\n", lorv);
+				return -1;
+			}
+			break;
+
+		case OAKLEY_ATTR_SA_LD:
+			/* should check the value */
+			break;
+
+		case OAKLEY_ATTR_PRF:
+		case OAKLEY_ATTR_KEY_LEN:
+			break;
+
+		case OAKLEY_ATTR_FIELD_SIZE:
+			plog(LLV_ERROR, LOCATION, NULL,
+				"attr type=%u isn't supported.\n", type);
+			return -1;
+
+		case OAKLEY_ATTR_GRP_ORDER:
+			break;
+
+		case OAKLEY_ATTR_GSS_ID:
+			break;
+
+		default:
+			plog(LLV_ERROR, LOCATION, NULL,
+				"invalid attribute type %d.\n", type);
+			return -1;
+		}
+
+		if (flag) {
+			tlen -= sizeof(*d);
+			d = (struct isakmp_data *)((char *)d
+				+ sizeof(*d));
+		} else {
+			tlen -= (sizeof(*d) + lorv);
+			d = (struct isakmp_data *)((char *)d
+				+ sizeof(*d) + lorv);
+		}
+	}
+
+	return 0;
+}
+
+/*
+ * check data attributes in IPSEC AH/ESP.
+ */
+static int
+check_attr_ah(trns)
+	struct isakmp_pl_t *trns;
+{
+	return check_attr_ipsec(IPSECDOI_PROTO_IPSEC_AH, trns);
+}
+
+static int
+check_attr_esp(trns)
+	struct isakmp_pl_t *trns;
+{
+	return check_attr_ipsec(IPSECDOI_PROTO_IPSEC_ESP, trns);
+}
+
+static int
+check_attr_ipsec(proto_id, trns)
+	int proto_id;
+	struct isakmp_pl_t *trns;
+{
+	struct isakmp_data *d;
+	int tlen;
+	int flag, type = 0;
+	u_int16_t lorv;
+	int attrseen[16];	/* XXX magic number */
+
+	tlen = ntohs(trns->h.len) - sizeof(struct isakmp_pl_t);
+	d = (struct isakmp_data *)((caddr_t)trns + sizeof(struct isakmp_pl_t));
+	memset(attrseen, 0, sizeof(attrseen));
+
+	while (tlen > 0) {
+		type = ntohs(d->type) & ~ISAKMP_GEN_MASK;
+		flag = ntohs(d->type) & ISAKMP_GEN_MASK;
+		lorv = ntohs(d->lorv);
+
+		plog(LLV_DEBUG, LOCATION, NULL,
+			"type=%s, flag=0x%04x, lorv=%s\n",
+			s_ipsecdoi_attr(type), flag,
+			s_ipsecdoi_attr_v(type, lorv));
+
+		if (type < sizeof(attrseen)/sizeof(attrseen[0]))
+			attrseen[type]++;
+
+		switch (type) {
+		case IPSECDOI_ATTR_ENC_MODE:
+			if (! flag) {
+				plog(LLV_ERROR, LOCATION, NULL,
+					"must be TV when ENC_MODE.\n");
+				return -1;
+			}
+
+			switch (lorv) {
+			case IPSECDOI_ATTR_ENC_MODE_TUNNEL:
+			case IPSECDOI_ATTR_ENC_MODE_TRNS:
+				break;
+#ifdef ENABLE_NATT
+			case IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_RFC:
+			case IPSECDOI_ATTR_ENC_MODE_UDPTRNS_RFC:
+			case IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_DRAFT:
+			case IPSECDOI_ATTR_ENC_MODE_UDPTRNS_DRAFT:
+				plog(LLV_DEBUG, LOCATION, NULL,
+				     "UDP encapsulation requested\n");
+				break;
+#endif
+			default:
+				plog(LLV_ERROR, LOCATION, NULL,
+					"invalid encryption mode=%u.\n",
+					lorv);
+				return -1;
+			}
+			break;
+
+		case IPSECDOI_ATTR_AUTH:
+			if (! flag) {
+				plog(LLV_ERROR, LOCATION, NULL,
+					"must be TV when AUTH.\n");
+				return -1;
+			}
+
+			switch (lorv) {
+			case IPSECDOI_ATTR_AUTH_HMAC_MD5:
+				if (proto_id == IPSECDOI_PROTO_IPSEC_AH &&
+				    trns->t_id != IPSECDOI_AH_MD5) {
+ahmismatch:
+					plog(LLV_ERROR, LOCATION, NULL,
+						"auth algorithm %u conflicts "
+						"with transform %u.\n",
+						lorv, trns->t_id);
+					return -1;
+				}
+				break;
+			case IPSECDOI_ATTR_AUTH_HMAC_SHA1:
+				if (proto_id == IPSECDOI_PROTO_IPSEC_AH) {
+					if (trns->t_id != IPSECDOI_AH_SHA)
+						goto ahmismatch;
+				}
+				break;
+ 			case IPSECDOI_ATTR_AUTH_HMAC_SHA2_256:
+ 				if (proto_id == IPSECDOI_PROTO_IPSEC_AH) {
+ 					if (trns->t_id != IPSECDOI_AH_SHA256)
+ 						goto ahmismatch;
+ 				}	
+ 				break;
+ 			case IPSECDOI_ATTR_AUTH_HMAC_SHA2_384:
+ 				if (proto_id == IPSECDOI_PROTO_IPSEC_AH) {
+ 					if (trns->t_id != IPSECDOI_AH_SHA384)
+ 						goto ahmismatch;
+ 				}
+ 				break;
+ 			case IPSECDOI_ATTR_AUTH_HMAC_SHA2_512:
+ 				if (proto_id == IPSECDOI_PROTO_IPSEC_AH) {
+ 					if (trns->t_id != IPSECDOI_AH_SHA512)
+ 					goto ahmismatch;
+ 				}
+ 				break;
+			case IPSECDOI_ATTR_AUTH_DES_MAC:
+			case IPSECDOI_ATTR_AUTH_KPDK:
+				plog(LLV_ERROR, LOCATION, NULL,
+					"auth algorithm %u isn't supported.\n",
+					lorv);
+				return -1;
+			default:
+				plog(LLV_ERROR, LOCATION, NULL,
+					"invalid auth algorithm=%u.\n",
+					lorv);
+				return -1;
+			}
+			break;
+
+		case IPSECDOI_ATTR_SA_LD_TYPE:
+			if (! flag) {
+				plog(LLV_ERROR, LOCATION, NULL,
+					"must be TV when LD_TYPE.\n");
+				return -1;
+			}
+
+			switch (lorv) {
+			case IPSECDOI_ATTR_SA_LD_TYPE_SEC:
+			case IPSECDOI_ATTR_SA_LD_TYPE_KB:
+				break;
+			default:
+				plog(LLV_ERROR, LOCATION, NULL,
+					"invalid life type %d.\n", lorv);
+				return -1;
+			}
+			break;
+
+		case IPSECDOI_ATTR_SA_LD:
+			if (flag) {
+				/* i.e. ISAKMP_GEN_TV */
+				plog(LLV_DEBUG, LOCATION, NULL,
+					"life duration was in TLV.\n");
+			} else {
+				/* i.e. ISAKMP_GEN_TLV */
+				if (lorv == 0) {
+					plog(LLV_ERROR, LOCATION, NULL,
+						"invalid length of LD\n");
+					return -1;
+				}
+			}
+			break;
+
+		case IPSECDOI_ATTR_GRP_DESC:
+			if (! flag) {
+				plog(LLV_ERROR, LOCATION, NULL,
+					"must be TV when GRP_DESC.\n");
+				return -1;
+			}
+
+			if (!alg_oakley_dhdef_ok(lorv)) {
+				plog(LLV_ERROR, LOCATION, NULL,
+					"invalid group description=%u.\n",
+					lorv);
+				return -1;
+			}
+			break;
+
+		case IPSECDOI_ATTR_KEY_LENGTH:
+			if (! flag) {
+				plog(LLV_ERROR, LOCATION, NULL,
+					"must be TV when KEY_LENGTH.\n");
+				return -1;
+			}
+			break;
+
+#ifdef HAVE_SECCTX
+		case IPSECDOI_ATTR_SECCTX:
+			if (flag) {
+				plog(LLV_ERROR, LOCATION, NULL,
+					"SECCTX must be in TLV.\n");
+				return -1;
+			}
+		break;
+#endif
+
+		case IPSECDOI_ATTR_KEY_ROUNDS:
+		case IPSECDOI_ATTR_COMP_DICT_SIZE:
+		case IPSECDOI_ATTR_COMP_PRIVALG:
+			plog(LLV_ERROR, LOCATION, NULL,
+				"attr type=%u isn't supported.\n", type);
+			return -1;
+
+		default:
+			plog(LLV_ERROR, LOCATION, NULL,
+				"invalid attribute type %d.\n", type);
+			return -1;
+		}
+
+		if (flag) {
+			tlen -= sizeof(*d);
+			d = (struct isakmp_data *)((char *)d
+				+ sizeof(*d));
+		} else {
+			tlen -= (sizeof(*d) + lorv);
+			d = (struct isakmp_data *)((caddr_t)d
+				+ sizeof(*d) + lorv);
+		}
+	}
+
+	if (proto_id == IPSECDOI_PROTO_IPSEC_AH &&
+	    !attrseen[IPSECDOI_ATTR_AUTH]) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"attr AUTH must be present for AH.\n");
+		return -1;
+	}
+
+	if (proto_id == IPSECDOI_PROTO_IPSEC_ESP &&
+	    trns->t_id == IPSECDOI_ESP_NULL &&
+	    !attrseen[IPSECDOI_ATTR_AUTH]) {
+		plog(LLV_ERROR, LOCATION, NULL,
+		    "attr AUTH must be present for ESP NULL encryption.\n");
+		return -1;
+	}
+
+	return 0;
+}
+
+static int
+check_attr_ipcomp(trns)
+	struct isakmp_pl_t *trns;
+{
+	struct isakmp_data *d;
+	int tlen;
+	int flag, type = 0;
+	u_int16_t lorv;
+	int attrseen[16];	/* XXX magic number */
+
+	tlen = ntohs(trns->h.len) - sizeof(struct isakmp_pl_t);
+	d = (struct isakmp_data *)((caddr_t)trns + sizeof(struct isakmp_pl_t));
+	memset(attrseen, 0, sizeof(attrseen));
+
+	while (tlen > 0) {
+		type = ntohs(d->type) & ~ISAKMP_GEN_MASK;
+		flag = ntohs(d->type) & ISAKMP_GEN_MASK;
+		lorv = ntohs(d->lorv);
+
+		plog(LLV_DEBUG, LOCATION, NULL,
+			"type=%d, flag=0x%04x, lorv=0x%04x\n",
+			type, flag, lorv);
+
+		if (type < sizeof(attrseen)/sizeof(attrseen[0]))
+			attrseen[type]++;
+
+		switch (type) {
+		case IPSECDOI_ATTR_ENC_MODE:
+			if (! flag) {
+				plog(LLV_ERROR, LOCATION, NULL,
+					"must be TV when ENC_MODE.\n");
+				return -1;
+			}
+
+			switch (lorv) {
+			case IPSECDOI_ATTR_ENC_MODE_TUNNEL:
+			case IPSECDOI_ATTR_ENC_MODE_TRNS:
+				break;
+#ifdef ENABLE_NATT
+			case IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_RFC:
+			case IPSECDOI_ATTR_ENC_MODE_UDPTRNS_RFC:
+			case IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_DRAFT:
+			case IPSECDOI_ATTR_ENC_MODE_UDPTRNS_DRAFT:
+				plog(LLV_DEBUG, LOCATION, NULL,
+				     "UDP encapsulation requested\n");
+				break;
+#endif
+			default:
+				plog(LLV_ERROR, LOCATION, NULL,
+					"invalid encryption mode=%u.\n",
+					lorv);
+				return -1;
+			}
+			break;
+
+		case IPSECDOI_ATTR_SA_LD_TYPE:
+			if (! flag) {
+				plog(LLV_ERROR, LOCATION, NULL,
+					"must be TV when LD_TYPE.\n");
+				return -1;
+			}
+
+			switch (lorv) {
+			case IPSECDOI_ATTR_SA_LD_TYPE_SEC:
+			case IPSECDOI_ATTR_SA_LD_TYPE_KB:
+				break;
+			default:
+				plog(LLV_ERROR, LOCATION, NULL,
+					"invalid life type %d.\n", lorv);
+				return -1;
+			}
+			break;
+
+		case IPSECDOI_ATTR_SA_LD:
+			if (flag) {
+				/* i.e. ISAKMP_GEN_TV */
+				plog(LLV_DEBUG, LOCATION, NULL,
+					"life duration was in TLV.\n");
+			} else {
+				/* i.e. ISAKMP_GEN_TLV */
+				if (lorv == 0) {
+					plog(LLV_ERROR, LOCATION, NULL,
+						"invalid length of LD\n");
+					return -1;
+				}
+			}
+			break;
+
+		case IPSECDOI_ATTR_GRP_DESC:
+			if (! flag) {
+				plog(LLV_ERROR, LOCATION, NULL,
+					"must be TV when GRP_DESC.\n");
+				return -1;
+			}
+
+			if (!alg_oakley_dhdef_ok(lorv)) {
+				plog(LLV_ERROR, LOCATION, NULL,
+					"invalid group description=%u.\n",
+					lorv);
+				return -1;
+			}
+			break;
+
+		case IPSECDOI_ATTR_AUTH:
+			plog(LLV_ERROR, LOCATION, NULL,
+				"invalid attr type=%u.\n", type);
+			return -1;
+
+		case IPSECDOI_ATTR_KEY_LENGTH:
+		case IPSECDOI_ATTR_KEY_ROUNDS:
+		case IPSECDOI_ATTR_COMP_DICT_SIZE:
+		case IPSECDOI_ATTR_COMP_PRIVALG:
+			plog(LLV_ERROR, LOCATION, NULL,
+				"attr type=%u isn't supported.\n", type);
+			return -1;
+
+		default:
+			plog(LLV_ERROR, LOCATION, NULL,
+				"invalid attribute type %d.\n", type);
+			return -1;
+		}
+
+		if (flag) {
+			tlen -= sizeof(*d);
+			d = (struct isakmp_data *)((char *)d
+				+ sizeof(*d));
+		} else {
+			tlen -= (sizeof(*d) + lorv);
+			d = (struct isakmp_data *)((caddr_t)d
+				+ sizeof(*d) + lorv);
+		}
+	}
+
+#if 0
+	if (proto_id == IPSECDOI_PROTO_IPCOMP &&
+	    !attrseen[IPSECDOI_ATTR_AUTH]) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"attr AUTH must be present for AH.\n", type);
+		return -1;
+	}
+#endif
+
+	return 0;
+}
+
+/* %%% */
+/*
+ * create phase1 proposal from remote configuration.
+ * NOT INCLUDING isakmp general header of SA payload
+ */
+vchar_t *
+ipsecdoi_setph1proposal(props)
+	struct isakmpsa *props;
+{
+	vchar_t *mysa;
+	int sablen;
+
+	/* count total size of SA minus isakmp general header */
+	/* not including isakmp general header of SA payload */
+	sablen = sizeof(struct ipsecdoi_sa_b);
+	sablen += setph1prop(props, NULL);
+
+	mysa = vmalloc(sablen);
+	if (mysa == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"failed to allocate my sa buffer\n");
+		return NULL;
+	}
+
+	/* create SA payload */
+	/* not including isakmp general header */
+	((struct ipsecdoi_sa_b *)mysa->v)->doi = htonl(props->rmconf->doitype);
+	((struct ipsecdoi_sa_b *)mysa->v)->sit = htonl(props->rmconf->sittype);
+
+	(void)setph1prop(props, mysa->v + sizeof(struct ipsecdoi_sa_b));
+
+	return mysa;
+}
+
+static int
+setph1prop(props, buf)
+	struct isakmpsa *props;
+	caddr_t buf;
+{
+	struct isakmp_pl_p *prop = NULL;
+	struct isakmpsa *s = NULL;
+	int proplen, trnslen;
+	u_int8_t *np_t; /* pointer next trns type in previous header */
+	int trns_num;
+	caddr_t p = buf;
+
+	proplen = sizeof(*prop);
+	if (buf) {
+		/* create proposal */
+		prop = (struct isakmp_pl_p *)p;
+		prop->h.np = ISAKMP_NPTYPE_NONE;
+		prop->p_no = props->prop_no;
+		prop->proto_id = IPSECDOI_PROTO_ISAKMP;
+		prop->spi_size = 0;
+		p += sizeof(*prop);
+	}
+
+	np_t = NULL;
+	trns_num = 0;
+
+	for (s = props; s != NULL; s = s->next) {
+		if (np_t)
+			*np_t = ISAKMP_NPTYPE_T;
+
+		trnslen = setph1trns(s, p);
+		proplen += trnslen;
+		if (buf) {
+			/* save buffer to pre-next payload */
+			np_t = &((struct isakmp_pl_t *)p)->h.np;
+			p += trnslen;
+
+			/* count up transform length */
+			trns_num++;
+		}
+	}
+
+	/* update proposal length */
+	if (buf) {
+		prop->h.len = htons(proplen);
+		prop->num_t = trns_num;
+	}
+
+	return proplen;
+}
+
+static int
+setph1trns(sa, buf)
+	struct isakmpsa *sa;
+	caddr_t buf;
+{
+	struct isakmp_pl_t *trns = NULL;
+	int trnslen, attrlen;
+	caddr_t p = buf;
+
+	trnslen = sizeof(*trns);
+	if (buf) {
+		/* create transform */
+		trns = (struct isakmp_pl_t *)p;
+		trns->h.np  = ISAKMP_NPTYPE_NONE;
+		trns->t_no  = sa->trns_no;
+		trns->t_id  = IPSECDOI_KEY_IKE;
+		p += sizeof(*trns);
+	}
+
+	attrlen = setph1attr(sa, p);
+	trnslen += attrlen;
+	if (buf)
+		p += attrlen;
+
+	if (buf)
+		trns->h.len = htons(trnslen);
+
+	return trnslen;
+}
+
+static int
+setph1attr(sa, buf)
+	struct isakmpsa *sa;
+	caddr_t buf;
+{
+	caddr_t p = buf;
+	int attrlen = 0;
+
+	if (sa->lifetime) {
+		u_int32_t lifetime = htonl((u_int32_t)sa->lifetime);
+
+		attrlen += sizeof(struct isakmp_data)
+			+ sizeof(struct isakmp_data);
+		if (sa->lifetime > 0xffff)
+			attrlen += sizeof(lifetime);
+		if (buf) {
+			p = isakmp_set_attr_l(p, OAKLEY_ATTR_SA_LD_TYPE,
+						OAKLEY_ATTR_SA_LD_TYPE_SEC);
+			if (sa->lifetime > 0xffff) {
+				p = isakmp_set_attr_v(p, OAKLEY_ATTR_SA_LD,
+						(caddr_t)&lifetime, 
+						sizeof(lifetime));
+			} else {
+				p = isakmp_set_attr_l(p, OAKLEY_ATTR_SA_LD,
+							sa->lifetime);
+			}
+		}
+	}
+
+	if (sa->lifebyte) {
+		u_int32_t lifebyte = htonl((u_int32_t)sa->lifebyte);
+		
+		attrlen += sizeof(struct isakmp_data)
+			+ sizeof(struct isakmp_data);
+		if (sa->lifebyte > 0xffff)
+			attrlen += sizeof(lifebyte);
+		if (buf) {
+			p = isakmp_set_attr_l(p, OAKLEY_ATTR_SA_LD_TYPE,
+						OAKLEY_ATTR_SA_LD_TYPE_KB);
+			if (sa->lifebyte > 0xffff) {
+				p = isakmp_set_attr_v(p, OAKLEY_ATTR_SA_LD,
+							(caddr_t)&lifebyte,
+							sizeof(lifebyte));
+			} else {
+				p = isakmp_set_attr_l(p, OAKLEY_ATTR_SA_LD,
+							sa->lifebyte);
+			}
+		}
+	}
+
+	if (sa->enctype) {
+		attrlen += sizeof(struct isakmp_data);
+		if (buf)
+			p = isakmp_set_attr_l(p, OAKLEY_ATTR_ENC_ALG, sa->enctype);
+	}
+	if (sa->encklen) {
+		attrlen += sizeof(struct isakmp_data);
+		if (buf)
+			p = isakmp_set_attr_l(p, OAKLEY_ATTR_KEY_LEN, sa->encklen);
+	}
+	if (sa->authmethod) {
+		int authmethod;
+
+#ifdef ENABLE_HYBRID
+		authmethod = switch_authmethod(sa->authmethod);
+#else
+		authmethod = sa->authmethod;
+#endif
+		attrlen += sizeof(struct isakmp_data);
+		if (buf)
+			p = isakmp_set_attr_l(p, OAKLEY_ATTR_AUTH_METHOD, authmethod);
+	}
+	if (sa->hashtype) {
+		attrlen += sizeof(struct isakmp_data);
+		if (buf)
+			p = isakmp_set_attr_l(p, OAKLEY_ATTR_HASH_ALG, sa->hashtype);
+	}
+	switch (sa->dh_group) {
+	case OAKLEY_ATTR_GRP_DESC_MODP768:
+	case OAKLEY_ATTR_GRP_DESC_MODP1024:
+	case OAKLEY_ATTR_GRP_DESC_MODP1536:
+	case OAKLEY_ATTR_GRP_DESC_MODP2048:
+	case OAKLEY_ATTR_GRP_DESC_MODP3072:
+	case OAKLEY_ATTR_GRP_DESC_MODP4096:
+	case OAKLEY_ATTR_GRP_DESC_MODP6144:
+	case OAKLEY_ATTR_GRP_DESC_MODP8192:
+		/* don't attach group type for known groups */
+		attrlen += sizeof(struct isakmp_data);
+		if (buf) {
+			p = isakmp_set_attr_l(p, OAKLEY_ATTR_GRP_DESC,
+				sa->dh_group);
+		}
+		break;
+	case OAKLEY_ATTR_GRP_DESC_EC2N155:
+	case OAKLEY_ATTR_GRP_DESC_EC2N185:
+		/* don't attach group type for known groups */
+		attrlen += sizeof(struct isakmp_data);
+		if (buf) {
+			p = isakmp_set_attr_l(p, OAKLEY_ATTR_GRP_TYPE,
+				OAKLEY_ATTR_GRP_TYPE_EC2N);
+		}
+		break;
+	case 0:
+	default:
+		break;
+	}
+
+#ifdef HAVE_GSSAPI
+	if (sa->authmethod == OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB &&
+	    sa->gssid != NULL) {
+		attrlen += sizeof(struct isakmp_data);
+		/*
+		 * Older versions of racoon just placed the ISO-Latin-1
+		 * string on the wire directly.  Check to see if we are
+		 * configured to be compatible with this behavior.  Otherwise,
+		 * we encode the GSS ID as UTF-16LE for Windows 2000
+		 * compatibility, which requires twice the number of octets.
+		 */
+		if (lcconf->gss_id_enc == LC_GSSENC_LATIN1)
+			attrlen += sa->gssid->l;
+		else
+			attrlen += sa->gssid->l * 2;
+		if (buf) {
+			plog(LLV_DEBUG, LOCATION, NULL, "gss id attr: len %zu, "
+			    "val '%.*s'\n", sa->gssid->l, (int)sa->gssid->l,
+			    sa->gssid->v);
+			if (lcconf->gss_id_enc == LC_GSSENC_LATIN1) {
+				p = isakmp_set_attr_v(p, OAKLEY_ATTR_GSS_ID,
+					(caddr_t)sa->gssid->v,
+					sa->gssid->l);
+			} else {
+				size_t dstleft = sa->gssid->l * 2;
+				size_t srcleft = sa->gssid->l;
+				const char *src = (const char *)sa->gssid->v;
+				char *odst, *dst = racoon_malloc(dstleft);
+				iconv_t cd;
+				size_t rv;
+
+				cd = iconv_open("utf-16le", "latin1");
+				if (cd == (iconv_t) -1) {
+					plog(LLV_ERROR, LOCATION, NULL,
+					    "unable to initialize "
+					    "latin1 -> utf-16le "
+					    "converstion descriptor: %s\n",
+					    strerror(errno));
+					attrlen -= sa->gssid->l * 2;
+					goto gssid_done;
+				}
+				odst = dst;
+				rv = iconv(cd, (__iconv_const char **)&src, 
+				    &srcleft, &dst, &dstleft);
+				if (rv != 0) {
+					if (rv == -1) {
+						plog(LLV_ERROR, LOCATION, NULL,
+						    "unable to convert GSS ID "
+						    "from latin1 -> utf-16le: "
+						    "%s\n", strerror(errno));
+					} else {
+						/* should never happen */
+						plog(LLV_ERROR, LOCATION, NULL,
+						    "%zd character%s in GSS ID "
+						    "cannot be represented "
+						    "in utf-16le\n",
+						    rv, rv == 1 ? "" : "s");
+					}
+					(void) iconv_close(cd);
+					attrlen -= sa->gssid->l * 2;
+					goto gssid_done;
+				}
+				(void) iconv_close(cd);
+
+				/* XXX Check srcleft and dstleft? */
+
+				p = isakmp_set_attr_v(p, OAKLEY_ATTR_GSS_ID,
+					odst, sa->gssid->l * 2);
+
+				racoon_free(odst);
+			}
+		}
+	}
+ gssid_done:
+#endif /* HAVE_GSSAPI */
+
+	return attrlen;
+}
+
+static vchar_t *
+setph2proposal0(iph2, pp, pr)
+	const struct ph2handle *iph2;
+	const struct saprop *pp;
+	const struct saproto *pr;
+{
+	vchar_t *p;
+	struct isakmp_pl_p *prop;
+	struct isakmp_pl_t *trns;
+	struct satrns *tr;
+	int attrlen;
+	size_t trnsoff;
+	caddr_t x0, x;
+	u_int8_t *np_t; /* pointer next trns type in previous header */
+	const u_int8_t *spi;
+#ifdef HAVE_SECCTX
+	int truectxlen = 0;
+#endif
+
+	p = vmalloc(sizeof(*prop) + sizeof(pr->spi));
+	if (p == NULL)
+		return NULL;
+
+	/* create proposal */
+	prop = (struct isakmp_pl_p *)p->v;
+	prop->h.np = ISAKMP_NPTYPE_NONE;
+	prop->p_no = pp->prop_no;
+	prop->proto_id = pr->proto_id;
+	prop->num_t = 1;
+
+	spi = (const u_int8_t *)&pr->spi;
+	switch (pr->proto_id) {
+	case IPSECDOI_PROTO_IPCOMP:
+		/*
+		 * draft-shacham-ippcp-rfc2393bis-05.txt:
+		 * construct 16bit SPI (CPI).
+		 * XXX we may need to provide a configuration option to
+		 * generate 32bit SPI.  otherwise we cannot interoeprate
+		 * with nodes that uses 32bit SPI, in case we are initiator.
+		 */
+		prop->spi_size = sizeof(u_int16_t);
+		spi += sizeof(pr->spi) - sizeof(u_int16_t);
+		p->l -= sizeof(pr->spi);
+		p->l += sizeof(u_int16_t);
+		break;
+	default:
+		prop->spi_size = sizeof(pr->spi);
+		break;
+	}
+	memcpy(prop + 1, spi, prop->spi_size);
+
+	/* create transform */
+	trnsoff = sizeof(*prop) + prop->spi_size;
+	np_t = NULL;
+
+	for (tr = pr->head; tr; tr = tr->next) {
+	
+		switch (pr->proto_id) {
+		case IPSECDOI_PROTO_IPSEC_ESP:
+			/*
+			 * don't build a null encryption
+			 * with no authentication transform.
+			 */
+			if (tr->trns_id == IPSECDOI_ESP_NULL &&
+			    tr->authtype == IPSECDOI_ATTR_AUTH_NONE)
+				continue;
+			break;
+		}
+
+		if (np_t) {
+			*np_t = ISAKMP_NPTYPE_T;
+			prop->num_t++;
+		}
+
+		/* get attribute length */
+		attrlen = 0;
+		if (pp->lifetime) {
+			attrlen += sizeof(struct isakmp_data)
+				+ sizeof(struct isakmp_data);
+			if (pp->lifetime > 0xffff)
+				attrlen += sizeof(u_int32_t);
+		}
+		if (pp->lifebyte && pp->lifebyte != IPSECDOI_ATTR_SA_LD_KB_MAX) {
+			attrlen += sizeof(struct isakmp_data)
+				+ sizeof(struct isakmp_data);
+			if (pp->lifebyte > 0xffff)
+				attrlen += sizeof(u_int32_t);
+		}
+		attrlen += sizeof(struct isakmp_data);	/* enc mode */
+		if (tr->encklen)
+			attrlen += sizeof(struct isakmp_data);
+
+		switch (pr->proto_id) {
+		case IPSECDOI_PROTO_IPSEC_ESP:
+			/* non authentication mode ? */
+			if (tr->authtype != IPSECDOI_ATTR_AUTH_NONE)
+				attrlen += sizeof(struct isakmp_data);
+			break;
+		case IPSECDOI_PROTO_IPSEC_AH:
+			if (tr->authtype == IPSECDOI_ATTR_AUTH_NONE) {
+				plog(LLV_ERROR, LOCATION, NULL,
+					"no authentication algorithm found "
+					"but protocol is AH.\n");
+				vfree(p);
+				return NULL;
+			}
+			attrlen += sizeof(struct isakmp_data);
+			break;
+		case IPSECDOI_PROTO_IPCOMP:
+			break;
+		default:
+			plog(LLV_ERROR, LOCATION, NULL,
+				"invalid protocol: %d\n", pr->proto_id);
+			vfree(p);
+			return NULL;
+		}
+
+		if (alg_oakley_dhdef_ok(iph2->sainfo->pfs_group))
+			attrlen += sizeof(struct isakmp_data);
+
+#ifdef HAVE_SECCTX
+		/* ctx_str is defined as char ctx_str[MAX_CTXSTR_SIZ].
+		 * The string may be smaller than MAX_CTXSTR_SIZ.
+		 */
+		if (*pp->sctx.ctx_str) {
+			truectxlen = sizeof(struct security_ctx) -
+				     (MAX_CTXSTR_SIZE - pp->sctx.ctx_strlen);
+			attrlen += sizeof(struct isakmp_data) + truectxlen;
+		}
+#endif /* HAVE_SECCTX */
+
+		p = vrealloc(p, p->l + sizeof(*trns) + attrlen);
+		if (p == NULL)
+			return NULL;
+		prop = (struct isakmp_pl_p *)p->v;
+
+		/* set transform's values */
+		trns = (struct isakmp_pl_t *)(p->v + trnsoff);
+		trns->h.np  = ISAKMP_NPTYPE_NONE;
+		trns->t_no  = tr->trns_no;
+		trns->t_id  = tr->trns_id;
+
+		/* set attributes */
+		x = x0 = p->v + trnsoff + sizeof(*trns);
+
+		if (pp->lifetime) {
+			x = isakmp_set_attr_l(x, IPSECDOI_ATTR_SA_LD_TYPE,
+						IPSECDOI_ATTR_SA_LD_TYPE_SEC);
+			if (pp->lifetime > 0xffff) {
+				u_int32_t v = htonl((u_int32_t)pp->lifetime);
+				x = isakmp_set_attr_v(x, IPSECDOI_ATTR_SA_LD,
+							(caddr_t)&v, sizeof(v));
+			} else {
+				x = isakmp_set_attr_l(x, IPSECDOI_ATTR_SA_LD,
+							pp->lifetime);
+			}
+		}
+
+		if (pp->lifebyte && pp->lifebyte != IPSECDOI_ATTR_SA_LD_KB_MAX) {
+			x = isakmp_set_attr_l(x, IPSECDOI_ATTR_SA_LD_TYPE,
+						IPSECDOI_ATTR_SA_LD_TYPE_KB);
+			if (pp->lifebyte > 0xffff) {
+				u_int32_t v = htonl((u_int32_t)pp->lifebyte);
+				x = isakmp_set_attr_v(x, IPSECDOI_ATTR_SA_LD,
+							(caddr_t)&v, sizeof(v));
+			} else {
+				x = isakmp_set_attr_l(x, IPSECDOI_ATTR_SA_LD,
+							pp->lifebyte);
+			}
+		}
+
+		x = isakmp_set_attr_l(x, IPSECDOI_ATTR_ENC_MODE, pr->encmode);
+
+		if (tr->encklen)
+			x = isakmp_set_attr_l(x, IPSECDOI_ATTR_KEY_LENGTH, tr->encklen);
+
+		/* mandatory check has done above. */
+		if ((pr->proto_id == IPSECDOI_PROTO_IPSEC_ESP && tr->authtype != IPSECDOI_ATTR_AUTH_NONE)
+		 || pr->proto_id == IPSECDOI_PROTO_IPSEC_AH)
+			x = isakmp_set_attr_l(x, IPSECDOI_ATTR_AUTH, tr->authtype);
+
+		if (alg_oakley_dhdef_ok(iph2->sainfo->pfs_group))
+			x = isakmp_set_attr_l(x, IPSECDOI_ATTR_GRP_DESC,
+				iph2->sainfo->pfs_group);
+
+#ifdef HAVE_SECCTX
+		if (*pp->sctx.ctx_str) {
+			struct security_ctx secctx;
+			secctx = pp->sctx;
+			secctx.ctx_strlen = htons(pp->sctx.ctx_strlen);
+			x = isakmp_set_attr_v(x, IPSECDOI_ATTR_SECCTX,
+					     (caddr_t)&secctx, truectxlen);
+		}
+#endif
+		/* update length of this transform. */
+		trns = (struct isakmp_pl_t *)(p->v + trnsoff);
+		trns->h.len = htons(sizeof(*trns) + attrlen);
+
+		/* save buffer to pre-next payload */
+		np_t = &trns->h.np;
+
+		trnsoff += (sizeof(*trns) + attrlen);
+	}
+
+	if (np_t == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"no suitable proposal was created.\n");
+		return NULL;
+	}
+
+	/* update length of this protocol. */
+	prop->h.len = htons(p->l);
+
+	return p;
+}
+
+/*
+ * create phase2 proposal from policy configuration.
+ * NOT INCLUDING isakmp general header of SA payload.
+ * This function is called by initiator only.
+ */
+int
+ipsecdoi_setph2proposal(iph2)
+	struct ph2handle *iph2;
+{
+	struct saprop *proposal, *a;
+	struct saproto *b = NULL;
+	vchar_t *q;
+	struct ipsecdoi_sa_b *sab;
+	struct isakmp_pl_p *prop;
+	size_t propoff;	/* for previous field of type of next payload. */
+
+	proposal = iph2->proposal;
+
+	iph2->sa = vmalloc(sizeof(*sab));
+	if (iph2->sa == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"failed to allocate my sa buffer\n");
+		return -1;
+	}
+
+	/* create SA payload */
+	sab = (struct ipsecdoi_sa_b *)iph2->sa->v;
+	sab->doi = htonl(IPSEC_DOI);
+	sab->sit = htonl(IPSECDOI_SIT_IDENTITY_ONLY);	/* XXX configurable ? */
+
+	prop = NULL;
+	propoff = 0;
+	for (a = proposal; a; a = a->next) {
+		for (b = a->head; b; b = b->next) {
+#ifdef ENABLE_NATT
+			if (iph2->ph1->natt_flags & NAT_DETECTED) {
+			  int udp_diff = iph2->ph1->natt_options->mode_udp_diff;
+			  plog (LLV_INFO, LOCATION, NULL,
+				"NAT detected -> UDP encapsulation "
+				"(ENC_MODE %d->%d).\n",
+				b->encmode,
+				b->encmode+udp_diff);
+			  /* Tunnel -> UDP-Tunnel, Transport -> UDP_Transport */
+			  b->encmode += udp_diff;
+			  b->udp_encap = 1;
+			}
+#endif
+
+			q = setph2proposal0(iph2, a, b);
+			if (q == NULL) {
+				VPTRINIT(iph2->sa);
+				return -1;
+			}
+
+			iph2->sa = vrealloc(iph2->sa, iph2->sa->l + q->l);
+			if (iph2->sa == NULL) {
+				plog(LLV_ERROR, LOCATION, NULL,
+					"failed to allocate my sa buffer\n");
+				if (q)
+					vfree(q);
+				return -1;
+			}
+			memcpy(iph2->sa->v + iph2->sa->l - q->l, q->v, q->l);
+			if (propoff != 0) {
+				prop = (struct isakmp_pl_p *)(iph2->sa->v +
+					propoff);
+				prop->h.np = ISAKMP_NPTYPE_P;
+			}
+			propoff = iph2->sa->l - q->l;
+
+			vfree(q);
+		}
+	}
+
+	return 0;
+}
+
+/*
+ * return 1 if all of the given protocols are transport mode.
+ */
+int
+ipsecdoi_transportmode(pp)
+	struct saprop *pp;
+{
+	struct saproto *pr = NULL;
+
+	for (; pp; pp = pp->next) {
+		for (pr = pp->head; pr; pr = pr->next) {
+			if (pr->encmode != IPSECDOI_ATTR_ENC_MODE_TRNS)
+				return 0;
+		}
+	}
+
+	return 1;
+}
+
+int
+ipsecdoi_get_defaultlifetime()
+{
+	return IPSECDOI_ATTR_SA_LD_SEC_DEFAULT;
+}
+
+int
+ipsecdoi_checkalgtypes(proto_id, enc, auth, comp)
+	int proto_id, enc, auth, comp;
+{
+#define TMPALGTYPE2STR(n) s_algtype(algclass_ipsec_##n, n)
+	switch (proto_id) {
+	case IPSECDOI_PROTO_IPSEC_ESP:
+		if (enc == 0 || comp != 0) {
+			plog(LLV_ERROR, LOCATION, NULL,
+				"illegal algorithm defined "
+				"ESP enc=%s auth=%s comp=%s.\n",
+				TMPALGTYPE2STR(enc),
+				TMPALGTYPE2STR(auth),
+				TMPALGTYPE2STR(comp));
+			return -1;
+		}
+		break;
+	case IPSECDOI_PROTO_IPSEC_AH:
+		if (enc != 0 || auth == 0 || comp != 0) {
+			plog(LLV_ERROR, LOCATION, NULL,
+				"illegal algorithm defined "
+				"AH enc=%s auth=%s comp=%s.\n",
+				TMPALGTYPE2STR(enc),
+				TMPALGTYPE2STR(auth),
+				TMPALGTYPE2STR(comp));
+			return -1;
+		}
+		break;
+	case IPSECDOI_PROTO_IPCOMP:
+		if (enc != 0 || auth != 0 || comp == 0) {
+			plog(LLV_ERROR, LOCATION, NULL,
+				"illegal algorithm defined "
+				"IPcomp enc=%s auth=%s comp=%s.\n",
+				TMPALGTYPE2STR(enc),
+				TMPALGTYPE2STR(auth),
+				TMPALGTYPE2STR(comp));
+			return -1;
+		}
+		break;
+	default:
+		plog(LLV_ERROR, LOCATION, NULL,
+			"invalid ipsec protocol %d\n", proto_id);
+		return -1;
+	}
+#undef TMPALGTYPE2STR
+	return 0;
+}
+
+int
+ipproto2doi(proto)
+	int proto;
+{
+	switch (proto) {
+	case IPPROTO_AH:
+		return IPSECDOI_PROTO_IPSEC_AH;
+	case IPPROTO_ESP:
+		return IPSECDOI_PROTO_IPSEC_ESP;
+	case IPPROTO_IPCOMP:
+		return IPSECDOI_PROTO_IPCOMP;
+	}
+	return -1;	/* XXX */
+}
+
+int
+doi2ipproto(proto)
+	int proto;
+{
+	switch (proto) {
+	case IPSECDOI_PROTO_IPSEC_AH:
+		return IPPROTO_AH;
+	case IPSECDOI_PROTO_IPSEC_ESP:
+		return IPPROTO_ESP;
+	case IPSECDOI_PROTO_IPCOMP:
+		return IPPROTO_IPCOMP;
+	}
+	return -1;	/* XXX */
+}
+
+/*
+ * Check if a subnet id is valid for comparison
+ * with an address id ( address length mask )
+ * and compare them
+ * Return value
+ * =  0 for match
+ * =  1 for mismatch
+ */
+
+int
+ipsecdoi_subnetisaddr_v4( subnet, address )
+	const vchar_t *subnet;
+	const vchar_t *address;
+{
+	struct in_addr *mask;
+
+	if (address->l != sizeof(struct in_addr))
+		return 1;
+
+	if (subnet->l != (sizeof(struct in_addr)*2))
+		return 1;
+
+	mask = (struct in_addr*)(subnet->v + sizeof(struct in_addr));
+
+	if (mask->s_addr!=0xffffffff)
+		return 1;
+
+	return memcmp(subnet->v,address->v,address->l);
+}
+
+#ifdef INET6
+
+int
+ipsecdoi_subnetisaddr_v6( subnet, address )
+	const vchar_t *subnet;
+	const vchar_t *address;
+{
+	struct in6_addr *mask;
+	int i;
+
+	if (address->l != sizeof(struct in6_addr))
+		return 1;
+
+	if (subnet->l != (sizeof(struct in6_addr)*2))
+		return 1;
+
+	mask = (struct in6_addr*)(subnet->v + sizeof(struct in6_addr));
+
+	for (i=0; i<16; i++)
+		if(mask->s6_addr[i]!=0xff)
+			return 1;
+
+	return memcmp(subnet->v,address->v,address->l);
+}
+
+#endif
+
+/*
+ * Check and Compare two IDs
+ * - specify 0 for exact if wildcards are allowed
+ * Return value
+ * =  0 for match
+ * =  1 for misatch
+ * = -1 for integrity error
+ */
+
+int
+ipsecdoi_chkcmpids( idt, ids, exact )
+	const vchar_t *idt; /* id cmp target */
+	const vchar_t *ids; /* id cmp source */
+	int exact;
+{
+	struct ipsecdoi_id_b *id_bt;
+	struct ipsecdoi_id_b *id_bs;
+	vchar_t ident_t;
+	vchar_t ident_s;
+	int result;
+
+	/* handle wildcard IDs */
+
+	if (idt == NULL || ids == NULL)
+	{
+		if( !exact )
+		{
+			plog(LLV_DEBUG, LOCATION, NULL,
+				"check and compare ids : values matched (ANONYMOUS)\n" );
+			return 0;
+		}
+		else
+		{
+			plog(LLV_DEBUG, LOCATION, NULL,
+				"check and compare ids : value mismatch (ANONYMOUS)\n" );
+			return -1;
+		}
+	}
+
+	/* make sure the ids are of the same type */
+
+	id_bt = (struct ipsecdoi_id_b *) idt->v;
+	id_bs = (struct ipsecdoi_id_b *) ids->v;
+
+	ident_t.v = idt->v + sizeof(*id_bt);
+	ident_t.l = idt->l - sizeof(*id_bt);
+	ident_s.v = ids->v + sizeof(*id_bs);
+	ident_s.l = ids->l - sizeof(*id_bs);
+
+	if (id_bs->type != id_bt->type)
+	{
+		/*
+		 * special exception for comparing
+                 * address to subnet id types when
+                 * the netmask is address length
+                 */
+
+		if ((id_bs->type == IPSECDOI_ID_IPV4_ADDR)&&
+		    (id_bt->type == IPSECDOI_ID_IPV4_ADDR_SUBNET)) {
+			result = ipsecdoi_subnetisaddr_v4(&ident_t,&ident_s);
+			goto cmpid_result;
+		}
+
+		if ((id_bs->type == IPSECDOI_ID_IPV4_ADDR_SUBNET)&&
+		    (id_bt->type == IPSECDOI_ID_IPV4_ADDR)) {
+			result = ipsecdoi_subnetisaddr_v4(&ident_s,&ident_t);
+			goto cmpid_result;
+		}
+
+#ifdef INET6
+		if ((id_bs->type == IPSECDOI_ID_IPV6_ADDR)&&
+		    (id_bt->type == IPSECDOI_ID_IPV6_ADDR_SUBNET)) {
+			result = ipsecdoi_subnetisaddr_v6(&ident_t,&ident_s);
+			goto cmpid_result;
+		}
+
+		if ((id_bs->type == IPSECDOI_ID_IPV6_ADDR_SUBNET)&&
+		    (id_bt->type == IPSECDOI_ID_IPV6_ADDR)) {
+			result = ipsecdoi_subnetisaddr_v6(&ident_s,&ident_t);
+			goto cmpid_result;
+		}
+#endif
+		plog(LLV_DEBUG, LOCATION, NULL,
+			"check and compare ids : id type mismatch %s != %s\n",
+			s_ipsecdoi_ident(id_bs->type),
+			s_ipsecdoi_ident(id_bt->type));
+
+		return 1;
+	}
+
+	if(id_bs->proto_id != id_bt->proto_id){
+		plog(LLV_DEBUG, LOCATION, NULL,
+			"check and compare ids : proto_id mismatch %d != %d\n",
+			id_bs->proto_id, id_bt->proto_id);
+
+		return 1;
+	}
+
+	/* compare the ID data. */
+
+	switch (id_bt->type) {
+	        case IPSECDOI_ID_DER_ASN1_DN:
+        	case IPSECDOI_ID_DER_ASN1_GN:
+			/* compare asn1 ids */
+			result = eay_cmp_asn1dn(&ident_t, &ident_s);
+			goto cmpid_result;
+
+		case IPSECDOI_ID_IPV4_ADDR:
+			/* validate lengths */
+			if ((ident_t.l != sizeof(struct in_addr))||
+			    (ident_s.l != sizeof(struct in_addr)))
+				goto cmpid_invalid;
+			break;
+
+		case IPSECDOI_ID_IPV4_ADDR_SUBNET:
+		case IPSECDOI_ID_IPV4_ADDR_RANGE:
+			/* validate lengths */
+			if ((ident_t.l != (sizeof(struct in_addr)*2))||
+			    (ident_s.l != (sizeof(struct in_addr)*2)))
+				goto cmpid_invalid;
+			break;
+
+#ifdef INET6
+		case IPSECDOI_ID_IPV6_ADDR:
+			/* validate lengths */
+			if ((ident_t.l != sizeof(struct in6_addr))||
+			    (ident_s.l != sizeof(struct in6_addr)))
+				goto cmpid_invalid;
+			break;
+
+		case IPSECDOI_ID_IPV6_ADDR_SUBNET:
+		case IPSECDOI_ID_IPV6_ADDR_RANGE:
+			/* validate lengths */
+			if ((ident_t.l != (sizeof(struct in6_addr)*2))||
+			    (ident_s.l != (sizeof(struct in6_addr)*2)))
+				goto cmpid_invalid;
+			break;
+#endif
+		case IPSECDOI_ID_FQDN:
+		case IPSECDOI_ID_USER_FQDN:
+		case IPSECDOI_ID_KEY_ID:
+			break;
+
+		default:
+			plog(LLV_ERROR, LOCATION, NULL,
+				"Unhandled id type %i specified for comparison\n",
+				id_bt->type);
+			return -1;
+	}
+
+	/* validate matching data and length */
+	if (ident_t.l == ident_s.l)
+		result = memcmp(ident_t.v,ident_s.v,ident_t.l);
+	else
+		result = 1;
+
+cmpid_result:
+
+	/* debug level output */
+	if(loglevel >= LLV_DEBUG) {
+		char *idstrt = ipsecdoi_id2str(idt);
+		char *idstrs = ipsecdoi_id2str(ids);
+
+		if (!result)
+	 		plog(LLV_DEBUG, LOCATION, NULL,
+				"check and compare ids : values matched (%s)\n",
+				 s_ipsecdoi_ident(id_bs->type) );
+		else
+ 			plog(LLV_DEBUG, LOCATION, NULL,
+				"check and compare ids : value mismatch (%s)\n",
+				 s_ipsecdoi_ident(id_bs->type));
+
+		plog(LLV_DEBUG, LOCATION, NULL, "cmpid target: \'%s\'\n", idstrt );
+		plog(LLV_DEBUG, LOCATION, NULL, "cmpid source: \'%s\'\n", idstrs );
+
+		racoon_free(idstrs);
+		racoon_free(idstrt);
+	}
+
+	/* return result */
+	if( !result )
+		return 0;
+	else
+		return 1;
+
+cmpid_invalid:
+
+	/* id integrity error */
+	plog(LLV_DEBUG, LOCATION, NULL, "check and compare ids : %s integrity error\n",
+		s_ipsecdoi_ident(id_bs->type));
+	plog(LLV_DEBUG, LOCATION, NULL, "cmpid target: length = \'%zu\'\n", ident_t.l );
+	plog(LLV_DEBUG, LOCATION, NULL, "cmpid source: length = \'%zu\'\n", ident_s.l );
+
+	return -1;
+}
+
+/*
+ * check the following:
+ * - In main mode with pre-shared key, only address type can be used.
+ * - if proper type for phase 1 ?
+ * - if phase 1 ID payload conformed RFC2407 4.6.2.
+ *   (proto, port) must be (0, 0), (udp, 500) or (udp, [specified]).
+ * - if ID payload sent from peer is equal to the ID expected by me.
+ *
+ * both of "id" and "id_p" should be ID payload without general header,
+ */
+int
+ipsecdoi_checkid1(iph1)
+	struct ph1handle *iph1;
+{
+	struct ipsecdoi_id_b *id_b;
+	struct sockaddr *sa;
+	caddr_t sa1, sa2;
+
+	if (iph1->id_p == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"invalid iph1 passed id_p == NULL\n");
+		return ISAKMP_INTERNAL_ERROR;
+	}
+	if (iph1->id_p->l < sizeof(*id_b)) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"invalid value passed as \"ident\" (len=%lu)\n",
+			(u_long)iph1->id_p->l);
+		return ISAKMP_NTYPE_INVALID_ID_INFORMATION;
+	}
+
+	id_b = (struct ipsecdoi_id_b *)iph1->id_p->v;
+
+	/* In main mode with pre-shared key, only address type can be used. */
+	if (iph1->etype == ISAKMP_ETYPE_IDENT &&
+	    iph1->approval->authmethod == OAKLEY_ATTR_AUTH_METHOD_PSKEY) {
+		 if (id_b->type != IPSECDOI_ID_IPV4_ADDR
+		  && id_b->type != IPSECDOI_ID_IPV6_ADDR) {
+			plog(LLV_ERROR, LOCATION, NULL,
+				"Expecting IP address type in main mode, "
+				"but %s.\n", s_ipsecdoi_ident(id_b->type));
+			return ISAKMP_NTYPE_INVALID_ID_INFORMATION;
+		}
+	}
+
+	/* if proper type for phase 1 ? */
+	switch (id_b->type) {
+	case IPSECDOI_ID_IPV4_ADDR_SUBNET:
+	case IPSECDOI_ID_IPV6_ADDR_SUBNET:
+	case IPSECDOI_ID_IPV4_ADDR_RANGE:
+	case IPSECDOI_ID_IPV6_ADDR_RANGE:
+		plog(LLV_WARNING, LOCATION, NULL,
+			"such ID type %s is not proper.\n",
+			s_ipsecdoi_ident(id_b->type));
+		/*FALLTHROUGH*/
+	}
+
+	/* if phase 1 ID payload conformed RFC2407 4.6.2. */
+	if (id_b->type == IPSECDOI_ID_IPV4_ADDR ||
+	    id_b->type == IPSECDOI_ID_IPV6_ADDR) {
+
+		if (id_b->proto_id == 0 && ntohs(id_b->port) != 0) {
+			plog(LLV_WARNING, LOCATION, NULL,
+				"protocol ID and Port mismatched. "
+				"proto_id:%d port:%d\n",
+				id_b->proto_id, ntohs(id_b->port));
+			/*FALLTHROUGH*/
+
+		} else if (id_b->proto_id == IPPROTO_UDP) {
+			/*
+			 * copmaring with expecting port.
+			 * always permit if port is equal to PORT_ISAKMP
+			 */
+			if (ntohs(id_b->port) != PORT_ISAKMP) {
+				u_int16_t port;
+
+				port = extract_port(iph1->remote);
+				if (ntohs(id_b->port) != port) {
+					plog(LLV_WARNING, LOCATION, NULL,
+						"port %d expected, but %d\n",
+						port, ntohs(id_b->port));
+					/*FALLTHROUGH*/
+				}
+			}
+		}
+	}
+
+	/* compare with the ID if specified. */
+	if (genlist_next(iph1->rmconf->idvl_p, 0)) {
+		vchar_t *ident0 = NULL;
+		vchar_t ident;
+		struct idspec *id;
+		struct genlist_entry *gpb;
+
+		for (id = genlist_next (iph1->rmconf->idvl_p, &gpb); id; id = genlist_next (0, &gpb)) {
+			/* check the type of both IDs */
+			if (id->idtype != doi2idtype(id_b->type))
+				continue;  /* ID type mismatch */
+			if (id->id == 0)
+				goto matched;
+
+			/* compare defined ID with the ID sent by peer. */
+			if (ident0 != NULL)
+				vfree(ident0);
+			ident0 = getidval(id->idtype, id->id);
+
+			switch (id->idtype) {
+			case IDTYPE_ASN1DN:
+				ident.v = iph1->id_p->v + sizeof(*id_b);
+				ident.l = iph1->id_p->l - sizeof(*id_b);
+				if (eay_cmp_asn1dn(ident0, &ident) == 0)
+					goto matched;
+				break;
+			case IDTYPE_ADDRESS:
+				sa = (struct sockaddr *)ident0->v;
+				sa2 = (caddr_t)(id_b + 1);
+				switch (sa->sa_family) {
+				case AF_INET:
+					if (iph1->id_p->l - sizeof(*id_b) != sizeof(struct in_addr))
+						continue;  /* ID value mismatch */
+					sa1 = (caddr_t)&((struct sockaddr_in *)sa)->sin_addr;
+					if (memcmp(sa1, sa2, sizeof(struct in_addr)) == 0)
+						goto matched;
+					break;
+#ifdef INET6
+				case AF_INET6:
+					if (iph1->id_p->l - sizeof(*id_b) != sizeof(struct in6_addr))
+						continue;  /* ID value mismatch */
+					sa1 = (caddr_t)&((struct sockaddr_in6 *)sa)->sin6_addr;
+					if (memcmp(sa1, sa2, sizeof(struct in6_addr)) == 0)
+						goto matched;
+					break;
+#endif
+				default:
+					break;
+				}
+				break;
+			default:
+				if (memcmp(ident0->v, id_b + 1, ident0->l) == 0)
+					goto matched;
+				break;
+			}
+		}
+		if (ident0 != NULL) {
+			vfree(ident0);
+			ident0 = NULL;
+		}
+		plog(LLV_WARNING, LOCATION, NULL, "No ID match.\n");
+		if (iph1->rmconf->verify_identifier)
+			return ISAKMP_NTYPE_INVALID_ID_INFORMATION;
+matched: /* ID value match */
+		if (ident0 != NULL)
+			vfree(ident0);
+	}
+
+	return 0;
+}
+
+/*
+ * create ID payload for phase 1 and set into iph1->id.
+ * NOT INCLUDING isakmp general header.
+ * see, RFC2407 4.6.2.1
+ */
+int
+ipsecdoi_setid1(iph1)
+	struct ph1handle *iph1;
+{
+	vchar_t *ret = NULL;
+	struct ipsecdoi_id_b id_b;
+	vchar_t *ident = NULL;
+	struct sockaddr *ipid = NULL;
+
+	/* init */
+	id_b.proto_id = 0;
+	id_b.port = 0;
+	ident = NULL;
+
+	switch (iph1->rmconf->idvtype) {
+	case IDTYPE_FQDN:
+		id_b.type = IPSECDOI_ID_FQDN;
+		ident = getidval(iph1->rmconf->idvtype, iph1->rmconf->idv);
+		break;
+	case IDTYPE_USERFQDN:
+		id_b.type = IPSECDOI_ID_USER_FQDN;
+		ident = getidval(iph1->rmconf->idvtype, iph1->rmconf->idv);
+		break;
+	case IDTYPE_KEYID:
+		id_b.type = IPSECDOI_ID_KEY_ID;
+		ident = getidval(iph1->rmconf->idvtype, iph1->rmconf->idv);
+		break;
+	case IDTYPE_ASN1DN:
+		id_b.type = IPSECDOI_ID_DER_ASN1_DN;
+		if (iph1->rmconf->idv) {
+			/* XXX it must be encoded to asn1dn. */
+			ident = vdup(iph1->rmconf->idv);
+		} else {
+			if (oakley_getmycert(iph1) < 0) {
+				plog(LLV_ERROR, LOCATION, NULL,
+					"failed to get own CERT.\n");
+				goto err;
+			}
+			ident = eay_get_x509asn1subjectname(&iph1->cert->cert);
+		}
+		break;
+	case IDTYPE_ADDRESS:
+		/*
+		 * if the value of the id type was set by the configuration
+		 * file, then use it.  otherwise the value is get from local
+		 * ip address by using ike negotiation.
+		 */
+		if (iph1->rmconf->idv)
+			ipid = (struct sockaddr *)iph1->rmconf->idv->v;
+		/*FALLTHROUGH*/
+	default:
+	    {
+		int l;
+		caddr_t p;
+
+		if (ipid == NULL)
+			ipid = iph1->local;
+
+		/* use IP address */
+		switch (ipid->sa_family) {
+		case AF_INET:
+			id_b.type = IPSECDOI_ID_IPV4_ADDR;
+			l = sizeof(struct in_addr);
+			p = (caddr_t)&((struct sockaddr_in *)ipid)->sin_addr;
+			break;
+#ifdef INET6
+		case AF_INET6:
+			id_b.type = IPSECDOI_ID_IPV6_ADDR;
+			l = sizeof(struct in6_addr);
+			p = (caddr_t)&((struct sockaddr_in6 *)ipid)->sin6_addr;
+			break;
+#endif
+		default:
+			plog(LLV_ERROR, LOCATION, NULL,
+				"invalid address family.\n");
+			goto err;
+		}
+		id_b.proto_id = IPPROTO_UDP;
+		id_b.port = htons(PORT_ISAKMP);
+		ident = vmalloc(l);
+		if (!ident) {
+			plog(LLV_ERROR, LOCATION, NULL,
+				"failed to get ID buffer.\n");
+			return 0;
+		}
+		memcpy(ident->v, p, ident->l);
+	    }
+	}
+	if (!ident) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"failed to get ID buffer.\n");
+		return 0;
+	}
+
+	ret = vmalloc(sizeof(id_b) + ident->l);
+	if (ret == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"failed to get ID buffer.\n");
+		goto err;
+	}
+
+	memcpy(ret->v, &id_b, sizeof(id_b));
+	memcpy(ret->v + sizeof(id_b), ident->v, ident->l);
+
+	iph1->id = ret;
+
+	plog(LLV_DEBUG, LOCATION, NULL,
+		"use ID type of %s\n", s_ipsecdoi_ident(id_b.type));
+	if (ident)
+		vfree(ident);
+	return 0;
+
+err:
+	if (ident)
+		vfree(ident);
+	plog(LLV_ERROR, LOCATION, NULL, "failed get my ID\n");
+	return -1;
+}
+
+static vchar_t *
+getidval(type, val)
+	int type;
+	vchar_t *val;
+{
+	vchar_t *new = NULL;
+
+	if (val)
+		new = vdup(val);
+	else if (lcconf->ident[type])
+		new = vdup(lcconf->ident[type]);
+
+	return new;
+}
+
+/* it's only called by cfparse.y. */
+int
+set_identifier(vpp, type, value)
+	vchar_t **vpp, *value;
+	int type;
+{
+	return set_identifier_qual(vpp, type, value, IDQUAL_UNSPEC);
+}
+
+int
+set_identifier_qual(vpp, type, value, qual)
+	vchar_t **vpp, *value;
+	int type;
+	int qual;
+{
+	vchar_t *new = NULL;
+
+	/* simply return if value is null. */
+	if (!value){
+		if( type == IDTYPE_FQDN || type == IDTYPE_USERFQDN){
+			plog(LLV_ERROR, LOCATION, NULL,
+				 "No %s\n", type == IDTYPE_FQDN ? "fqdn":"user fqdn");
+			return -1;
+		}
+		return 0;
+	}
+
+	switch (type) {
+	case IDTYPE_FQDN:
+	case IDTYPE_USERFQDN:
+		if(value->l <= 1){
+			plog(LLV_ERROR, LOCATION, NULL,
+				 "Empty %s\n", type == IDTYPE_FQDN ? "fqdn":"user fqdn");
+			return -1;
+		}
+		/* length is adjusted since QUOTEDSTRING teminates NULL. */
+		new = vmalloc(value->l - 1);
+		if (new == NULL)
+			return -1;
+		memcpy(new->v, value->v, new->l);
+		break;
+	case IDTYPE_KEYID:
+		/* 
+		 * If no qualifier is specified: IDQUAL_UNSPEC. It means
+		 * to use a file for backward compatibility sake. 
+		 */
+		switch(qual) {
+		case IDQUAL_FILE:
+		case IDQUAL_UNSPEC: {
+			FILE *fp;
+			char b[512];
+			int tlen, len;
+
+			fp = fopen(value->v, "r");
+			if (fp == NULL) {
+				plog(LLV_ERROR, LOCATION, NULL,
+					"can not open %s\n", value->v);
+				return -1;
+			}
+			tlen = 0;
+			while ((len = fread(b, 1, sizeof(b), fp)) != 0) {
+				new = vrealloc(new, tlen + len);
+				if (!new) {
+					fclose(fp);
+					return -1;
+				}
+				memcpy(new->v + tlen, b, len);
+				tlen += len;
+			}
+			break;
+		}
+
+		case IDQUAL_TAG:
+			new = vmalloc(value->l - 1);
+			if (new == NULL) {
+				plog(LLV_ERROR, LOCATION, NULL,
+					"can not allocate memory");
+				return -1;
+			}
+			memcpy(new->v, value->v, new->l);
+			break;
+
+		default:
+			plog(LLV_ERROR, LOCATION, NULL,
+				"unknown qualifier");
+			return -1;
+		}
+		break;
+	
+	case IDTYPE_ADDRESS: {
+		struct sockaddr *sa;
+
+		/* length is adjusted since QUOTEDSTRING teminates NULL. */
+		if (value->l == 0)
+			break;
+
+		sa = str2saddr(value->v, NULL);
+		if (sa == NULL) {
+			plog(LLV_ERROR, LOCATION, NULL,
+				"invalid ip address %s\n", value->v);
+			return -1;
+		}
+
+		new = vmalloc(sysdep_sa_len(sa));
+		if (new == NULL) {
+			racoon_free(sa);
+			return -1;
+		}
+		memcpy(new->v, sa, new->l);
+		racoon_free(sa);
+		break;
+	}
+	case IDTYPE_ASN1DN:
+		if (value->v[0] == '~')
+			/* Hex-encoded ASN1 strings */
+			new = eay_hex2asn1dn(value->v + 1, - 1);
+		else
+			/* DN encoded strings */
+			new = eay_str2asn1dn(value->v, value->l - 1);
+
+		if (new == NULL)
+			return -1;
+
+		if (loglevel >= LLV_DEBUG) {
+			X509_NAME *xn;
+			BIO *bio;
+			unsigned char *ptr = (unsigned char *) new->v, *buf;
+			size_t len;
+			char save;
+
+			xn = d2i_X509_NAME(NULL, (void *)&ptr, new->l);
+			bio = BIO_new(BIO_s_mem());
+			
+			X509_NAME_print_ex(bio, xn, 0, 0);
+			len = BIO_get_mem_data(bio, &ptr);
+			save = ptr[len];
+			ptr[len] = 0;
+			plog(LLV_DEBUG, LOCATION, NULL, "Parsed DN: %s\n", ptr);
+			ptr[len] = save;
+			X509_NAME_free(xn);
+			BIO_free(bio);
+		}
+
+		break;
+	}
+
+	*vpp = new;
+
+	return 0;
+}
+
+/*
+ * create ID payload for phase 2, and set into iph2->id and id_p.  There are
+ * NOT INCLUDING isakmp general header.
+ * this function is for initiator.  responder will get to copy from payload.
+ * responder ID type is always address type.
+ * see, RFC2407 4.6.2.1
+ */
+int
+ipsecdoi_setid2(iph2)
+	struct ph2handle *iph2;
+{
+	struct secpolicy *sp;
+
+	/* check there is phase 2 handler ? */
+	sp = getspbyspid(iph2->spid);
+	if (sp == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"no policy found for spid:%u.\n", iph2->spid);
+		return -1;
+	}
+
+	iph2->id = ipsecdoi_sockaddr2id((struct sockaddr *)&sp->spidx.src,
+					sp->spidx.prefs, sp->spidx.ul_proto);
+	if (iph2->id == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"failed to get ID for %s\n",
+			spidx2str(&sp->spidx));
+		return -1;
+	}
+	plog(LLV_DEBUG, LOCATION, NULL, "use local ID type %s\n",
+		s_ipsecdoi_ident(((struct ipsecdoi_id_b *)iph2->id->v)->type));
+
+	/* remote side */
+	iph2->id_p = ipsecdoi_sockaddr2id((struct sockaddr *)&sp->spidx.dst,
+				sp->spidx.prefd, sp->spidx.ul_proto);
+	if (iph2->id_p == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"failed to get ID for %s\n",
+			spidx2str(&sp->spidx));
+		VPTRINIT(iph2->id);
+		return -1;
+	}
+	plog(LLV_DEBUG, LOCATION, NULL,
+		"use remote ID type %s\n",
+		s_ipsecdoi_ident(((struct ipsecdoi_id_b *)iph2->id_p->v)->type));
+
+	return 0;
+}
+
+/*
+ * set address type of ID.
+ * NOT INCLUDING general header.
+ */
+vchar_t *
+ipsecdoi_sockaddr2id(saddr, prefixlen, ul_proto)
+	struct sockaddr *saddr;
+	u_int prefixlen;
+	u_int ul_proto;
+{
+	vchar_t *new;
+	int type, len1, len2;
+	caddr_t sa;
+	u_short port;
+
+	/*
+	 * Q. When type is SUBNET, is it allowed to be ::1/128.
+	 * A. Yes. (consensus at bake-off)
+	 */
+	switch (saddr->sa_family) {
+	case AF_INET:
+		len1 = sizeof(struct in_addr);
+		if (prefixlen == (sizeof(struct in_addr) << 3)) {
+			type = IPSECDOI_ID_IPV4_ADDR;
+			len2 = 0;
+		} else {
+			type = IPSECDOI_ID_IPV4_ADDR_SUBNET;
+			len2 = sizeof(struct in_addr);
+		}
+		sa = (caddr_t)&((struct sockaddr_in *)(saddr))->sin_addr;
+		port = ((struct sockaddr_in *)(saddr))->sin_port;
+		break;
+#ifdef INET6
+	case AF_INET6:
+		len1 = sizeof(struct in6_addr);
+		if (prefixlen == (sizeof(struct in6_addr) << 3)) {
+			type = IPSECDOI_ID_IPV6_ADDR;
+			len2 = 0;
+		} else {
+			type = IPSECDOI_ID_IPV6_ADDR_SUBNET;
+			len2 = sizeof(struct in6_addr);
+		}
+		sa = (caddr_t)&((struct sockaddr_in6 *)(saddr))->sin6_addr;
+		port = ((struct sockaddr_in6 *)(saddr))->sin6_port;
+		break;
+#endif
+	default:
+		plog(LLV_ERROR, LOCATION, NULL,
+			"invalid family: %d.\n", saddr->sa_family);
+		return NULL;
+	}
+
+	/* get ID buffer */
+	new = vmalloc(sizeof(struct ipsecdoi_id_b) + len1 + len2);
+	if (new == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"failed to get ID buffer.\n");
+		return NULL;
+	}
+
+	memset(new->v, 0, new->l);
+
+	/* set the part of header. */
+	((struct ipsecdoi_id_b *)new->v)->type = type;
+
+	/* set ul_proto and port */
+	/*
+	 * NOTE: we use both IPSEC_ULPROTO_ANY and IPSEC_PORT_ANY as wild card
+	 * because 0 means port number of 0.  Instead of 0, we use IPSEC_*_ANY.
+	 */
+	((struct ipsecdoi_id_b *)new->v)->proto_id =
+		ul_proto == IPSEC_ULPROTO_ANY ? 0 : ul_proto;
+	((struct ipsecdoi_id_b *)new->v)->port =
+		port == IPSEC_PORT_ANY ? 0 : port;
+	memcpy(new->v + sizeof(struct ipsecdoi_id_b), sa, len1);
+
+	/* set address */
+
+	/* set prefix */
+	if (len2) {
+		u_char *p = (unsigned char *) new->v + 
+			sizeof(struct ipsecdoi_id_b) + len1;
+		u_int bits = prefixlen;
+
+		while (bits >= 8) {
+			*p++ = 0xff;
+			bits -= 8;
+		}
+
+		if (bits > 0)
+			*p = ~((1 << (8 - bits)) - 1);
+	}
+
+	return new;
+}
+
+vchar_t *
+ipsecdoi_sockrange2id(laddr, haddr, ul_proto)
+	struct sockaddr *laddr, *haddr;
+	u_int ul_proto;
+{
+	vchar_t *new;
+	int type, len1, len2;
+	u_short port;
+
+	if (laddr->sa_family != haddr->sa_family) {
+	    plog(LLV_ERROR, LOCATION, NULL, "Address family mismatch\n");
+	    return NULL;
+	}
+
+	switch (laddr->sa_family) {
+	case AF_INET:
+	    type = IPSECDOI_ID_IPV4_ADDR_RANGE;
+	    len1 = sizeof(struct in_addr);
+	    len2 = sizeof(struct in_addr);
+	    break;
+#ifdef INET6
+	case AF_INET6:
+		type = IPSECDOI_ID_IPV6_ADDR_RANGE;
+		len1 = sizeof(struct in6_addr);
+		len2 = sizeof(struct in6_addr);
+		break;
+#endif
+	default:
+		plog(LLV_ERROR, LOCATION, NULL,
+			"invalid family: %d.\n", laddr->sa_family);
+		return NULL;
+	}
+
+	/* get ID buffer */
+	new = vmalloc(sizeof(struct ipsecdoi_id_b) + len1 + len2);
+	if (new == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"failed to get ID buffer.\n");
+		return NULL;
+	}
+
+	memset(new->v, 0, new->l);
+	/* set the part of header. */
+	((struct ipsecdoi_id_b *)new->v)->type = type;
+
+	/* set ul_proto and port */
+	/*
+	 * NOTE: we use both IPSEC_ULPROTO_ANY and IPSEC_PORT_ANY as wild card
+	 * because 0 means port number of 0.  Instead of 0, we use IPSEC_*_ANY.
+	 */
+	((struct ipsecdoi_id_b *)new->v)->proto_id =
+		ul_proto == IPSEC_ULPROTO_ANY ? 0 : ul_proto;
+	port = ((struct sockaddr_in *)(laddr))->sin_port;
+	((struct ipsecdoi_id_b *)new->v)->port =
+		port == IPSEC_PORT_ANY ? 0 : port;
+	memcpy(new->v + sizeof(struct ipsecdoi_id_b), 
+	       (caddr_t)&((struct sockaddr_in *)(laddr))->sin_addr, 
+	       len1);
+	memcpy(new->v + sizeof(struct ipsecdoi_id_b) + len1, 
+	       (caddr_t)&((struct sockaddr_in *)haddr)->sin_addr,
+	       len2);
+	return new;
+}
+
+
+/*
+ * create sockaddr structure from ID payload (buf).
+ * buffers (saddr, prefixlen, ul_proto) must be allocated.
+ * see, RFC2407 4.6.2.1
+ */
+int
+ipsecdoi_id2sockaddr(buf, saddr, prefixlen, ul_proto)
+	vchar_t *buf;
+	struct sockaddr *saddr;
+	u_int8_t *prefixlen;
+	u_int16_t *ul_proto;
+{
+	struct ipsecdoi_id_b *id_b = (struct ipsecdoi_id_b *)buf->v;
+	u_int plen = 0;
+
+	/*
+	 * When a ID payload of subnet type with a IP address of full bit
+	 * masked, it has to be processed as host address.
+	 * e.g. below 2 type are same.
+	 *      type = ipv6 subnet, data = 2001::1/128
+	 *      type = ipv6 address, data = 2001::1
+	 */
+	switch (id_b->type) {
+	case IPSECDOI_ID_IPV4_ADDR:
+	case IPSECDOI_ID_IPV4_ADDR_SUBNET:
+#ifndef __linux__
+		saddr->sa_len = sizeof(struct sockaddr_in);
+#endif
+		saddr->sa_family = AF_INET;
+		((struct sockaddr_in *)saddr)->sin_port =
+			(id_b->port == 0
+				? IPSEC_PORT_ANY
+				: id_b->port);		/* see sockaddr2id() */
+		memcpy(&((struct sockaddr_in *)saddr)->sin_addr,
+			buf->v + sizeof(*id_b), sizeof(struct in_addr));
+		break;
+#ifdef INET6
+	case IPSECDOI_ID_IPV6_ADDR:
+	case IPSECDOI_ID_IPV6_ADDR_SUBNET:
+#ifndef __linux__
+		saddr->sa_len = sizeof(struct sockaddr_in6);
+#endif
+		saddr->sa_family = AF_INET6;
+		((struct sockaddr_in6 *)saddr)->sin6_port =
+			(id_b->port == 0
+				? IPSEC_PORT_ANY
+				: id_b->port);		/* see sockaddr2id() */
+		memcpy(&((struct sockaddr_in6 *)saddr)->sin6_addr,
+			buf->v + sizeof(*id_b), sizeof(struct in6_addr));
+		break;
+#endif
+	default:
+		plog(LLV_ERROR, LOCATION, NULL,
+			"unsupported ID type %d\n", id_b->type);
+		return ISAKMP_NTYPE_INVALID_ID_INFORMATION;
+	}
+
+	/* get prefix length */
+	switch (id_b->type) {
+	case IPSECDOI_ID_IPV4_ADDR:
+		plen = sizeof(struct in_addr) << 3;
+		break;
+#ifdef INET6
+	case IPSECDOI_ID_IPV6_ADDR:
+		plen = sizeof(struct in6_addr) << 3;
+		break;
+#endif
+	case IPSECDOI_ID_IPV4_ADDR_SUBNET:
+#ifdef INET6
+	case IPSECDOI_ID_IPV6_ADDR_SUBNET:
+#endif
+	    {
+		u_char *p;
+		u_int max;
+		int alen = sizeof(struct in_addr);
+
+		switch (id_b->type) {
+		case IPSECDOI_ID_IPV4_ADDR_SUBNET:
+			alen = sizeof(struct in_addr);
+			break;
+#ifdef INET6
+		case IPSECDOI_ID_IPV6_ADDR_SUBNET:
+			alen = sizeof(struct in6_addr);
+			break;
+#endif
+		}
+
+		/* sanity check */
+		if (buf->l < alen)
+			return ISAKMP_INTERNAL_ERROR;
+
+		/* get subnet mask length */
+		plen = 0;
+		max = alen <<3;
+
+		p = (unsigned char *) buf->v
+			+ sizeof(struct ipsecdoi_id_b)
+			+ alen;
+
+		for (; *p == 0xff; p++) {
+			plen += 8;
+			if (plen >= max)
+				break;
+		}
+
+		if (plen < max) {
+			u_int l = 0;
+			u_char b = ~(*p);
+
+			while (b) {
+				b >>= 1;
+				l++;
+			}
+
+			l = 8 - l;
+			plen += l;
+		}
+	    }
+		break;
+	}
+
+	*prefixlen = plen;
+	*ul_proto = id_b->proto_id == 0
+				? IPSEC_ULPROTO_ANY
+				: id_b->proto_id;	/* see sockaddr2id() */
+
+	return 0;
+}
+
+/*
+ * make printable string from ID payload except of general header.
+ */
+char *
+ipsecdoi_id2str(id)
+	const vchar_t *id;
+{
+#define BUFLEN 512
+	char * ret = NULL;
+	int len = 0;
+	char *dat;
+	static char buf[BUFLEN];
+	struct ipsecdoi_id_b *id_b = (struct ipsecdoi_id_b *)id->v;
+	struct sockaddr saddr;
+	u_int plen = 0;
+
+	switch (id_b->type) {
+	case IPSECDOI_ID_IPV4_ADDR:
+	case IPSECDOI_ID_IPV4_ADDR_SUBNET:
+	case IPSECDOI_ID_IPV4_ADDR_RANGE:
+
+#ifndef __linux__
+		saddr.sa_len = sizeof(struct sockaddr_in);
+#endif
+		saddr.sa_family = AF_INET;
+		((struct sockaddr_in *)&saddr)->sin_port = IPSEC_PORT_ANY;
+		memcpy(&((struct sockaddr_in *)&saddr)->sin_addr,
+			id->v + sizeof(*id_b), sizeof(struct in_addr));
+		break;
+#ifdef INET6
+	case IPSECDOI_ID_IPV6_ADDR:
+	case IPSECDOI_ID_IPV6_ADDR_SUBNET:
+	case IPSECDOI_ID_IPV6_ADDR_RANGE:
+
+#ifndef __linux__
+		saddr.sa_len = sizeof(struct sockaddr_in6);
+#endif
+		saddr.sa_family = AF_INET6;
+		((struct sockaddr_in6 *)&saddr)->sin6_port = IPSEC_PORT_ANY;
+		memcpy(&((struct sockaddr_in6 *)&saddr)->sin6_addr,
+			id->v + sizeof(*id_b), sizeof(struct in6_addr));
+		break;
+#endif
+	}
+
+	switch (id_b->type) {
+	case IPSECDOI_ID_IPV4_ADDR:
+#ifdef INET6
+	case IPSECDOI_ID_IPV6_ADDR:
+#endif
+		len = snprintf( buf, BUFLEN, "%s", saddrwop2str(&saddr));
+		break;
+
+	case IPSECDOI_ID_IPV4_ADDR_SUBNET:
+#ifdef INET6
+	case IPSECDOI_ID_IPV6_ADDR_SUBNET:
+#endif
+	    {
+		u_char *p;
+		u_int max;
+		int alen = sizeof(struct in_addr);
+
+		switch (id_b->type) {
+		case IPSECDOI_ID_IPV4_ADDR_SUBNET:
+			alen = sizeof(struct in_addr);
+			break;
+#ifdef INET6
+		case IPSECDOI_ID_IPV6_ADDR_SUBNET:
+			alen = sizeof(struct in6_addr);
+			break;
+#endif
+		}
+
+		/* sanity check */
+		if (id->l < alen) {
+			len = 0;
+			break;
+		}
+
+		/* get subnet mask length */
+		plen = 0;
+		max = alen <<3;
+
+		p = (unsigned char *) id->v
+			+ sizeof(struct ipsecdoi_id_b)
+			+ alen;
+
+		for (; *p == 0xff; p++) {
+			plen += 8;
+			if (plen >= max)
+				break;
+		}
+
+		if (plen < max) {
+			u_int l = 0;
+			u_char b = ~(*p);
+
+			while (b) {
+				b >>= 1;
+				l++;
+			}
+
+			l = 8 - l;
+			plen += l;
+		}
+
+		len = snprintf( buf, BUFLEN, "%s/%i", saddrwop2str(&saddr), plen);
+	    }
+		break;
+
+	case IPSECDOI_ID_IPV4_ADDR_RANGE:
+
+		len = snprintf( buf, BUFLEN, "%s-", saddrwop2str(&saddr));
+
+#ifndef __linux__
+		saddr.sa_len = sizeof(struct sockaddr_in);
+#endif
+		saddr.sa_family = AF_INET;
+		((struct sockaddr_in *)&saddr)->sin_port = IPSEC_PORT_ANY;
+		memcpy(&((struct sockaddr_in *)&saddr)->sin_addr,
+			id->v + sizeof(*id_b) + sizeof(struct in_addr),
+			sizeof(struct in_addr));
+
+		len += snprintf( buf + len, BUFLEN - len, "%s", saddrwop2str(&saddr));
+
+		break;
+
+#ifdef INET6
+	case IPSECDOI_ID_IPV6_ADDR_RANGE:
+
+		len = snprintf( buf, BUFLEN, "%s-", saddrwop2str(&saddr));
+
+#ifndef __linux__
+		saddr.sa_len = sizeof(struct sockaddr_in6);
+#endif
+		saddr.sa_family = AF_INET6;
+		((struct sockaddr_in6 *)&saddr)->sin6_port = IPSEC_PORT_ANY;
+		memcpy(&((struct sockaddr_in6 *)&saddr)->sin6_addr,
+			id->v + sizeof(*id_b) + sizeof(struct in6_addr),
+			sizeof(struct in6_addr));
+
+		len += snprintf( buf + len, BUFLEN - len, "%s", saddrwop2str(&saddr));
+
+		break;
+#endif
+
+	case IPSECDOI_ID_FQDN:
+	case IPSECDOI_ID_USER_FQDN:
+		len = id->l - sizeof(*id_b);
+		if (len > BUFLEN)
+			len = BUFLEN;
+		memcpy(buf, id->v + sizeof(*id_b), len);
+		break;
+
+	case IPSECDOI_ID_DER_ASN1_DN:
+	case IPSECDOI_ID_DER_ASN1_GN:
+	{
+		X509_NAME *xn = NULL;
+
+		dat = id->v + sizeof(*id_b);
+		len = id->l - sizeof(*id_b);
+
+		if (d2i_X509_NAME(&xn, (void*) &dat, len) != NULL) {
+			BIO *bio = BIO_new(BIO_s_mem());
+			X509_NAME_print_ex(bio, xn, 0, 0);
+			len = BIO_get_mem_data(bio, &dat);
+			if (len > BUFLEN)
+				len = BUFLEN;
+			memcpy(buf,dat,len);
+			BIO_free(bio);
+			X509_NAME_free(xn);
+		} else {
+			plog(LLV_ERROR, LOCATION, NULL,
+				"unable to extract asn1dn from id\n");
+
+			len = sprintf(buf, "<ASN1-DN>");
+		}
+
+		break;
+	}
+
+	/* currently unhandled id types */
+	case IPSECDOI_ID_KEY_ID:
+		len = sprintf( buf, "<KEY-ID>");
+		break;
+
+	default:
+		plog(LLV_ERROR, LOCATION, NULL,
+			"unknown ID type %d\n", id_b->type);
+	}
+
+	if (!len)
+		len = sprintf( buf, "<?>");
+
+	ret = racoon_malloc(len+1);
+	if (ret != NULL) {
+		memcpy(ret,buf,len);
+		ret[len]=0;
+	}
+
+	return ret;
+}
+
+/*
+ * set IPsec data attributes into a proposal.
+ * NOTE: MUST called per a transform.
+ */
+int
+ipsecdoi_t2satrns(t, pp, pr, tr)
+	struct isakmp_pl_t *t;
+	struct saprop *pp;
+	struct saproto *pr;
+	struct satrns *tr;
+{
+	struct isakmp_data *d, *prev;
+	int flag, type;
+	int error = -1;
+	int life_t;
+	int tlen;
+
+	tr->trns_no = t->t_no;
+	tr->trns_id = t->t_id;
+
+	tlen = ntohs(t->h.len) - sizeof(*t);
+	prev = (struct isakmp_data *)NULL;
+	d = (struct isakmp_data *)(t + 1);
+
+	/* default */
+	life_t = IPSECDOI_ATTR_SA_LD_TYPE_DEFAULT;
+	pp->lifetime = IPSECDOI_ATTR_SA_LD_SEC_DEFAULT;
+	pp->lifebyte = 0;
+	tr->authtype = IPSECDOI_ATTR_AUTH_NONE;
+
+	while (tlen > 0) {
+
+		type = ntohs(d->type) & ~ISAKMP_GEN_MASK;
+		flag = ntohs(d->type) & ISAKMP_GEN_MASK;
+
+		plog(LLV_DEBUG, LOCATION, NULL,
+			"type=%s, flag=0x%04x, lorv=%s\n",
+			s_ipsecdoi_attr(type), flag,
+			s_ipsecdoi_attr_v(type, ntohs(d->lorv)));
+
+		switch (type) {
+		case IPSECDOI_ATTR_SA_LD_TYPE:
+		{
+			int type = ntohs(d->lorv);
+			switch (type) {
+			case IPSECDOI_ATTR_SA_LD_TYPE_SEC:
+			case IPSECDOI_ATTR_SA_LD_TYPE_KB:
+				life_t = type;
+				break;
+			default:
+				plog(LLV_WARNING, LOCATION, NULL,
+					"invalid life duration type. "
+					"use default\n");
+				life_t = IPSECDOI_ATTR_SA_LD_TYPE_DEFAULT;
+				break;
+			}
+			break;
+		}
+		case IPSECDOI_ATTR_SA_LD:
+			if (prev == NULL
+			 || (ntohs(prev->type) & ~ISAKMP_GEN_MASK) !=
+					IPSECDOI_ATTR_SA_LD_TYPE) {
+				plog(LLV_ERROR, LOCATION, NULL,
+				    "life duration must follow ltype\n");
+				break;
+			}
+
+		    {
+			u_int32_t t;
+			vchar_t *ld_buf = NULL;
+
+			if (flag) {
+				/* i.e. ISAKMP_GEN_TV */
+				ld_buf = vmalloc(sizeof(d->lorv));
+				if (ld_buf == NULL) {
+					plog(LLV_ERROR, LOCATION, NULL,
+					    "failed to get LD buffer.\n");
+					goto end;
+				}
+				memcpy(ld_buf->v, &d->lorv, sizeof(d->lorv));
+			} else {
+				int len = ntohs(d->lorv);
+				/* i.e. ISAKMP_GEN_TLV */
+				ld_buf = vmalloc(len);
+				if (ld_buf == NULL) {
+					plog(LLV_ERROR, LOCATION, NULL,
+					    "failed to get LD buffer.\n");
+					goto end;
+				}
+				memcpy(ld_buf->v, d + 1, len);
+			}
+			switch (life_t) {
+			case IPSECDOI_ATTR_SA_LD_TYPE_SEC:
+				t = ipsecdoi_set_ld(ld_buf);
+				vfree(ld_buf);
+				if (t == 0) {
+					plog(LLV_ERROR, LOCATION, NULL,
+						"invalid life duration.\n");
+					goto end;
+				}
+				/* lifetime must be equal in a proposal. */
+				if (pp->lifetime == IPSECDOI_ATTR_SA_LD_SEC_DEFAULT)
+					pp->lifetime = t;
+				else if (pp->lifetime != t) {
+					plog(LLV_ERROR, LOCATION, NULL,
+						"lifetime mismatched "
+						"in a proposal, "
+						"prev:%ld curr:%u.\n",
+						(long)pp->lifetime, t);
+					goto end;
+				}
+				break;
+			case IPSECDOI_ATTR_SA_LD_TYPE_KB:
+				t = ipsecdoi_set_ld(ld_buf);
+				vfree(ld_buf);
+				if (t == 0) {
+					plog(LLV_ERROR, LOCATION, NULL,
+						"invalid life duration.\n");
+					goto end;
+				}
+				/* lifebyte must be equal in a proposal. */
+				if (pp->lifebyte == 0)
+					pp->lifebyte = t;
+				else if (pp->lifebyte != t) {
+					plog(LLV_ERROR, LOCATION, NULL,
+						"lifebyte mismatched "
+						"in a proposal, "
+						"prev:%d curr:%u.\n",
+						pp->lifebyte, t);
+					goto end;
+				}
+				break;
+			default:
+				vfree(ld_buf);
+				plog(LLV_ERROR, LOCATION, NULL,
+					"invalid life type: %d\n", life_t);
+				goto end;
+			}
+		    }
+			break;
+
+		case IPSECDOI_ATTR_GRP_DESC:
+			/*
+			 * RFC2407: 4.5 IPSEC Security Association Attributes
+			 *   Specifies the Oakley Group to be used in a PFS QM
+			 *   negotiation.  For a list of supported values, see
+			 *   Appendix A of [IKE].
+			 */
+			if (pp->pfs_group == 0)
+				pp->pfs_group = (u_int16_t)ntohs(d->lorv);
+			else if (pp->pfs_group != (u_int16_t)ntohs(d->lorv)) {
+				plog(LLV_ERROR, LOCATION, NULL,
+					"pfs_group mismatched "
+					"in a proposal.\n");
+				goto end;
+			}
+			break;
+
+		case IPSECDOI_ATTR_ENC_MODE:
+			if (pr->encmode &&
+			    pr->encmode != (u_int16_t)ntohs(d->lorv)) {
+				plog(LLV_ERROR, LOCATION, NULL,
+					"multiple encmode exist "
+					"in a transform.\n");
+				goto end;
+			}
+			pr->encmode = (u_int16_t)ntohs(d->lorv);
+			break;
+
+		case IPSECDOI_ATTR_AUTH:
+			if (tr->authtype != IPSECDOI_ATTR_AUTH_NONE) {
+				plog(LLV_ERROR, LOCATION, NULL,
+					"multiple authtype exist "
+					"in a transform.\n");
+				goto end;
+			}
+			tr->authtype = (u_int16_t)ntohs(d->lorv);
+			break;
+
+		case IPSECDOI_ATTR_KEY_LENGTH:
+			if (pr->proto_id != IPSECDOI_PROTO_IPSEC_ESP) {
+				plog(LLV_ERROR, LOCATION, NULL,
+					"key length defined but not ESP");
+				goto end;
+			}
+			tr->encklen = ntohs(d->lorv);
+			break;
+#ifdef HAVE_SECCTX
+		case IPSECDOI_ATTR_SECCTX:
+		{
+			int len = ntohs(d->lorv);
+			memcpy(&pp->sctx, d + 1, len);
+			pp->sctx.ctx_strlen = ntohs(pp->sctx.ctx_strlen);
+			break;
+		}
+#endif /* HAVE_SECCTX */
+		case IPSECDOI_ATTR_KEY_ROUNDS:
+		case IPSECDOI_ATTR_COMP_DICT_SIZE:
+		case IPSECDOI_ATTR_COMP_PRIVALG:
+		default:
+			break;
+		}
+
+		prev = d;
+		if (flag) {
+			tlen -= sizeof(*d);
+			d = (struct isakmp_data *)((char *)d + sizeof(*d));
+		} else {
+			tlen -= (sizeof(*d) + ntohs(d->lorv));
+			d = (struct isakmp_data *)((caddr_t)d + sizeof(*d) + ntohs(d->lorv));
+		}
+	}
+
+	error = 0;
+end:
+	return error;
+}
+
+int
+ipsecdoi_authalg2trnsid(alg)
+	int alg;
+{
+	switch (alg) {
+        case IPSECDOI_ATTR_AUTH_HMAC_MD5:
+		return IPSECDOI_AH_MD5;
+        case IPSECDOI_ATTR_AUTH_HMAC_SHA1:
+		return IPSECDOI_AH_SHA;
+	case IPSECDOI_ATTR_AUTH_HMAC_SHA2_256:
+		return IPSECDOI_AH_SHA256;
+	case IPSECDOI_ATTR_AUTH_HMAC_SHA2_384:
+		return IPSECDOI_AH_SHA384;
+	case IPSECDOI_ATTR_AUTH_HMAC_SHA2_512:
+		return IPSECDOI_AH_SHA512;
+        case IPSECDOI_ATTR_AUTH_DES_MAC:
+		return IPSECDOI_AH_DES;
+	case IPSECDOI_ATTR_AUTH_KPDK:
+		return IPSECDOI_AH_MD5;	/* XXX */
+	default:
+		plog(LLV_ERROR, LOCATION, NULL,
+			"invalid authentication algorithm:%d\n", alg);
+	}
+	return -1;
+}
+
+#ifdef HAVE_GSSAPI
+struct isakmpsa *
+fixup_initiator_sa(match, received)
+	struct isakmpsa *match, *received;
+{
+	if (received->gssid != NULL)
+		match->gssid = vdup(received->gssid);
+
+	return match;
+}
+#endif
+
+static int rm_idtype2doi[] = {
+	255,				/* IDTYPE_UNDEFINED, 0 */
+	IPSECDOI_ID_FQDN,		/* IDTYPE_FQDN, 1 */
+	IPSECDOI_ID_USER_FQDN,		/* IDTYPE_USERFQDN, 2 */
+	IPSECDOI_ID_KEY_ID,		/* IDTYPE_KEYID, 3 */
+	255,    /*			   IDTYPE_ADDRESS, 4 
+		 * it expands into 4 types by another function. */
+	IPSECDOI_ID_DER_ASN1_DN,	/* IDTYPE_ASN1DN, 5 */
+};
+
+/*
+ * convert idtype to DOI value.
+ * OUT	255  : NG
+ *	other: converted.
+ */
+int
+idtype2doi(idtype)
+	int idtype;
+{
+	if (ARRAYLEN(rm_idtype2doi) > idtype)
+		return rm_idtype2doi[idtype];
+	return 255;
+}
+
+int
+doi2idtype(doi)
+	int doi;
+{
+	switch(doi) {
+	case IPSECDOI_ID_FQDN:
+		return(IDTYPE_FQDN);
+	case IPSECDOI_ID_USER_FQDN:
+		return(IDTYPE_USERFQDN);
+	case IPSECDOI_ID_KEY_ID:
+		return(IDTYPE_KEYID);
+	case IPSECDOI_ID_DER_ASN1_DN:
+		return(IDTYPE_ASN1DN);
+	case IPSECDOI_ID_IPV4_ADDR:
+	case IPSECDOI_ID_IPV4_ADDR_SUBNET:
+	case IPSECDOI_ID_IPV6_ADDR:
+	case IPSECDOI_ID_IPV6_ADDR_SUBNET:
+		return(IDTYPE_ADDRESS);
+	default:
+		plog(LLV_WARNING, LOCATION, NULL,
+			"Inproper idtype:%s in this function.\n",
+			s_ipsecdoi_ident(doi));
+		return(IDTYPE_ADDRESS);	/* XXX */
+	}
+	/*NOTREACHED*/
+}
+
+#ifdef ENABLE_HYBRID
+static int
+switch_authmethod(authmethod)
+	int authmethod;
+{
+	switch(authmethod) {
+	case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_R:
+		authmethod = OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_I;
+		break;
+	case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_R:
+		authmethod = OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_I;
+		break;
+	case OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_R:
+		authmethod = OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_I;
+		break;
+	case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_R:
+		authmethod = OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_I;
+		break;
+	/* Those are not implemented */
+	case OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_R:
+		authmethod = OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_I;
+		break;
+	case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAENC_R:
+		authmethod = OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAENC_I;
+		break;
+	case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAREV_R:
+		authmethod = OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAREV_I;
+		break;
+	default:
+		break;
+	}
+
+	return authmethod;
+}
+#endif
diff --git a/src/racoon/ipsec_doi.h b/src/racoon/ipsec_doi.h
new file mode 100644
index 0000000..21dd93d
--- /dev/null
+++ b/src/racoon/ipsec_doi.h
@@ -0,0 +1,243 @@
+/*	$NetBSD: ipsec_doi.h,v 1.9 2006/12/09 05:52:57 manu Exp $	*/
+
+/* Id: ipsec_doi.h,v 1.15 2006/08/11 16:06:30 vanhu Exp */
+
+/*
+ * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _IPSEC_DOI_H
+#define _IPSEC_DOI_H
+
+/* refered to RFC2407 */
+
+#define IPSEC_DOI 1
+
+/* 4.2 IPSEC Situation Definition */
+#define IPSECDOI_SIT_IDENTITY_ONLY           0x00000001
+#define IPSECDOI_SIT_SECRECY                 0x00000002
+#define IPSECDOI_SIT_INTEGRITY               0x00000004
+
+/* 4.4.1 IPSEC Security Protocol Identifiers */
+  /* 4.4.2 IPSEC ISAKMP Transform Values */
+#define IPSECDOI_PROTO_ISAKMP                        1
+#define   IPSECDOI_KEY_IKE                             1
+
+/* 4.4.1 IPSEC Security Protocol Identifiers */
+#define IPSECDOI_PROTO_IPSEC_AH                      2
+  /* 4.4.3 IPSEC AH Transform Values */
+#define   IPSECDOI_AH_MD5                              2
+#define   IPSECDOI_AH_SHA                              3
+#define   IPSECDOI_AH_DES                              4
+#define   IPSECDOI_AH_SHA256                           5
+#define   IPSECDOI_AH_SHA384                           6
+#define   IPSECDOI_AH_SHA512                           7
+
+/* 4.4.1 IPSEC Security Protocol Identifiers */
+#define IPSECDOI_PROTO_IPSEC_ESP                     3
+  /* 4.4.4 IPSEC ESP Transform Identifiers */
+#define   IPSECDOI_ESP_DES_IV64				1
+#define   IPSECDOI_ESP_DES				2
+#define   IPSECDOI_ESP_3DES				3
+#define   IPSECDOI_ESP_RC5				4
+#define   IPSECDOI_ESP_IDEA				5
+#define   IPSECDOI_ESP_CAST				6
+#define   IPSECDOI_ESP_BLOWFISH				7
+#define   IPSECDOI_ESP_3IDEA				8
+#define   IPSECDOI_ESP_DES_IV32				9
+#define   IPSECDOI_ESP_RC4				10
+#define   IPSECDOI_ESP_NULL				11
+#define   IPSECDOI_ESP_AES				12
+#define   IPSECDOI_ESP_CAMELLIA				22
+#if 1
+  /* draft-ietf-ipsec-ciph-aes-cbc-00.txt */
+#define   IPSECDOI_ESP_TWOFISH				253
+#else
+  /* SSH uses these value for now */
+#define   IPSECDOI_ESP_TWOFISH				250
+#endif
+
+/* 4.4.1 IPSEC Security Protocol Identifiers */
+#define IPSECDOI_PROTO_IPCOMP                        4
+  /* 4.4.5 IPSEC IPCOMP Transform Identifiers */
+#define   IPSECDOI_IPCOMP_OUI				1
+#define   IPSECDOI_IPCOMP_DEFLATE			2
+#define   IPSECDOI_IPCOMP_LZS				3
+
+/* 4.5 IPSEC Security Association Attributes */
+/* NOTE: default value is not included in a packet. */
+#define IPSECDOI_ATTR_SA_LD_TYPE              1 /* B */
+#define   IPSECDOI_ATTR_SA_LD_TYPE_DEFAULT      1
+#define   IPSECDOI_ATTR_SA_LD_TYPE_SEC          1
+#define   IPSECDOI_ATTR_SA_LD_TYPE_KB           2
+#define   IPSECDOI_ATTR_SA_LD_TYPE_MAX          3
+#define IPSECDOI_ATTR_SA_LD                   2 /* V */
+#define   IPSECDOI_ATTR_SA_LD_SEC_DEFAULT      28800 /* 8 hours */
+#define   IPSECDOI_ATTR_SA_LD_KB_MAX  (~(1 << ((sizeof(int) << 3) - 1)))
+#define IPSECDOI_ATTR_GRP_DESC                3 /* B */
+#define IPSECDOI_ATTR_ENC_MODE                4 /* B */
+	/* default value: host dependent */
+#define   IPSECDOI_ATTR_ENC_MODE_ANY            0	/* NOTE:internal use */
+#define   IPSECDOI_ATTR_ENC_MODE_TUNNEL         1
+#define   IPSECDOI_ATTR_ENC_MODE_TRNS           2
+
+/* NAT-T draft-ietf-ipsec-nat-t-ike-05 and later */
+#define   IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_RFC	3
+#define   IPSECDOI_ATTR_ENC_MODE_UDPTRNS_RFC	4
+
+/* NAT-T up to draft-ietf-ipsec-nat-t-ike-04 */
+#define   IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_DRAFT	61443
+#define   IPSECDOI_ATTR_ENC_MODE_UDPTRNS_DRAFT		61444
+
+#define IPSECDOI_ATTR_AUTH                    5 /* B */
+	/* 0 means not to use authentication. */
+#define   IPSECDOI_ATTR_AUTH_HMAC_MD5           1
+#define   IPSECDOI_ATTR_AUTH_HMAC_SHA1          2
+#define   IPSECDOI_ATTR_AUTH_DES_MAC            3
+#define   IPSECDOI_ATTR_AUTH_KPDK               4 /*RFC-1826(Key/Pad/Data/Key)*/
+#define   IPSECDOI_ATTR_AUTH_HMAC_SHA2_256      5
+#define   IPSECDOI_ATTR_AUTH_HMAC_SHA2_384      6
+#define   IPSECDOI_ATTR_AUTH_HMAC_SHA2_512      7
+#define   IPSECDOI_ATTR_AUTH_NONE               254	/* NOTE:internal use */
+	/*
+	 * When negotiating ESP without authentication, the Auth
+	 * Algorithm attribute MUST NOT be included in the proposal.
+	 * When negotiating ESP without confidentiality, the Auth
+	 * Algorithm attribute MUST be included in the proposal and
+	 * the ESP transform ID must be ESP_NULL.
+	*/
+#define IPSECDOI_ATTR_KEY_LENGTH              6 /* B */
+#define IPSECDOI_ATTR_KEY_ROUNDS              7 /* B */
+#define IPSECDOI_ATTR_COMP_DICT_SIZE          8 /* B */
+#define IPSECDOI_ATTR_COMP_PRIVALG            9 /* V */
+
+#ifdef HAVE_SECCTX
+#define IPSECDOI_ATTR_SECCTX		     10 /* V */
+#endif
+
+/* 4.6.1 Security Association Payload */
+struct ipsecdoi_pl_sa {
+	struct isakmp_gen h;
+	struct ipsecdoi_sa_b {
+		u_int32_t doi; /* Domain of Interpretation */
+		u_int32_t sit; /* Situation */
+	} b;
+	/* followed by Leveled Domain Identifier and so on. */
+} __attribute__((__packed__));
+
+struct ipsecdoi_secrecy_h {
+	u_int16_t len;
+	u_int16_t reserved;
+	/* followed by the value */
+} __attribute__((__packed__));
+
+/* 4.6.2 Identification Payload Content */
+struct ipsecdoi_pl_id {
+	struct isakmp_gen h;
+	struct ipsecdoi_id_b {
+		u_int8_t type;		/* ID Type */
+		u_int8_t proto_id;	/* Protocol ID */
+		u_int16_t port;		/* Port */
+	} b;
+	/* followed by Identification Data */
+} __attribute__((__packed__));
+
+#define IPSECDOI_ID_IPV4_ADDR                        1
+#define IPSECDOI_ID_FQDN                             2
+#define IPSECDOI_ID_USER_FQDN                        3
+#define IPSECDOI_ID_IPV4_ADDR_SUBNET                 4
+#define IPSECDOI_ID_IPV6_ADDR                        5
+#define IPSECDOI_ID_IPV6_ADDR_SUBNET                 6
+#define IPSECDOI_ID_IPV4_ADDR_RANGE                  7
+#define IPSECDOI_ID_IPV6_ADDR_RANGE                  8
+#define IPSECDOI_ID_DER_ASN1_DN                      9
+#define IPSECDOI_ID_DER_ASN1_GN                      10
+#define IPSECDOI_ID_KEY_ID                           11
+
+/* compressing doi type, it's internal use. */
+#define IDTYPE_UNDEFINED	0
+#define IDTYPE_FQDN		1
+#define IDTYPE_USERFQDN		2
+#define IDTYPE_KEYID		3
+#define IDTYPE_ADDRESS		4
+#define IDTYPE_ASN1DN		5
+#define IDTYPE_SUBNET		6
+
+/* qualifiers for KEYID (and maybe others) */
+#define IDQUAL_UNSPEC		0
+#define IDQUAL_FILE		1
+#define IDQUAL_TAG		2
+
+/* The use for checking proposal payload. This is not exchange type. */
+#define IPSECDOI_TYPE_PH1	0
+#define IPSECDOI_TYPE_PH2	1
+
+struct isakmpsa;
+struct ipsecdoi_pl_sa;
+struct saprop;
+struct saproto;
+struct satrns;
+struct prop_pair;
+
+extern int ipsecdoi_checkph1proposal __P((vchar_t *, struct ph1handle *));
+extern int ipsecdoi_selectph2proposal __P((struct ph2handle *));
+extern int ipsecdoi_checkph2proposal __P((struct ph2handle *));
+
+extern struct prop_pair **get_proppair __P((vchar_t *, int));
+extern vchar_t *get_sabyproppair __P((struct prop_pair *, struct ph1handle *));
+extern int ipsecdoi_updatespi __P((struct ph2handle *iph2));
+extern vchar_t *get_sabysaprop __P((struct saprop *, vchar_t *));
+extern int ipsecdoi_chkcmpids( const vchar_t *, const vchar_t *, int );
+extern int ipsecdoi_checkid1 __P((struct ph1handle *));
+extern int ipsecdoi_setid1 __P((struct ph1handle *));
+extern int set_identifier __P((vchar_t **, int, vchar_t *));
+extern int set_identifier_qual __P((vchar_t **, int, vchar_t *, int));
+extern int ipsecdoi_setid2 __P((struct ph2handle *));
+extern vchar_t *ipsecdoi_sockaddr2id __P((struct sockaddr *, u_int, u_int));
+extern int ipsecdoi_id2sockaddr __P((vchar_t *, struct sockaddr *,
+	u_int8_t *, u_int16_t *));
+extern char *ipsecdoi_id2str __P((const vchar_t *));
+extern vchar_t *ipsecdoi_sockrange2id __P((	struct sockaddr *,
+	struct sockaddr *, u_int));
+
+extern vchar_t *ipsecdoi_setph1proposal __P((struct isakmpsa *));
+extern int ipsecdoi_setph2proposal __P((struct ph2handle *));
+extern int ipsecdoi_transportmode __P((struct saprop *));
+extern int ipsecdoi_get_defaultlifetime __P((void));
+extern int ipsecdoi_checkalgtypes __P((int, int, int, int));
+extern int ipproto2doi __P((int));
+extern int doi2ipproto __P((int));
+
+extern int ipsecdoi_t2satrns __P((struct isakmp_pl_t *,
+	struct saprop *, struct saproto *, struct satrns *));
+extern int ipsecdoi_authalg2trnsid __P((int));
+extern int idtype2doi __P((int));
+extern int doi2idtype __P((int));
+
+
+#endif /* _IPSEC_DOI_H */
diff --git a/src/racoon/isakmp.c b/src/racoon/isakmp.c
new file mode 100644
index 0000000..319cf61
--- /dev/null
+++ b/src/racoon/isakmp.c
@@ -0,0 +1,3624 @@
+/*	$NetBSD: isakmp.c,v 1.20.6.11 2008/07/11 08:08:41 tteras Exp $	*/
+
+/* Id: isakmp.c,v 1.74 2006/05/07 21:32:59 manubsd Exp */
+
+/*
+ * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <sys/queue.h>
+
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include PATH_IPSEC_H
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#if TIME_WITH_SYS_TIME
+# include <sys/time.h>
+# include <time.h>
+#else
+# if HAVE_SYS_TIME_H
+#  include <sys/time.h>
+# else
+#  include <time.h>
+# endif
+#endif
+#include <netdb.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <ctype.h>
+#ifdef ENABLE_HYBRID
+#include <resolv.h>
+#endif
+
+#include "var.h"
+#include "misc.h"
+#include "vmbuf.h"
+#include "plog.h"
+#include "sockmisc.h"
+#include "schedule.h"
+#include "debug.h"
+
+#include "remoteconf.h"
+#include "localconf.h"
+#include "grabmyaddr.h"
+#include "admin.h"
+#include "privsep.h"
+#include "isakmp_var.h"
+#include "isakmp.h"
+#include "oakley.h"
+#include "evt.h"
+#include "handler.h"
+#include "ipsec_doi.h"
+#include "pfkey.h"
+#include "crypto_openssl.h"
+#include "policy.h"
+#include "isakmp_ident.h"
+#include "isakmp_agg.h"
+#include "isakmp_base.h"
+#include "isakmp_quick.h"
+#include "isakmp_inf.h"
+#include "isakmp_newg.h"
+#ifdef ENABLE_HYBRID
+#include "vendorid.h"
+#include "isakmp_xauth.h"
+#include "isakmp_unity.h"
+#include "isakmp_cfg.h"
+#endif
+#ifdef ENABLE_FRAG
+#include "isakmp_frag.h"
+#endif
+#include "strnames.h"
+
+#include <fcntl.h>
+
+#ifdef ENABLE_NATT
+# include "nattraversal.h"
+#endif
+# ifdef __linux__
+#  include <linux/udp.h>
+#  include <linux/ip.h>
+#  ifndef SOL_UDP
+#   define SOL_UDP 17
+#  endif
+# endif /* __linux__ */
+# if defined(__NetBSD__) || defined(__FreeBSD__) ||	\
+  (defined(__APPLE__) && defined(__MACH__))
+#  include <netinet/in.h>
+#  include <netinet/udp.h>
+#  include <netinet/in_systm.h>
+#  include <netinet/ip.h>
+#  define SOL_UDP IPPROTO_UDP
+# endif /* __NetBSD__ / __FreeBSD__ */
+
+static int nostate1 __P((struct ph1handle *, vchar_t *));
+static int nostate2 __P((struct ph2handle *, vchar_t *));
+
+extern caddr_t val2str(const char *, size_t);
+
+static int (*ph1exchange[][2][PHASE1ST_MAX])
+	__P((struct ph1handle *, vchar_t *)) = {
+ /* error */
+ { {}, {}, },
+ /* Identity Protection exchange */
+ {
+  { nostate1, ident_i1send, nostate1, ident_i2recv, ident_i2send,
+    ident_i3recv, ident_i3send, ident_i4recv, ident_i4send, nostate1, },
+  { nostate1, ident_r1recv, ident_r1send, ident_r2recv, ident_r2send,
+    ident_r3recv, ident_r3send, nostate1, nostate1, nostate1, },
+ },
+ /* Aggressive exchange */
+ {
+  { nostate1, agg_i1send, nostate1, agg_i2recv, agg_i2send,
+    nostate1, nostate1, nostate1, nostate1, nostate1, },
+  { nostate1, agg_r1recv, agg_r1send, agg_r2recv, agg_r2send,
+    nostate1, nostate1, nostate1, nostate1, nostate1, },
+ },
+ /* Base exchange */
+ {
+  { nostate1, base_i1send, nostate1, base_i2recv, base_i2send,
+    base_i3recv, base_i3send, nostate1, nostate1, nostate1, },
+  { nostate1, base_r1recv, base_r1send, base_r2recv, base_r2send,
+    nostate1, nostate1, nostate1, nostate1, nostate1, },
+ },
+};
+
+static int (*ph2exchange[][2][PHASE2ST_MAX])
+	__P((struct ph2handle *, vchar_t *)) = {
+ /* error */
+ { {}, {}, },
+ /* Quick mode for IKE */
+ {
+  { nostate2, nostate2, quick_i1prep, nostate2, quick_i1send,
+    quick_i2recv, quick_i2send, quick_i3recv, nostate2, nostate2, },
+  { nostate2, quick_r1recv, quick_r1prep, nostate2, quick_r2send,
+    quick_r3recv, quick_r3prep, quick_r3send, nostate2, nostate2, }
+ },
+};
+
+static u_char r_ck0[] = { 0,0,0,0,0,0,0,0 }; /* used to verify the r_ck. */
+ 
+static int isakmp_main __P((vchar_t *, struct sockaddr *, struct sockaddr *));
+static int ph1_main __P((struct ph1handle *, vchar_t *));
+static int quick_main __P((struct ph2handle *, vchar_t *));
+static int isakmp_ph1begin_r __P((vchar_t *,
+	struct sockaddr *, struct sockaddr *, u_int8_t));
+static int isakmp_ph2begin_i __P((struct ph1handle *, struct ph2handle *));
+static int isakmp_ph2begin_r __P((struct ph1handle *, vchar_t *));
+static int etypesw1 __P((int));
+static int etypesw2 __P((int));
+#ifdef ENABLE_FRAG
+static int frag_handler(struct ph1handle *, 
+    vchar_t *, struct sockaddr *, struct sockaddr *);
+#endif
+
+/*
+ * isakmp packet handler
+ */
+int
+isakmp_handler(so_isakmp)
+	int so_isakmp;
+{
+	struct isakmp isakmp;
+	union {
+		char		buf[sizeof (isakmp) + 4];
+		u_int32_t	non_esp[2];
+		char		lbuf[sizeof(struct udphdr) + 
+#ifdef ANDROID_CHANGES
+#define __linux
+#endif
+#ifdef __linux
+				     sizeof(struct iphdr) + 
+#else
+				     sizeof(struct ip) + 
+#endif
+				     sizeof(isakmp) + 4];
+	} x;
+	struct sockaddr_storage remote;
+	struct sockaddr_storage local;
+	unsigned int remote_len = sizeof(remote);
+	unsigned int local_len = sizeof(local);
+	int len = 0, extralen = 0;
+	vchar_t *buf = NULL, *tmpbuf = NULL;
+	int error = -1;
+
+	/* read message by MSG_PEEK */
+	while ((len = recvfromto(so_isakmp, x.buf, sizeof(x),
+		    MSG_PEEK, (struct sockaddr *)&remote, &remote_len,
+		    (struct sockaddr *)&local, &local_len)) < 0) {
+		if (errno == EINTR)
+			continue;
+		plog(LLV_ERROR, LOCATION, NULL,
+			"failed to receive isakmp packet: %s\n",
+			strerror (errno));
+		goto end;
+	}
+
+	/* keep-alive packet - ignore */
+	if (len == 1 && (x.buf[0]&0xff) == 0xff) {
+		/* Pull the keep-alive packet */
+		if ((len = recvfrom(so_isakmp, (char *)x.buf, 1,
+		    0, (struct sockaddr *)&remote, &remote_len)) != 1) {
+			plog(LLV_ERROR, LOCATION, NULL,
+			    "failed to receive keep alive packet: %s\n",
+			    strerror (errno));
+		}
+		goto end;
+	}
+
+	/* Lucent IKE in UDP encapsulation */
+	{
+		struct udphdr *udp;
+#ifdef __linux__
+		struct iphdr *ip;
+
+		udp = (struct udphdr *)&x.lbuf[0];
+		if (ntohs(udp->dest) == 501) {
+			ip = (struct iphdr *)(x.lbuf + sizeof(*udp));
+			extralen += sizeof(*udp) + ip->ihl;
+		}
+#else
+		struct ip *ip;
+
+		udp = (struct udphdr *)&x.lbuf[0];
+		if (ntohs(udp->uh_dport) == 501) {
+			ip = (struct ip *)(x.lbuf + sizeof(*udp));
+			extralen += sizeof(*udp) + ip->ip_hl;
+		}
+#endif
+	}	
+
+#ifdef ENABLE_NATT
+	/* we don't know about portchange yet, 
+	   look for non-esp marker instead */
+	if (x.non_esp[0] == 0 && x.non_esp[1] != 0)
+		extralen = NON_ESP_MARKER_LEN;
+#endif
+
+	/* now we know if there is an extra non-esp 
+	   marker at the beginning or not */
+	memcpy ((char *)&isakmp, x.buf + extralen, sizeof (isakmp));
+
+	/* check isakmp header length, as well as sanity of header length */
+	if (len < sizeof(isakmp) || ntohl(isakmp.len) < sizeof(isakmp)) {
+		plog(LLV_ERROR, LOCATION, (struct sockaddr *)&remote,
+			"packet shorter than isakmp header size (%u, %u, %zu)\n",
+			len, ntohl(isakmp.len), sizeof(isakmp));
+		/* dummy receive */
+		if ((len = recvfrom(so_isakmp, (char *)&isakmp, sizeof(isakmp),
+			    0, (struct sockaddr *)&remote, &remote_len)) < 0) {
+			plog(LLV_ERROR, LOCATION, NULL,
+				"failed to receive isakmp packet: %s\n",
+				strerror (errno));
+		}
+		goto end;
+	}
+
+	/* reject it if the size is tooooo big. */
+	if (ntohl(isakmp.len) > 0xffff) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"the length in the isakmp header is too big.\n");
+		if ((len = recvfrom(so_isakmp, (char *)&isakmp, sizeof(isakmp),
+			    0, (struct sockaddr *)&remote, &remote_len)) < 0) {
+			plog(LLV_ERROR, LOCATION, NULL,
+				"failed to receive isakmp packet: %s\n",
+				strerror (errno));
+		}
+		goto end;
+	}
+
+	/* read real message */
+	if ((tmpbuf = vmalloc(ntohl(isakmp.len) + extralen)) == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"failed to allocate reading buffer (%u Bytes)\n",
+			ntohl(isakmp.len) + extralen);
+		/* dummy receive */
+		if ((len = recvfrom(so_isakmp, (char *)&isakmp, sizeof(isakmp),
+			    0, (struct sockaddr *)&remote, &remote_len)) < 0) {
+			plog(LLV_ERROR, LOCATION, NULL,
+				"failed to receive isakmp packet: %s\n", 
+				strerror (errno));
+		}
+		goto end;
+	}
+
+	while ((len = recvfromto(so_isakmp, (char *)tmpbuf->v, tmpbuf->l,
+	                    0, (struct sockaddr *)&remote, &remote_len,
+	                    (struct sockaddr *)&local, &local_len)) < 0) {
+		if (errno == EINTR)
+			continue;
+		plog(LLV_ERROR, LOCATION, NULL,
+			"failed to receive isakmp packet: %s\n",
+			strerror (errno));
+		goto end;
+	}
+
+	if ((buf = vmalloc(len - extralen)) == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"failed to allocate reading buffer (%u Bytes)\n",
+			(len - extralen));
+		goto end;
+	}
+	
+	memcpy (buf->v, tmpbuf->v + extralen, buf->l);
+
+	len -= extralen;
+	
+	if (len != buf->l) {
+		plog(LLV_ERROR, LOCATION, (struct sockaddr *)&remote,
+			"received invalid length (%d != %zu), why ?\n",
+			len, buf->l);
+		goto end;
+	}
+
+	plog(LLV_DEBUG, LOCATION, NULL, "===\n");
+	plog(LLV_DEBUG, LOCATION, NULL,
+		"%d bytes message received %s\n",
+		len, saddr2str_fromto("from %s to %s", 
+			(struct sockaddr *)&remote,
+			(struct sockaddr *)&local));
+	plogdump(LLV_DEBUG, buf->v, buf->l);
+
+	/* avoid packets with malicious port/address */
+	if (extract_port((struct sockaddr *)&remote) == 0) {
+		plog(LLV_ERROR, LOCATION, (struct sockaddr *)&remote,
+			"src port == 0 (valid as UDP but not with IKE)\n");
+		goto end;
+	}
+
+	/* XXX: check sender whether to be allowed or not to accept */
+
+	/* XXX: I don't know how to check isakmp half connection attack. */
+
+	/* simply reply if the packet was processed. */
+	if (check_recvdpkt((struct sockaddr *)&remote,
+			(struct sockaddr *)&local, buf)) {
+		plog(LLV_NOTIFY, LOCATION, NULL,
+			"the packet is retransmitted by %s.\n",
+			saddr2str((struct sockaddr *)&remote));
+		error = 0;
+		goto end;
+	}
+
+	/* isakmp main routine */
+	if (isakmp_main(buf, (struct sockaddr *)&remote,
+			(struct sockaddr *)&local) != 0) goto end;
+
+	error = 0;
+
+end:
+	if (tmpbuf != NULL)
+		vfree(tmpbuf);
+	if (buf != NULL)
+		vfree(buf);
+
+	return(error);
+}
+
+/*
+ * main processing to handle isakmp payload
+ */
+static int
+isakmp_main(msg, remote, local)
+	vchar_t *msg;
+	struct sockaddr *remote, *local;
+{
+	struct isakmp *isakmp = (struct isakmp *)msg->v;
+	isakmp_index *index = (isakmp_index *)isakmp;
+	u_int32_t msgid = isakmp->msgid;
+	struct ph1handle *iph1;
+
+#ifdef HAVE_PRINT_ISAKMP_C
+	isakmp_printpacket(msg, remote, local, 0);
+#endif
+
+	/* the initiator's cookie must not be zero */
+	if (memcmp(&isakmp->i_ck, r_ck0, sizeof(cookie_t)) == 0) {
+		plog(LLV_ERROR, LOCATION, remote,
+			"malformed cookie received.\n");
+		return -1;
+	}
+
+	/* Check the Major and Minor Version fields. */
+	/*
+	 * XXX Is is right to check version here ?
+	 * I think it may no be here because the version depends
+	 * on exchange status.
+	 */
+	if (isakmp->v < ISAKMP_VERSION_NUMBER) {
+		if (ISAKMP_GETMAJORV(isakmp->v) < ISAKMP_MAJOR_VERSION) {
+			plog(LLV_ERROR, LOCATION, remote,
+				"invalid major version %d.\n",
+				ISAKMP_GETMAJORV(isakmp->v));
+			return -1;
+		}
+#if ISAKMP_MINOR_VERSION > 0
+		if (ISAKMP_GETMINORV(isakmp->v) < ISAKMP_MINOR_VERSION) {
+			plog(LLV_ERROR, LOCATION, remote,
+				"invalid minor version %d.\n",
+				ISAKMP_GETMINORV(isakmp->v));
+			return -1;
+		}
+#endif
+	}
+
+	/* check the Flags field. */
+	/* XXX How is the exclusive check, E and A ? */
+	if (isakmp->flags & ~(ISAKMP_FLAG_E | ISAKMP_FLAG_C | ISAKMP_FLAG_A)) {
+		plog(LLV_ERROR, LOCATION, remote,
+			"invalid flag 0x%02x.\n", isakmp->flags);
+		return -1;
+	}
+
+	/* ignore commit bit. */
+	if (ISSET(isakmp->flags, ISAKMP_FLAG_C)) {
+		if (isakmp->msgid == 0) {
+			isakmp_info_send_nx(isakmp, remote, local,
+				ISAKMP_NTYPE_INVALID_FLAGS, NULL);
+			plog(LLV_ERROR, LOCATION, remote,
+				"Commit bit on phase1 forbidden.\n");
+			return -1;
+		}
+	}
+
+	iph1 = getph1byindex(index);
+	if (iph1 != NULL) {
+		/* validity check */
+		if (memcmp(&isakmp->r_ck, r_ck0, sizeof(cookie_t)) == 0 &&
+		    iph1->side == INITIATOR) {
+			plog(LLV_DEBUG, LOCATION, remote,
+				"malformed cookie received or "
+				"the initiator's cookies collide.\n");
+			return -1;
+		}
+
+#ifdef ENABLE_NATT
+		/* Floating ports for NAT-T */
+		if (NATT_AVAILABLE(iph1) &&
+		    ! (iph1->natt_flags & NAT_PORTS_CHANGED) &&
+		    ((cmpsaddrstrict(iph1->remote, remote) != 0) ||
+		    (cmpsaddrstrict(iph1->local, local) != 0)))
+		{
+			/* prevent memory leak */
+			racoon_free(iph1->remote);
+			racoon_free(iph1->local);
+			iph1->remote = NULL;
+			iph1->local = NULL;
+
+			/* copy-in new addresses */
+			iph1->remote = dupsaddr(remote);
+			if (iph1->remote == NULL) {
+           			plog(LLV_ERROR, LOCATION, iph1->remote,
+				   "phase1 failed: dupsaddr failed.\n");
+				remph1(iph1);
+				delph1(iph1);
+				return -1;
+			}
+			iph1->local = dupsaddr(local);
+			if (iph1->local == NULL) {
+           			plog(LLV_ERROR, LOCATION, iph1->remote,
+				   "phase1 failed: dupsaddr failed.\n");
+				remph1(iph1);
+				delph1(iph1);
+				return -1;
+			}
+
+			/* set the flag to prevent further port floating
+			   (FIXME: should we allow it? E.g. when the NAT gw 
+			    is rebooted?) */
+			iph1->natt_flags |= NAT_PORTS_CHANGED | NAT_ADD_NON_ESP_MARKER;
+			
+			/* print some neat info */
+			plog (LLV_INFO, LOCATION, NULL, 
+			      "NAT-T: ports changed to: %s\n",
+			      saddr2str_fromto ("%s<->%s", iph1->remote, iph1->local));
+
+			natt_keepalive_add_ph1 (iph1);
+		}
+#endif
+
+		/* must be same addresses in one stream of a phase at least. */
+		if (cmpsaddrstrict(iph1->remote, remote) != 0) {
+			char *saddr_db, *saddr_act;
+
+			saddr_db = racoon_strdup(saddr2str(iph1->remote));
+			saddr_act = racoon_strdup(saddr2str(remote));
+			STRDUP_FATAL(saddr_db);
+			STRDUP_FATAL(saddr_act);
+
+			plog(LLV_WARNING, LOCATION, remote,
+				"remote address mismatched. db=%s, act=%s\n",
+				saddr_db, saddr_act);
+
+			racoon_free(saddr_db);
+			racoon_free(saddr_act);
+		}
+
+		/*
+		 * don't check of exchange type here because other type will be
+		 * with same index, for example, informational exchange.
+		 */
+
+		/* XXX more acceptable check */
+	}
+
+	switch (isakmp->etype) {
+	case ISAKMP_ETYPE_IDENT:
+	case ISAKMP_ETYPE_AGG:
+	case ISAKMP_ETYPE_BASE:
+		/* phase 1 validity check */
+		if (isakmp->msgid != 0) {
+			plog(LLV_ERROR, LOCATION, remote,
+				"message id should be zero in phase1.\n");
+			return -1;
+		}
+
+		/* search for isakmp status record of phase 1 */
+		if (iph1 == NULL) {
+			/*
+			 * the packet must be the 1st message from a initiator
+			 * or the 2nd message from the responder.
+			 */
+
+			/* search for phase1 handle by index without r_ck */
+			iph1 = getph1byindex0(index);
+			if (iph1 == NULL) {
+				/*it must be the 1st message from a initiator.*/
+				if (memcmp(&isakmp->r_ck, r_ck0,
+					sizeof(cookie_t)) != 0) {
+
+					plog(LLV_DEBUG, LOCATION, remote,
+						"malformed cookie received "
+						"or the spi expired.\n");
+					return -1;
+				}
+
+				/* it must be responder's 1st exchange. */
+				if (isakmp_ph1begin_r(msg, remote, local,
+					isakmp->etype) < 0)
+					return -1;
+				break;
+
+				/*NOTREACHED*/
+			}
+
+			/* it must be the 2nd message from the responder. */
+			if (iph1->side != INITIATOR) {
+				plog(LLV_DEBUG, LOCATION, remote,
+					"malformed cookie received. "
+					"it has to be as the initiator.  %s\n",
+					isakmp_pindex(&iph1->index, 0));
+				return -1;
+			}
+		}
+
+		/*
+		 * Don't delete phase 1 handler when the exchange type
+		 * in handler is not equal to packet's one because of no
+		 * authencication completed.
+		 */
+		if (iph1->etype != isakmp->etype) {
+			plog(LLV_ERROR, LOCATION, iph1->remote,
+				"exchange type is mismatched: "
+				"db=%s packet=%s, ignore it.\n",
+				s_isakmp_etype(iph1->etype),
+				s_isakmp_etype(isakmp->etype));
+			return -1;
+		}
+
+#ifdef ENABLE_FRAG
+		if (isakmp->np == ISAKMP_NPTYPE_FRAG)
+			return frag_handler(iph1, msg, remote, local);
+#endif
+
+		/* call main process of phase 1 */
+		if (ph1_main(iph1, msg) < 0) {
+			plog(LLV_ERROR, LOCATION, iph1->remote,
+				"phase1 negotiation failed.\n");
+			remph1(iph1);
+			delph1(iph1);
+			return -1;
+		}
+		break;
+
+	case ISAKMP_ETYPE_AUTH:
+		plog(LLV_INFO, LOCATION, remote,
+			"unsupported exchange %d received.\n",
+			isakmp->etype);
+		break;
+
+	case ISAKMP_ETYPE_INFO:
+	case ISAKMP_ETYPE_ACKINFO:
+		/*
+		 * iph1 must be present for Information message.
+		 * if iph1 is null then trying to get the phase1 status
+		 * as the packet from responder againt initiator's 1st
+		 * exchange in phase 1.
+		 * NOTE: We think such informational exchange should be ignored.
+		 */
+		if (iph1 == NULL) {
+			iph1 = getph1byindex0(index);
+			if (iph1 == NULL) {
+				plog(LLV_ERROR, LOCATION, remote,
+					"unknown Informational "
+					"exchange received.\n");
+				return -1;
+			}
+			if (cmpsaddrstrict(iph1->remote, remote) != 0) {
+				plog(LLV_WARNING, LOCATION, remote,
+					"remote address mismatched. "
+					"db=%s\n",
+					saddr2str(iph1->remote));
+			}
+		}
+
+#ifdef ENABLE_FRAG
+		if (isakmp->np == ISAKMP_NPTYPE_FRAG)
+			return frag_handler(iph1, msg, remote, local);
+#endif
+
+		if (isakmp_info_recv(iph1, msg) < 0)
+			return -1;
+		break;
+
+	case ISAKMP_ETYPE_QUICK:
+	{
+		struct ph2handle *iph2;
+
+		if (iph1 == NULL) {
+			isakmp_info_send_nx(isakmp, remote, local,
+				ISAKMP_NTYPE_INVALID_COOKIE, NULL);
+			plog(LLV_ERROR, LOCATION, remote,
+				"can't start the quick mode, "
+				"there is no ISAKMP-SA, %s\n",
+				isakmp_pindex((isakmp_index *)&isakmp->i_ck,
+					isakmp->msgid));
+			return -1;
+		}
+#ifdef ENABLE_HYBRID
+		/* Reinit the IVM if it's still there */		
+		if (iph1->mode_cfg && iph1->mode_cfg->ivm) {
+			oakley_delivm(iph1->mode_cfg->ivm);
+			iph1->mode_cfg->ivm = NULL;
+		}
+#endif
+#ifdef ENABLE_FRAG
+		if (isakmp->np == ISAKMP_NPTYPE_FRAG)
+			return frag_handler(iph1, msg, remote, local);
+#endif
+
+		/* check status of phase 1 whether negotiated or not. */
+		if (iph1->status != PHASE1ST_ESTABLISHED) {
+			plog(LLV_ERROR, LOCATION, remote,
+				"can't start the quick mode, "
+				"there is no valid ISAKMP-SA, %s\n",
+				isakmp_pindex(&iph1->index, iph1->msgid));
+			return -1;
+		}
+
+		/* search isakmp phase 2 stauts record. */
+		iph2 = getph2bymsgid(iph1, msgid);
+		if (iph2 == NULL) {
+			/* it must be new negotiation as responder */
+			if (isakmp_ph2begin_r(iph1, msg) < 0)
+				return -1;
+			return 0;
+			/*NOTREACHED*/
+		}
+
+		/* commit bit. */
+		/* XXX
+		 * we keep to set commit bit during negotiation.
+		 * When SA is configured, bit will be reset.
+		 * XXX
+		 * don't initiate commit bit.  should be fixed in the future.
+		 */
+		if (ISSET(isakmp->flags, ISAKMP_FLAG_C))
+			iph2->flags |= ISAKMP_FLAG_C;
+
+		/* call main process of quick mode */
+		if (quick_main(iph2, msg) < 0) {
+			plog(LLV_ERROR, LOCATION, iph1->remote,
+				"phase2 negotiation failed.\n");
+			unbindph12(iph2);
+			remph2(iph2);
+			delph2(iph2);
+			return -1;
+		}
+	}
+		break;
+
+	case ISAKMP_ETYPE_NEWGRP:
+		if (iph1 == NULL) {
+			plog(LLV_ERROR, LOCATION, remote,
+				"Unknown new group mode exchange, "
+				"there is no ISAKMP-SA.\n");
+			return -1;
+		}
+
+#ifdef ENABLE_FRAG
+		if (isakmp->np == ISAKMP_NPTYPE_FRAG)
+			return frag_handler(iph1, msg, remote, local);
+#endif
+
+		isakmp_newgroup_r(iph1, msg);
+		break;
+
+#ifdef ENABLE_HYBRID
+	case ISAKMP_ETYPE_CFG:
+		if (iph1 == NULL) {
+			plog(LLV_ERROR, LOCATION, NULL,
+			     "mode config %d from %s, "
+			     "but we have no ISAKMP-SA.\n",
+			     isakmp->etype, saddr2str(remote));
+			return -1;
+		}
+
+#ifdef ENABLE_FRAG
+		if (isakmp->np == ISAKMP_NPTYPE_FRAG)
+			return frag_handler(iph1, msg, remote, local);
+#endif
+
+		isakmp_cfg_r(iph1, msg);
+		break;
+#endif	 
+
+	case ISAKMP_ETYPE_NONE:
+	default:
+		plog(LLV_ERROR, LOCATION, NULL,
+			"Invalid exchange type %d from %s.\n",
+			isakmp->etype, saddr2str(remote));
+		return -1;
+	}
+
+	return 0;
+}
+
+/*
+ * main function of phase 1.
+ */
+static int
+ph1_main(iph1, msg)
+	struct ph1handle *iph1;
+	vchar_t *msg;
+{
+	int error;
+#ifdef ENABLE_STATS
+	struct timeval start, end;
+#endif
+
+	/* ignore a packet */
+	if (iph1->status == PHASE1ST_ESTABLISHED)
+		return 0;
+
+#ifdef ENABLE_STATS
+	gettimeofday(&start, NULL);
+#endif
+	/* receive */
+	if (ph1exchange[etypesw1(iph1->etype)]
+		       [iph1->side]
+		       [iph1->status] == NULL) {
+		plog(LLV_ERROR, LOCATION, iph1->remote,
+			"why isn't the function defined.\n");
+		return -1;
+	}
+	error = (ph1exchange[etypesw1(iph1->etype)]
+			    [iph1->side]
+			    [iph1->status])(iph1, msg);
+	if (error != 0) {
+#if 0
+		/* XXX
+		 * When an invalid packet is received on phase1, it should
+		 * be selected to process this packet.  That is to respond
+		 * with a notify and delete phase 1 handler, OR not to respond
+		 * and keep phase 1 handler.
+		 */
+		plog(LLV_ERROR, LOCATION, iph1->remote,
+			"failed to pre-process packet.\n");
+		return -1;
+#else
+		/* ignore the error and keep phase 1 handler */
+		return 0;
+#endif
+	}
+
+#ifndef ENABLE_FRAG
+	/* free resend buffer */
+	if (iph1->sendbuf == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"no buffer found as sendbuf\n"); 
+		return -1;
+	}
+#endif
+
+	VPTRINIT(iph1->sendbuf);
+
+	/* turn off schedule */
+	SCHED_KILL(iph1->scr);
+
+	/* send */
+	plog(LLV_DEBUG, LOCATION, NULL, "===\n");
+	if ((ph1exchange[etypesw1(iph1->etype)]
+			[iph1->side]
+			[iph1->status])(iph1, msg) != 0) {
+		plog(LLV_ERROR, LOCATION, iph1->remote,
+			"failed to process packet.\n");
+		return -1;
+	}
+
+#ifdef ENABLE_STATS
+	gettimeofday(&end, NULL);
+	syslog(LOG_NOTICE, "%s(%s): %8.6f",
+		"phase1", s_isakmp_state(iph1->etype, iph1->side, iph1->status),
+		timedelta(&start, &end));
+#endif
+	if (iph1->status == PHASE1ST_ESTABLISHED) {
+
+#ifdef ENABLE_STATS
+		gettimeofday(&iph1->end, NULL);
+		syslog(LOG_NOTICE, "%s(%s): %8.6f",
+			"phase1", s_isakmp_etype(iph1->etype),
+			timedelta(&iph1->start, &iph1->end));
+#endif
+
+		/* save created date. */
+		(void)time(&iph1->created);
+
+		/* add to the schedule to expire, and seve back pointer. */
+		iph1->sce = sched_new(iph1->approval->lifetime,
+		    isakmp_ph1expire_stub, iph1);
+#ifdef ENABLE_HYBRID
+		if (iph1->mode_cfg->flags & ISAKMP_CFG_VENDORID_XAUTH) {
+			switch(AUTHMETHOD(iph1)) {
+			case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_R:
+			case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_R:
+			case OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_R:
+			case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_R:
+			case OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_R:
+			case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAENC_R:
+			case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAREV_R:
+				xauth_sendreq(iph1);
+				/* XXX Don't process INITIAL_CONTACT */
+				iph1->rmconf->ini_contact = 0;
+				break;
+			default:
+				break;
+			}
+		}
+#endif
+#ifdef ENABLE_DPD
+		/* Schedule the r_u_there.... */
+		if(iph1->dpd_support && iph1->rmconf->dpd_interval)
+			isakmp_sched_r_u(iph1, 0);
+#endif
+
+		/* INITIAL-CONTACT processing */
+		/* don't anything if local test mode. */
+		if (!f_local
+		 && iph1->rmconf->ini_contact && !getcontacted(iph1->remote)) {
+			/* send INITIAL-CONTACT */
+			isakmp_info_send_n1(iph1,
+					ISAKMP_NTYPE_INITIAL_CONTACT, NULL);
+			/* insert a node into contacted list. */
+			if (inscontacted(iph1->remote) == -1) {
+				plog(LLV_ERROR, LOCATION, iph1->remote,
+					"failed to add contacted list.\n");
+				/* ignore */
+			}
+		}
+
+		log_ph1established(iph1);
+		plog(LLV_DEBUG, LOCATION, NULL, "===\n");
+
+		/* 
+		 * SA up shell script hook: do it now,except if
+		 * ISAKMP mode config was requested. In the later
+		 * case it is done when we receive the configuration.
+		 */
+		if ((iph1->status == PHASE1ST_ESTABLISHED) &&
+		    !iph1->rmconf->mode_cfg) { 
+			switch (AUTHMETHOD(iph1)) {
+#ifdef ENABLE_HYBRID
+			case OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_R:
+			case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_R:
+			case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_R:
+			/* Unimplemeted... */
+			case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_R:
+			case OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_R:
+			case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAENC_R:
+			case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAREV_R:
+				break;
+#endif
+			default:
+				script_hook(iph1, SCRIPT_PHASE1_UP);
+				break;
+			}
+		}
+	}
+
+	return 0;
+}
+
+/*
+ * main function of quick mode.
+ */
+static int
+quick_main(iph2, msg)
+	struct ph2handle *iph2;
+	vchar_t *msg;
+{
+	struct isakmp *isakmp = (struct isakmp *)msg->v;
+	int error;
+#ifdef ENABLE_STATS
+	struct timeval start, end;
+#endif
+
+	/* ignore a packet */
+	if (iph2->status == PHASE2ST_ESTABLISHED
+	 || iph2->status == PHASE2ST_GETSPISENT)
+		return 0;
+
+#ifdef ENABLE_STATS
+	gettimeofday(&start, NULL);
+#endif
+
+	/* receive */
+	if (ph2exchange[etypesw2(isakmp->etype)]
+		       [iph2->side]
+		       [iph2->status] == NULL) {
+		plog(LLV_ERROR, LOCATION, iph2->ph1->remote,
+			"why isn't the function defined.\n");
+		return -1;
+	}
+	error = (ph2exchange[etypesw2(isakmp->etype)]
+			    [iph2->side]
+			    [iph2->status])(iph2, msg);
+	if (error != 0) {
+		plog(LLV_ERROR, LOCATION, iph2->ph1->remote,
+			"failed to pre-process packet.\n");
+		if (error == ISAKMP_INTERNAL_ERROR)
+			return 0;
+		isakmp_info_send_n1(iph2->ph1, error, NULL);
+		return -1;
+	}
+
+	/* when using commit bit, status will be reached here. */
+	if (iph2->status == PHASE2ST_ADDSA)
+		return 0;
+
+	/* free resend buffer */
+	if (iph2->sendbuf == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"no buffer found as sendbuf\n"); 
+		return -1;
+	}
+	VPTRINIT(iph2->sendbuf);
+
+	/* turn off schedule */
+	SCHED_KILL(iph2->scr);
+
+	/* send */
+	plog(LLV_DEBUG, LOCATION, NULL, "===\n");
+	if ((ph2exchange[etypesw2(isakmp->etype)]
+			[iph2->side]
+			[iph2->status])(iph2, msg) != 0) {
+		plog(LLV_ERROR, LOCATION, iph2->ph1->remote,
+			"failed to process packet.\n");
+		return -1;
+	}
+
+#ifdef ENABLE_STATS
+	gettimeofday(&end, NULL);
+	syslog(LOG_NOTICE, "%s(%s): %8.6f",
+		"phase2",
+		s_isakmp_state(ISAKMP_ETYPE_QUICK, iph2->side, iph2->status),
+		timedelta(&start, &end));
+#endif
+
+	return 0;
+}
+
+/* new negotiation of phase 1 for initiator */
+int
+isakmp_ph1begin_i(rmconf, remote, local)
+	struct remoteconf *rmconf;
+	struct sockaddr *remote, *local;
+{
+	struct ph1handle *iph1;
+#ifdef ENABLE_STATS
+	struct timeval start, end;
+#endif
+
+	/* get new entry to isakmp status table. */
+	iph1 = newph1();
+	if (iph1 == NULL)
+		return -1;
+
+	iph1->status = PHASE1ST_START;
+	iph1->rmconf = rmconf;
+	iph1->side = INITIATOR;
+	iph1->version = ISAKMP_VERSION_NUMBER;
+	iph1->msgid = 0;
+	iph1->flags = 0;
+	iph1->ph2cnt = 0;
+#ifdef HAVE_GSSAPI
+	iph1->gssapi_state = NULL;
+#endif
+#ifdef ENABLE_HYBRID
+	if ((iph1->mode_cfg = isakmp_cfg_mkstate()) == NULL) {
+		delph1(iph1);
+		return -1;
+	}
+#endif
+#ifdef ENABLE_FRAG
+
+	if(rmconf->ike_frag == ISAKMP_FRAG_FORCE)
+		iph1->frag = 1;
+	else
+		iph1->frag = 0;
+	iph1->frag_chain = NULL;
+#endif
+	iph1->approval = NULL;
+
+	/* XXX copy remote address */
+	if (copy_ph1addresses(iph1, rmconf, remote, local) < 0) {
+		delph1(iph1);
+		return -1;
+	}
+
+	(void)insph1(iph1);
+
+	/* start phase 1 exchange */
+	iph1->etype = rmconf->etypes->type;
+
+	plog(LLV_DEBUG, LOCATION, NULL, "===\n");
+    {
+	char *a;
+
+	a = racoon_strdup(saddr2str(iph1->local));
+	STRDUP_FATAL(a);
+
+	plog(LLV_INFO, LOCATION, NULL,
+		"initiate new phase 1 negotiation: %s<=>%s\n",
+		a, saddr2str(iph1->remote));
+	racoon_free(a);
+    }
+	plog(LLV_INFO, LOCATION, NULL,
+		"begin %s mode.\n",
+		s_isakmp_etype(iph1->etype));
+
+#ifdef ENABLE_STATS
+	gettimeofday(&iph1->start, NULL);
+	gettimeofday(&start, NULL);
+#endif
+	/* start exchange */
+	if ((ph1exchange[etypesw1(iph1->etype)]
+			[iph1->side]
+			[iph1->status])(iph1, NULL) != 0) {
+		/* failed to start phase 1 negotiation */
+		remph1(iph1);
+		delph1(iph1);
+
+		return -1;
+	}
+
+#ifdef ENABLE_STATS
+	gettimeofday(&end, NULL);
+	syslog(LOG_NOTICE, "%s(%s): %8.6f",
+		"phase1",
+		s_isakmp_state(iph1->etype, iph1->side, iph1->status),
+		timedelta(&start, &end));
+#endif
+
+	return 0;
+}
+
+/* new negotiation of phase 1 for responder */
+static int
+isakmp_ph1begin_r(msg, remote, local, etype)
+	vchar_t *msg;
+	struct sockaddr *remote, *local;
+	u_int8_t etype;
+{
+	struct isakmp *isakmp = (struct isakmp *)msg->v;
+	struct remoteconf *rmconf;
+	struct ph1handle *iph1;
+	struct etypes *etypeok;
+#ifdef ENABLE_STATS
+	struct timeval start, end;
+#endif
+
+	/* look for my configuration */
+	rmconf = getrmconf(remote);
+	if (rmconf == NULL) {
+		plog(LLV_ERROR, LOCATION, remote,
+			"couldn't find "
+			"configuration.\n");
+		return -1;
+	}
+
+	/* check to be acceptable exchange type */
+	etypeok = check_etypeok(rmconf, etype);
+	if (etypeok == NULL) {
+		plog(LLV_ERROR, LOCATION, remote,
+			"not acceptable %s mode\n", s_isakmp_etype(etype));
+		return -1;
+	}
+
+	/* get new entry to isakmp status table. */
+	iph1 = newph1();
+	if (iph1 == NULL)
+		return -1;
+
+	memcpy(&iph1->index.i_ck, &isakmp->i_ck, sizeof(iph1->index.i_ck));
+	iph1->status = PHASE1ST_START;
+	iph1->rmconf = rmconf;
+	iph1->flags = 0;
+	iph1->side = RESPONDER;
+	iph1->etype = etypeok->type;
+	iph1->version = isakmp->v;
+	iph1->msgid = 0;
+#ifdef HAVE_GSSAPI
+	iph1->gssapi_state = NULL;
+#endif
+#ifdef ENABLE_HYBRID
+	if ((iph1->mode_cfg = isakmp_cfg_mkstate()) == NULL) {
+		delph1(iph1);
+		return -1;
+	}
+#endif
+#ifdef ENABLE_FRAG
+	iph1->frag = 0;
+	iph1->frag_chain = NULL;
+#endif
+	iph1->approval = NULL;
+
+#ifdef ENABLE_NATT
+	/* RFC3947 says that we MUST accept new phases1 on NAT-T floated port.
+	 * We have to setup this flag now to correctly generate the first reply.
+	 * Don't know if a better check could be done for that ?
+	 */
+	if(extract_port(local) == lcconf->port_isakmp_natt)
+		iph1->natt_flags |= (NAT_PORTS_CHANGED);
+#endif
+
+	/* copy remote address */
+	if (copy_ph1addresses(iph1, rmconf, remote, local) < 0) {
+		delph1(iph1);
+		return -1;
+	}
+	(void)insph1(iph1);
+
+	plog(LLV_DEBUG, LOCATION, NULL, "===\n");
+    {
+	char *a;
+
+	a = racoon_strdup(saddr2str(iph1->local));
+	STRDUP_FATAL(a);
+
+	plog(LLV_INFO, LOCATION, NULL,
+		"respond new phase 1 negotiation: %s<=>%s\n",
+		a, saddr2str(iph1->remote));
+	racoon_free(a);
+    }
+	plog(LLV_INFO, LOCATION, NULL,
+		"begin %s mode.\n", s_isakmp_etype(etype));
+
+#ifdef ENABLE_STATS
+	gettimeofday(&iph1->start, NULL);
+	gettimeofday(&start, NULL);
+#endif
+
+#ifndef ENABLE_FRAG
+
+	/* start exchange */
+	if ((ph1exchange[etypesw1(iph1->etype)]
+	                [iph1->side]
+	                [iph1->status])(iph1, msg) < 0
+	 || (ph1exchange[etypesw1(iph1->etype)]
+			[iph1->side]
+			[iph1->status])(iph1, msg) < 0) {
+		plog(LLV_ERROR, LOCATION, remote,
+			"failed to process packet.\n");
+		remph1(iph1);
+		delph1(iph1);
+		return -1;
+	}
+
+#ifdef ENABLE_STATS
+	gettimeofday(&end, NULL);
+	syslog(LOG_NOTICE, "%s(%s): %8.6f",
+		"phase1",
+		s_isakmp_state(iph1->etype, iph1->side, iph1->status),
+		timedelta(&start, &end));
+#endif
+
+	return 0;
+
+#else /* ENABLE_FRAG */
+
+	/* now that we have a phase1 handle, feed back into our
+	 * main receive function to catch fragmented packets
+	 */
+
+	return isakmp_main(msg, remote, local);
+
+#endif /* ENABLE_FRAG */
+
+}
+
+/* new negotiation of phase 2 for initiator */
+static int
+isakmp_ph2begin_i(iph1, iph2)
+	struct ph1handle *iph1;
+	struct ph2handle *iph2;
+{
+#ifdef ENABLE_HYBRID
+	if (xauth_check(iph1) != 0) {
+		plog(LLV_ERROR, LOCATION, NULL,
+		    "Attempt to start phase 2 whereas Xauth failed\n");
+		return -1;
+	}
+#endif
+
+	/* found ISAKMP-SA. */
+	plog(LLV_DEBUG, LOCATION, NULL, "===\n");
+	plog(LLV_DEBUG, LOCATION, NULL, "begin QUICK mode.\n");
+    {
+	char *a;
+	a = racoon_strdup(saddr2str(iph2->src));
+	STRDUP_FATAL(a);
+
+	plog(LLV_INFO, LOCATION, NULL,
+		"initiate new phase 2 negotiation: %s<=>%s\n",
+		a, saddr2str(iph2->dst));
+	racoon_free(a);
+    }
+
+#ifdef ENABLE_STATS
+	gettimeofday(&iph2->start, NULL);
+#endif
+	/* found isakmp-sa */
+	bindph12(iph1, iph2);
+	iph2->status = PHASE2ST_STATUS2;
+
+	if ((ph2exchange[etypesw2(ISAKMP_ETYPE_QUICK)]
+			 [iph2->side]
+			 [iph2->status])(iph2, NULL) < 0) {
+		unbindph12(iph2);
+		/* release ipsecsa handler due to internal error. */
+		remph2(iph2);
+		return -1;
+	}
+	return 0;
+}
+
+/* new negotiation of phase 2 for responder */
+static int
+isakmp_ph2begin_r(iph1, msg)
+	struct ph1handle *iph1;
+	vchar_t *msg;
+{
+	struct isakmp *isakmp = (struct isakmp *)msg->v;
+	struct ph2handle *iph2 = 0;
+	int error;
+#ifdef ENABLE_STATS
+	struct timeval start, end;
+#endif
+#ifdef ENABLE_HYBRID
+	if (xauth_check(iph1) != 0) {
+		plog(LLV_ERROR, LOCATION, NULL,
+		    "Attempt to start phase 2 whereas Xauth failed\n");
+		return -1;
+	}
+#endif
+
+	iph2 = newph2();
+	if (iph2 == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"failed to allocate phase2 entry.\n");
+		return -1;
+	}
+
+	iph2->ph1 = iph1;
+	iph2->side = RESPONDER;
+	iph2->status = PHASE2ST_START;
+	iph2->flags = isakmp->flags;
+	iph2->msgid = isakmp->msgid;
+	iph2->seq = pk_getseq();
+	iph2->ivm = oakley_newiv2(iph1, iph2->msgid);
+	if (iph2->ivm == NULL) {
+		delph2(iph2);
+		return -1;
+	}
+	iph2->dst = dupsaddr(iph1->remote);	/* XXX should be considered */
+	if (iph2->dst == NULL) {
+		delph2(iph2);
+		return -1;
+	}
+	iph2->src = dupsaddr(iph1->local);	/* XXX should be considered */
+	if (iph2->src == NULL) {
+		delph2(iph2);
+		return -1;
+	}
+#if (!defined(ENABLE_NATT)) || (defined(BROKEN_NATT))
+	if (set_port(iph2->dst, 0) == NULL ||
+	    set_port(iph2->src, 0) == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL,
+		     "invalid family: %d\n", iph2->dst->sa_family);
+		delph2(iph2);
+		return -1;
+	}
+#endif
+
+	/* add new entry to isakmp status table */
+	insph2(iph2);
+	bindph12(iph1, iph2);
+
+	plog(LLV_DEBUG, LOCATION, NULL, "===\n");
+    {
+	char *a;
+
+	a = racoon_strdup(saddr2str(iph2->src));
+	STRDUP_FATAL(a);
+
+	plog(LLV_INFO, LOCATION, NULL,
+		"respond new phase 2 negotiation: %s<=>%s\n",
+		a, saddr2str(iph2->dst));
+	racoon_free(a);
+    }
+
+#ifdef ENABLE_STATS
+	gettimeofday(&start, NULL);
+#endif
+
+	error = (ph2exchange[etypesw2(ISAKMP_ETYPE_QUICK)]
+	                   [iph2->side]
+	                   [iph2->status])(iph2, msg);
+	if (error != 0) {
+		plog(LLV_ERROR, LOCATION, iph1->remote,
+			"failed to pre-process packet.\n");
+		if (error != ISAKMP_INTERNAL_ERROR)
+			isakmp_info_send_n1(iph2->ph1, error, NULL);
+		/*
+		 * release handler because it's wrong that ph2handle is kept
+		 * after failed to check message for responder's.
+		 */
+		unbindph12(iph2);
+		remph2(iph2);
+		delph2(iph2);
+		return -1;
+	}
+
+	/* send */
+	plog(LLV_DEBUG, LOCATION, NULL, "===\n");
+	if ((ph2exchange[etypesw2(isakmp->etype)]
+			[iph2->side]
+			[iph2->status])(iph2, msg) < 0) {
+		plog(LLV_ERROR, LOCATION, iph2->ph1->remote,
+			"failed to process packet.\n");
+		/* don't release handler */
+		return -1;
+	}
+#ifdef ENABLE_STATS
+	gettimeofday(&end, NULL);
+	syslog(LOG_NOTICE, "%s(%s): %8.6f",
+		"phase2",
+		s_isakmp_state(ISAKMP_ETYPE_QUICK, iph2->side, iph2->status),
+		timedelta(&start, &end));
+#endif
+
+	return 0;
+}
+
+/*
+ * parse ISAKMP payloads, without ISAKMP base header.
+ */
+vchar_t *
+isakmp_parsewoh(np0, gen, len)
+	int np0;
+	struct isakmp_gen *gen;
+	int len;
+{
+	u_char np = np0 & 0xff;
+	int tlen, plen;
+	vchar_t *result;
+	struct isakmp_parse_t *p, *ep;
+
+	plog(LLV_DEBUG, LOCATION, NULL, "begin.\n");
+
+	/*
+	 * 5 is a magic number, but any value larger than 2 should be fine
+	 * as we do vrealloc() in the following loop.
+	 */
+	result = vmalloc(sizeof(struct isakmp_parse_t) * 5);
+	if (result == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"failed to get buffer.\n");
+		return NULL;
+	}
+	p = (struct isakmp_parse_t *)result->v;
+	ep = (struct isakmp_parse_t *)(result->v + result->l - sizeof(*ep));
+
+	tlen = len;
+
+	/* parse through general headers */
+	while (0 < tlen && np != ISAKMP_NPTYPE_NONE) {
+		if (tlen <= sizeof(struct isakmp_gen)) {
+			/* don't send information, see isakmp_ident_r1() */
+			plog(LLV_ERROR, LOCATION, NULL,
+				"invalid length of payload\n");
+			vfree(result);
+			return NULL;
+		}
+
+		plog(LLV_DEBUG, LOCATION, NULL,
+			"seen nptype=%u(%s)\n", np, s_isakmp_nptype(np));
+
+		p->type = np;
+		p->len = ntohs(gen->len);
+		if (p->len < sizeof(struct isakmp_gen) || p->len > tlen) {
+			plog(LLV_DEBUG, LOCATION, NULL,
+				"invalid length of payload\n");
+			vfree(result);
+			return NULL;
+		}
+		p->ptr = gen;
+		p++;
+		if (ep <= p) {
+			int off;
+
+			off = p - (struct isakmp_parse_t *)result->v;
+			result = vrealloc(result, result->l * 2);
+			if (result == NULL) {
+				plog(LLV_DEBUG, LOCATION, NULL,
+					"failed to realloc buffer.\n");
+				vfree(result);
+				return NULL;
+			}
+			ep = (struct isakmp_parse_t *)
+				(result->v + result->l - sizeof(*ep));
+			p = (struct isakmp_parse_t *)result->v;
+			p += off;
+		}
+
+		np = gen->np;
+		plen = ntohs(gen->len);
+		gen = (struct isakmp_gen *)((caddr_t)gen + plen);
+		tlen -= plen;
+	}
+	p->type = ISAKMP_NPTYPE_NONE;
+	p->len = 0;
+	p->ptr = NULL;
+
+	plog(LLV_DEBUG, LOCATION, NULL, "succeed.\n");
+
+	return result;
+}
+
+/*
+ * parse ISAKMP payloads, including ISAKMP base header.
+ */
+vchar_t *
+isakmp_parse(buf)
+	vchar_t *buf;
+{
+	struct isakmp *isakmp = (struct isakmp *)buf->v;
+	struct isakmp_gen *gen;
+	int tlen;
+	vchar_t *result;
+	u_char np;
+
+	np = isakmp->np;
+	gen = (struct isakmp_gen *)(buf->v + sizeof(*isakmp));
+	tlen = buf->l - sizeof(struct isakmp);
+	result = isakmp_parsewoh(np, gen, tlen);
+
+	return result;
+}
+
+/* %%% */
+int
+isakmp_init()
+{
+	/* initialize a isakmp status table */
+	initph1tree();
+	initph2tree();
+	initctdtree();
+	init_recvdpkt();
+
+	if (isakmp_open() < 0)
+		goto err;
+
+	return(0);
+
+err:
+	isakmp_close();
+	return(-1);
+}
+
+/*
+ * make strings containing i_cookie + r_cookie + msgid
+ */
+const char *
+isakmp_pindex(index, msgid)
+	const isakmp_index *index;
+	const u_int32_t msgid;
+{
+	static char buf[64];
+	const u_char *p;
+	int i, j;
+
+	memset(buf, 0, sizeof(buf));
+
+	/* copy index */
+	p = (const u_char *)index;
+	for (j = 0, i = 0; i < sizeof(isakmp_index); i++) {
+		snprintf((char *)&buf[j], sizeof(buf) - j, "%02x", p[i]);
+		j += 2;
+		switch (i) {
+		case 7:
+			buf[j++] = ':';
+		}
+	}
+
+	if (msgid == 0)
+		return buf;
+
+	/* copy msgid */
+	snprintf((char *)&buf[j], sizeof(buf) - j, ":%08x", ntohs(msgid));
+
+	return buf;
+}
+
+/* open ISAKMP sockets. */
+int
+isakmp_open()
+{
+	const int yes = 1;
+	int ifnum = 0, encap_ifnum = 0;
+#ifdef INET6
+	int pktinfo;
+#endif
+	struct myaddrs *p;
+
+	for (p = lcconf->myaddrs; p; p = p->next) {
+		if (!p->addr)
+			continue;
+
+		/* warn if wildcard address - should we forbid this? */
+		switch (p->addr->sa_family) {
+		case AF_INET:
+			if (((struct sockaddr_in *)p->addr)->sin_addr.s_addr == 0)
+				plog(LLV_WARNING, LOCATION, NULL,
+					"listening to wildcard address,"
+					"broadcast IKE packet may kill you\n");
+			break;
+#ifdef INET6
+		case AF_INET6:
+			if (IN6_IS_ADDR_UNSPECIFIED(&((struct sockaddr_in6 *)p->addr)->sin6_addr))
+				plog(LLV_WARNING, LOCATION, NULL,
+					"listening to wildcard address, "
+					"broadcast IKE packet may kill you\n");
+			break;
+#endif
+		default:
+			plog(LLV_ERROR, LOCATION, NULL,
+				"unsupported address family %d\n",
+				lcconf->default_af);
+			goto err_and_next;
+		}
+
+#ifdef INET6
+		if (p->addr->sa_family == AF_INET6 &&
+		    IN6_IS_ADDR_MULTICAST(&((struct sockaddr_in6 *)
+					    p->addr)->sin6_addr))
+		{
+			plog(LLV_DEBUG, LOCATION, NULL, 
+				"Ignoring multicast address %s\n",
+				saddr2str(p->addr));
+				racoon_free(p->addr);
+				p->addr = NULL;
+			continue;
+		}
+#endif
+
+		if ((p->sock = socket(p->addr->sa_family, SOCK_DGRAM, 0)) < 0) {
+			plog(LLV_ERROR, LOCATION, NULL,
+				"socket (%s)\n", strerror(errno));
+			goto err_and_next;
+		}
+
+		if (fcntl(p->sock, F_SETFL, O_NONBLOCK) == -1)
+			plog(LLV_WARNING, LOCATION, NULL,
+				"failed to put socket in non-blocking mode\n");
+
+		/* receive my interface address on inbound packets. */
+		switch (p->addr->sa_family) {
+		case AF_INET:
+			if (setsockopt(p->sock, IPPROTO_IP,
+#ifdef __linux__
+				       IP_PKTINFO,
+#else
+				       IP_RECVDSTADDR,
+#endif
+					(const void *)&yes, sizeof(yes)) < 0) {
+				plog(LLV_ERROR, LOCATION, NULL,
+					"setsockopt IP_RECVDSTADDR (%s)\n", 
+					strerror(errno));
+				goto err_and_next;
+			}
+			break;
+#ifdef INET6
+		case AF_INET6:
+#ifdef INET6_ADVAPI
+#ifdef IPV6_RECVPKTINFO
+			pktinfo = IPV6_RECVPKTINFO;
+#else  /* old adv. API */
+			pktinfo = IPV6_PKTINFO;
+#endif /* IPV6_RECVPKTINFO */
+#else
+			pktinfo = IPV6_RECVDSTADDR;
+#endif
+			if (setsockopt(p->sock, IPPROTO_IPV6, pktinfo,
+					(const void *)&yes, sizeof(yes)) < 0)
+			{
+				plog(LLV_ERROR, LOCATION, NULL,
+					"setsockopt IPV6_RECVDSTADDR (%d):%s\n",
+					pktinfo, strerror(errno));
+				goto err_and_next;
+			}
+			break;
+#endif
+		}
+
+#ifdef IPV6_USE_MIN_MTU
+		if (p->addr->sa_family == AF_INET6 &&
+		    setsockopt(p->sock, IPPROTO_IPV6, IPV6_USE_MIN_MTU,
+		    (void *)&yes, sizeof(yes)) < 0) {
+			plog(LLV_ERROR, LOCATION, NULL,
+			    "setsockopt IPV6_USE_MIN_MTU (%s)\n", 
+			    strerror(errno));
+			return -1;
+		}
+#endif
+
+		if (setsockopt_bypass(p->sock, p->addr->sa_family) < 0)
+			goto err_and_next;
+
+		if (bind(p->sock, p->addr, sysdep_sa_len(p->addr)) < 0) {
+			plog(LLV_ERROR, LOCATION, p->addr,
+				"failed to bind to address %s (%s).\n",
+				saddr2str(p->addr), strerror(errno));
+			close(p->sock);
+			goto err_and_next;
+		}
+
+		ifnum++;
+
+		plog(LLV_INFO, LOCATION, NULL,
+			"%s used as isakmp port (fd=%d)\n",
+			saddr2str(p->addr), p->sock);
+
+#ifdef ENABLE_NATT
+		if (p->addr->sa_family == AF_INET) {
+			int option = -1;
+
+
+			if(p->udp_encap)
+				option = UDP_ENCAP_ESPINUDP;
+#if defined(ENABLE_NATT_00) || defined(ENABLE_NATT_01)
+			else
+				option = UDP_ENCAP_ESPINUDP_NON_IKE;
+#endif
+			if(option != -1){
+				if (setsockopt (p->sock, SOL_UDP, 
+				    UDP_ENCAP, &option, sizeof (option)) < 0) {
+					plog(LLV_WARNING, LOCATION, NULL,
+					    "setsockopt(%s): UDP_ENCAP %s\n",
+					    option == UDP_ENCAP_ESPINUDP ? "UDP_ENCAP_ESPINUDP" : "UDP_ENCAP_ESPINUDP_NON_IKE",
+						 strerror(errno));
+					goto skip_encap;
+				}
+				else {
+					plog(LLV_INFO, LOCATION, NULL,
+						 "%s used for NAT-T\n",
+						 saddr2str(p->addr));
+					encap_ifnum++;
+				}
+			}
+		}
+skip_encap:
+#endif
+		continue;
+
+	err_and_next:
+		racoon_free(p->addr);
+		p->addr = NULL;
+		if (! lcconf->autograbaddr && lcconf->strict_address)
+			return -1;
+		continue;
+	}
+
+	if (!ifnum) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"no address could be bound.\n");
+		return -1;
+	}
+
+#ifdef ENABLE_NATT
+	if (natt_enabled_in_rmconf() && !encap_ifnum) {
+		plog(LLV_WARNING, LOCATION, NULL, 
+			"NAT-T is enabled in at least one remote{} section,\n");
+		plog(LLV_WARNING, LOCATION, NULL, 
+			"but no 'isakmp_natt' address was specified!\n");
+	}
+#endif
+
+	return 0;
+}
+
+void
+isakmp_close()
+{
+	struct myaddrs *p, *next;
+
+	for (p = lcconf->myaddrs; p; p = next) {
+		next = p->next;
+
+		if (!p->addr) {
+			racoon_free(p);
+			continue;
+		}
+		close(p->sock);
+		racoon_free(p->addr);
+		racoon_free(p);
+	}
+
+	lcconf->myaddrs = NULL;
+}
+
+int
+isakmp_send(iph1, sbuf)
+	struct ph1handle *iph1;
+	vchar_t *sbuf;
+{
+	int len = 0;
+	int s;
+	vchar_t *vbuf = NULL;
+
+#ifdef ENABLE_NATT
+	size_t extralen = NON_ESP_MARKER_USE(iph1) ? NON_ESP_MARKER_LEN : 0;
+
+#ifdef ENABLE_FRAG
+	/* 
+	 * Do not add the non ESP marker for a packet that will
+	 * be fragmented. The non ESP marker should appear in 
+	 * all fragment's packets, but not in the fragmented packet
+	 */
+	if (iph1->frag && sbuf->l > ISAKMP_FRAG_MAXLEN) 
+		extralen = 0;
+#endif
+	if (extralen)
+		plog (LLV_DEBUG, LOCATION, NULL, "Adding NON-ESP marker\n");
+
+	/* If NAT-T port floating is in use, 4 zero bytes (non-ESP marker) 
+	   must added just before the packet itself. For this we must 
+	   allocate a new buffer and release it at the end. */
+	if (extralen) {
+		if ((vbuf = vmalloc (sbuf->l + extralen)) == NULL) {
+			plog(LLV_ERROR, LOCATION, NULL, 
+			    "vbuf allocation failed\n");
+			return -1;
+		}
+		*(u_int32_t *)vbuf->v = 0;
+		memcpy (vbuf->v + extralen, sbuf->v, sbuf->l);
+		sbuf = vbuf;
+	}
+#endif
+
+	/* select the socket to be sent */
+	s = getsockmyaddr(iph1->local);
+	if (s == -1){
+		if ( vbuf != NULL )
+			vfree(vbuf);
+		return -1;
+	}
+
+	plog (LLV_DEBUG, LOCATION, NULL, "%zu bytes %s\n", sbuf->l, 
+	      saddr2str_fromto("from %s to %s", iph1->local, iph1->remote));
+
+#ifdef ENABLE_FRAG
+	if (iph1->frag && sbuf->l > ISAKMP_FRAG_MAXLEN) {
+		if (isakmp_sendfrags(iph1, sbuf) == -1) {
+			plog(LLV_ERROR, LOCATION, NULL, 
+			    "isakmp_sendfrags failed\n");
+			if ( vbuf != NULL )
+				vfree(vbuf);
+			return -1;
+		}
+	} else 
+#endif
+	{
+		len = sendfromto(s, sbuf->v, sbuf->l,
+		    iph1->local, iph1->remote, lcconf->count_persend);
+
+		if (len == -1) {
+			plog(LLV_ERROR, LOCATION, NULL, "sendfromto failed\n");
+			if ( vbuf != NULL )
+				vfree(vbuf);
+			return -1;
+		}
+	}
+	
+	if ( vbuf != NULL )
+		vfree(vbuf);
+	
+	return 0;
+}
+
+/* called from scheduler */
+void
+isakmp_ph1resend_stub(p)
+	void *p;
+{
+	struct ph1handle *iph1;
+
+	iph1=(struct ph1handle *)p;
+	if(isakmp_ph1resend(iph1) < 0){
+		if(iph1->scr != NULL){
+			/* Should not happen...
+			 */
+			sched_kill(iph1->scr);
+			iph1->scr=NULL;
+		}
+
+		remph1(iph1);
+		delph1(iph1);
+	}
+}
+
+int
+isakmp_ph1resend(iph1)
+	struct ph1handle *iph1;
+{
+	/* Note: NEVER do the rem/del here, it will be done by the caller or by the _stub function
+	 */
+	if (iph1->retry_counter <= 0) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"phase1 negotiation failed due to time up. %s\n",
+			isakmp_pindex(&iph1->index, iph1->msgid));
+		EVT_PUSH(iph1->local, iph1->remote, 
+		    EVTT_PEER_NO_RESPONSE, NULL);
+
+		return -1;
+	}
+
+	if (isakmp_send(iph1, iph1->sendbuf) < 0){
+		plog(LLV_ERROR, LOCATION, NULL,
+			 "phase1 negotiation failed due to send error. %s\n",
+			 isakmp_pindex(&iph1->index, iph1->msgid));
+		EVT_PUSH(iph1->local, iph1->remote, 
+				 EVTT_PEER_NO_RESPONSE, NULL);
+		return -1;
+	}
+
+	plog(LLV_DEBUG, LOCATION, NULL,
+		"resend phase1 packet %s\n",
+		isakmp_pindex(&iph1->index, iph1->msgid));
+
+	iph1->retry_counter--;
+
+	iph1->scr = sched_new(iph1->rmconf->retry_interval,
+		isakmp_ph1resend_stub, iph1);
+
+	return 0;
+}
+
+/* called from scheduler */
+void
+isakmp_ph2resend_stub(p)
+	void *p;
+{
+	struct ph2handle *iph2;
+
+	iph2=(struct ph2handle *)p;
+
+	if(isakmp_ph2resend(iph2) < 0){
+		unbindph12(iph2);
+		remph2(iph2);
+		delph2(iph2);
+	}
+}
+
+int
+isakmp_ph2resend(iph2)
+	struct ph2handle *iph2;
+{
+	/* Note: NEVER do the unbind/rem/del here, it will be done by the caller or by the _stub function
+	 */
+	if (iph2->ph1->status == PHASE1ST_EXPIRED){
+		plog(LLV_ERROR, LOCATION, NULL,
+			"phase2 negotiation failed due to phase1 expired. %s\n",
+				isakmp_pindex(&iph2->ph1->index, iph2->msgid));
+		return -1;
+	}
+
+	if (iph2->retry_counter <= 0) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"phase2 negotiation failed due to time up. %s\n",
+				isakmp_pindex(&iph2->ph1->index, iph2->msgid));
+		EVT_PUSH(iph2->src, iph2->dst, EVTT_PEER_NO_RESPONSE, NULL);
+		unbindph12(iph2);
+		return -1;
+	}
+
+	if (isakmp_send(iph2->ph1, iph2->sendbuf) < 0){
+		plog(LLV_ERROR, LOCATION, NULL,
+			"phase2 negotiation failed due to send error. %s\n",
+				isakmp_pindex(&iph2->ph1->index, iph2->msgid));
+		EVT_PUSH(iph2->src, iph2->dst, EVTT_PEER_NO_RESPONSE, NULL);
+
+		return -1;
+	}
+
+	plog(LLV_DEBUG, LOCATION, NULL,
+		"resend phase2 packet %s\n",
+		isakmp_pindex(&iph2->ph1->index, iph2->msgid));
+
+	iph2->retry_counter--;
+
+	iph2->scr = sched_new(iph2->ph1->rmconf->retry_interval,
+		isakmp_ph2resend_stub, iph2);
+
+	return 0;
+}
+
+/* called from scheduler */
+void
+isakmp_ph1expire_stub(p)
+	void *p;
+{
+
+	isakmp_ph1expire((struct ph1handle *)p);
+}
+
+void
+isakmp_ph1expire(iph1)
+	struct ph1handle *iph1;
+{
+	char *src, *dst;
+
+	SCHED_KILL(iph1->sce);
+
+	if(iph1->status != PHASE1ST_EXPIRED){
+		src = racoon_strdup(saddr2str(iph1->local));
+		dst = racoon_strdup(saddr2str(iph1->remote));
+		STRDUP_FATAL(src);
+		STRDUP_FATAL(dst);
+
+		plog(LLV_INFO, LOCATION, NULL,
+			 "ISAKMP-SA expired %s-%s spi:%s\n",
+			 src, dst,
+			 isakmp_pindex(&iph1->index, 0));
+		racoon_free(src);
+		racoon_free(dst);
+		iph1->status = PHASE1ST_EXPIRED;
+	}
+
+	/*
+	 * the phase1 deletion is postponed until there is no phase2.
+	 */
+	if (LIST_FIRST(&iph1->ph2tree) != NULL) {
+		iph1->sce = sched_new(1, isakmp_ph1expire_stub, iph1);
+		return;
+	}
+
+	iph1->sce = sched_new(1, isakmp_ph1delete_stub, iph1);
+}
+
+/* called from scheduler */
+void
+isakmp_ph1delete_stub(p)
+	void *p;
+{
+
+	isakmp_ph1delete((struct ph1handle *)p);
+}
+
+void
+isakmp_ph1delete(iph1)
+	struct ph1handle *iph1;
+{
+	char *src, *dst;
+
+	SCHED_KILL(iph1->sce);
+
+	if (LIST_FIRST(&iph1->ph2tree) != NULL) {
+		iph1->sce = sched_new(1, isakmp_ph1delete_stub, iph1);
+		return;
+	}
+
+	/* don't re-negosiation when the phase 1 SA expires. */
+
+	src = racoon_strdup(saddr2str(iph1->local));
+	dst = racoon_strdup(saddr2str(iph1->remote));
+	STRDUP_FATAL(src);
+	STRDUP_FATAL(dst);
+
+	plog(LLV_INFO, LOCATION, NULL,
+		"ISAKMP-SA deleted %s-%s spi:%s\n",
+		src, dst, isakmp_pindex(&iph1->index, 0));
+	EVT_PUSH(iph1->local, iph1->remote, EVTT_PHASE1_DOWN, NULL);
+	racoon_free(src);
+	racoon_free(dst);
+
+	remph1(iph1);
+	delph1(iph1);
+
+	return;
+}
+
+/* called from scheduler.
+ * this function will call only isakmp_ph2delete().
+ * phase 2 handler remain forever if kernel doesn't cry a expire of phase 2 SA
+ * by something cause.  That's why this function is called after phase 2 SA
+ * expires in the userland.
+ */
+void
+isakmp_ph2expire_stub(p)
+	void *p;
+{
+
+	isakmp_ph2expire((struct ph2handle *)p);
+}
+
+void
+isakmp_ph2expire(iph2)
+	struct ph2handle *iph2;
+{
+	char *src, *dst;
+
+	SCHED_KILL(iph2->sce);
+
+	src = racoon_strdup(saddrwop2str(iph2->src));
+	dst = racoon_strdup(saddrwop2str(iph2->dst));
+	STRDUP_FATAL(src);
+	STRDUP_FATAL(dst);
+
+	plog(LLV_INFO, LOCATION, NULL,
+		"phase2 sa expired %s-%s\n", src, dst);
+	racoon_free(src);
+	racoon_free(dst);
+
+	iph2->status = PHASE2ST_EXPIRED;
+
+	iph2->sce = sched_new(1, isakmp_ph2delete_stub, iph2);
+
+	return;
+}
+
+/* called from scheduler */
+void
+isakmp_ph2delete_stub(p)
+	void *p;
+{
+
+	isakmp_ph2delete((struct ph2handle *)p);
+}
+
+void
+isakmp_ph2delete(iph2)
+	struct ph2handle *iph2;
+{
+	char *src, *dst;
+
+	SCHED_KILL(iph2->sce);
+
+	src = racoon_strdup(saddrwop2str(iph2->src));
+	dst = racoon_strdup(saddrwop2str(iph2->dst));
+	STRDUP_FATAL(src);
+	STRDUP_FATAL(dst);
+
+	plog(LLV_INFO, LOCATION, NULL,
+		"phase2 sa deleted %s-%s\n", src, dst);
+	racoon_free(src);
+	racoon_free(dst);
+
+	unbindph12(iph2);
+	remph2(iph2);
+	delph2(iph2);
+
+	return;
+}
+
+/* %%%
+ * Interface between PF_KEYv2 and ISAKMP
+ */
+/*
+ * receive ACQUIRE from kernel, and begin either phase1 or phase2.
+ * if phase1 has been finished, begin phase2.
+ */
+int
+isakmp_post_acquire(iph2)
+	struct ph2handle *iph2;
+{
+	struct remoteconf *rmconf;
+	struct ph1handle *iph1 = NULL;
+	
+	plog(LLV_DEBUG, LOCATION, NULL, "in post_acquire\n");
+
+	/* search appropreate configuration with masking port. */
+	rmconf = getrmconf(iph2->dst);
+	if (rmconf == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"no configuration found for %s.\n",
+			saddrwop2str(iph2->dst));
+		return -1;
+	}
+
+	/* if passive mode, ignore the acquire message */
+	if (rmconf->passive) {
+		plog(LLV_DEBUG, LOCATION, NULL,
+			"because of passive mode, "
+			"ignore the acquire message for %s.\n",
+			saddrwop2str(iph2->dst));
+		return 0;
+	}
+
+	/* 
+	 * Search isakmp status table by address and port 
+	 * If NAT-T is in use, consider null ports as a 
+	 * wildcard and use IKE ports instead.
+	 */
+#ifdef ENABLE_NATT
+	if (!extract_port(iph2->src) && !extract_port(iph2->dst)) {
+		if ((iph1 = getph1byaddrwop(iph2->src, iph2->dst)) != NULL) {
+			set_port(iph2->src, extract_port(iph1->local));
+			set_port(iph2->dst, extract_port(iph1->remote));
+		}
+	} else {
+		iph1 = getph1byaddr(iph2->src, iph2->dst, 0);
+	}
+#else
+	iph1 = getph1byaddr(iph2->src, iph2->dst, 0);
+#endif
+
+	/* no ISAKMP-SA found. */
+	if (iph1 == NULL) {
+		struct sched *sc;
+
+		iph2->retry_checkph1 = lcconf->retry_checkph1;
+		sc = sched_new(1, isakmp_chkph1there_stub, iph2);
+		plog(LLV_INFO, LOCATION, NULL,
+			"IPsec-SA request for %s queued "
+			"due to no phase1 found.\n",
+			saddrwop2str(iph2->dst));
+
+		/* start phase 1 negotiation as a initiator. */
+		if (isakmp_ph1begin_i(rmconf, iph2->dst, iph2->src) < 0) {
+			SCHED_KILL(sc);
+			return -1;
+		}
+
+		return 0;
+		/*NOTREACHED*/
+	}
+
+	/* found ISAKMP-SA, but on negotiation. */
+	if (iph1->status != PHASE1ST_ESTABLISHED) {
+		iph2->retry_checkph1 = lcconf->retry_checkph1;
+		sched_new(1, isakmp_chkph1there_stub, iph2);
+		plog(LLV_INFO, LOCATION, iph2->dst,
+			"request for establishing IPsec-SA was queued "
+			"due to no phase1 found.\n");
+		return 0;
+		/*NOTREACHED*/
+	}
+
+	/* found established ISAKMP-SA */
+	/* i.e. iph1->status == PHASE1ST_ESTABLISHED */
+
+	/* found ISAKMP-SA. */
+	plog(LLV_DEBUG, LOCATION, NULL, "begin QUICK mode.\n");
+
+	/* begin quick mode */
+	if (isakmp_ph2begin_i(iph1, iph2))
+		return -1;
+
+	return 0;
+}
+
+/*
+ * receive GETSPI from kernel.
+ */
+int
+isakmp_post_getspi(iph2)
+	struct ph2handle *iph2;
+{
+#ifdef ENABLE_STATS
+	struct timeval start, end;
+#endif
+
+	/* don't process it because there is no suitable phase1-sa. */
+	if (iph2->ph1->status == PHASE1ST_EXPIRED) {
+		plog(LLV_ERROR, LOCATION, iph2->ph1->remote,
+			"the negotiation is stopped, "
+			"because there is no suitable ISAKMP-SA.\n");
+		return -1;
+	}
+
+#ifdef ENABLE_STATS
+	gettimeofday(&start, NULL);
+#endif
+	if ((ph2exchange[etypesw2(ISAKMP_ETYPE_QUICK)]
+	                [iph2->side]
+	                [iph2->status])(iph2, NULL) != 0)
+		return -1;
+#ifdef ENABLE_STATS
+	gettimeofday(&end, NULL);
+	syslog(LOG_NOTICE, "%s(%s): %8.6f",
+		"phase2",
+		s_isakmp_state(ISAKMP_ETYPE_QUICK, iph2->side, iph2->status),
+		timedelta(&start, &end));
+#endif
+
+	return 0;
+}
+
+/* called by scheduler */
+void
+isakmp_chkph1there_stub(p)
+	void *p;
+{
+	isakmp_chkph1there((struct ph2handle *)p);
+}
+
+void
+isakmp_chkph1there(iph2)
+	struct ph2handle *iph2;
+{
+	struct ph1handle *iph1;
+
+	iph2->retry_checkph1--;
+	if (iph2->retry_checkph1 < 0) {
+		plog(LLV_ERROR, LOCATION, iph2->dst,
+			"phase2 negotiation failed "
+			"due to time up waiting for phase1. %s\n",
+			sadbsecas2str(iph2->dst, iph2->src,
+				iph2->satype, 0, 0));
+		plog(LLV_INFO, LOCATION, NULL,
+			"delete phase 2 handler.\n");
+
+		/* send acquire to kernel as error */
+		pk_sendeacquire(iph2);
+
+		unbindph12(iph2);
+		remph2(iph2);
+		delph2(iph2);
+
+		return;
+	}
+
+	/* 
+	 * Search isakmp status table by address and port 
+	 * If NAT-T is in use, consider null ports as a 
+	 * wildcard and use IKE ports instead.
+	 */
+#ifdef ENABLE_NATT
+	if (!extract_port(iph2->src) && !extract_port(iph2->dst)) {
+		plog(LLV_DEBUG2, LOCATION, NULL, "CHKPH1THERE: extract_port.\n");
+		if( (iph1 = getph1byaddrwop(iph2->src, iph2->dst)) != NULL){
+			plog(LLV_DEBUG2, LOCATION, NULL, "CHKPH1THERE: found a ph1 wop.\n");
+		}
+	} else {
+		plog(LLV_DEBUG2, LOCATION, NULL, "CHKPH1THERE: searching byaddr.\n");
+		iph1 = getph1byaddr(iph2->src, iph2->dst, 0);
+		if(iph1 != NULL)
+			plog(LLV_DEBUG2, LOCATION, NULL, "CHKPH1THERE: found byaddr.\n");
+	}
+#else
+	iph1 = getph1byaddr(iph2->src, iph2->dst, 0);
+#endif
+
+	/* XXX Even if ph1 as responder is there, should we not start
+	 * phase 2 negotiation ? */
+	if (iph1 != NULL
+	 && iph1->status == PHASE1ST_ESTABLISHED) {
+		/* found isakmp-sa */
+
+		plog(LLV_DEBUG2, LOCATION, NULL, "CHKPH1THERE: got a ph1 handler, setting ports.\n");
+		plog(LLV_DEBUG2, LOCATION, NULL, "iph1->local: %s\n", saddr2str(iph1->local));
+		plog(LLV_DEBUG2, LOCATION, NULL, "iph1->remote: %s\n", saddr2str(iph1->remote));
+		plog(LLV_DEBUG2, LOCATION, NULL, "before:\n");
+		plog(LLV_DEBUG2, LOCATION, NULL, "src: %s\n", saddr2str(iph2->src));
+		plog(LLV_DEBUG2, LOCATION, NULL, "dst: %s\n", saddr2str(iph2->dst));
+		set_port(iph2->src, extract_port(iph1->local));
+		set_port(iph2->dst, extract_port(iph1->remote));
+		plog(LLV_DEBUG2, LOCATION, NULL, "After:\n");
+		plog(LLV_DEBUG2, LOCATION, NULL, "src: %s\n", saddr2str(iph2->src));
+		plog(LLV_DEBUG2, LOCATION, NULL, "dst: %s\n", saddr2str(iph2->dst));
+
+		/* begin quick mode */
+		(void)isakmp_ph2begin_i(iph1, iph2);
+		return;
+	}
+
+	plog(LLV_DEBUG2, LOCATION, NULL, "CHKPH1THERE: no established ph1 handler found\n");
+
+	/* no isakmp-sa found */
+	sched_new(1, isakmp_chkph1there_stub, iph2);
+
+	return;
+}
+
+/* copy variable data into ALLOCATED buffer. */
+caddr_t
+isakmp_set_attr_v(buf, type, val, len)
+	caddr_t buf;
+	int type;
+	caddr_t val;
+	int len;
+{
+	struct isakmp_data *data;
+
+	data = (struct isakmp_data *)buf;
+	data->type = htons((u_int16_t)type | ISAKMP_GEN_TLV);
+	data->lorv = htons((u_int16_t)len);
+	memcpy(data + 1, val, len);
+
+	return buf + sizeof(*data) + len;
+}
+
+/* copy fixed length data into ALLOCATED buffer. */
+caddr_t
+isakmp_set_attr_l(buf, type, val)
+	caddr_t buf;
+	int type;
+	u_int32_t val;
+{
+	struct isakmp_data *data;
+
+	data = (struct isakmp_data *)buf;
+	data->type = htons((u_int16_t)type | ISAKMP_GEN_TV);
+	data->lorv = htons((u_int16_t)val);
+
+	return buf + sizeof(*data);
+}
+
+/* add a variable data attribute to the buffer by reallocating it. */
+vchar_t *
+isakmp_add_attr_v(buf0, type, val, len)
+	vchar_t *buf0;
+	int type;
+	caddr_t val;
+	int len;
+{
+	vchar_t *buf = NULL;
+	struct isakmp_data *data;
+	int tlen;
+	int oldlen = 0;
+
+	tlen = sizeof(*data) + len;
+
+	if (buf0) {
+		oldlen = buf0->l;
+		buf = vrealloc(buf0, oldlen + tlen);
+	} else
+		buf = vmalloc(tlen);
+	if (!buf) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"failed to get a attribute buffer.\n");
+		return NULL;
+	}
+
+	data = (struct isakmp_data *)(buf->v + oldlen);
+	data->type = htons((u_int16_t)type | ISAKMP_GEN_TLV);
+	data->lorv = htons((u_int16_t)len);
+	memcpy(data + 1, val, len);
+
+	return buf;
+}
+
+/* add a fixed data attribute to the buffer by reallocating it. */
+vchar_t *
+isakmp_add_attr_l(buf0, type, val)
+	vchar_t *buf0;
+	int type;
+	u_int32_t val;
+{
+	vchar_t *buf = NULL;
+	struct isakmp_data *data;
+	int tlen;
+	int oldlen = 0;
+
+	tlen = sizeof(*data);
+
+	if (buf0) {
+		oldlen = buf0->l;
+		buf = vrealloc(buf0, oldlen + tlen);
+	} else
+		buf = vmalloc(tlen);
+	if (!buf) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"failed to get a attribute buffer.\n");
+		return NULL;
+	}
+
+	data = (struct isakmp_data *)(buf->v + oldlen);
+	data->type = htons((u_int16_t)type | ISAKMP_GEN_TV);
+	data->lorv = htons((u_int16_t)val);
+
+	return buf;
+}
+
+/*
+ * calculate cookie and set.
+ */
+int
+isakmp_newcookie(place, remote, local)
+	caddr_t place;
+	struct sockaddr *remote;
+	struct sockaddr *local;
+{
+	vchar_t *buf = NULL, *buf2 = NULL;
+	char *p;
+	int blen;
+	int alen;
+	caddr_t sa1, sa2;
+	time_t t;
+	int error = -1;
+	u_short port;
+
+
+	if (remote->sa_family != local->sa_family) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"address family mismatch, remote:%d local:%d\n",
+			remote->sa_family, local->sa_family);
+		goto end;
+	}
+	switch (remote->sa_family) {
+	case AF_INET:
+		alen = sizeof(struct in_addr);
+		sa1 = (caddr_t)&((struct sockaddr_in *)remote)->sin_addr;
+		sa2 = (caddr_t)&((struct sockaddr_in *)local)->sin_addr;
+		break;
+#ifdef INET6
+	case AF_INET6:
+		alen = sizeof(struct in6_addr);
+		sa1 = (caddr_t)&((struct sockaddr_in6 *)remote)->sin6_addr;
+		sa2 = (caddr_t)&((struct sockaddr_in6 *)local)->sin6_addr;
+		break;
+#endif
+	default:
+		plog(LLV_ERROR, LOCATION, NULL,
+			"invalid family: %d\n", remote->sa_family);
+		goto end;
+	}
+	blen = (alen + sizeof(u_short)) * 2
+		+ sizeof(time_t) + lcconf->secret_size;
+	buf = vmalloc(blen);
+	if (buf == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"failed to get a cookie.\n");
+		goto end;
+	}
+	p = buf->v;
+
+	/* copy my address */
+	memcpy(p, sa1, alen);
+	p += alen;
+	port = ((struct sockaddr_in *)remote)->sin_port;
+	memcpy(p, &port, sizeof(u_short));
+	p += sizeof(u_short);
+
+	/* copy target address */
+	memcpy(p, sa2, alen);
+	p += alen;
+	port = ((struct sockaddr_in *)local)->sin_port;
+	memcpy(p, &port, sizeof(u_short));
+	p += sizeof(u_short);
+
+	/* copy time */
+	t = time(0);
+	memcpy(p, (caddr_t)&t, sizeof(t));
+	p += sizeof(t);
+
+	/* copy random value */
+	buf2 = eay_set_random(lcconf->secret_size);
+	if (buf2 == NULL)
+		goto end;
+	memcpy(p, buf2->v, lcconf->secret_size);
+	p += lcconf->secret_size;
+	vfree(buf2);
+
+	buf2 = eay_sha1_one(buf);
+	memcpy(place, buf2->v, sizeof(cookie_t));
+
+	sa1 = val2str(place, sizeof (cookie_t));
+	plog(LLV_DEBUG, LOCATION, NULL, "new cookie:\n%s\n", sa1);
+	racoon_free(sa1);
+
+	error = 0;
+end:
+	if (buf != NULL)
+		vfree(buf);
+	if (buf2 != NULL)
+		vfree(buf2);
+	return error;
+}
+
+/*
+ * save partner's(payload) data into phhandle.
+ */
+int
+isakmp_p2ph(buf, gen)
+	vchar_t **buf;
+	struct isakmp_gen *gen;
+{
+	/* XXX to be checked in each functions for logging. */
+	if (*buf) {
+		plog(LLV_WARNING, LOCATION, NULL,
+			"ignore this payload, same payload type exist.\n");
+		return -1;
+	}
+
+	*buf = vmalloc(ntohs(gen->len) - sizeof(*gen));
+	if (*buf == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"failed to get buffer.\n");
+		return -1;
+	}
+	memcpy((*buf)->v, gen + 1, (*buf)->l);
+
+	return 0;
+}
+
+u_int32_t
+isakmp_newmsgid2(iph1)
+	struct ph1handle *iph1;
+{
+	u_int32_t msgid2;
+
+	do {
+		msgid2 = eay_random();
+	} while (getph2bymsgid(iph1, msgid2));
+
+	return msgid2;
+}
+
+/*
+ * set values into allocated buffer of isakmp header for phase 1
+ */
+static caddr_t
+set_isakmp_header(vbuf, iph1, nptype, etype, flags, msgid)
+	vchar_t *vbuf;
+	struct ph1handle *iph1;
+	int nptype;
+	u_int8_t etype;
+	u_int8_t flags;
+	u_int32_t msgid;
+{
+	struct isakmp *isakmp;
+
+	if (vbuf->l < sizeof(*isakmp))
+		return NULL;
+
+	isakmp = (struct isakmp *)vbuf->v;
+
+	memcpy(&isakmp->i_ck, &iph1->index.i_ck, sizeof(cookie_t));
+	memcpy(&isakmp->r_ck, &iph1->index.r_ck, sizeof(cookie_t));
+	isakmp->np = nptype;
+	isakmp->v = iph1->version;
+	isakmp->etype = etype;
+	isakmp->flags = flags;
+	isakmp->msgid = msgid;
+	isakmp->len = htonl(vbuf->l);
+
+	return vbuf->v + sizeof(*isakmp);
+}
+
+/*
+ * set values into allocated buffer of isakmp header for phase 1
+ */
+caddr_t
+set_isakmp_header1(vbuf, iph1, nptype)
+	vchar_t *vbuf;
+	struct ph1handle *iph1;
+	int nptype;
+{
+	return set_isakmp_header (vbuf, iph1, nptype, iph1->etype, iph1->flags, iph1->msgid);
+}
+
+/*
+ * set values into allocated buffer of isakmp header for phase 2
+ */
+caddr_t
+set_isakmp_header2(vbuf, iph2, nptype)
+	vchar_t *vbuf;
+	struct ph2handle *iph2;
+	int nptype;
+{
+	return set_isakmp_header (vbuf, iph2->ph1, nptype, ISAKMP_ETYPE_QUICK, iph2->flags, iph2->msgid);
+}
+
+/*
+ * set values into allocated buffer of isakmp payload.
+ */
+caddr_t
+set_isakmp_payload(buf, src, nptype)
+	caddr_t buf;
+	vchar_t *src;
+	int nptype;
+{
+	struct isakmp_gen *gen;
+	caddr_t p = buf;
+
+	plog(LLV_DEBUG, LOCATION, NULL, "add payload of len %zu, next type %d\n",
+	    src->l, nptype);
+
+	gen = (struct isakmp_gen *)p;
+	gen->np = nptype;
+	gen->len = htons(sizeof(*gen) + src->l);
+	p += sizeof(*gen);
+	memcpy(p, src->v, src->l);
+	p += src->l;
+
+	return p;
+}
+
+static int
+etypesw1(etype)
+	int etype;
+{
+	switch (etype) {
+	case ISAKMP_ETYPE_IDENT:
+		return 1;
+	case ISAKMP_ETYPE_AGG:
+		return 2;
+	case ISAKMP_ETYPE_BASE:
+		return 3;
+	default:
+		return 0;
+	}
+	/*NOTREACHED*/
+}
+
+static int
+etypesw2(etype)
+	int etype;
+{
+	switch (etype) {
+	case ISAKMP_ETYPE_QUICK:
+		return 1;
+	default:
+		return 0;
+	}
+	/*NOTREACHED*/
+}
+
+#ifdef HAVE_PRINT_ISAKMP_C
+/* for print-isakmp.c */
+char *snapend;
+extern void isakmp_print __P((const u_char *, u_int, const u_char *));
+
+char *getname __P((const u_char *));
+#ifdef INET6
+char *getname6 __P((const u_char *));
+#endif
+int safeputchar __P((int));
+
+/*
+ * Return a name for the IP address pointed to by ap.  This address
+ * is assumed to be in network byte order.
+ */
+char *
+getname(ap)
+	const u_char *ap;
+{
+	struct sockaddr_in addr;
+	static char ntop_buf[NI_MAXHOST];
+
+	memset(&addr, 0, sizeof(addr));
+#ifndef __linux__
+	addr.sin_len = sizeof(struct sockaddr_in);
+#endif
+	addr.sin_family = AF_INET;
+	memcpy(&addr.sin_addr, ap, sizeof(addr.sin_addr));
+	if (getnameinfo((struct sockaddr *)&addr, sizeof(addr),
+			ntop_buf, sizeof(ntop_buf), NULL, 0,
+			NI_NUMERICHOST | niflags))
+		strlcpy(ntop_buf, "?", sizeof(ntop_buf));
+
+	return ntop_buf;
+}
+
+#ifdef INET6
+/*
+ * Return a name for the IP6 address pointed to by ap.  This address
+ * is assumed to be in network byte order.
+ */
+char *
+getname6(ap)
+	const u_char *ap;
+{
+	struct sockaddr_in6 addr;
+	static char ntop_buf[NI_MAXHOST];
+
+	memset(&addr, 0, sizeof(addr));
+	addr.sin6_len = sizeof(struct sockaddr_in6);
+	addr.sin6_family = AF_INET6;
+	memcpy(&addr.sin6_addr, ap, sizeof(addr.sin6_addr));
+	if (getnameinfo((struct sockaddr *)&addr, addr.sin6_len,
+			ntop_buf, sizeof(ntop_buf), NULL, 0,
+			NI_NUMERICHOST | niflags))
+		strlcpy(ntop_buf, "?", sizeof(ntop_buf));
+
+	return ntop_buf;
+}
+#endif /* INET6 */
+
+int
+safeputchar(c)
+	int c;
+{
+	unsigned char ch;
+
+	ch = (unsigned char)(c & 0xff);
+	if (c < 0x80 && isprint(c))
+		return printf("%c", c & 0xff);
+	else
+		return printf("\\%03o", c & 0xff);
+}
+
+void
+isakmp_printpacket(msg, from, my, decoded)
+	vchar_t *msg;
+	struct sockaddr *from;
+	struct sockaddr *my;
+	int decoded;
+{
+#ifdef YIPS_DEBUG
+	struct timeval tv;
+	int s;
+	char hostbuf[NI_MAXHOST];
+	char portbuf[NI_MAXSERV];
+	struct isakmp *isakmp;
+	vchar_t *buf;
+#endif
+
+	if (loglevel < LLV_DEBUG)
+		return;
+
+#ifdef YIPS_DEBUG
+	plog(LLV_DEBUG, LOCATION, NULL, "begin.\n");
+
+	gettimeofday(&tv, NULL);
+	s = tv.tv_sec % 3600;
+	printf("%02d:%02d.%06u ", s / 60, s % 60, (u_int32_t)tv.tv_usec);
+
+	if (from) {
+		if (getnameinfo(from, sysdep_sa_len(from), hostbuf, sizeof(hostbuf),
+				portbuf, sizeof(portbuf),
+				NI_NUMERICHOST | NI_NUMERICSERV | niflags)) {
+			strlcpy(hostbuf, "?", sizeof(hostbuf));
+			strlcpy(portbuf, "?", sizeof(portbuf));
+		}
+		printf("%s:%s", hostbuf, portbuf);
+	} else
+		printf("?");
+	printf(" -> ");
+	if (my) {
+		if (getnameinfo(my, sysdep_sa_len(my), hostbuf, sizeof(hostbuf),
+				portbuf, sizeof(portbuf),
+				NI_NUMERICHOST | NI_NUMERICSERV | niflags)) {
+			strlcpy(hostbuf, "?", sizeof(hostbuf));
+			strlcpy(portbuf, "?", sizeof(portbuf));
+		}
+		printf("%s:%s", hostbuf, portbuf);
+	} else
+		printf("?");
+	printf(": ");
+
+	buf = vdup(msg);
+	if (!buf) {
+		printf("(malloc fail)\n");
+		return;
+	}
+	if (decoded) {
+		isakmp = (struct isakmp *)buf->v;
+		if (isakmp->flags & ISAKMP_FLAG_E) {
+#if 0
+			int pad;
+			pad = *(u_char *)(buf->v + buf->l - 1);
+			if (buf->l < pad && 2 < vflag)
+				printf("(wrong padding)");
+#endif
+			isakmp->flags &= ~ISAKMP_FLAG_E;
+		}
+	}
+
+	snapend = buf->v + buf->l;
+	isakmp_print(buf->v, buf->l, NULL);
+	vfree(buf);
+	printf("\n");
+	fflush(stdout);
+
+	return;
+#endif
+}
+#endif /*HAVE_PRINT_ISAKMP_C*/
+
+int
+copy_ph1addresses(iph1, rmconf, remote, local)
+	struct ph1handle *iph1;
+	struct remoteconf *rmconf;
+	struct sockaddr *remote, *local;
+{
+	u_int16_t port;
+
+	/* address portion must be grabbed from real remote address "remote" */
+	iph1->remote = dupsaddr(remote);
+	if (iph1->remote == NULL)
+		return -1;
+
+	/*
+	 * if remote has no port # (in case of initiator - from ACQUIRE msg)
+	 * - if remote.conf specifies port #, use that
+	 * - if remote.conf does not, use 500
+	 * if remote has port # (in case of responder - from recvfrom(2))
+	 * respect content of "remote".
+	 */
+	if (extract_port(iph1->remote) == 0) {
+		port = extract_port(rmconf->remote);
+		if (port == 0)
+			port = PORT_ISAKMP;
+		set_port(iph1->remote, port);
+	}
+
+	if (local == NULL)
+		iph1->local = getlocaladdr(iph1->remote);
+	else
+		iph1->local = dupsaddr(local);
+	if (iph1->local == NULL)
+		return -1;
+
+	if (extract_port(iph1->local) == 0)
+		set_port(iph1->local, PORT_ISAKMP);
+
+#ifdef ENABLE_NATT
+	if (extract_port(iph1->local) == lcconf->port_isakmp_natt) {
+		plog(LLV_DEBUG, LOCATION, NULL, "Marking ports as changed\n");
+		iph1->natt_flags |= NAT_ADD_NON_ESP_MARKER;
+	}
+#endif
+
+	return 0;
+}
+
+static int
+nostate1(iph1, msg)
+	struct ph1handle *iph1;
+	vchar_t *msg;
+{
+	plog(LLV_ERROR, LOCATION, iph1->remote, "wrong state %u.\n",
+			iph1->status);
+	return -1;
+}
+
+static int
+nostate2(iph2, msg)
+	struct ph2handle *iph2;
+	vchar_t *msg;
+{
+	plog(LLV_ERROR, LOCATION, iph2->ph1->remote, "wrong state %u.\n",
+		iph2->status);
+	return -1;
+}
+
+void
+log_ph1established(iph1)
+	const struct ph1handle *iph1;
+{
+	char *src, *dst;
+
+	src = racoon_strdup(saddr2str(iph1->local));
+	dst = racoon_strdup(saddr2str(iph1->remote));
+	STRDUP_FATAL(src);
+	STRDUP_FATAL(dst);
+
+	plog(LLV_INFO, LOCATION, NULL,
+		"ISAKMP-SA established %s-%s spi:%s\n",
+		src, dst,
+		isakmp_pindex(&iph1->index, 0));
+	
+	EVT_PUSH(iph1->local, iph1->remote, EVTT_PHASE1_UP, NULL);
+	if(!iph1->rmconf->mode_cfg)
+		EVT_PUSH(iph1->local, iph1->remote, EVTT_NO_ISAKMP_CFG, NULL);
+
+	racoon_free(src);
+	racoon_free(dst);
+
+	return;
+}
+
+struct payload_list *
+isakmp_plist_append (struct payload_list *plist, vchar_t *payload, int payload_type)
+{
+	if (! plist) {
+		plist = racoon_malloc (sizeof (struct payload_list));
+		plist->prev = NULL;
+	}
+	else {
+		plist->next = racoon_malloc (sizeof (struct payload_list));
+		plist->next->prev = plist;
+		plist = plist->next;
+	}
+
+	plist->next = NULL;
+	plist->payload = payload;
+	plist->payload_type = payload_type;
+
+	return plist;
+}
+
+vchar_t * 
+isakmp_plist_set_all (struct payload_list **plist, struct ph1handle *iph1)
+{
+	struct payload_list *ptr = *plist, *first;
+	size_t tlen = sizeof (struct isakmp), n = 0;
+	vchar_t *buf = NULL;
+	char *p;
+
+	/* Seek to the first item.  */
+	while (ptr->prev) ptr = ptr->prev;
+	first = ptr;
+	
+	/* Compute the whole length.  */
+	while (ptr) {
+		tlen += ptr->payload->l + sizeof (struct isakmp_gen);
+		ptr = ptr->next;
+	}
+
+	buf = vmalloc(tlen);
+	if (buf == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"failed to get buffer to send.\n");
+		goto end;
+	}
+
+	ptr = first;
+
+	p = set_isakmp_header1(buf, iph1, ptr->payload_type);
+	if (p == NULL)
+		goto end;
+
+	while (ptr)
+	{
+		p = set_isakmp_payload (p, ptr->payload, ptr->next ? ptr->next->payload_type : ISAKMP_NPTYPE_NONE);
+		first = ptr;
+		ptr = ptr->next;
+		racoon_free (first);
+		/* ptr->prev = NULL; first = NULL; ... omitted.  */
+		n++;
+	}
+
+	*plist = NULL;
+
+	return buf;
+end:
+	if (buf != NULL)
+		vfree(buf);
+	return NULL;
+}
+
+#ifdef ENABLE_FRAG
+int 
+frag_handler(iph1, msg, remote, local)
+	struct ph1handle *iph1;
+	vchar_t *msg;
+	struct sockaddr *remote;
+	struct sockaddr *local;
+{
+	vchar_t *newmsg;
+
+	if (isakmp_frag_extract(iph1, msg) == 1) {
+		if ((newmsg = isakmp_frag_reassembly(iph1)) == NULL) {
+			plog(LLV_ERROR, LOCATION, remote, 
+			    "Packet reassembly failed\n");
+			return -1;
+		}
+		return isakmp_main(newmsg, remote, local);
+	}
+
+	return 0;
+}
+#endif
+
+void
+script_hook(iph1, script)
+	struct ph1handle *iph1;
+	int script;
+{
+#define IP_MAX 40
+#define PORT_MAX 6
+	char addrstr[IP_MAX];
+	char portstr[PORT_MAX];
+	char **envp = NULL;
+	int envc = 1;
+	struct sockaddr_in *sin;
+	char **c;
+
+	if (iph1 == NULL ||
+		iph1->rmconf == NULL ||
+		iph1->rmconf->script[script] == NULL)
+		return;
+
+#ifdef ENABLE_HYBRID
+	(void)isakmp_cfg_setenv(iph1, &envp, &envc);
+#endif
+
+	/* local address */
+	sin = (struct sockaddr_in *)iph1->local;
+	inet_ntop(sin->sin_family, &sin->sin_addr, addrstr, IP_MAX);
+	snprintf(portstr, PORT_MAX, "%d", ntohs(sin->sin_port));
+
+	if (script_env_append(&envp, &envc, "LOCAL_ADDR", addrstr) != 0) {
+		plog(LLV_ERROR, LOCATION, NULL, "Cannot set LOCAL_ADDR\n");
+		goto out;
+	}
+
+	if (script_env_append(&envp, &envc, "LOCAL_PORT", portstr) != 0) {
+		plog(LLV_ERROR, LOCATION, NULL, "Cannot set LOCAL_PORT\n");
+		goto out;
+	}
+
+	/* Peer address */
+	if (iph1->remote != NULL) {
+		sin = (struct sockaddr_in *)iph1->remote;
+		inet_ntop(sin->sin_family, &sin->sin_addr, addrstr, IP_MAX);
+		snprintf(portstr, PORT_MAX, "%d", ntohs(sin->sin_port));
+
+		if (script_env_append(&envp, &envc, 
+		    "REMOTE_ADDR", addrstr) != 0) {
+			plog(LLV_ERROR, LOCATION, NULL, 
+			    "Cannot set REMOTE_ADDR\n");
+			goto out;
+		}
+
+		if (script_env_append(&envp, &envc, 
+		    "REMOTE_PORT", portstr) != 0) {
+			plog(LLV_ERROR, LOCATION, NULL, 
+			    "Cannot set REMOTEL_PORT\n");
+			goto out;
+		}
+	}
+
+	if (privsep_script_exec(iph1->rmconf->script[script]->v, 
+	    script, envp) != 0) 
+		plog(LLV_ERROR, LOCATION, NULL, 
+		    "Script %s execution failed\n", script_names[script]);
+
+out:
+	for (c = envp; *c; c++)
+		racoon_free(*c);
+
+	racoon_free(envp);
+
+	return;
+}
+
+int
+script_env_append(envp, envc, name, value)
+	char ***envp;
+	int *envc;
+	char *name;
+	char *value;
+{
+	char *envitem;
+	char **newenvp;
+	int newenvc;
+
+	envitem = racoon_malloc(strlen(name) + 1 + strlen(value) + 1);
+	if (envitem == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL,
+		    "Cannot allocate memory: %s\n", strerror(errno));
+		return -1;
+	}
+	sprintf(envitem, "%s=%s", name, value);
+
+	newenvc = (*envc) + 1;
+	newenvp = racoon_realloc(*envp, newenvc * sizeof(char *));
+	if (newenvp == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL,
+		    "Cannot allocate memory: %s\n", strerror(errno));
+		racoon_free(envitem);
+		return -1;
+	}
+
+	newenvp[newenvc - 2] = envitem;
+	newenvp[newenvc - 1] = NULL;
+
+	*envp = newenvp;
+	*envc = newenvc;
+	return 0;
+}
+
+int
+script_exec(script, name, envp)
+	char *script;
+	int name;
+	char *const envp[];
+{
+	char *argv[] = { NULL, NULL, NULL };
+
+	argv[0] = script;
+	argv[1] = script_names[name];
+	argv[2] = NULL;
+
+	switch (fork()) { 
+	case 0:
+		execve(argv[0], argv, envp);
+		plog(LLV_ERROR, LOCATION, NULL,
+		    "execve(\"%s\") failed: %s\n",
+		    argv[0], strerror(errno));
+		_exit(1);
+		break;
+	case -1:
+		plog(LLV_ERROR, LOCATION, NULL,
+		    "Cannot fork: %s\n", strerror(errno));
+		return -1;
+		break;
+	default:
+		break;
+	}	
+	return 0;
+
+}
+
+void
+purge_remote(iph1)
+	struct ph1handle *iph1;
+{
+	vchar_t *buf = NULL;
+	struct sadb_msg *msg, *next, *end;
+	struct sadb_sa *sa;
+	struct sockaddr *src, *dst;
+	caddr_t mhp[SADB_EXT_MAX + 1];
+	u_int proto_id;
+	struct ph2handle *iph2;
+	struct ph1handle *new_iph1;
+
+	plog(LLV_INFO, LOCATION, NULL,
+		 "purging ISAKMP-SA spi=%s.\n",
+		 isakmp_pindex(&(iph1->index), iph1->msgid));
+
+	/* Mark as expired. */
+	iph1->status = PHASE1ST_EXPIRED;
+
+	/* Check if we have another, still valid, phase1 SA. */
+	new_iph1 = getph1byaddr(iph1->local, iph1->remote, 1);
+
+	/*
+	 * Delete all orphaned or binded to the deleting ph1handle phase2 SAs.
+	 * Keep all others phase2 SAs.
+	 */
+	buf = pfkey_dump_sadb(SADB_SATYPE_UNSPEC);
+	if (buf == NULL) {
+		plog(LLV_DEBUG, LOCATION, NULL,
+			"pfkey_dump_sadb returned nothing.\n");
+		return;
+	}
+
+	msg = (struct sadb_msg *)buf->v;
+	end = (struct sadb_msg *)(buf->v + buf->l);
+
+	while (msg < end) {
+		if ((msg->sadb_msg_len << 3) < sizeof(*msg))
+			break;
+		next = (struct sadb_msg *)((caddr_t)msg + (msg->sadb_msg_len << 3));
+		if (msg->sadb_msg_type != SADB_DUMP) {
+			msg = next;
+			continue;
+		}
+
+		if (pfkey_align(msg, mhp) || pfkey_check(mhp)) {
+			plog(LLV_ERROR, LOCATION, NULL,
+				"pfkey_check (%s)\n", ipsec_strerror());
+			msg = next;
+			continue;
+		}
+
+		sa = (struct sadb_sa *)(mhp[SADB_EXT_SA]);
+		if (!sa ||
+		    !mhp[SADB_EXT_ADDRESS_SRC] ||
+		    !mhp[SADB_EXT_ADDRESS_DST]) {
+			msg = next;
+			continue;
+		}
+		src = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_SRC]);
+		dst = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_DST]);
+
+		if (sa->sadb_sa_state != SADB_SASTATE_LARVAL &&
+		    sa->sadb_sa_state != SADB_SASTATE_MATURE &&
+		    sa->sadb_sa_state != SADB_SASTATE_DYING) {
+			msg = next;
+			continue;
+		}
+
+		/*
+		 * check in/outbound SAs.
+		 * Select only SAs where src == local and dst == remote (outgoing)
+		 * or src == remote and dst == local (incoming).
+		 */
+		if ((CMPSADDR(iph1->local, src) || CMPSADDR(iph1->remote, dst)) &&
+			(CMPSADDR(iph1->local, dst) || CMPSADDR(iph1->remote, src))) {
+			msg = next;
+			continue;
+		}
+
+		proto_id = pfkey2ipsecdoi_proto(msg->sadb_msg_satype);
+		iph2 = getph2bysaidx(src, dst, proto_id, sa->sadb_sa_spi);
+
+		/* Check if there is another valid ISAKMP-SA */
+		if (new_iph1 != NULL) {
+
+			if (iph2 == NULL) {
+				/* No handler... still send a pfkey_delete message, but log this !*/
+				plog(LLV_INFO, LOCATION, NULL,
+					"Unknown IPsec-SA spi=%u, hmmmm?\n",
+					ntohl(sa->sadb_sa_spi));
+			}else{
+
+				/* 
+				 * If we have a new ph1, do not purge IPsec-SAs binded
+				 *  to a different ISAKMP-SA
+				 */
+				if (iph2->ph1 != NULL && iph2->ph1 != iph1){
+					msg = next;
+					continue;
+				}
+
+				/* If the ph2handle is established, do not purge IPsec-SA */
+				if (iph2->status == PHASE2ST_ESTABLISHED ||
+					iph2->status == PHASE2ST_EXPIRED) {
+					
+					plog(LLV_INFO, LOCATION, NULL,
+						 "keeping IPsec-SA spi=%u - found valid ISAKMP-SA spi=%s.\n",
+						 ntohl(sa->sadb_sa_spi),
+						 isakmp_pindex(&(new_iph1->index), new_iph1->msgid));
+					msg = next;
+					continue;
+				}
+			}
+		}
+
+		
+		pfkey_send_delete(lcconf->sock_pfkey,
+				  msg->sadb_msg_satype,
+				  IPSEC_MODE_ANY,
+				  src, dst, sa->sadb_sa_spi);
+
+		/* delete a relative phase 2 handle. */
+		if (iph2 != NULL) {
+			delete_spd(iph2, 0);
+			unbindph12(iph2);
+			remph2(iph2);
+			delph2(iph2);
+		}
+
+		plog(LLV_INFO, LOCATION, NULL,
+			 "purged IPsec-SA spi=%u.\n",
+			 ntohl(sa->sadb_sa_spi));
+
+		msg = next;
+	}
+
+	if (buf)
+		vfree(buf);
+
+	/* Mark the phase1 handler as EXPIRED */
+	plog(LLV_INFO, LOCATION, NULL,
+		 "purged ISAKMP-SA spi=%s.\n",
+		 isakmp_pindex(&(iph1->index), iph1->msgid));
+
+	SCHED_KILL(iph1->sce);
+
+	iph1->sce = sched_new(1, isakmp_ph1delete_stub, iph1);
+}
+
+void 
+delete_spd(iph2, created)
+	struct ph2handle *iph2;
+ 	u_int64_t created;
+{
+	struct policyindex spidx;
+	struct sockaddr_storage addr;
+	u_int8_t pref;
+	struct sockaddr *src;
+	struct sockaddr *dst;
+	int error;
+	int idi2type = 0;/* switch whether copy IDs into id[src,dst]. */
+
+	if (iph2 == NULL)
+		return;
+
+	/* Delete the SPD entry if we generated it
+	 */
+	if (! iph2->generated_spidx )
+		return;
+
+	src = iph2->src;
+	dst = iph2->dst;
+
+	plog(LLV_INFO, LOCATION, NULL,
+		 "generated policy, deleting it.\n");
+		
+	memset(&spidx, 0, sizeof(spidx));
+	iph2->spidx_gen = (caddr_t )&spidx;
+		
+	/* make inbound policy */
+	iph2->src = dst;
+	iph2->dst = src;
+	spidx.dir = IPSEC_DIR_INBOUND;
+	spidx.ul_proto = 0;
+		
+	/* 
+	 * Note: code from get_proposal_r
+	 */
+		
+#define _XIDT(d) ((struct ipsecdoi_id_b *)(d)->v)->type
+		
+	/*
+	 * make destination address in spidx from either ID payload
+	 * or phase 1 address into a address in spidx.
+	 */
+	if (iph2->id != NULL
+		&& (_XIDT(iph2->id) == IPSECDOI_ID_IPV4_ADDR
+			|| _XIDT(iph2->id) == IPSECDOI_ID_IPV6_ADDR
+			|| _XIDT(iph2->id) == IPSECDOI_ID_IPV4_ADDR_SUBNET
+			|| _XIDT(iph2->id) == IPSECDOI_ID_IPV6_ADDR_SUBNET)) {
+		/* get a destination address of a policy */
+		error = ipsecdoi_id2sockaddr(iph2->id,
+									 (struct sockaddr *)&spidx.dst,
+									 &spidx.prefd, &spidx.ul_proto);
+		if (error)
+			goto purge;
+			
+#ifdef INET6
+		/*
+		 * get scopeid from the SA address.
+		 * note that the phase 1 source address is used as
+		 * a destination address to search for a inbound 
+		 * policy entry because rcoon is responder.
+		 */
+		if (_XIDT(iph2->id) == IPSECDOI_ID_IPV6_ADDR) {
+			if ((error = 
+				 setscopeid((struct sockaddr *)&spidx.dst,
+							iph2->src)) != 0)
+				goto purge;
+		}
+#endif
+			
+		if (_XIDT(iph2->id) == IPSECDOI_ID_IPV4_ADDR
+			|| _XIDT(iph2->id) == IPSECDOI_ID_IPV6_ADDR)
+			idi2type = _XIDT(iph2->id);
+			
+	} else {
+			
+		plog(LLV_DEBUG, LOCATION, NULL,
+			 "get a destination address of SP index "
+			 "from phase1 address "
+			 "due to no ID payloads found "
+			 "OR because ID type is not address.\n");
+			
+		/*
+		 * copy the SOURCE address of IKE into the 
+		 * DESTINATION address of the key to search the 
+		 * SPD because the direction of policy is inbound.
+		 */
+		memcpy(&spidx.dst, iph2->src, sysdep_sa_len(iph2->src));
+		switch (spidx.dst.ss_family) {
+		case AF_INET:
+			spidx.prefd = 
+				sizeof(struct in_addr) << 3;
+			break;
+#ifdef INET6
+		case AF_INET6:
+			spidx.prefd = 
+				sizeof(struct in6_addr) << 3;
+			break;
+#endif
+		default:
+			spidx.prefd = 0;
+			break;
+		}
+	}
+					
+	/* make source address in spidx */
+	if (iph2->id_p != NULL
+		&& (_XIDT(iph2->id_p) == IPSECDOI_ID_IPV4_ADDR
+			|| _XIDT(iph2->id_p) == IPSECDOI_ID_IPV6_ADDR
+			|| _XIDT(iph2->id_p) == IPSECDOI_ID_IPV4_ADDR_SUBNET
+			|| _XIDT(iph2->id_p) == IPSECDOI_ID_IPV6_ADDR_SUBNET)) {
+		/* get a source address of inbound SA */
+		error = ipsecdoi_id2sockaddr(iph2->id_p,
+									 (struct sockaddr *)&spidx.src,
+									 &spidx.prefs, &spidx.ul_proto);
+		if (error)
+			goto purge;
+
+#ifdef INET6
+		/*
+		 * get scopeid from the SA address.
+		 * for more detail, see above of this function.
+		 */
+		if (_XIDT(iph2->id_p) == IPSECDOI_ID_IPV6_ADDR) {
+			error = 
+				setscopeid((struct sockaddr *)&spidx.src,
+						   iph2->dst);
+			if (error)
+				goto purge;
+		}
+#endif
+
+		/* make id[src,dst] if both ID types are IP address and same */
+		if (_XIDT(iph2->id_p) == idi2type
+			&& spidx.dst.ss_family == spidx.src.ss_family) {
+			iph2->src_id = 
+				dupsaddr((struct sockaddr *)&spidx.dst);
+			if (iph2->src_id == NULL) {
+				plog(LLV_ERROR, LOCATION, NULL,
+					 "allocation failed\n");
+				goto purge;
+			}
+			iph2->dst_id = 
+				dupsaddr((struct sockaddr *)&spidx.src);
+			if (iph2->dst_id == NULL) {
+				plog(LLV_ERROR, LOCATION, NULL,
+					 "allocation failed\n");
+				goto purge;
+			}
+		}
+
+	} else {
+		plog(LLV_DEBUG, LOCATION, NULL,
+			 "get a source address of SP index "
+			 "from phase1 address "
+			 "due to no ID payloads found "
+			 "OR because ID type is not address.\n");
+
+		/* see above comment. */
+		memcpy(&spidx.src, iph2->dst, sysdep_sa_len(iph2->dst));
+		switch (spidx.src.ss_family) {
+		case AF_INET:
+			spidx.prefs = 
+				sizeof(struct in_addr) << 3;
+			break;
+#ifdef INET6
+		case AF_INET6:
+			spidx.prefs = 
+				sizeof(struct in6_addr) << 3;
+			break;
+#endif
+		default:
+			spidx.prefs = 0;
+			break;
+		}
+	}
+
+#undef _XIDT
+
+	plog(LLV_DEBUG, LOCATION, NULL,
+		 "get a src address from ID payload "
+		 "%s prefixlen=%u ul_proto=%u\n",
+		 saddr2str((struct sockaddr *)&spidx.src),
+		 spidx.prefs, spidx.ul_proto);
+	plog(LLV_DEBUG, LOCATION, NULL,
+		 "get dst address from ID payload "
+		 "%s prefixlen=%u ul_proto=%u\n",
+		 saddr2str((struct sockaddr *)&spidx.dst),
+		 spidx.prefd, spidx.ul_proto);
+
+	/*
+	 * convert the ul_proto if it is 0
+	 * because 0 in ID payload means a wild card.
+	 */
+	if (spidx.ul_proto == 0)
+		spidx.ul_proto = IPSEC_ULPROTO_ANY;
+
+#undef _XIDT
+
+	/* Check if the generated SPD has the same timestamp as the SA.
+	 * If timestamps are different, this means that the SPD entry has been
+	 * refreshed by another SA, and should NOT be deleted with the current SA.
+	 */
+	if( created ){
+		struct secpolicy *p;
+		
+		p = getsp(&spidx);
+		if(p != NULL){
+			/* just do no test if p is NULL, because this probably just means
+			 * that the policy has already be deleted for some reason.
+			 */
+			if(p->spidx.created != created)
+				goto purge;
+		}
+	}
+
+	/* End of code from get_proposal_r
+	 */
+
+	if (pk_sendspddelete(iph2) < 0) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			 "pfkey spddelete(inbound) failed.\n");
+	}else{
+		plog(LLV_DEBUG, LOCATION, NULL,
+			 "pfkey spddelete(inbound) sent.\n");
+	}
+
+#ifdef HAVE_POLICY_FWD
+	/* make forward policy if required */
+	if (tunnel_mode_prop(iph2->approval)) {
+		spidx.dir = IPSEC_DIR_FWD;
+		if (pk_sendspddelete(iph2) < 0) {
+			plog(LLV_ERROR, LOCATION, NULL,
+				 "pfkey spddelete(forward) failed.\n");
+		}else{
+			plog(LLV_DEBUG, LOCATION, NULL,
+				 "pfkey spddelete(forward) sent.\n");
+		}
+	}
+#endif
+
+	/* make outbound policy */
+	iph2->src = src;
+	iph2->dst = dst;
+	spidx.dir = IPSEC_DIR_OUTBOUND;
+	addr = spidx.src;
+	spidx.src = spidx.dst;
+	spidx.dst = addr;
+	pref = spidx.prefs;
+	spidx.prefs = spidx.prefd;
+	spidx.prefd = pref;
+
+	if (pk_sendspddelete(iph2) < 0) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			 "pfkey spddelete(outbound) failed.\n");
+	}else{
+		plog(LLV_DEBUG, LOCATION, NULL,
+			 "pfkey spddelete(outbound) sent.\n");
+	}
+purge:
+	iph2->spidx_gen=NULL;
+}
+
+
+#ifdef INET6
+u_int32_t
+setscopeid(sp_addr0, sa_addr0)
+	struct sockaddr *sp_addr0, *sa_addr0;
+{
+	struct sockaddr_in6 *sp_addr, *sa_addr;
+    
+	sp_addr = (struct sockaddr_in6 *)sp_addr0;
+	sa_addr = (struct sockaddr_in6 *)sa_addr0;
+
+	if (!IN6_IS_ADDR_LINKLOCAL(&sp_addr->sin6_addr)
+	 && !IN6_IS_ADDR_SITELOCAL(&sp_addr->sin6_addr)
+	 && !IN6_IS_ADDR_MULTICAST(&sp_addr->sin6_addr))
+		return 0;
+
+	/* this check should not be here ? */
+	if (sa_addr->sin6_family != AF_INET6) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"can't get scope ID: family mismatch\n");
+		return -1;
+	}
+
+	if (!IN6_IS_ADDR_LINKLOCAL(&sa_addr->sin6_addr)) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"scope ID is not supported except of lladdr.\n");
+		return -1;
+	}
+
+	sp_addr->sin6_scope_id = sa_addr->sin6_scope_id;
+
+	return 0;
+}
+#endif
diff --git a/src/racoon/isakmp.h b/src/racoon/isakmp.h
new file mode 100644
index 0000000..d0fd242
--- /dev/null
+++ b/src/racoon/isakmp.h
@@ -0,0 +1,429 @@
+/*	$NetBSD: isakmp.h,v 1.4 2006/09/09 16:22:09 manu Exp $	*/
+
+/* Id: isakmp.h,v 1.11 2005/04/25 22:19:39 manubsd Exp */
+
+/*
+ * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _ISAKMP_H
+#define _ISAKMP_H
+
+/* refer to RFC 2408 */
+
+/* must include <netinet/in.h> first. */
+/* must include "isakmp_var.h" first. */
+
+#define INITIATOR	0	/* synonym sender */
+#define RESPONDER	1	/* synonym receiver */
+
+#define GENERATE	1
+#define VALIDATE	0
+
+/* 3.1 ISAKMP Header Format
+         0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+        !                          Initiator                            !
+        !                            Cookie                             !
+        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+        !                          Responder                            !
+        !                            Cookie                             !
+        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+        !  Next Payload ! MjVer ! MnVer ! Exchange Type !     Flags     !
+        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+        !                          Message ID                           !
+        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+        !                            Length                             !
+        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+*/
+struct isakmp {
+	cookie_t i_ck;		/* Initiator Cookie */
+	cookie_t r_ck;		/* Responder Cookie */
+	u_int8_t np;		/* Next Payload Type */
+	u_int8_t v;
+	u_int8_t etype;		/* Exchange Type */
+	u_int8_t flags;		/* Flags */
+	u_int32_t msgid;
+	u_int32_t len;		/* Length */
+} __attribute__((__packed__));
+
+/* Next Payload Type */
+#define ISAKMP_NPTYPE_NONE	0	/* NONE*/
+#define ISAKMP_NPTYPE_SA	1	/* Security Association */
+#define ISAKMP_NPTYPE_P		2	/* Proposal */
+#define ISAKMP_NPTYPE_T		3	/* Transform */
+#define ISAKMP_NPTYPE_KE	4	/* Key Exchange */
+#define ISAKMP_NPTYPE_ID	5	/* Identification */
+#define ISAKMP_NPTYPE_CERT	6	/* Certificate */
+#define ISAKMP_NPTYPE_CR	7	/* Certificate Request */
+#define ISAKMP_NPTYPE_HASH	8	/* Hash */
+#define ISAKMP_NPTYPE_SIG	9	/* Signature */
+#define ISAKMP_NPTYPE_NONCE	10	/* Nonce */
+#define ISAKMP_NPTYPE_N		11	/* Notification */
+#define ISAKMP_NPTYPE_D		12	/* Delete */
+#define ISAKMP_NPTYPE_VID	13	/* Vendor ID */
+#define ISAKMP_NPTYPE_ATTR	14	/* Attribute */
+
+
+/* NAT-T draft-ietf-ipsec-nat-t-ike-05 and later */
+/* XXX conflicts with values assigned to RFC 3547 */
+#define ISAKMP_NPTYPE_NATD_BADDRAFT		15	/* NAT Discovery */
+#define ISAKMP_NPTYPE_NATOA_BADDRAFT	16	/* NAT Original Address */
+
+
+/* NAT-T RFC */
+#define ISAKMP_NPTYPE_NATD_RFC	20	/* NAT Discovery */
+#define ISAKMP_NPTYPE_NATOA_RFC	21	/* NAT Original Address */
+
+/* NAT-T up to draft-ietf-ipsec-nat-t-ike-04 */
+#define ISAKMP_NPTYPE_NATD_DRAFT	130	/* NAT Discovery */
+#define ISAKMP_NPTYPE_NATOA_DRAFT	131	/* NAT Original Address */
+
+/* Frag does not seems to be documented */
+#define ISAKMP_NPTYPE_FRAG	132	/* IKE fragmentation payload */
+
+#define ISAKMP_NPTYPE_MAX	17
+			/*	128 - 255 Private Use */
+
+/*
+ * The following are valid when the Vendor ID is one of the
+ * following:
+ *
+ *	MD5("A GSS-API Authentication Method for IKE")
+ *	MD5("GSSAPI") (recognized by Windows 2000)
+ *	MD5("MS NT5 ISAKMPOAKLEY") (sent by Windows 2000)
+ *
+ * See draft-ietf-ipsec-isakmp-gss-auth-06.txt.
+ */
+#define ISAKMP_NPTYPE_GSS	129	/* GSS token */
+
+#define ISAKMP_MAJOR_VERSION	1
+#define ISAKMP_MINOR_VERSION	0
+#define ISAKMP_VERSION_NUMBER	0x10
+#define ISAKMP_GETMAJORV(v)	(((v) & 0xf0) >> 4)
+#define ISAKMP_SETMAJORV(v, m)	((v) = ((v) & 0x0f) | (((m) << 4) & 0xf0))
+#define ISAKMP_GETMINORV(v)	((v) & 0x0f)
+#define ISAKMP_SETMINORV(v, m)	((v) = ((v) & 0xf0) | ((m) & 0x0f))
+
+/* Exchange Type */
+#define ISAKMP_ETYPE_NONE	0	/* NONE */
+#define ISAKMP_ETYPE_BASE	1	/* Base */
+#define ISAKMP_ETYPE_IDENT	2	/* Identity Proteciton */
+#define ISAKMP_ETYPE_AUTH	3	/* Authentication Only */
+#define ISAKMP_ETYPE_AGG	4	/* Aggressive */
+#define ISAKMP_ETYPE_INFO	5	/* Informational */
+#define ISAKMP_ETYPE_CFG	6	/* Mode config */
+/* Additional Exchange Type */
+#define ISAKMP_ETYPE_QUICK	32	/* Quick Mode */
+#define ISAKMP_ETYPE_NEWGRP	33	/* New group Mode */
+#define ISAKMP_ETYPE_ACKINFO	34	/* Acknowledged Informational */
+
+/* Flags */
+#define ISAKMP_FLAG_E 0x01 /* Encryption Bit */
+#define ISAKMP_FLAG_C 0x02 /* Commit Bit */
+#define ISAKMP_FLAG_A 0x04 /* Authentication Only Bit */
+
+/* 3.2 Payload Generic Header
+         0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+        ! Next Payload  !   RESERVED    !         Payload Length        !
+        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+*/
+struct isakmp_gen {
+	u_int8_t np;		/* Next Payload */
+	u_int8_t reserved;	/* RESERVED, unused, must set to 0 */
+	u_int16_t len;		/* Payload Length */
+} __attribute__((__packed__));
+
+/* 3.3 Data Attributes
+         0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+        !A!       Attribute Type        !    AF=0  Attribute Length     !
+        !F!                             !    AF=1  Attribute Value      !
+        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+        .                   AF=0  Attribute Value                       .
+        .                   AF=1  Not Transmitted                       .
+        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+*/
+struct isakmp_data {
+	u_int16_t type;		/* defined by DOI-spec, and Attribute Format */
+	u_int16_t lorv;		/* if f equal 1, Attribute Length */
+				/* if f equal 0, Attribute Value */
+	/* if f equal 1, Attribute Value */
+} __attribute__((__packed__));
+#define ISAKMP_GEN_TLV 0x0000
+#define ISAKMP_GEN_TV  0x8000
+	/* mask for type of attribute format */
+#define ISAKMP_GEN_MASK 0x8000
+
+#if 0
+/* MAY NOT be used, because of being defined in ipsec-doi. */
+/* 3.4 Security Association Payload */
+struct isakmp_pl_sa {
+	struct isakmp_gen h;
+	u_int32_t doi;		/* Domain of Interpretation */
+	u_int32_t sit;		/* Situation */
+} __attribute__((__packed__));
+#endif
+
+/* 3.5 Proposal Payload */
+	/*
+	The value of the next payload field MUST only contain the value "2"
+	or "0".  If there are additional Proposal payloads in the message,
+	then this field will be 2.  If the current Proposal payload is the
+	last within the security association proposal, then this field will
+	be 0.
+	*/
+struct isakmp_pl_p {
+	struct isakmp_gen h;
+	u_int8_t p_no;		/* Proposal # */
+	u_int8_t proto_id;	/* Protocol */
+	u_int8_t spi_size;	/* SPI Size */
+	u_int8_t num_t;		/* Number of Transforms */
+	/* SPI */
+} __attribute__((__packed__));
+
+/* 3.6 Transform Payload */
+	/*
+	The value of the next payload field MUST only contain the value "3"
+	or "0".  If there are additional Transform payloads in the proposal,
+	then this field will be 3.  If the current Transform payload is the
+	last within the proposal, then this field will be 0.
+	*/
+struct isakmp_pl_t {
+	struct isakmp_gen h;
+	u_int8_t t_no;		/* Transform # */
+	u_int8_t t_id;		/* Transform-Id */
+	u_int16_t reserved;	/* RESERVED2 */
+	/* SA Attributes */
+} __attribute__((__packed__));
+
+/* 3.7 Key Exchange Payload */
+struct isakmp_pl_ke {
+	struct isakmp_gen h;
+	/* Key Exchange Data */
+} __attribute__((__packed__));
+
+#if 0
+/* NOTE: MUST NOT use because of being defined in ipsec-doi instead them. */
+/* 3.8 Identification Payload */
+struct isakmp_pl_id {
+	struct isakmp_gen h;
+	union {
+		u_int8_t id_type;	/* ID Type */
+		u_int32_t doi_data;	/* DOI Specific ID Data */
+	} d;
+	/* Identification Data */
+} __attribute__((__packed__));
+/* A.4 ISAKMP Identification Type Values */
+#define ISAKMP_ID_IPV4_ADDR		0
+#define ISAKMP_ID_IPV4_ADDR_SUBNET	1
+#define ISAKMP_ID_IPV6_ADDR		2
+#define ISAKMP_ID_IPV6_ADDR_SUBNET	3
+#endif
+
+/* 3.9 Certificate Payload */
+struct isakmp_pl_cert {
+	struct isakmp_gen h;
+	/*
+	 * Encoding type of 1 octet follows immediately,
+	 * variable length CERT data follows encoding type.
+	 */
+} __attribute__((__packed__));
+
+/* Certificate Type */
+#define ISAKMP_CERT_NONE	0
+#define ISAKMP_CERT_PKCS7	1
+#define ISAKMP_CERT_PGP		2
+#define ISAKMP_CERT_DNS		3
+#define ISAKMP_CERT_X509SIGN	4
+#define ISAKMP_CERT_X509KE	5
+#define ISAKMP_CERT_KERBEROS	6
+#define ISAKMP_CERT_CRL		7
+#define ISAKMP_CERT_ARL		8
+#define ISAKMP_CERT_SPKI	9
+#define ISAKMP_CERT_X509ATTR	10
+#define ISAKMP_CERT_PLAINRSA	11
+
+/* the method to get peers certificate */
+#define ISAKMP_GETCERT_PAYLOAD		1
+#define ISAKMP_GETCERT_LOCALFILE	2
+#define ISAKMP_GETCERT_DNS		3
+
+/* 3.10 Certificate Request Payload */
+struct isakmp_pl_cr {
+	struct isakmp_gen h;
+	u_int8_t num_cert; /* # Cert. Types */
+	/*
+	Certificate Types (variable length)
+	  -- Contains a list of the types of certificates requested,
+	  sorted in order of preference.  Each individual certificate
+	  type is 1 octet.  This field is NOT required.
+	*/
+	/* # Certificate Authorities (1 octet) */
+	/* Certificate Authorities (variable length) */
+} __attribute__((__packed__));
+
+/* 3.11 Hash Payload */
+struct isakmp_pl_hash {
+	struct isakmp_gen h;
+	/* Hash Data */
+} __attribute__((__packed__));
+
+/* 3.12 Signature Payload */
+struct isakmp_pl_sig {
+	struct isakmp_gen h;
+	/* Signature Data */
+} __attribute__((__packed__));
+
+/* 3.13 Nonce Payload */
+struct isakmp_pl_nonce {
+	struct isakmp_gen h;
+	/* Nonce Data */
+} __attribute__((__packed__));
+
+/* 3.14 Notification Payload */
+struct isakmp_pl_n {
+	struct isakmp_gen h;
+	u_int32_t doi;		/* Domain of Interpretation */
+	u_int8_t proto_id;	/* Protocol-ID */
+	u_int8_t spi_size;	/* SPI Size */
+	u_int16_t type;		/* Notify Message Type */
+	/* SPI */
+	/* Notification Data */
+} __attribute__((__packed__));
+
+/* 3.14.1 Notify Message Types */
+/* NOTIFY MESSAGES - ERROR TYPES */
+#define ISAKMP_NTYPE_INVALID_PAYLOAD_TYPE	1
+#define ISAKMP_NTYPE_DOI_NOT_SUPPORTED		2
+#define ISAKMP_NTYPE_SITUATION_NOT_SUPPORTED	3
+#define ISAKMP_NTYPE_INVALID_COOKIE		4
+#define ISAKMP_NTYPE_INVALID_MAJOR_VERSION	5
+#define ISAKMP_NTYPE_INVALID_MINOR_VERSION	6
+#define ISAKMP_NTYPE_INVALID_EXCHANGE_TYPE	7
+#define ISAKMP_NTYPE_INVALID_FLAGS		8
+#define ISAKMP_NTYPE_INVALID_MESSAGE_ID		9
+#define ISAKMP_NTYPE_INVALID_PROTOCOL_ID	10
+#define ISAKMP_NTYPE_INVALID_SPI		11
+#define ISAKMP_NTYPE_INVALID_TRANSFORM_ID	12
+#define ISAKMP_NTYPE_ATTRIBUTES_NOT_SUPPORTED	13
+#define ISAKMP_NTYPE_NO_PROPOSAL_CHOSEN		14
+#define ISAKMP_NTYPE_BAD_PROPOSAL_SYNTAX	15
+#define ISAKMP_NTYPE_PAYLOAD_MALFORMED		16
+#define ISAKMP_NTYPE_INVALID_KEY_INFORMATION	17
+#define ISAKMP_NTYPE_INVALID_ID_INFORMATION	18
+#define ISAKMP_NTYPE_INVALID_CERT_ENCODING	19
+#define ISAKMP_NTYPE_INVALID_CERTIFICATE	20
+#define ISAKMP_NTYPE_BAD_CERT_REQUEST_SYNTAX	21
+#define ISAKMP_NTYPE_INVALID_CERT_AUTHORITY	22
+#define ISAKMP_NTYPE_INVALID_HASH_INFORMATION	23
+#define ISAKMP_NTYPE_AUTHENTICATION_FAILED	24
+#define ISAKMP_NTYPE_INVALID_SIGNATURE		25
+#define ISAKMP_NTYPE_ADDRESS_NOTIFICATION	26
+#define ISAKMP_NTYPE_NOTIFY_SA_LIFETIME		27
+#define ISAKMP_NTYPE_CERTIFICATE_UNAVAILABLE	28
+#define ISAKMP_NTYPE_UNSUPPORTED_EXCHANGE_TYPE	29
+#define ISAKMP_NTYPE_UNEQUAL_PAYLOAD_LENGTHS	30
+#define ISAKMP_NTYPE_MINERROR			1
+#define ISAKMP_NTYPE_MAXERROR			16383
+/* NOTIFY MESSAGES - STATUS TYPES */
+#define ISAKMP_NTYPE_CONNECTED			16384
+/* 4.6.3 IPSEC DOI Notify Message Types */
+#define ISAKMP_NTYPE_RESPONDER_LIFETIME		24576
+#define ISAKMP_NTYPE_REPLAY_STATUS		24577
+#define ISAKMP_NTYPE_INITIAL_CONTACT		24578
+
+/* DPD */
+#define ISAKMP_NTYPE_R_U_THERE			36136
+#define ISAKMP_NTYPE_R_U_THERE_ACK		36137
+
+#define ISAKMP_NTYPE_HEARTBEAT			40503
+
+/* using only to log */
+#define ISAKMP_LOG_RETRY_LIMIT_REACHED		65530
+
+/* XXX means internal error but it's not reserved by any drafts... */
+#define ISAKMP_INTERNAL_ERROR			-1
+
+/* 3.15 Delete Payload */
+struct isakmp_pl_d {
+	struct isakmp_gen h;
+	u_int32_t doi;		/* Domain of Interpretation */
+	u_int8_t proto_id;	/* Protocol-Id */
+	u_int8_t spi_size;	/* SPI Size */
+	u_int16_t num_spi;	/* # of SPIs */
+	/* SPI(es) */
+} __attribute__((__packed__));
+
+struct payload_list {
+	struct payload_list	*next, *prev;
+	vchar_t			*payload;
+	int			payload_type;
+};
+
+
+/* See draft-ietf-ipsec-isakmp-mode-cfg-04.txt, 3.2 */
+struct isakmp_pl_attr {
+	struct isakmp_gen h;
+	u_int8_t type;		/* Exchange type */
+	u_int8_t res2;
+	u_int16_t id;		/* Per transaction id */
+} __attribute__((__packed__));
+            
+/* Exchange type */
+#define ISAKMP_CFG_REQUEST	1
+#define ISAKMP_CFG_REPLY	2
+#define ISAKMP_CFG_SET		3
+#define ISAKMP_CFG_ACK		4
+
+/* IKE fragmentation payload */
+struct isakmp_frag {
+	u_int16_t unknown0;	/* always set to zero? */
+	u_int16_t len;
+	u_int16_t unknown1;	/* always set to 1? */
+	u_int8_t index;
+	u_int8_t flags;
+} __attribute__((__packed__)); 
+
+/* flags */
+#define ISAKMP_FRAG_LAST	1
+
+/* DPD R-U-THERE / R-U-THERE-ACK Payload */
+struct isakmp_pl_ru {
+	struct isakmp_gen h;
+	u_int32_t doi;		/* Domain of Interpretation */
+	u_int8_t proto_id;	/* Protocol-Id */
+	u_int8_t spi_size;	/* SPI Size */
+	u_int16_t type;		/* Notify type */
+	cookie_t  i_ck;	/* Initiator Cookie */
+	cookie_t r_ck;	/* Responder cookie*/
+	u_int32_t data;		/* Notification data */
+} __attribute__((__packed__));
+
+#endif /* _ISAKMP_H */
diff --git a/src/racoon/isakmp_agg.c b/src/racoon/isakmp_agg.c
new file mode 100644
index 0000000..0d43883
--- /dev/null
+++ b/src/racoon/isakmp_agg.c
@@ -0,0 +1,1546 @@
+/*	$NetBSD: isakmp_agg.c,v 1.9 2006/09/30 21:49:37 manu Exp $	*/
+
+/* Id: isakmp_agg.c,v 1.28 2006/04/06 16:46:08 manubsd Exp */
+
+/*
+ * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* Aggressive Exchange (Aggressive Mode) */
+
+#include "config.h"
+
+#include <sys/types.h>
+#include <sys/param.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#if TIME_WITH_SYS_TIME
+# include <sys/time.h>
+# include <time.h>
+#else
+# if HAVE_SYS_TIME_H
+#  include <sys/time.h>
+# else
+#  include <time.h>
+# endif
+#endif
+
+#include "var.h"
+#include "misc.h"
+#include "vmbuf.h"
+#include "plog.h"
+#include "sockmisc.h"
+#include "schedule.h"
+#include "debug.h"
+
+#ifdef ENABLE_HYBRID
+#include <resolv.h>
+#endif
+
+#include "localconf.h"
+#include "remoteconf.h"
+#include "isakmp_var.h"
+#include "isakmp.h"
+#include "evt.h"
+#include "oakley.h"
+#include "handler.h"
+#include "ipsec_doi.h"
+#include "crypto_openssl.h"
+#include "pfkey.h"
+#include "isakmp_agg.h"
+#include "isakmp_inf.h"
+#ifdef ENABLE_HYBRID
+#include "isakmp_xauth.h"
+#include "isakmp_cfg.h"
+#endif
+#ifdef ENABLE_FRAG
+#include "isakmp_frag.h"
+#endif
+#include "vendorid.h"
+#include "strnames.h"
+
+#ifdef ENABLE_NATT
+#include "nattraversal.h"
+#endif
+
+#ifdef HAVE_GSSAPI
+#include "gssapi.h"
+#endif
+
+/*
+ * begin Aggressive Mode as initiator.
+ */
+/*
+ * send to responder
+ * 	psk: HDR, SA, KE, Ni, IDi1
+ * 	sig: HDR, SA, KE, Ni, IDi1 [, CR ]
+ *   gssapi: HDR, SA, KE, Ni, IDi1, GSSi
+ * 	rsa: HDR, SA, [ HASH(1),] KE, <IDi1_b>Pubkey_r, <Ni_b>Pubkey_r
+ * 	rev: HDR, SA, [ HASH(1),] <Ni_b>Pubkey_r, <KE_b>Ke_i,
+ * 	     <IDii_b>Ke_i [, <Cert-I_b>Ke_i ]
+ */
+int
+agg_i1send(iph1, msg)
+	struct ph1handle *iph1;
+	vchar_t *msg; /* must be null */
+{
+	struct payload_list *plist = NULL;
+	int need_cr = 0;
+	vchar_t *cr = NULL; 
+	int error = -1;
+#ifdef ENABLE_NATT
+	vchar_t *vid_natt[MAX_NATT_VID_COUNT] = { NULL };
+	int i;
+#endif
+#ifdef ENABLE_HYBRID
+	vchar_t *vid_xauth = NULL;
+	vchar_t *vid_unity = NULL;
+#endif
+#ifdef ENABLE_FRAG
+	vchar_t *vid_frag = NULL;
+#endif
+#ifdef HAVE_GSSAPI
+	vchar_t *gsstoken = NULL;
+	int len;
+#endif
+#ifdef ENABLE_DPD
+	vchar_t *vid_dpd = NULL;
+#endif
+
+
+	/* validity check */
+	if (msg != NULL) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"msg has to be NULL in this function.\n");
+		goto end;
+	}
+	if (iph1->status != PHASE1ST_START) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"status mismatched %d.\n", iph1->status);
+		goto end;
+	}
+
+	/* create isakmp index */
+	memset(&iph1->index, 0, sizeof(iph1->index));
+	isakmp_newcookie((caddr_t)&iph1->index, iph1->remote, iph1->local);
+
+	/* make ID payload into isakmp status */
+	if (ipsecdoi_setid1(iph1) < 0)
+		goto end;
+
+	/* create SA payload for my proposal */
+	iph1->sa = ipsecdoi_setph1proposal(iph1->rmconf->proposal);
+	if (iph1->sa == NULL)
+		goto end;
+
+	/* consistency check of proposals */
+	if (iph1->rmconf->dhgrp == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"configuration failure about DH group.\n");
+		goto end;
+	}
+
+	/* generate DH public value */
+	if (oakley_dh_generate(iph1->rmconf->dhgrp,
+				&iph1->dhpub, &iph1->dhpriv) < 0)
+		goto end;
+
+	/* generate NONCE value */
+	iph1->nonce = eay_set_random(iph1->rmconf->nonce_size);
+	if (iph1->nonce == NULL)
+		goto end;
+
+#ifdef ENABLE_HYBRID
+	/* Do we need Xauth VID? */
+	switch (RMAUTHMETHOD(iph1)) {
+	case FICTIVE_AUTH_METHOD_XAUTH_PSKEY_I:
+	case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_I:
+	case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_I:
+	case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_I:
+	case OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_I:
+	case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAENC_I:
+	case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAREV_I:
+		if ((vid_xauth = set_vendorid(VENDORID_XAUTH)) == NULL)
+			plog(LLV_ERROR, LOCATION, NULL, 
+			     "Xauth vendor ID generation failed\n");
+		if ((vid_unity = set_vendorid(VENDORID_UNITY)) == NULL)
+			plog(LLV_ERROR, LOCATION, NULL, 
+			     "Unity vendor ID generation failed\n");
+		break;
+	default:
+		break;
+	}
+#endif
+
+#ifdef ENABLE_FRAG
+	if (iph1->rmconf->ike_frag) {
+		vid_frag = set_vendorid(VENDORID_FRAG);
+		if (vid_frag != NULL)
+			vid_frag = isakmp_frag_addcap(vid_frag,
+			    VENDORID_FRAG_AGG);
+		if (vid_frag == NULL)
+			plog(LLV_ERROR, LOCATION, NULL,
+			    "Frag vendorID construction failed\n");
+	}		
+#endif
+
+	/* create CR if need */
+	if (iph1->rmconf->send_cr
+	 && oakley_needcr(iph1->rmconf->proposal->authmethod)
+	 && iph1->rmconf->peerscertfile == NULL) {
+		need_cr = 1;
+		cr = oakley_getcr(iph1);
+		if (cr == NULL) {
+			plog(LLV_ERROR, LOCATION, NULL,
+				"failed to get cr buffer.\n");
+			goto end;
+		}
+	}
+
+	plog(LLV_DEBUG, LOCATION, NULL, "authmethod is %s\n",
+		s_oakley_attr_method(iph1->rmconf->proposal->authmethod));
+#ifdef HAVE_GSSAPI
+	if (RMAUTHMETHOD(iph1) == OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB)
+		gssapi_get_itoken(iph1, &len);
+#endif
+
+	/* set SA payload to propose */
+	plist = isakmp_plist_append(plist, iph1->sa, ISAKMP_NPTYPE_SA);
+
+	/* create isakmp KE payload */
+	plist = isakmp_plist_append(plist, iph1->dhpub, ISAKMP_NPTYPE_KE);
+
+	/* create isakmp NONCE payload */
+	plist = isakmp_plist_append(plist, iph1->nonce, ISAKMP_NPTYPE_NONCE);
+
+	/* create isakmp ID payload */
+	plist = isakmp_plist_append(plist, iph1->id, ISAKMP_NPTYPE_ID);
+
+#ifdef HAVE_GSSAPI
+	if (RMAUTHMETHOD(iph1) == OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB) {
+		gssapi_get_token_to_send(iph1, &gsstoken);
+		plist = isakmp_plist_append(plist, gsstoken, ISAKMP_NPTYPE_GSS);
+	}
+#endif
+	/* create isakmp CR payload */
+	if (need_cr)
+		plist = isakmp_plist_append(plist, cr, ISAKMP_NPTYPE_CR);
+
+#ifdef ENABLE_FRAG
+	if (vid_frag)
+		plist = isakmp_plist_append(plist, vid_frag, ISAKMP_NPTYPE_VID);
+#endif
+#ifdef ENABLE_NATT
+	/* 
+	 * set VID payload for NAT-T if NAT-T 
+	 * support allowed in the config file 
+	 */
+	if (iph1->rmconf->nat_traversal) 
+		plist = isakmp_plist_append_natt_vids(plist, vid_natt);
+#endif
+#ifdef ENABLE_HYBRID
+	if (vid_xauth)
+		plist = isakmp_plist_append(plist, 
+		    vid_xauth, ISAKMP_NPTYPE_VID);
+	if (vid_unity)
+		plist = isakmp_plist_append(plist, 
+		    vid_unity, ISAKMP_NPTYPE_VID);
+#endif
+#ifdef ENABLE_DPD
+	if(iph1->rmconf->dpd){
+		vid_dpd = set_vendorid(VENDORID_DPD);
+		if (vid_dpd != NULL)
+			plist = isakmp_plist_append(plist, vid_dpd, ISAKMP_NPTYPE_VID);
+	}
+#endif
+
+	iph1->sendbuf = isakmp_plist_set_all (&plist, iph1);
+
+#ifdef HAVE_PRINT_ISAKMP_C
+	isakmp_printpacket(iph1->sendbuf, iph1->local, iph1->remote, 0);
+#endif
+
+	/* send the packet, add to the schedule to resend */
+	iph1->retry_counter = iph1->rmconf->retry_counter;
+	if (isakmp_ph1resend(iph1) == -1)
+		goto end;
+
+	iph1->status = PHASE1ST_MSG1SENT;
+
+	error = 0;
+
+end:
+	if (cr)
+		vfree(cr);
+#ifdef HAVE_GSSAPI
+	if (gsstoken)
+		vfree(gsstoken);
+#endif
+#ifdef ENABLE_FRAG
+	if (vid_frag)
+		vfree(vid_frag);
+#endif
+#ifdef ENABLE_NATT
+	for (i = 0; i < MAX_NATT_VID_COUNT && vid_natt[i] != NULL; i++)
+		vfree(vid_natt[i]);
+#endif
+#ifdef ENABLE_HYBRID
+	if (vid_xauth != NULL)
+		vfree(vid_xauth);
+	if (vid_unity != NULL)
+		vfree(vid_unity);
+#endif
+#ifdef ENABLE_DPD
+	if (vid_dpd != NULL)
+		vfree(vid_dpd);
+#endif
+
+	return error;
+}
+
+/*
+ * receive from responder
+ * 	psk: HDR, SA, KE, Nr, IDr1, HASH_R
+ * 	sig: HDR, SA, KE, Nr, IDr1, [ CR, ] [ CERT, ] SIG_R
+ *   gssapi: HDR, SA, KE, Nr, IDr1, GSSr, HASH_R
+ * 	rsa: HDR, SA, KE, <IDr1_b>PubKey_i, <Nr_b>PubKey_i, HASH_R
+ * 	rev: HDR, SA, <Nr_b>PubKey_i, <KE_b>Ke_r, <IDir_b>Ke_r, HASH_R
+ */
+int
+agg_i2recv(iph1, msg)
+	struct ph1handle *iph1;
+	vchar_t *msg;
+{
+	vchar_t *pbuf = NULL;
+	struct isakmp_parse_t *pa;
+	vchar_t *satmp = NULL;
+	int error = -1;
+	int vid_numeric;
+	int ptype;
+#ifdef ENABLE_HYBRID
+	vchar_t *unity_vid;
+	vchar_t *xauth_vid;
+#endif
+#ifdef HAVE_GSSAPI
+	vchar_t *gsstoken = NULL;
+#endif
+
+#ifdef ENABLE_NATT
+	int natd_seq = 0;
+	struct natd_payload {
+		int seq;
+		vchar_t *payload;
+		TAILQ_ENTRY(natd_payload) chain;
+	};
+	TAILQ_HEAD(_natd_payload, natd_payload) natd_tree;
+	TAILQ_INIT(&natd_tree);
+#endif
+
+	/* validity check */
+	if (iph1->status != PHASE1ST_MSG1SENT) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"status mismatched %d.\n", iph1->status);
+		goto end;
+	}
+
+	/* validate the type of next payload */
+	pbuf = isakmp_parse(msg);
+	if (pbuf == NULL)
+		goto end;
+	pa = (struct isakmp_parse_t *)pbuf->v;
+
+	iph1->pl_hash = NULL;
+
+	/* SA payload is fixed postion */
+	if (pa->type != ISAKMP_NPTYPE_SA) {
+		plog(LLV_ERROR, LOCATION, iph1->remote,
+			"received invalid next payload type %d, "
+			"expecting %d.\n",
+			pa->type, ISAKMP_NPTYPE_SA);
+		goto end;
+	}
+
+	if (isakmp_p2ph(&satmp, pa->ptr) < 0)
+		goto end;
+	pa++;
+
+	for (/*nothing*/;
+	     pa->type != ISAKMP_NPTYPE_NONE;
+	     pa++) {
+
+		switch (pa->type) {
+		case ISAKMP_NPTYPE_KE:
+			if (isakmp_p2ph(&iph1->dhpub_p, pa->ptr) < 0)
+				goto end;
+			break;
+		case ISAKMP_NPTYPE_NONCE:
+			if (isakmp_p2ph(&iph1->nonce_p, pa->ptr) < 0)
+				goto end;
+			break;
+		case ISAKMP_NPTYPE_ID:
+			if (isakmp_p2ph(&iph1->id_p, pa->ptr) < 0)
+				goto end;
+			break;
+		case ISAKMP_NPTYPE_HASH:
+			iph1->pl_hash = (struct isakmp_pl_hash *)pa->ptr;
+			break;
+		case ISAKMP_NPTYPE_CR:
+			if (oakley_savecr(iph1, pa->ptr) < 0)
+				goto end;
+			break;
+		case ISAKMP_NPTYPE_CERT:
+			if (oakley_savecert(iph1, pa->ptr) < 0)
+				goto end;
+			break;
+		case ISAKMP_NPTYPE_SIG:
+			if (isakmp_p2ph(&iph1->sig_p, pa->ptr) < 0)
+				goto end;
+			break;
+		case ISAKMP_NPTYPE_VID:
+			vid_numeric = check_vendorid(pa->ptr);
+#ifdef ENABLE_NATT
+			if (iph1->rmconf->nat_traversal && 
+			    natt_vendorid(vid_numeric))
+				natt_handle_vendorid(iph1, vid_numeric);
+#endif
+#ifdef ENABLE_HYBRID
+			switch (vid_numeric) {
+			case VENDORID_XAUTH:
+				iph1->mode_cfg->flags |= 
+				    ISAKMP_CFG_VENDORID_XAUTH;
+				break;
+
+			case VENDORID_UNITY:
+				iph1->mode_cfg->flags |= 
+				    ISAKMP_CFG_VENDORID_UNITY;
+				break;
+			default:
+				break;
+			}
+#endif
+#ifdef ENABLE_DPD
+			if (vid_numeric == VENDORID_DPD && iph1->rmconf->dpd) {
+				iph1->dpd_support=1;
+				plog(LLV_DEBUG, LOCATION, NULL,
+					 "remote supports DPD\n");
+			}
+#endif
+			break;
+		case ISAKMP_NPTYPE_N:
+			isakmp_check_notify(pa->ptr, iph1);
+			break;
+#ifdef HAVE_GSSAPI
+		case ISAKMP_NPTYPE_GSS:
+			if (isakmp_p2ph(&gsstoken, pa->ptr) < 0)
+				goto end;
+			gssapi_save_received_token(iph1, gsstoken);
+			break;
+#endif
+
+#ifdef ENABLE_NATT
+		case ISAKMP_NPTYPE_NATD_DRAFT:
+		case ISAKMP_NPTYPE_NATD_RFC:
+			if (NATT_AVAILABLE(iph1) && iph1->natt_options != NULL &&
+			    pa->type == iph1->natt_options->payload_nat_d) {
+				struct natd_payload *natd;
+				natd = (struct natd_payload *)racoon_malloc(sizeof(*natd));
+				if (!natd)
+					goto end;
+
+				natd->payload = NULL;
+
+				if (isakmp_p2ph (&natd->payload, pa->ptr) < 0)
+					goto end;
+
+				natd->seq = natd_seq++;
+
+				TAILQ_INSERT_TAIL(&natd_tree, natd, chain);
+				break;
+			}
+			/* passthrough to default... */
+#endif
+
+		default:
+			/* don't send information, see isakmp_ident_r1() */
+			plog(LLV_ERROR, LOCATION, iph1->remote,
+				"ignore the packet, "
+				"received unexpecting payload type %d.\n",
+				pa->type);
+			goto end;
+		}
+	}
+
+	/* payload existency check */
+	if (iph1->dhpub_p == NULL || iph1->nonce_p == NULL) {
+		plog(LLV_ERROR, LOCATION, iph1->remote,
+			"few isakmp message received.\n");
+		goto end;
+	}
+
+	/* verify identifier */
+	if (ipsecdoi_checkid1(iph1) != 0) {
+		plog(LLV_ERROR, LOCATION, iph1->remote,
+			"invalid ID payload.\n");
+		goto end;
+	}
+
+	/* check SA payload and set approval SA for use */
+	if (ipsecdoi_checkph1proposal(satmp, iph1) < 0) {
+		plog(LLV_ERROR, LOCATION, iph1->remote,
+			"failed to get valid proposal.\n");
+		/* XXX send information */
+		goto end;
+	}
+	VPTRINIT(iph1->sa_ret);
+
+	/* fix isakmp index */
+	memcpy(&iph1->index.r_ck, &((struct isakmp *)msg->v)->r_ck,
+		sizeof(cookie_t));
+
+#ifdef ENABLE_NATT
+	if (NATT_AVAILABLE(iph1)) {
+		struct natd_payload *natd = NULL;
+		int natd_verified;
+		
+		plog(LLV_INFO, LOCATION, iph1->remote,
+		     "Selected NAT-T version: %s\n",
+		     vid_string_by_id(iph1->natt_options->version));
+
+		/* set both bits first so that we can clear them
+		   upon verifying hashes */
+		iph1->natt_flags |= NAT_DETECTED;
+                        
+		while ((natd = TAILQ_FIRST(&natd_tree)) != NULL) {
+			/* this function will clear appropriate bits bits 
+			   from iph1->natt_flags */
+			natd_verified = natt_compare_addr_hash (iph1,
+				natd->payload, natd->seq);
+
+			plog (LLV_INFO, LOCATION, NULL, "NAT-D payload #%d %s\n",
+				natd->seq - 1,
+				natd_verified ? "verified" : "doesn't match");
+			
+			vfree (natd->payload);
+
+			TAILQ_REMOVE(&natd_tree, natd, chain);
+			racoon_free (natd);
+		}
+
+		plog (LLV_INFO, LOCATION, NULL, "NAT %s %s%s\n",
+		      iph1->natt_flags & NAT_DETECTED ? 
+		      		"detected:" : "not detected",
+		      iph1->natt_flags & NAT_DETECTED_ME ? "ME " : "",
+		      iph1->natt_flags & NAT_DETECTED_PEER ? "PEER" : "");
+
+		if (iph1->natt_flags & NAT_DETECTED)
+			natt_float_ports (iph1);
+	}
+#endif
+
+	/* compute sharing secret of DH */
+	if (oakley_dh_compute(iph1->rmconf->dhgrp, iph1->dhpub,
+				iph1->dhpriv, iph1->dhpub_p, &iph1->dhgxy) < 0)
+		goto end;
+
+	/* generate SKEYIDs & IV & final cipher key */
+	if (oakley_skeyid(iph1) < 0)
+		goto end;
+	if (oakley_skeyid_dae(iph1) < 0)
+		goto end;
+	if (oakley_compute_enckey(iph1) < 0)
+		goto end;
+	if (oakley_newiv(iph1) < 0)
+		goto end;
+
+	/* validate authentication value */
+	ptype = oakley_validate_auth(iph1);
+	if (ptype != 0) {
+		if (ptype == -1) {
+			/* message printed inner oakley_validate_auth() */
+			goto end;
+		}
+		EVT_PUSH(iph1->local, iph1->remote, 
+		    EVTT_PEERPH1AUTH_FAILED, NULL);
+		isakmp_info_send_n1(iph1, ptype, NULL);
+		goto end;
+	}
+
+	if (oakley_checkcr(iph1) < 0) {
+		/* Ignore this error in order to be interoperability. */
+		;
+	}
+
+	/* change status of isakmp status entry */
+	iph1->status = PHASE1ST_MSG2RECEIVED;
+
+	error = 0;
+
+end:
+#ifdef HAVE_GSSAPI
+	if (gsstoken)
+		vfree(gsstoken);
+#endif
+	if (pbuf)
+		vfree(pbuf);
+	if (satmp)
+		vfree(satmp);
+	if (error) {
+		VPTRINIT(iph1->dhpub_p);
+		VPTRINIT(iph1->nonce_p);
+		VPTRINIT(iph1->id_p);
+		oakley_delcert(iph1->cert_p);
+		iph1->cert_p = NULL;
+		oakley_delcert(iph1->crl_p);
+		iph1->crl_p = NULL;
+		VPTRINIT(iph1->sig_p);
+		oakley_delcert(iph1->cr_p);
+		iph1->cr_p = NULL;
+	}
+
+	return error;
+}
+
+/*
+ * send to responder
+ * 	psk: HDR, HASH_I
+ *   gssapi: HDR, HASH_I
+ * 	sig: HDR, [ CERT, ] SIG_I
+ * 	rsa: HDR, HASH_I
+ * 	rev: HDR, HASH_I
+ */
+int
+agg_i2send(iph1, msg)
+	struct ph1handle *iph1;
+	vchar_t *msg;
+{
+	struct payload_list *plist = NULL;
+	int need_cert = 0;
+	int error = -1;
+	vchar_t *gsshash = NULL;
+
+	/* validity check */
+	if (iph1->status != PHASE1ST_MSG2RECEIVED) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"status mismatched %d.\n", iph1->status);
+		goto end;
+	}
+
+	/* generate HASH to send */
+	plog(LLV_DEBUG, LOCATION, NULL, "generate HASH_I\n");
+	iph1->hash = oakley_ph1hash_common(iph1, GENERATE);
+	if (iph1->hash == NULL) {
+#ifdef HAVE_GSSAPI
+		if (gssapi_more_tokens(iph1) &&
+#ifdef ENABLE_HYBRID
+		    !iph1->rmconf->xauth &&
+#endif
+		    1)
+			isakmp_info_send_n1(iph1,
+			    ISAKMP_NTYPE_INVALID_EXCHANGE_TYPE, NULL);
+#endif
+		goto end;
+	}
+
+	switch (AUTHMETHOD(iph1)) {
+	case OAKLEY_ATTR_AUTH_METHOD_PSKEY:
+#ifdef ENABLE_HYBRID
+	case FICTIVE_AUTH_METHOD_XAUTH_PSKEY_I:
+	case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_I:
+	case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_I:
+#endif  
+		/* set HASH payload */
+		plist = isakmp_plist_append(plist, 
+		    iph1->hash, ISAKMP_NPTYPE_HASH);
+		break;
+
+	case OAKLEY_ATTR_AUTH_METHOD_DSSSIG:
+	case OAKLEY_ATTR_AUTH_METHOD_RSASIG:
+#ifdef ENABLE_HYBRID
+	case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_I:
+	case OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_I:
+#endif
+		/* XXX if there is CR or not ? */
+
+		if (oakley_getmycert(iph1) < 0)
+			goto end;
+
+		if (oakley_getsign(iph1) < 0)
+			goto end;
+
+		if (iph1->cert != NULL && iph1->rmconf->send_cert)
+			need_cert = 1;
+
+		/* add CERT payload if there */
+		if (need_cert)
+			plist = isakmp_plist_append(plist, 
+			    iph1->cert->pl, ISAKMP_NPTYPE_CERT);
+
+		/* add SIG payload */
+		plist = isakmp_plist_append(plist, 
+		    iph1->sig, ISAKMP_NPTYPE_SIG);
+		break;
+
+	case OAKLEY_ATTR_AUTH_METHOD_RSAENC:
+	case OAKLEY_ATTR_AUTH_METHOD_RSAREV:
+#ifdef ENABLE_HYBRID
+	case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAENC_I:
+	case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAREV_I:
+#endif
+		break;
+#ifdef HAVE_GSSAPI
+	case OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB:
+		gsshash = gssapi_wraphash(iph1);
+		if (gsshash == NULL) {
+			plog(LLV_ERROR, LOCATION, NULL,
+				"failed to wrap hash\n");
+			isakmp_info_send_n1(iph1,
+				ISAKMP_NTYPE_INVALID_EXCHANGE_TYPE, NULL);
+			goto end;
+		}
+
+		plist = isakmp_plist_append(plist, 
+		    gsshash, ISAKMP_NPTYPE_HASH);
+		break;
+#endif
+	}
+
+#ifdef ENABLE_NATT
+	/* generate NAT-D payloads */
+	if (NATT_AVAILABLE(iph1)) {
+		vchar_t *natd[2] = { NULL, NULL };
+
+		plog(LLV_INFO, LOCATION, 
+		    NULL, "Adding remote and local NAT-D payloads.\n");
+
+		if ((natd[0] = natt_hash_addr (iph1, iph1->remote)) == NULL) {
+			plog(LLV_ERROR, LOCATION, NULL,
+			    "NAT-D hashing failed for %s\n", 
+			    saddr2str(iph1->remote));
+			goto end;
+		}
+
+		if ((natd[1] = natt_hash_addr (iph1, iph1->local)) == NULL) {
+			plog(LLV_ERROR, LOCATION, NULL,
+			    "NAT-D hashing failed for %s\n", 
+			    saddr2str(iph1->local));
+			goto end;
+		}
+
+		plist = isakmp_plist_append(plist, 
+		    natd[0], iph1->natt_options->payload_nat_d);
+		plist = isakmp_plist_append(plist, 
+		    natd[1], iph1->natt_options->payload_nat_d);
+	}
+#endif
+
+	iph1->sendbuf = isakmp_plist_set_all (&plist, iph1);
+
+#ifdef HAVE_PRINT_ISAKMP_C
+	isakmp_printpacket(iph1->sendbuf, iph1->local, iph1->remote, 0);
+#endif
+
+	/* send to responder */
+	if (isakmp_send(iph1, iph1->sendbuf) < 0)
+		goto end;
+
+	/* the sending message is added to the received-list. */
+	if (add_recvdpkt(iph1->remote, iph1->local, iph1->sendbuf, msg) == -1) {
+		plog(LLV_ERROR , LOCATION, NULL,
+			"failed to add a response packet to the tree.\n");
+		goto end;
+	}
+
+	/* set encryption flag */
+	iph1->flags |= ISAKMP_FLAG_E;
+
+	iph1->status = PHASE1ST_ESTABLISHED;
+
+	error = 0;
+
+end:
+	if (gsshash)
+		vfree(gsshash);
+	return error;
+}
+
+/*
+ * receive from initiator
+ * 	psk: HDR, SA, KE, Ni, IDi1
+ * 	sig: HDR, SA, KE, Ni, IDi1 [, CR ]
+ *   gssapi: HDR, SA, KE, Ni, IDi1 , GSSi
+ * 	rsa: HDR, SA, [ HASH(1),] KE, <IDi1_b>Pubkey_r, <Ni_b>Pubkey_r
+ * 	rev: HDR, SA, [ HASH(1),] <Ni_b>Pubkey_r, <KE_b>Ke_i,
+ * 	     <IDii_b>Ke_i [, <Cert-I_b>Ke_i ]
+ */
+int
+agg_r1recv(iph1, msg)
+	struct ph1handle *iph1;
+	vchar_t *msg;
+{
+	int error = -1;
+	vchar_t *pbuf = NULL;
+	struct isakmp_parse_t *pa;
+	int vid_numeric;
+#ifdef HAVE_GSSAPI
+	vchar_t *gsstoken = NULL;
+#endif
+
+	/* validity check */
+	if (iph1->status != PHASE1ST_START) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"status mismatched %d.\n", iph1->status);
+		goto end;
+	}
+
+	/* validate the type of next payload */
+	pbuf = isakmp_parse(msg);
+	if (pbuf == NULL)
+		goto end;
+	pa = (struct isakmp_parse_t *)pbuf->v;
+
+	/* SA payload is fixed postion */
+	if (pa->type != ISAKMP_NPTYPE_SA) {
+		plog(LLV_ERROR, LOCATION, iph1->remote,
+			"received invalid next payload type %d, "
+			"expecting %d.\n",
+			pa->type, ISAKMP_NPTYPE_SA);
+		goto end;
+	}
+	if (isakmp_p2ph(&iph1->sa, pa->ptr) < 0)
+		goto end;
+	pa++;
+
+	for (/*nothing*/;
+	     pa->type != ISAKMP_NPTYPE_NONE;
+	     pa++) {
+
+		plog(LLV_DEBUG, LOCATION, NULL,
+			"received payload of type %s\n",
+			s_isakmp_nptype(pa->type));
+
+		switch (pa->type) {
+		case ISAKMP_NPTYPE_KE:
+			if (isakmp_p2ph(&iph1->dhpub_p, pa->ptr) < 0)
+				goto end;
+			break;
+		case ISAKMP_NPTYPE_NONCE:
+			if (isakmp_p2ph(&iph1->nonce_p, pa->ptr) < 0)
+				goto end;
+			break;
+		case ISAKMP_NPTYPE_ID:
+			if (isakmp_p2ph(&iph1->id_p, pa->ptr) < 0)
+				goto end;
+			break;
+		case ISAKMP_NPTYPE_VID:
+			vid_numeric = check_vendorid(pa->ptr);
+
+#ifdef ENABLE_NATT
+			if (iph1->rmconf->nat_traversal &&
+			    natt_vendorid(vid_numeric)) {
+				natt_handle_vendorid(iph1, vid_numeric);
+				break;
+			}
+#endif
+#ifdef ENABLE_HYBRID
+			switch (vid_numeric) {
+			case VENDORID_XAUTH:
+				iph1->mode_cfg->flags |= 
+				    ISAKMP_CFG_VENDORID_XAUTH;
+				break;
+
+			case VENDORID_UNITY:
+				iph1->mode_cfg->flags |= 
+				    ISAKMP_CFG_VENDORID_UNITY;
+				break;
+			default:
+				break;
+			}
+#endif
+#ifdef ENABLE_DPD
+			if (vid_numeric == VENDORID_DPD && iph1->rmconf->dpd) {
+				iph1->dpd_support=1;
+				plog(LLV_DEBUG, LOCATION, NULL,
+					 "remote supports DPD\n");
+			}
+#endif
+#ifdef ENABLE_FRAG
+			if ((vid_numeric == VENDORID_FRAG) &&
+			    (vendorid_frag_cap(pa->ptr) & VENDORID_FRAG_AGG))
+				iph1->frag = 1;
+#endif
+			break;
+
+		case ISAKMP_NPTYPE_CR:
+			if (oakley_savecr(iph1, pa->ptr) < 0)
+				goto end;
+			break;
+
+#ifdef HAVE_GSSAPI
+		case ISAKMP_NPTYPE_GSS:
+			if (isakmp_p2ph(&gsstoken, pa->ptr) < 0)
+				goto end;
+			gssapi_save_received_token(iph1, gsstoken);
+			break;
+#endif
+		default:
+			/* don't send information, see isakmp_ident_r1() */
+			plog(LLV_ERROR, LOCATION, iph1->remote,
+				"ignore the packet, "
+				"received unexpecting payload type %d.\n",
+				pa->type);
+			goto end;
+		}
+	}
+
+	/* payload existency check */
+	if (iph1->dhpub_p == NULL || iph1->nonce_p == NULL) {
+		plog(LLV_ERROR, LOCATION, iph1->remote,
+			"few isakmp message received.\n");
+		goto end;
+	}
+
+	/* verify identifier */
+	if (ipsecdoi_checkid1(iph1) != 0) {
+		plog(LLV_ERROR, LOCATION, iph1->remote,
+			"invalid ID payload.\n");
+		goto end;
+	}
+
+#ifdef ENABLE_NATT
+	if (NATT_AVAILABLE(iph1))
+		plog(LLV_INFO, LOCATION, iph1->remote,
+		     "Selected NAT-T version: %s\n",
+		     vid_string_by_id(iph1->natt_options->version));
+#endif
+
+	/* check SA payload and set approval SA for use */
+	if (ipsecdoi_checkph1proposal(iph1->sa, iph1) < 0) {
+		plog(LLV_ERROR, LOCATION, iph1->remote,
+			"failed to get valid proposal.\n");
+		/* XXX send information */
+		goto end;
+	}
+
+	if (oakley_checkcr(iph1) < 0) {
+		/* Ignore this error in order to be interoperability. */
+		;
+	}
+
+	iph1->status = PHASE1ST_MSG1RECEIVED;
+
+	error = 0;
+
+end:
+#ifdef HAVE_GSSAPI
+	if (gsstoken)
+		vfree(gsstoken);
+#endif
+	if (pbuf)
+		vfree(pbuf);
+	if (error) {
+		VPTRINIT(iph1->sa);
+		VPTRINIT(iph1->dhpub_p);
+		VPTRINIT(iph1->nonce_p);
+		VPTRINIT(iph1->id_p);
+		oakley_delcert(iph1->cr_p);
+		iph1->cr_p = NULL;
+	}
+
+	return error;
+}
+
+/*
+ * send to initiator
+ * 	psk: HDR, SA, KE, Nr, IDr1, HASH_R
+ * 	sig: HDR, SA, KE, Nr, IDr1, [ CR, ] [ CERT, ] SIG_R
+ *   gssapi: HDR, SA, KE, Nr, IDr1, GSSr, HASH_R
+ * 	rsa: HDR, SA, KE, <IDr1_b>PubKey_i, <Nr_b>PubKey_i, HASH_R
+ * 	rev: HDR, SA, <Nr_b>PubKey_i, <KE_b>Ke_r, <IDir_b>Ke_r, HASH_R
+ */
+int
+agg_r1send(iph1, msg)
+	struct ph1handle *iph1;
+	vchar_t *msg;
+{
+	struct payload_list *plist = NULL;
+	int need_cr = 0;
+	int need_cert = 0;
+	vchar_t *cr = NULL;
+	int error = -1;
+#ifdef ENABLE_HYBRID
+	vchar_t *xauth_vid = NULL;
+	vchar_t *unity_vid = NULL;
+#endif
+#ifdef ENABLE_NATT
+	vchar_t *vid_natt = NULL;
+	vchar_t *natd[2] = { NULL, NULL };
+#endif
+#ifdef ENABLE_DPD
+	vchar_t *vid_dpd = NULL;
+#endif
+#ifdef ENABLE_FRAG
+	vchar_t *vid_frag = NULL;
+#endif
+
+#ifdef HAVE_GSSAPI
+	int gsslen;
+	vchar_t *gsstoken = NULL, *gsshash = NULL;
+	vchar_t *gss_sa = NULL;
+	int free_gss_sa = 0;
+#endif
+
+	/* validity check */
+	if (iph1->status != PHASE1ST_MSG1RECEIVED) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"status mismatched %d.\n", iph1->status);
+		goto end;
+	}
+
+	/* set responder's cookie */
+	isakmp_newcookie((caddr_t)&iph1->index.r_ck, iph1->remote, iph1->local);
+
+	/* make ID payload into isakmp status */
+	if (ipsecdoi_setid1(iph1) < 0)
+		goto end;
+
+	/* generate DH public value */
+	if (oakley_dh_generate(iph1->rmconf->dhgrp,
+				&iph1->dhpub, &iph1->dhpriv) < 0)
+		goto end;
+
+	/* generate NONCE value */
+	iph1->nonce = eay_set_random(iph1->rmconf->nonce_size);
+	if (iph1->nonce == NULL)
+		goto end;
+
+	/* compute sharing secret of DH */
+	if (oakley_dh_compute(iph1->approval->dhgrp, iph1->dhpub,
+				iph1->dhpriv, iph1->dhpub_p, &iph1->dhgxy) < 0)
+		goto end;
+
+	/* generate SKEYIDs & IV & final cipher key */
+	if (oakley_skeyid(iph1) < 0)
+		goto end;
+	if (oakley_skeyid_dae(iph1) < 0)
+		goto end;
+	if (oakley_compute_enckey(iph1) < 0)
+		goto end;
+	if (oakley_newiv(iph1) < 0)
+		goto end;
+
+#ifdef HAVE_GSSAPI
+	if (RMAUTHMETHOD(iph1) == OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB)
+		gssapi_get_rtoken(iph1, &gsslen);
+#endif
+
+	/* generate HASH to send */
+	plog(LLV_DEBUG, LOCATION, NULL, "generate HASH_R\n");
+	iph1->hash = oakley_ph1hash_common(iph1, GENERATE);
+	if (iph1->hash == NULL) {
+#ifdef HAVE_GSSAPI
+		if (gssapi_more_tokens(iph1))
+			isakmp_info_send_n1(iph1,
+			    ISAKMP_NTYPE_INVALID_EXCHANGE_TYPE, NULL);
+#endif
+		goto end;
+	}
+
+	/* create CR if need */
+	if (iph1->rmconf->send_cr
+	 && oakley_needcr(iph1->approval->authmethod)
+	 && iph1->rmconf->peerscertfile == NULL) {
+		need_cr = 1;
+		cr = oakley_getcr(iph1);
+		if (cr == NULL) {
+			plog(LLV_ERROR, LOCATION, NULL,
+				"failed to get cr buffer.\n");
+			goto end;
+		}
+	}
+
+#ifdef ENABLE_NATT
+	/* Has the peer announced NAT-T? */
+	if (NATT_AVAILABLE(iph1)) {
+	  	/* set chosen VID */
+		vid_natt = set_vendorid(iph1->natt_options->version);
+
+		/* generate NAT-D payloads */
+		plog (LLV_INFO, LOCATION, NULL, "Adding remote and local NAT-D payloads.\n");
+		if ((natd[0] = natt_hash_addr (iph1, iph1->remote)) == NULL) {
+			plog(LLV_ERROR, LOCATION, NULL,
+				"NAT-D hashing failed for %s\n", saddr2str(iph1->remote));
+			goto end;
+		}
+
+		if ((natd[1] = natt_hash_addr (iph1, iph1->local)) == NULL) {
+			plog(LLV_ERROR, LOCATION, NULL,
+				"NAT-D hashing failed for %s\n", saddr2str(iph1->local));
+			goto end;
+		}
+	}
+#endif
+#ifdef ENABLE_DPD
+	/* Only send DPD support if remote announced DPD and if DPD support is active */
+	if (iph1->dpd_support && iph1->rmconf->dpd)
+		vid_dpd = set_vendorid(VENDORID_DPD);
+#endif
+#ifdef ENABLE_FRAG
+	if (iph1->frag) {
+		vid_frag = set_vendorid(VENDORID_FRAG);
+		if (vid_frag != NULL)
+			vid_frag = isakmp_frag_addcap(vid_frag,
+			    VENDORID_FRAG_AGG);
+		if (vid_frag == NULL)
+			plog(LLV_ERROR, LOCATION, NULL,
+			    "Frag vendorID construction failed\n");
+	}
+#endif
+
+	switch (AUTHMETHOD(iph1)) {
+	case OAKLEY_ATTR_AUTH_METHOD_PSKEY:
+#ifdef ENABLE_HYBRID
+	case OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_R:
+#endif
+		/* set SA payload to reply */
+		plist = isakmp_plist_append(plist, 
+		    iph1->sa_ret, ISAKMP_NPTYPE_SA);
+
+		/* create isakmp KE payload */
+		plist = isakmp_plist_append(plist, 
+		    iph1->dhpub, ISAKMP_NPTYPE_KE);
+
+		/* create isakmp NONCE payload */
+		plist = isakmp_plist_append(plist, 
+		    iph1->nonce, ISAKMP_NPTYPE_NONCE);
+
+		/* create isakmp ID payload */
+		plist = isakmp_plist_append(plist, 
+		    iph1->id, ISAKMP_NPTYPE_ID);
+
+		/* create isakmp HASH payload */
+		plist = isakmp_plist_append(plist, 
+		    iph1->hash, ISAKMP_NPTYPE_HASH);
+
+		/* create isakmp CR payload if needed */
+		if (need_cr)
+			plist = isakmp_plist_append(plist, 
+			    cr, ISAKMP_NPTYPE_CR);
+		break;
+	case OAKLEY_ATTR_AUTH_METHOD_DSSSIG:
+	case OAKLEY_ATTR_AUTH_METHOD_RSASIG:
+#ifdef ENABLE_HYBRID
+	case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_R:
+	case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_R:
+	case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_R:
+	case OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_R:
+#endif
+		/* XXX if there is CR or not ? */
+
+		if (oakley_getmycert(iph1) < 0)
+			goto end;
+
+		if (oakley_getsign(iph1) < 0)
+			goto end;
+
+		if (iph1->cert != NULL && iph1->rmconf->send_cert)
+			need_cert = 1;
+
+		/* set SA payload to reply */
+		plist = isakmp_plist_append(plist, 
+		    iph1->sa_ret, ISAKMP_NPTYPE_SA);
+
+		/* create isakmp KE payload */
+		plist = isakmp_plist_append(plist, 
+		    iph1->dhpub, ISAKMP_NPTYPE_KE);
+
+		/* create isakmp NONCE payload */
+		plist = isakmp_plist_append(plist, 
+		    iph1->nonce, ISAKMP_NPTYPE_NONCE);
+
+		/* add ID payload */
+		plist = isakmp_plist_append(plist, 
+		    iph1->id, ISAKMP_NPTYPE_ID);
+
+		/* add CERT payload if there */
+		if (need_cert)
+			plist = isakmp_plist_append(plist, 
+			    iph1->cert->pl, ISAKMP_NPTYPE_CERT);
+
+		/* add SIG payload */
+		plist = isakmp_plist_append(plist, 
+		    iph1->sig, ISAKMP_NPTYPE_SIG);
+
+		/* create isakmp CR payload if needed */
+		if (need_cr)
+			plist = isakmp_plist_append(plist, 
+			    cr, ISAKMP_NPTYPE_CR);
+		break;
+
+	case OAKLEY_ATTR_AUTH_METHOD_RSAENC:
+	case OAKLEY_ATTR_AUTH_METHOD_RSAREV:
+#ifdef ENABLE_HYBRID
+	case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAENC_R:
+	case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAREV_R:
+#endif
+		break;
+#ifdef HAVE_GSSAPI
+	case OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB:
+			/* create buffer to send isakmp payload */
+			gsshash = gssapi_wraphash(iph1);
+			if (gsshash == NULL) {
+				plog(LLV_ERROR, LOCATION, NULL,
+					"failed to wrap hash\n");
+				/*
+				 * This is probably due to the GSS 
+				 * roundtrips not being finished yet. 
+				 * Return this error in the hope that 
+				 * a fallback to main mode will be done.
+				 */
+				isakmp_info_send_n1(iph1,
+				    ISAKMP_NTYPE_INVALID_EXCHANGE_TYPE, NULL);
+				goto end;
+			}
+			if (iph1->approval->gssid != NULL)
+				gss_sa = 
+				    ipsecdoi_setph1proposal(iph1->approval);  
+			else
+				gss_sa = iph1->sa_ret;
+
+			if (gss_sa != iph1->sa_ret)
+				free_gss_sa = 1;
+
+			/* set SA payload to reply */
+			plist = isakmp_plist_append(plist, 
+			    gss_sa, ISAKMP_NPTYPE_SA);
+
+			/* create isakmp KE payload */
+			plist = isakmp_plist_append(plist, 
+			    iph1->dhpub, ISAKMP_NPTYPE_KE);
+
+			/* create isakmp NONCE payload */
+			plist = isakmp_plist_append(plist, 
+			    iph1->nonce, ISAKMP_NPTYPE_NONCE);
+
+			/* create isakmp ID payload */
+			plist = isakmp_plist_append(plist, 
+			    iph1->id, ISAKMP_NPTYPE_ID);
+
+			/* create GSS payload */
+			gssapi_get_token_to_send(iph1, &gsstoken);
+			plist = isakmp_plist_append(plist, 
+			    gsstoken, ISAKMP_NPTYPE_GSS);
+
+			/* create isakmp HASH payload */
+			plist = isakmp_plist_append(plist, 
+			    gsshash, ISAKMP_NPTYPE_HASH);
+
+			/* append vendor id, if needed */
+			break;
+#endif
+	}
+
+#ifdef ENABLE_HYBRID
+	if (iph1->mode_cfg->flags & ISAKMP_CFG_VENDORID_XAUTH) {
+		plog (LLV_INFO, LOCATION, NULL, "Adding xauth VID payload.\n");
+		if ((xauth_vid = set_vendorid(VENDORID_XAUTH)) == NULL) {
+			plog(LLV_ERROR, LOCATION, NULL,
+			    "Cannot create Xauth vendor ID\n");
+			goto end;
+		}
+		plist = isakmp_plist_append(plist, 
+		    xauth_vid, ISAKMP_NPTYPE_VID);
+	}
+
+	if (iph1->mode_cfg->flags & ISAKMP_CFG_VENDORID_UNITY) {
+		if ((unity_vid = set_vendorid(VENDORID_UNITY)) == NULL) {
+			plog(LLV_ERROR, LOCATION, NULL,
+			    "Cannot create Unity vendor ID\n");
+			goto end;
+		}
+		plist = isakmp_plist_append(plist, 
+		    unity_vid, ISAKMP_NPTYPE_VID);
+	}
+#endif
+
+#ifdef ENABLE_NATT
+	/* append NAT-T payloads */
+	if (vid_natt) {
+		/* chosen VID */
+		plist = isakmp_plist_append(plist, vid_natt, ISAKMP_NPTYPE_VID);
+		/* NAT-D */
+		plist = isakmp_plist_append(plist, natd[0], iph1->natt_options->payload_nat_d);
+		plist = isakmp_plist_append(plist, natd[1], iph1->natt_options->payload_nat_d);
+	}
+#endif
+
+#ifdef ENABLE_FRAG
+	if (vid_frag)
+		plist = isakmp_plist_append(plist, vid_frag, ISAKMP_NPTYPE_VID);
+#endif
+
+#ifdef ENABLE_DPD
+	if (vid_dpd)
+		plist = isakmp_plist_append(plist, vid_dpd, ISAKMP_NPTYPE_VID);
+#endif
+
+	iph1->sendbuf = isakmp_plist_set_all (&plist, iph1);
+
+#ifdef HAVE_PRINT_ISAKMP_C
+	isakmp_printpacket(iph1->sendbuf, iph1->local, iph1->remote, 1);
+#endif
+
+	/* send the packet, add to the schedule to resend */
+	iph1->retry_counter = iph1->rmconf->retry_counter;
+	if (isakmp_ph1resend(iph1) == -1)
+		goto end;
+
+	/* the sending message is added to the received-list. */
+	if (add_recvdpkt(iph1->remote, iph1->local, iph1->sendbuf, msg) == -1) {
+		plog(LLV_ERROR , LOCATION, NULL,
+			"failed to add a response packet to the tree.\n");
+		goto end;
+	}
+
+	iph1->status = PHASE1ST_MSG1SENT;
+
+	error = 0;
+
+end:
+	if (cr)
+		vfree(cr);
+#ifdef ENABLE_HYBRID
+	if (xauth_vid)
+		vfree(xauth_vid);
+	if (unity_vid)
+		vfree(unity_vid);
+#endif
+#ifdef HAVE_GSSAPI
+	if (gsstoken)
+		vfree(gsstoken);
+	if (gsshash)
+		vfree(gsshash);
+	if (free_gss_sa)
+		vfree(gss_sa);
+#endif
+#ifdef ENABLE_DPD
+	if (vid_dpd)
+		vfree(vid_dpd);
+#endif
+#ifdef ENABLE_FRAG
+	if (vid_frag)
+		vfree(vid_frag);
+#endif
+
+	return error;
+}
+
+/*
+ * receive from initiator
+ * 	psk: HDR, HASH_I
+ *   gssapi: HDR, HASH_I
+ * 	sig: HDR, [ CERT, ] SIG_I
+ * 	rsa: HDR, HASH_I
+ * 	rev: HDR, HASH_I
+ */
+int
+agg_r2recv(iph1, msg0)
+	struct ph1handle *iph1;
+	vchar_t *msg0;
+{
+	vchar_t *msg = NULL;
+	vchar_t *pbuf = NULL;
+	struct isakmp_parse_t *pa;
+	int error = -1;
+	int ptype;
+
+#ifdef ENABLE_NATT
+	int natd_seq = 0;
+#endif
+
+	/* validity check */
+	if (iph1->status != PHASE1ST_MSG1SENT) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"status mismatched %d.\n", iph1->status);
+		goto end;
+	}
+
+	/* decrypting if need. */
+	/* XXX configurable ? */
+	if (ISSET(((struct isakmp *)msg0->v)->flags, ISAKMP_FLAG_E)) {
+		msg = oakley_do_decrypt(iph1, msg0,
+					iph1->ivm->iv, iph1->ivm->ive);
+		if (msg == NULL)
+			goto end;
+	} else
+		msg = vdup(msg0);
+
+	/* validate the type of next payload */
+	pbuf = isakmp_parse(msg);
+	if (pbuf == NULL)
+		goto end;
+
+	iph1->pl_hash = NULL;
+
+	for (pa = (struct isakmp_parse_t *)pbuf->v;
+	     pa->type != ISAKMP_NPTYPE_NONE;
+	     pa++) {
+
+		switch (pa->type) {
+		case ISAKMP_NPTYPE_HASH:
+			iph1->pl_hash = (struct isakmp_pl_hash *)pa->ptr;
+			break;
+		case ISAKMP_NPTYPE_VID:
+			(void)check_vendorid(pa->ptr);
+			break;
+		case ISAKMP_NPTYPE_CERT:
+			if (oakley_savecert(iph1, pa->ptr) < 0)
+				goto end;
+			break;
+		case ISAKMP_NPTYPE_SIG:
+			if (isakmp_p2ph(&iph1->sig_p, pa->ptr) < 0)
+				goto end;
+			break;
+		case ISAKMP_NPTYPE_N:
+			isakmp_check_notify(pa->ptr, iph1);
+			break;
+
+#ifdef ENABLE_NATT
+		case ISAKMP_NPTYPE_NATD_DRAFT:
+		case ISAKMP_NPTYPE_NATD_RFC:
+			if (NATT_AVAILABLE(iph1) && iph1->natt_options != NULL &&
+				pa->type == iph1->natt_options->payload_nat_d)
+			{
+				vchar_t *natd_received = NULL;
+				int natd_verified;
+				
+				if (isakmp_p2ph (&natd_received, pa->ptr) < 0)
+					goto end;
+				
+				if (natd_seq == 0)
+					iph1->natt_flags |= NAT_DETECTED;
+				
+				natd_verified = natt_compare_addr_hash (iph1,
+					natd_received, natd_seq++);
+				
+				plog (LLV_INFO, LOCATION, NULL, "NAT-D payload #%d %s\n",
+					natd_seq - 1,
+					natd_verified ? "verified" : "doesn't match");
+				
+				vfree (natd_received);
+				break;
+			}
+			/* passthrough to default... */
+#endif
+
+		default:
+			/* don't send information, see isakmp_ident_r1() */
+			plog(LLV_ERROR, LOCATION, iph1->remote,
+				"ignore the packet, "
+				"received unexpecting payload type %d.\n",
+				pa->type);
+			goto end;
+		}
+	}
+
+#ifdef ENABLE_NATT
+	if (NATT_AVAILABLE(iph1))
+		plog (LLV_INFO, LOCATION, NULL, "NAT %s %s%s\n",
+		      iph1->natt_flags & NAT_DETECTED ? 
+		      		"detected:" : "not detected",
+		      iph1->natt_flags & NAT_DETECTED_ME ? "ME " : "",
+		      iph1->natt_flags & NAT_DETECTED_PEER ? "PEER" : "");
+#endif
+
+	/* validate authentication value */
+	ptype = oakley_validate_auth(iph1);
+	if (ptype != 0) {
+		if (ptype == -1) {
+			/* message printed inner oakley_validate_auth() */
+			goto end;
+		}
+		EVT_PUSH(iph1->local, iph1->remote, 
+		    EVTT_PEERPH1AUTH_FAILED, NULL);
+		isakmp_info_send_n1(iph1, ptype, NULL);
+		goto end;
+	}
+
+	iph1->status = PHASE1ST_MSG2RECEIVED;
+
+	error = 0;
+
+end:
+	if (pbuf)
+		vfree(pbuf);
+	if (msg)
+		vfree(msg);
+	if (error) {
+		oakley_delcert(iph1->cert_p);
+		iph1->cert_p = NULL;
+		oakley_delcert(iph1->crl_p);
+		iph1->crl_p = NULL;
+		VPTRINIT(iph1->sig_p);
+	}
+
+	return error;
+}
+
+/*
+ * status update and establish isakmp sa.
+ */
+int
+agg_r2send(iph1, msg)
+	struct ph1handle *iph1;
+	vchar_t *msg;
+{
+	int error = -1;
+
+	/* validity check */
+	if (iph1->status != PHASE1ST_MSG2RECEIVED) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"status mismatched %d.\n", iph1->status);
+		goto end;
+	}
+
+	/* IV synchronized when packet encrypted. */
+	/* see handler.h about IV synchronization. */
+	if (ISSET(((struct isakmp *)msg->v)->flags, ISAKMP_FLAG_E))
+		memcpy(iph1->ivm->iv->v, iph1->ivm->ive->v, iph1->ivm->iv->l);
+
+	/* set encryption flag */
+	iph1->flags |= ISAKMP_FLAG_E;
+
+	iph1->status = PHASE1ST_ESTABLISHED;
+
+	error = 0;
+
+end:
+	return error;
+}
diff --git a/src/racoon/isakmp_agg.h b/src/racoon/isakmp_agg.h
new file mode 100644
index 0000000..89645eb
--- /dev/null
+++ b/src/racoon/isakmp_agg.h
@@ -0,0 +1,46 @@
+/*	$NetBSD: isakmp_agg.h,v 1.4 2006/09/09 16:22:09 manu Exp $	*/
+
+/* Id: isakmp_agg.h,v 1.3 2004/06/11 16:00:16 ludvigm Exp */
+
+/*
+ * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _ISAKMP_AGG_H
+#define _ISAKMP_AGG_H
+
+extern int agg_i1send __P((struct ph1handle *, vchar_t *));
+extern int agg_i2recv __P((struct ph1handle *, vchar_t *));
+extern int agg_i2send __P((struct ph1handle *, vchar_t *));
+
+extern int agg_r1recv __P((struct ph1handle *, vchar_t *));
+extern int agg_r1send __P((struct ph1handle *, vchar_t *));
+extern int agg_r2recv __P((struct ph1handle *, vchar_t *));
+extern int agg_r2send __P((struct ph1handle *, vchar_t *));
+
+#endif /* _ISAKMP_AGG_H */
diff --git a/src/racoon/isakmp_base.c b/src/racoon/isakmp_base.c
new file mode 100644
index 0000000..3ac0b72
--- /dev/null
+++ b/src/racoon/isakmp_base.c
@@ -0,0 +1,1461 @@
+/*	$NetBSD: isakmp_base.c,v 1.7 2006/10/02 21:51:33 manu Exp $	*/
+
+/*	$KAME: isakmp_base.c,v 1.49 2003/11/13 02:30:20 sakane Exp $	*/
+
+/*
+ * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* Base Exchange (Base Mode) */
+
+#include "config.h"
+
+#include <sys/types.h>
+#include <sys/param.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#if TIME_WITH_SYS_TIME
+# include <sys/time.h>
+# include <time.h>
+#else
+# if HAVE_SYS_TIME_H
+#  include <sys/time.h>
+# else
+#  include <time.h>
+# endif
+#endif
+
+#include "var.h"
+#include "misc.h"
+#include "vmbuf.h"
+#include "plog.h"
+#include "sockmisc.h"
+#include "schedule.h"
+#include "debug.h"
+
+#ifdef ENABLE_HYBRID
+#include <resolv.h>
+#endif
+
+#include "localconf.h"
+#include "remoteconf.h"
+#include "isakmp_var.h"
+#include "isakmp.h"
+#include "evt.h"
+#include "oakley.h"
+#include "handler.h"
+#include "ipsec_doi.h"
+#include "crypto_openssl.h"
+#include "pfkey.h"
+#include "isakmp_base.h"
+#include "isakmp_inf.h"
+#include "vendorid.h"
+#ifdef ENABLE_NATT
+#include "nattraversal.h"
+#endif
+#ifdef ENABLE_FRAG
+#include "isakmp_frag.h"
+#endif
+#ifdef ENABLE_HYBRID
+#include "isakmp_xauth.h"
+#include "isakmp_cfg.h"
+#endif
+
+/* %%%
+ * begin Identity Protection Mode as initiator.
+ */
+/*
+ * send to responder
+ * 	psk: HDR, SA, Idii, Ni_b
+ * 	sig: HDR, SA, Idii, Ni_b
+ * 	rsa: HDR, SA, [HASH(1),] <IDii_b>Pubkey_r, <Ni_b>Pubkey_r
+ * 	rev: HDR, SA, [HASH(1),] <Ni_b>Pubkey_r, <IDii_b>Ke_i
+ */
+int
+base_i1send(iph1, msg)
+	struct ph1handle *iph1;
+	vchar_t *msg; /* must be null */
+{
+	struct payload_list *plist = NULL;
+	int error = -1;
+#ifdef ENABLE_NATT
+	vchar_t *vid_natt[MAX_NATT_VID_COUNT] = { NULL };
+	int i, vid_natt_i = 0;
+#endif
+#ifdef ENABLE_FRAG
+	vchar_t *vid_frag = NULL;
+#endif
+#ifdef ENABLE_HYBRID
+	vchar_t *vid_xauth = NULL;
+	vchar_t *vid_unity = NULL;
+#endif
+#ifdef ENABLE_DPD
+	vchar_t *vid_dpd = NULL;
+#endif
+
+
+	/* validity check */
+	if (msg != NULL) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"msg has to be NULL in this function.\n");
+		goto end;
+	}
+	if (iph1->status != PHASE1ST_START) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"status mismatched %d.\n", iph1->status);
+		goto end;
+	}
+
+	/* create isakmp index */
+	memset(&iph1->index, 0, sizeof(iph1->index));
+	isakmp_newcookie((caddr_t)&iph1->index, iph1->remote, iph1->local);
+
+	/* make ID payload into isakmp status */
+	if (ipsecdoi_setid1(iph1) < 0)
+		goto end;
+
+	/* create SA payload for my proposal */
+	iph1->sa = ipsecdoi_setph1proposal(iph1->rmconf->proposal);
+	if (iph1->sa == NULL)
+		goto end;
+
+	/* generate NONCE value */
+	iph1->nonce = eay_set_random(iph1->rmconf->nonce_size);
+	if (iph1->nonce == NULL)
+		goto end;
+
+#ifdef ENABLE_HYBRID
+        /* Do we need Xauth VID? */
+        switch (RMAUTHMETHOD(iph1)) {
+        case FICTIVE_AUTH_METHOD_XAUTH_PSKEY_I:
+        case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_I:
+        case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_I:
+        case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_I:
+        case OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_I:
+        case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAENC_I:
+        case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAREV_I:
+                if ((vid_xauth = set_vendorid(VENDORID_XAUTH)) == NULL)
+                        plog(LLV_ERROR, LOCATION, NULL,
+                             "Xauth vendor ID generation failed\n");
+
+                if ((vid_unity = set_vendorid(VENDORID_UNITY)) == NULL)
+                        plog(LLV_ERROR, LOCATION, NULL,
+                             "Unity vendor ID generation failed\n");
+                break;
+        default:
+                break;
+        }
+#endif
+#ifdef ENABLE_FRAG
+	if (iph1->rmconf->ike_frag) {
+		vid_frag = set_vendorid(VENDORID_FRAG);
+		if (vid_frag != NULL)
+			vid_frag = isakmp_frag_addcap(vid_frag, 
+			    VENDORID_FRAG_BASE);
+		if (vid_frag == NULL)
+			plog(LLV_ERROR, LOCATION, NULL, 
+			    "Frag vendorID construction failed\n");
+	}
+#endif
+#ifdef ENABLE_NATT
+	/* Is NAT-T support allowed in the config file? */
+	if (iph1->rmconf->nat_traversal) {
+		/* Advertise NAT-T capability */
+		memset (vid_natt, 0, sizeof (vid_natt));
+#ifdef VENDORID_NATT_00
+		if ((vid_natt[vid_natt_i] = set_vendorid(VENDORID_NATT_00)) != NULL)
+			vid_natt_i++;
+#endif
+#ifdef VENDORID_NATT_02
+		if ((vid_natt[vid_natt_i] = set_vendorid(VENDORID_NATT_02)) != NULL)
+			vid_natt_i++;
+#endif
+#ifdef VENDORID_NATT_02_N
+		if ((vid_natt[vid_natt_i] = set_vendorid(VENDORID_NATT_02_N)) != NULL)
+			vid_natt_i++;
+#endif
+#ifdef VENDORID_NATT_RFC
+		if ((vid_natt[vid_natt_i] = set_vendorid(VENDORID_NATT_RFC)) != NULL)
+			vid_natt_i++;
+#endif
+	}
+#endif
+
+	/* set SA payload to propose */
+	plist = isakmp_plist_append(plist, iph1->sa, ISAKMP_NPTYPE_SA);
+
+	/* create isakmp ID payload */
+	plist = isakmp_plist_append(plist, iph1->id, ISAKMP_NPTYPE_ID);
+
+	/* create isakmp NONCE payload */
+	plist = isakmp_plist_append(plist, iph1->nonce, ISAKMP_NPTYPE_NONCE);
+
+#ifdef ENABLE_FRAG
+	if (vid_frag)
+		plist = isakmp_plist_append(plist, vid_frag, ISAKMP_NPTYPE_VID);
+#endif
+#ifdef ENABLE_HYBRID
+	if (vid_xauth)
+		plist = isakmp_plist_append(plist, 
+		    vid_xauth, ISAKMP_NPTYPE_VID);
+	if (vid_unity)
+		plist = isakmp_plist_append(plist, 
+		    vid_unity, ISAKMP_NPTYPE_VID);
+#endif
+#ifdef ENABLE_DPD
+	if (iph1->rmconf->dpd) {
+		vid_dpd = set_vendorid(VENDORID_DPD);
+		if (vid_dpd != NULL)
+			plist = isakmp_plist_append(plist, vid_dpd, ISAKMP_NPTYPE_VID); 
+	}
+#endif  
+#ifdef ENABLE_NATT
+	/* set VID payload for NAT-T */
+	for (i = 0; i < vid_natt_i; i++)
+		plist = isakmp_plist_append(plist, vid_natt[i], ISAKMP_NPTYPE_VID);
+#endif
+	iph1->sendbuf = isakmp_plist_set_all (&plist, iph1);
+
+
+#ifdef HAVE_PRINT_ISAKMP_C
+	isakmp_printpacket(iph1->sendbuf, iph1->local, iph1->remote, 0);
+#endif
+
+	/* send the packet, add to the schedule to resend */
+	iph1->retry_counter = iph1->rmconf->retry_counter;
+	if (isakmp_ph1resend(iph1) == -1)
+		goto end;
+
+	iph1->status = PHASE1ST_MSG1SENT;
+
+	error = 0;
+
+end:
+#ifdef ENABLE_FRAG
+	if (vid_frag)
+		vfree(vid_frag);
+#endif 
+#ifdef ENABLE_NATT
+	for (i = 0; i < vid_natt_i; i++)
+		vfree(vid_natt[i]);
+#endif
+#ifdef ENABLE_HYBRID    
+	if (vid_xauth != NULL)
+		vfree(vid_xauth);
+	if (vid_unity != NULL) 
+		vfree(vid_unity);
+#endif 
+#ifdef ENABLE_DPD
+	if (vid_dpd != NULL)    
+		vfree(vid_dpd);
+#endif     
+
+	return error;
+}
+
+/*
+ * receive from responder
+ * 	psk: HDR, SA, Idir, Nr_b
+ * 	sig: HDR, SA, Idir, Nr_b, [ CR ]
+ * 	rsa: HDR, SA, <IDir_b>PubKey_i, <Nr_b>PubKey_i
+ * 	rev: HDR, SA, <Nr_b>PubKey_i, <IDir_b>Ke_r
+ */
+int
+base_i2recv(iph1, msg)
+	struct ph1handle *iph1;
+	vchar_t *msg;
+{
+	vchar_t *pbuf = NULL;
+	struct isakmp_parse_t *pa;
+	vchar_t *satmp = NULL;
+	int error = -1;
+	int vid_numeric;
+#ifdef ENABLE_HYBRID
+	vchar_t *unity_vid;
+	vchar_t *xauth_vid;
+#endif
+
+	/* validity check */
+	if (iph1->status != PHASE1ST_MSG1SENT) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"status mismatched %d.\n", iph1->status);
+		goto end;
+	}
+
+	/* validate the type of next payload */
+	pbuf = isakmp_parse(msg);
+	if (pbuf == NULL)
+		goto end;
+	pa = (struct isakmp_parse_t *)pbuf->v;
+
+	/* SA payload is fixed postion */
+	if (pa->type != ISAKMP_NPTYPE_SA) {
+		plog(LLV_ERROR, LOCATION, iph1->remote,
+			"received invalid next payload type %d, "
+			"expecting %d.\n",
+			pa->type, ISAKMP_NPTYPE_SA);
+		goto end;
+	}
+	if (isakmp_p2ph(&satmp, pa->ptr) < 0)
+		goto end;
+	pa++;
+
+	for (/*nothing*/;
+	     pa->type != ISAKMP_NPTYPE_NONE;
+	     pa++) {
+
+		switch (pa->type) {
+		case ISAKMP_NPTYPE_NONCE:
+			if (isakmp_p2ph(&iph1->nonce_p, pa->ptr) < 0)
+				goto end;
+			break;
+		case ISAKMP_NPTYPE_ID:
+			if (isakmp_p2ph(&iph1->id_p, pa->ptr) < 0)
+				goto end;
+			break;
+		case ISAKMP_NPTYPE_VID:
+			vid_numeric = check_vendorid(pa->ptr);
+#ifdef ENABLE_NATT
+			if (iph1->rmconf->nat_traversal && natt_vendorid(vid_numeric))
+			  natt_handle_vendorid(iph1, vid_numeric);
+#endif
+#ifdef ENABLE_HYBRID
+			switch (vid_numeric) {
+			case VENDORID_XAUTH:
+				iph1->mode_cfg->flags |=
+				    ISAKMP_CFG_VENDORID_XAUTH;
+				break;
+
+			case VENDORID_UNITY:
+				iph1->mode_cfg->flags |=
+				    ISAKMP_CFG_VENDORID_UNITY;
+				break;
+
+			default:
+				break;
+			}
+#endif
+#ifdef ENABLE_DPD
+			if (vid_numeric == VENDORID_DPD && iph1->rmconf->dpd) {
+				iph1->dpd_support=1;
+				plog(LLV_DEBUG, LOCATION, NULL,
+					 "remote supports DPD\n");
+			}
+#endif
+			break;
+		default:
+			/* don't send information, see ident_r1recv() */
+			plog(LLV_ERROR, LOCATION, iph1->remote,
+				"ignore the packet, "
+				"received unexpecting payload type %d.\n",
+				pa->type);
+			goto end;
+		}
+	}
+
+	if (iph1->nonce_p == NULL || iph1->id_p == NULL) {
+		plog(LLV_ERROR, LOCATION, iph1->remote,
+			"few isakmp message received.\n");
+		goto end;
+	}
+
+	/* verify identifier */
+	if (ipsecdoi_checkid1(iph1) != 0) {
+		plog(LLV_ERROR, LOCATION, iph1->remote,
+			"invalid ID payload.\n");
+		goto end;
+	}
+
+#ifdef ENABLE_NATT
+	if (NATT_AVAILABLE(iph1))
+		plog(LLV_INFO, LOCATION, iph1->remote,
+		     "Selected NAT-T version: %s\n",
+		     vid_string_by_id(iph1->natt_options->version));
+#endif
+
+	/* check SA payload and set approval SA for use */
+	if (ipsecdoi_checkph1proposal(satmp, iph1) < 0) {
+		plog(LLV_ERROR, LOCATION, iph1->remote,
+			"failed to get valid proposal.\n");
+		/* XXX send information */
+		goto end;
+	}
+	VPTRINIT(iph1->sa_ret);
+
+	iph1->status = PHASE1ST_MSG2RECEIVED;
+
+	error = 0;
+
+end:
+	if (pbuf)
+		vfree(pbuf);
+	if (satmp)
+		vfree(satmp);
+
+	if (error) {
+		VPTRINIT(iph1->nonce_p);
+		VPTRINIT(iph1->id_p);
+	}
+
+	return error;
+}
+
+/*
+ * send to responder
+ * 	psk: HDR, KE, HASH_I
+ * 	sig: HDR, KE, [ CR, ] [CERT,] SIG_I
+ * 	rsa: HDR, KE, HASH_I
+ * 	rev: HDR, <KE>Ke_i, HASH_I
+ */
+int
+base_i2send(iph1, msg)
+	struct ph1handle *iph1;
+	vchar_t *msg;
+{
+	struct payload_list *plist = NULL;
+	vchar_t *vid = NULL;
+	int need_cert = 0;
+	int error = -1;
+
+	/* validity check */
+	if (iph1->status != PHASE1ST_MSG2RECEIVED) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"status mismatched %d.\n", iph1->status);
+		goto end;
+	}
+
+	/* fix isakmp index */
+	memcpy(&iph1->index.r_ck, &((struct isakmp *)msg->v)->r_ck,
+		sizeof(cookie_t));
+
+	/* generate DH public value */
+	if (oakley_dh_generate(iph1->approval->dhgrp,
+				&iph1->dhpub, &iph1->dhpriv) < 0)
+		goto end;
+
+	/* generate SKEYID to compute hash if not signature mode */
+	switch (AUTHMETHOD(iph1)) {
+	case OAKLEY_ATTR_AUTH_METHOD_RSASIG:
+	case OAKLEY_ATTR_AUTH_METHOD_DSSSIG:
+#ifdef ENABLE_HYBRID
+	case OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_I:
+	case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_I:
+	case OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_I:
+	case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_I:
+	case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_I:
+#endif
+		break;
+	default:
+		if (oakley_skeyid(iph1) < 0)
+			goto end;
+		break;
+	}
+
+	/* generate HASH to send */
+	plog(LLV_DEBUG, LOCATION, NULL, "generate HASH_I\n");
+	iph1->hash = oakley_ph1hash_base_i(iph1, GENERATE);
+	if (iph1->hash == NULL)
+		goto end;
+	switch (AUTHMETHOD(iph1)) {
+	case OAKLEY_ATTR_AUTH_METHOD_PSKEY:
+#ifdef ENABLE_HYBRID
+	case FICTIVE_AUTH_METHOD_XAUTH_PSKEY_I:
+	case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_I:
+	case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_I:
+#endif
+		vid = set_vendorid(iph1->approval->vendorid);
+
+		/* create isakmp KE payload */
+		plist = isakmp_plist_append(plist, iph1->dhpub, ISAKMP_NPTYPE_KE);
+
+		/* create isakmp HASH payload */
+		plist = isakmp_plist_append(plist, iph1->hash, ISAKMP_NPTYPE_HASH);
+
+		/* append vendor id, if needed */
+		if (vid)
+			plist = isakmp_plist_append(plist, vid, ISAKMP_NPTYPE_VID);
+		break;
+	case OAKLEY_ATTR_AUTH_METHOD_DSSSIG:
+	case OAKLEY_ATTR_AUTH_METHOD_RSASIG:
+#ifdef ENABLE_HYBRID
+	case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_I:
+	case OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_I:
+#endif
+		/* XXX if there is CR or not ? */
+
+		if (oakley_getmycert(iph1) < 0)
+			goto end;
+
+		if (oakley_getsign(iph1) < 0)
+			goto end;
+
+		if (iph1->cert && iph1->rmconf->send_cert)
+			need_cert = 1;
+
+		/* create isakmp KE payload */
+		plist = isakmp_plist_append(plist, 
+		    iph1->dhpub, ISAKMP_NPTYPE_KE);
+
+		/* add CERT payload if there */
+		if (need_cert)
+			plist = isakmp_plist_append(plist, 
+			    iph1->cert->pl, ISAKMP_NPTYPE_CERT);
+
+		/* add SIG payload */
+		plist = isakmp_plist_append(plist, 
+		    iph1->sig, ISAKMP_NPTYPE_SIG);
+
+		break;
+#ifdef HAVE_GSSAPI
+	case OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB:
+		/* ... */
+		break;
+#endif
+	case OAKLEY_ATTR_AUTH_METHOD_RSAENC:
+	case OAKLEY_ATTR_AUTH_METHOD_RSAREV:
+#ifdef ENABLE_HYBRID
+	case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAENC_I:
+	case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAREV_I:
+#endif
+		break;
+	}
+
+#ifdef ENABLE_NATT
+	/* generate NAT-D payloads */
+	if (NATT_AVAILABLE(iph1))
+	{
+		vchar_t *natd[2] = { NULL, NULL };
+
+		plog (LLV_INFO, LOCATION, NULL, "Adding remote and local NAT-D payloads.\n");
+		if ((natd[0] = natt_hash_addr (iph1, iph1->remote)) == NULL) {
+			plog(LLV_ERROR, LOCATION, NULL,
+				"NAT-D hashing failed for %s\n", saddr2str(iph1->remote));
+			goto end;
+		}
+
+		if ((natd[1] = natt_hash_addr (iph1, iph1->local)) == NULL) {
+			plog(LLV_ERROR, LOCATION, NULL,
+				"NAT-D hashing failed for %s\n", saddr2str(iph1->local));
+			goto end;
+		}
+
+		plist = isakmp_plist_append(plist, natd[0], iph1->natt_options->payload_nat_d);
+		plist = isakmp_plist_append(plist, natd[1], iph1->natt_options->payload_nat_d);
+	}
+#endif
+
+	iph1->sendbuf = isakmp_plist_set_all (&plist, iph1);
+
+#ifdef HAVE_PRINT_ISAKMP_C
+	isakmp_printpacket(iph1->sendbuf, iph1->local, iph1->remote, 0);
+#endif
+
+	/* send the packet, add to the schedule to resend */
+	iph1->retry_counter = iph1->rmconf->retry_counter;
+	if (isakmp_ph1resend(iph1) == -1)
+		goto end;
+
+	/* the sending message is added to the received-list. */
+	if (add_recvdpkt(iph1->remote, iph1->local, iph1->sendbuf, msg) == -1) {
+		plog(LLV_ERROR , LOCATION, NULL,
+			"failed to add a response packet to the tree.\n");
+		goto end;
+	}
+
+	iph1->status = PHASE1ST_MSG2SENT;
+
+	error = 0;
+
+end:
+	if (vid)
+		vfree(vid);
+	return error;
+}
+
+/*
+ * receive from responder
+ * 	psk: HDR, KE, HASH_R
+ * 	sig: HDR, KE, [CERT,] SIG_R
+ * 	rsa: HDR, KE, HASH_R
+ * 	rev: HDR, <KE>_Ke_r, HASH_R
+ */
+int
+base_i3recv(iph1, msg)
+	struct ph1handle *iph1;
+	vchar_t *msg;
+{
+	vchar_t *pbuf = NULL;
+	struct isakmp_parse_t *pa;
+	int error = -1;
+	int ptype;
+#ifdef ENABLE_NATT
+	vchar_t	*natd_received;
+	int natd_seq = 0, natd_verified;
+#endif
+
+	/* validity check */
+	if (iph1->status != PHASE1ST_MSG2SENT) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"status mismatched %d.\n", iph1->status);
+		goto end;
+	}
+
+	/* validate the type of next payload */
+	pbuf = isakmp_parse(msg);
+	if (pbuf == NULL)
+		goto end;
+
+	for (pa = (struct isakmp_parse_t *)pbuf->v;
+	     pa->type != ISAKMP_NPTYPE_NONE;
+	     pa++) {
+
+		switch (pa->type) {
+		case ISAKMP_NPTYPE_KE:
+			if (isakmp_p2ph(&iph1->dhpub_p, pa->ptr) < 0)
+				goto end;
+			break;
+		case ISAKMP_NPTYPE_HASH:
+			iph1->pl_hash = (struct isakmp_pl_hash *)pa->ptr;
+			break;
+		case ISAKMP_NPTYPE_CERT:
+			if (oakley_savecert(iph1, pa->ptr) < 0)
+				goto end;
+			break;
+		case ISAKMP_NPTYPE_SIG:
+			if (isakmp_p2ph(&iph1->sig_p, pa->ptr) < 0)
+				goto end;
+			break;
+		case ISAKMP_NPTYPE_VID:
+			(void)check_vendorid(pa->ptr);
+			break;
+
+#ifdef ENABLE_NATT
+		case ISAKMP_NPTYPE_NATD_DRAFT:
+		case ISAKMP_NPTYPE_NATD_RFC:
+			if (NATT_AVAILABLE(iph1) && iph1->natt_options &&
+			    pa->type == iph1->natt_options->payload_nat_d) {
+				natd_received = NULL;
+				if (isakmp_p2ph (&natd_received, pa->ptr) < 0)
+					goto end;
+                        
+				/* set both bits first so that we can clear them
+				   upon verifying hashes */
+				if (natd_seq == 0)
+					iph1->natt_flags |= NAT_DETECTED;
+                        
+				/* this function will clear appropriate bits bits 
+				   from iph1->natt_flags */
+				natd_verified = natt_compare_addr_hash (iph1,
+					natd_received, natd_seq++);
+                        
+				plog (LLV_INFO, LOCATION, NULL, "NAT-D payload #%d %s\n",
+					natd_seq - 1,
+					natd_verified ? "verified" : "doesn't match");
+                        
+				vfree (natd_received);
+				break;
+			}
+			/* passthrough to default... */
+#endif
+
+		default:
+			/* don't send information, see ident_r1recv() */
+			plog(LLV_ERROR, LOCATION, iph1->remote,
+				"ignore the packet, "
+				"received unexpecting payload type %d.\n",
+				pa->type);
+			goto end;
+		}
+	}
+
+#ifdef ENABLE_NATT
+	if (NATT_AVAILABLE(iph1)) {
+		plog (LLV_INFO, LOCATION, NULL, "NAT %s %s%s\n",
+		      iph1->natt_flags & NAT_DETECTED ? 
+		      		"detected:" : "not detected",
+		      iph1->natt_flags & NAT_DETECTED_ME ? "ME " : "",
+		      iph1->natt_flags & NAT_DETECTED_PEER ? "PEER" : "");
+		if (iph1->natt_flags & NAT_DETECTED)
+			natt_float_ports (iph1);
+	}
+#endif
+
+	/* payload existency check */
+	/* validate authentication value */
+	ptype = oakley_validate_auth(iph1);
+	if (ptype != 0) {
+		if (ptype == -1) {
+			/* message printed inner oakley_validate_auth() */
+			goto end;
+		}
+		EVT_PUSH(iph1->local, iph1->remote, 
+		    EVTT_PEERPH1AUTH_FAILED, NULL);
+		isakmp_info_send_n1(iph1, ptype, NULL);
+		goto end;
+	}
+
+	/* compute sharing secret of DH */
+	if (oakley_dh_compute(iph1->approval->dhgrp, iph1->dhpub,
+				iph1->dhpriv, iph1->dhpub_p, &iph1->dhgxy) < 0)
+		goto end;
+
+	/* generate SKEYID to compute hash if signature mode */
+	switch (AUTHMETHOD(iph1)) {
+	case OAKLEY_ATTR_AUTH_METHOD_RSASIG:
+	case OAKLEY_ATTR_AUTH_METHOD_DSSSIG:
+#ifdef ENABLE_HYBRID
+	case OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_I:
+	case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_I:
+	case OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_I:
+	case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_I:
+	case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_I:
+#endif
+		if (oakley_skeyid(iph1) < 0)
+			goto end;
+		break;
+	default:
+		break;
+	}
+
+	/* generate SKEYIDs & IV & final cipher key */
+	if (oakley_skeyid_dae(iph1) < 0)
+		goto end;
+	if (oakley_compute_enckey(iph1) < 0)
+		goto end;
+	if (oakley_newiv(iph1) < 0)
+		goto end;
+
+	/* see handler.h about IV synchronization. */
+	memcpy(iph1->ivm->iv->v, iph1->ivm->ive->v, iph1->ivm->iv->l);
+
+	/* set encryption flag */
+	iph1->flags |= ISAKMP_FLAG_E;
+
+	iph1->status = PHASE1ST_MSG3RECEIVED;
+
+	error = 0;
+
+end:
+	if (pbuf)
+		vfree(pbuf);
+
+	if (error) {
+		VPTRINIT(iph1->dhpub_p);
+		oakley_delcert(iph1->cert_p);
+		iph1->cert_p = NULL;
+		oakley_delcert(iph1->crl_p);
+		iph1->crl_p = NULL;
+		VPTRINIT(iph1->sig_p);
+	}
+
+	return error;
+}
+
+/*
+ * status update and establish isakmp sa.
+ */
+int
+base_i3send(iph1, msg)
+	struct ph1handle *iph1;
+	vchar_t *msg;
+{
+	int error = -1;
+
+	/* validity check */
+	if (iph1->status != PHASE1ST_MSG3RECEIVED) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"status mismatched %d.\n", iph1->status);
+		goto end;
+	}
+
+	iph1->status = PHASE1ST_ESTABLISHED;
+
+	error = 0;
+
+end:
+	return error;
+}
+
+/*
+ * receive from initiator
+ * 	psk: HDR, SA, Idii, Ni_b
+ * 	sig: HDR, SA, Idii, Ni_b
+ * 	rsa: HDR, SA, [HASH(1),] <IDii_b>Pubkey_r, <Ni_b>Pubkey_r
+ * 	rev: HDR, SA, [HASH(1),] <Ni_b>Pubkey_r, <IDii_b>Ke_i
+ */
+int
+base_r1recv(iph1, msg)
+	struct ph1handle *iph1;
+	vchar_t *msg;
+{
+	vchar_t *pbuf = NULL;
+	struct isakmp_parse_t *pa;
+	int error = -1;
+	int vid_numeric;
+
+	/* validity check */
+	if (iph1->status != PHASE1ST_START) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"status mismatched %d.\n", iph1->status);
+		goto end;
+	}
+
+	/* validate the type of next payload */
+	/*
+	 * NOTE: XXX even if multiple VID, we'll silently ignore those.
+	 */
+	pbuf = isakmp_parse(msg);
+	if (pbuf == NULL)
+		goto end;
+	pa = (struct isakmp_parse_t *)pbuf->v;
+
+	/* check the position of SA payload */
+	if (pa->type != ISAKMP_NPTYPE_SA) {
+		plog(LLV_ERROR, LOCATION, iph1->remote,
+			"received invalid next payload type %d, "
+			"expecting %d.\n",
+			pa->type, ISAKMP_NPTYPE_SA);
+		goto end;
+	}
+	if (isakmp_p2ph(&iph1->sa, pa->ptr) < 0)
+		goto end;
+	pa++;
+
+	for (/*nothing*/;
+	     pa->type != ISAKMP_NPTYPE_NONE;
+	     pa++) {
+
+		switch (pa->type) {
+		case ISAKMP_NPTYPE_NONCE:
+			if (isakmp_p2ph(&iph1->nonce_p, pa->ptr) < 0)
+				goto end;
+			break;
+		case ISAKMP_NPTYPE_ID:
+			if (isakmp_p2ph(&iph1->id_p, pa->ptr) < 0)
+				goto end;
+			break;
+		case ISAKMP_NPTYPE_VID:
+			vid_numeric = check_vendorid(pa->ptr);
+#ifdef ENABLE_NATT
+			if (iph1->rmconf->nat_traversal && natt_vendorid(vid_numeric))
+				natt_handle_vendorid(iph1, vid_numeric);
+#endif
+#ifdef ENABLE_FRAG
+			if ((vid_numeric == VENDORID_FRAG) &&
+			    (vendorid_frag_cap(pa->ptr) & VENDORID_FRAG_BASE))
+				iph1->frag = 1;
+#endif
+#ifdef ENABLE_HYBRID
+			switch (vid_numeric) {
+			case VENDORID_XAUTH:
+				iph1->mode_cfg->flags |=
+				    ISAKMP_CFG_VENDORID_XAUTH;
+				break;
+
+			case VENDORID_UNITY:
+				iph1->mode_cfg->flags |=
+				    ISAKMP_CFG_VENDORID_UNITY;
+				break;
+
+			default:
+				break;
+			}
+#endif
+#ifdef ENABLE_DPD
+			if (vid_numeric == VENDORID_DPD && iph1->rmconf->dpd) {
+				iph1->dpd_support=1;
+				plog(LLV_DEBUG, LOCATION, NULL,
+					 "remote supports DPD\n");
+			}
+#endif 
+			break;
+		default:
+			/* don't send information, see ident_r1recv() */
+			plog(LLV_ERROR, LOCATION, iph1->remote,
+				"ignore the packet, "
+				"received unexpecting payload type %d.\n",
+				pa->type);
+			goto end;
+		}
+	}
+
+	if (iph1->nonce_p == NULL || iph1->id_p == NULL) {
+		plog(LLV_ERROR, LOCATION, iph1->remote,
+			"few isakmp message received.\n");
+		goto end;
+	}
+
+	/* verify identifier */
+	if (ipsecdoi_checkid1(iph1) != 0) {
+		plog(LLV_ERROR, LOCATION, iph1->remote,
+			"invalid ID payload.\n");
+		goto end;
+	}
+
+#ifdef ENABLE_NATT
+	if (NATT_AVAILABLE(iph1))
+		plog(LLV_INFO, LOCATION, iph1->remote,
+		     "Selected NAT-T version: %s\n",
+		     vid_string_by_id(iph1->natt_options->version));
+#endif
+
+	/* check SA payload and set approval SA for use */
+	if (ipsecdoi_checkph1proposal(iph1->sa, iph1) < 0) {
+		plog(LLV_ERROR, LOCATION, iph1->remote,
+			"failed to get valid proposal.\n");
+		/* XXX send information */
+		goto end;
+	}
+
+	iph1->status = PHASE1ST_MSG1RECEIVED;
+
+	error = 0;
+
+end:
+	if (pbuf)
+		vfree(pbuf);
+
+	if (error) {
+		VPTRINIT(iph1->sa);
+		VPTRINIT(iph1->nonce_p);
+		VPTRINIT(iph1->id_p);
+	}
+
+	return error;
+}
+
+/*
+ * send to initiator
+ * 	psk: HDR, SA, Idir, Nr_b
+ * 	sig: HDR, SA, Idir, Nr_b, [ CR ]
+ * 	rsa: HDR, SA, <IDir_b>PubKey_i, <Nr_b>PubKey_i
+ * 	rev: HDR, SA, <Nr_b>PubKey_i, <IDir_b>Ke_r
+ */
+int
+base_r1send(iph1, msg)
+	struct ph1handle *iph1;
+	vchar_t *msg;
+{
+	struct payload_list *plist = NULL;
+	int error = -1;
+#ifdef ENABLE_NATT
+	vchar_t *vid_natt = NULL;
+#endif
+#ifdef ENABLE_HYBRID    
+        vchar_t *vid_xauth = NULL;
+        vchar_t *vid_unity = NULL;
+#endif  
+#ifdef ENABLE_FRAG
+	vchar_t *vid_frag = NULL;
+#endif
+#ifdef ENABLE_DPD
+	vchar_t *vid_dpd = NULL;
+#endif  
+
+	/* validity check */
+	if (iph1->status != PHASE1ST_MSG1RECEIVED) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"status mismatched %d.\n", iph1->status);
+		goto end;
+	}
+
+	/* set responder's cookie */
+	isakmp_newcookie((caddr_t)&iph1->index.r_ck, iph1->remote, iph1->local);
+
+	/* make ID payload into isakmp status */
+	if (ipsecdoi_setid1(iph1) < 0)
+		goto end;
+
+	/* generate NONCE value */
+	iph1->nonce = eay_set_random(iph1->rmconf->nonce_size);
+	if (iph1->nonce == NULL)
+		goto end;
+
+	/* set SA payload to reply */
+	plist = isakmp_plist_append(plist, iph1->sa_ret, ISAKMP_NPTYPE_SA);
+
+	/* create isakmp ID payload */
+	plist = isakmp_plist_append(plist, iph1->id, ISAKMP_NPTYPE_ID);
+
+	/* create isakmp NONCE payload */
+	plist = isakmp_plist_append(plist, iph1->nonce, ISAKMP_NPTYPE_NONCE);
+
+#ifdef ENABLE_NATT
+	/* has the peer announced nat-t? */
+	if (NATT_AVAILABLE(iph1))
+		vid_natt = set_vendorid(iph1->natt_options->version);
+	if (vid_natt)
+		plist = isakmp_plist_append(plist, vid_natt, ISAKMP_NPTYPE_VID);
+#endif
+#ifdef ENABLE_HYBRID
+	if (iph1->mode_cfg->flags & ISAKMP_CFG_VENDORID_XAUTH) {
+		plog (LLV_INFO, LOCATION, NULL, "Adding xauth VID payload.\n");
+		if ((vid_xauth = set_vendorid(VENDORID_XAUTH)) == NULL) {
+			plog(LLV_ERROR, LOCATION, NULL,
+			    "Cannot create Xauth vendor ID\n");
+			goto end;
+		}
+		plist = isakmp_plist_append(plist,
+		    vid_xauth, ISAKMP_NPTYPE_VID);
+	}
+
+	if (iph1->mode_cfg->flags & ISAKMP_CFG_VENDORID_UNITY) {
+		if ((vid_unity = set_vendorid(VENDORID_UNITY)) == NULL) {
+			plog(LLV_ERROR, LOCATION, NULL,
+			    "Cannot create Unity vendor ID\n");
+			goto end;
+		}
+		plist = isakmp_plist_append(plist,
+		    vid_unity, ISAKMP_NPTYPE_VID);
+	}
+#endif
+#ifdef ENABLE_DPD
+	/* 
+	 * Only send DPD support if remote announced DPD 
+	 * and if DPD support is active 
+	 */
+	if (iph1->dpd_support && iph1->rmconf->dpd) {
+		if ((vid_dpd = set_vendorid(VENDORID_DPD)) == NULL) {
+			plog(LLV_ERROR, LOCATION, NULL,
+			    "DPD vendorID construction failed\n");
+		} else {
+			plist = isakmp_plist_append(plist, vid_dpd,
+			    ISAKMP_NPTYPE_VID);
+		}
+	}
+#endif
+#ifdef ENABLE_FRAG
+	if (iph1->rmconf->ike_frag) {
+		if ((vid_frag = set_vendorid(VENDORID_FRAG)) == NULL) {
+			plog(LLV_ERROR, LOCATION, NULL,
+			    "Frag vendorID construction failed\n");
+		} else {
+			vid_frag = isakmp_frag_addcap(vid_frag,
+			    VENDORID_FRAG_BASE);
+			plist = isakmp_plist_append(plist,
+			    vid_frag, ISAKMP_NPTYPE_VID);
+		}
+	}
+#endif
+
+	iph1->sendbuf = isakmp_plist_set_all (&plist, iph1);
+
+#ifdef HAVE_PRINT_ISAKMP_C
+	isakmp_printpacket(iph1->sendbuf, iph1->local, iph1->remote, 0);
+#endif
+
+	/* send the packet, add to the schedule to resend */
+	iph1->retry_counter = iph1->rmconf->retry_counter;
+	if (isakmp_ph1resend(iph1) == -1) {
+		iph1 = NULL;
+		goto end;
+	}
+
+	/* the sending message is added to the received-list. */
+	if (add_recvdpkt(iph1->remote, iph1->local, iph1->sendbuf, msg) == -1) {
+		plog(LLV_ERROR , LOCATION, NULL,
+			"failed to add a response packet to the tree.\n");
+		goto end;
+	}
+
+	iph1->status = PHASE1ST_MSG1SENT;
+
+	error = 0;
+
+end:
+#ifdef ENABLE_NATT
+	if (vid_natt)
+		vfree(vid_natt);
+#endif
+#ifdef ENABLE_HYBRID    
+	if (vid_xauth != NULL)
+		vfree(vid_xauth);
+	if (vid_unity != NULL)
+		vfree(vid_unity);
+#endif    
+#ifdef ENABLE_FRAG
+	if (vid_frag)
+		vfree(vid_frag);
+#endif
+#ifdef ENABLE_DPD
+	if (vid_dpd)
+		vfree(vid_dpd);
+#endif
+
+	if (iph1 != NULL)
+		VPTRINIT(iph1->sa_ret);
+
+	return error;
+}
+
+/*
+ * receive from initiator
+ * 	psk: HDR, KE, HASH_I
+ * 	sig: HDR, KE, [ CR, ] [CERT,] SIG_I
+ * 	rsa: HDR, KE, HASH_I
+ * 	rev: HDR, <KE>Ke_i, HASH_I
+ */
+int
+base_r2recv(iph1, msg)
+	struct ph1handle *iph1;
+	vchar_t *msg;
+{
+	vchar_t *pbuf = NULL;
+	struct isakmp_parse_t *pa;
+	int error = -1;
+	int ptype;
+#ifdef ENABLE_NATT
+	int natd_seq = 0;
+#endif
+
+	/* validity check */
+	if (iph1->status != PHASE1ST_MSG1SENT) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"status mismatched %d.\n", iph1->status);
+		goto end;
+	}
+
+	/* validate the type of next payload */
+	pbuf = isakmp_parse(msg);
+	if (pbuf == NULL)
+		goto end;
+
+	iph1->pl_hash = NULL;
+
+	for (pa = (struct isakmp_parse_t *)pbuf->v;
+	     pa->type != ISAKMP_NPTYPE_NONE;
+	     pa++) {
+
+		switch (pa->type) {
+		case ISAKMP_NPTYPE_KE:
+			if (isakmp_p2ph(&iph1->dhpub_p, pa->ptr) < 0)
+				goto end;
+			break;
+		case ISAKMP_NPTYPE_HASH:
+			iph1->pl_hash = (struct isakmp_pl_hash *)pa->ptr;
+			break;
+		case ISAKMP_NPTYPE_CERT:
+			if (oakley_savecert(iph1, pa->ptr) < 0)
+				goto end;
+			break;
+		case ISAKMP_NPTYPE_SIG:
+			if (isakmp_p2ph(&iph1->sig_p, pa->ptr) < 0)
+				goto end;
+			break;
+		case ISAKMP_NPTYPE_VID:
+			(void)check_vendorid(pa->ptr);
+			break;
+
+#ifdef ENABLE_NATT
+		case ISAKMP_NPTYPE_NATD_DRAFT:
+		case ISAKMP_NPTYPE_NATD_RFC:
+			if (pa->type == iph1->natt_options->payload_nat_d)
+			{
+				vchar_t *natd_received = NULL;
+				int natd_verified;
+				
+				if (isakmp_p2ph (&natd_received, pa->ptr) < 0)
+					goto end;
+				
+				if (natd_seq == 0)
+					iph1->natt_flags |= NAT_DETECTED;
+				
+				natd_verified = natt_compare_addr_hash (iph1,
+					natd_received, natd_seq++);
+				
+				plog (LLV_INFO, LOCATION, NULL, "NAT-D payload #%d %s\n",
+					natd_seq - 1,
+					natd_verified ? "verified" : "doesn't match");
+				
+				vfree (natd_received);
+				break;
+			}
+			/* passthrough to default... */
+#endif
+
+		default:
+			/* don't send information, see ident_r1recv() */
+			plog(LLV_ERROR, LOCATION, iph1->remote,
+				"ignore the packet, "
+				"received unexpecting payload type %d.\n",
+				pa->type);
+			goto end;
+		}
+	}
+
+	/* generate DH public value */
+	if (oakley_dh_generate(iph1->approval->dhgrp,
+				&iph1->dhpub, &iph1->dhpriv) < 0)
+		goto end;
+
+	/* compute sharing secret of DH */
+	if (oakley_dh_compute(iph1->approval->dhgrp, iph1->dhpub,
+				iph1->dhpriv, iph1->dhpub_p, &iph1->dhgxy) < 0)
+		goto end;
+
+	/* generate SKEYID */
+	if (oakley_skeyid(iph1) < 0)
+		goto end;
+
+#ifdef ENABLE_NATT
+	if (NATT_AVAILABLE(iph1))
+		plog (LLV_INFO, LOCATION, NULL, "NAT %s %s%s\n",
+		      iph1->natt_flags & NAT_DETECTED ? 
+		      		"detected:" : "not detected",
+		      iph1->natt_flags & NAT_DETECTED_ME ? "ME " : "",
+		      iph1->natt_flags & NAT_DETECTED_PEER ? "PEER" : "");
+#endif
+
+	/* payload existency check */
+	/* validate authentication value */
+	ptype = oakley_validate_auth(iph1);
+	if (ptype != 0) {
+		if (ptype == -1) {
+			/* message printed inner oakley_validate_auth() */
+			goto end;
+		}
+		EVT_PUSH(iph1->local, iph1->remote, 
+		    EVTT_PEERPH1AUTH_FAILED, NULL);
+		isakmp_info_send_n1(iph1, ptype, NULL);
+		goto end;
+	}
+
+	iph1->status = PHASE1ST_MSG2RECEIVED;
+
+	error = 0;
+
+end:
+	if (pbuf)
+		vfree(pbuf);
+
+	if (error) {
+		VPTRINIT(iph1->dhpub_p);
+		oakley_delcert(iph1->cert_p);
+		iph1->cert_p = NULL;
+		oakley_delcert(iph1->crl_p);
+		iph1->crl_p = NULL;
+		VPTRINIT(iph1->sig_p);
+	}
+
+	return error;
+}
+
+/*
+ * send to initiator
+ * 	psk: HDR, KE, HASH_R
+ * 	sig: HDR, KE, [CERT,] SIG_R
+ * 	rsa: HDR, KE, HASH_R
+ * 	rev: HDR, <KE>_Ke_r, HASH_R
+ */
+int
+base_r2send(iph1, msg)
+	struct ph1handle *iph1;
+	vchar_t *msg;
+{
+	struct payload_list *plist = NULL;
+	vchar_t *vid = NULL;
+	int need_cert = 0;
+	int error = -1;
+
+	/* validity check */
+	if (iph1->status != PHASE1ST_MSG2RECEIVED) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"status mismatched %d.\n", iph1->status);
+		goto end;
+	}
+
+	/* generate HASH to send */
+	plog(LLV_DEBUG, LOCATION, NULL, "generate HASH_I\n");
+	switch (AUTHMETHOD(iph1)) {
+	case OAKLEY_ATTR_AUTH_METHOD_PSKEY:
+#ifdef ENABLE_HYBRID
+	case OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_R:
+#endif
+	case OAKLEY_ATTR_AUTH_METHOD_RSAENC:
+	case OAKLEY_ATTR_AUTH_METHOD_RSAREV:
+#ifdef ENABLE_HYBRID
+	case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAENC_R:
+	case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAREV_R:
+#endif
+		iph1->hash = oakley_ph1hash_common(iph1, GENERATE);
+		break;
+	case OAKLEY_ATTR_AUTH_METHOD_DSSSIG:
+	case OAKLEY_ATTR_AUTH_METHOD_RSASIG:
+#ifdef ENABLE_HYBRID
+	case OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_R:
+	case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_R:
+	case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_R:
+	case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_R:
+#endif
+#ifdef HAVE_GSSAPI
+	case OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB:
+#endif
+		iph1->hash = oakley_ph1hash_base_r(iph1, GENERATE);
+		break;
+	default:
+		plog(LLV_ERROR, LOCATION, NULL,
+			"invalid authentication method %d\n",
+			iph1->approval->authmethod);
+		goto end; 
+	}
+	if (iph1->hash == NULL)
+		goto end;
+
+	switch (AUTHMETHOD(iph1)) {
+	case OAKLEY_ATTR_AUTH_METHOD_PSKEY:
+#ifdef ENABLE_HYBRID
+	case OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_R:
+#endif
+		vid = set_vendorid(iph1->approval->vendorid);
+
+		/* create isakmp KE payload */
+		plist = isakmp_plist_append(plist, 
+		    iph1->dhpub, ISAKMP_NPTYPE_KE);
+
+		/* create isakmp HASH payload */
+		plist = isakmp_plist_append(plist, 
+		    iph1->hash, ISAKMP_NPTYPE_HASH);
+
+		/* append vendor id, if needed */
+		if (vid)
+			plist = isakmp_plist_append(plist, 
+			    vid, ISAKMP_NPTYPE_VID);
+		break;
+	case OAKLEY_ATTR_AUTH_METHOD_DSSSIG:
+	case OAKLEY_ATTR_AUTH_METHOD_RSASIG:
+#ifdef ENABLE_HYBRID
+	case OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_R:
+	case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_R:
+	case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_R:
+	case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_R:
+#endif
+		/* XXX if there is CR or not ? */
+
+		if (oakley_getmycert(iph1) < 0)
+			goto end;
+
+		if (oakley_getsign(iph1) < 0)
+			goto end;
+
+		if (iph1->cert && iph1->rmconf->send_cert)
+			need_cert = 1;
+
+		/* create isakmp KE payload */
+		plist = isakmp_plist_append(plist, 
+		    iph1->dhpub, ISAKMP_NPTYPE_KE);
+
+		/* add CERT payload if there */
+		if (need_cert)
+			plist = isakmp_plist_append(plist, 
+			    iph1->cert->pl, ISAKMP_NPTYPE_CERT);
+		/* add SIG payload */
+		plist = isakmp_plist_append(plist, 
+		    iph1->sig, ISAKMP_NPTYPE_SIG);
+		break;
+#ifdef HAVE_GSSAPI
+	case OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB:
+		/* ... */
+		break;
+#endif
+	case OAKLEY_ATTR_AUTH_METHOD_RSAENC:
+	case OAKLEY_ATTR_AUTH_METHOD_RSAREV:
+#ifdef ENABLE_HYBRID
+	case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAENC_R:
+	case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAREV_R:
+#endif
+		break;
+	}
+
+#ifdef ENABLE_NATT
+	/* generate NAT-D payloads */
+	if (NATT_AVAILABLE(iph1)) {
+		vchar_t *natd[2] = { NULL, NULL };
+
+		plog(LLV_INFO, LOCATION, 
+		    NULL, "Adding remote and local NAT-D payloads.\n");
+		if ((natd[0] = natt_hash_addr(iph1, iph1->remote)) == NULL) {
+			plog(LLV_ERROR, LOCATION, NULL,
+			    "NAT-D hashing failed for %s\n", 
+			    saddr2str(iph1->remote));
+			goto end;
+		}
+
+		if ((natd[1] = natt_hash_addr(iph1, iph1->local)) == NULL) {
+			plog(LLV_ERROR, LOCATION, NULL,
+			    "NAT-D hashing failed for %s\n", 
+			    saddr2str(iph1->local));
+			goto end;
+		}
+
+		plist = isakmp_plist_append(plist, 
+		    natd[0], iph1->natt_options->payload_nat_d);
+		plist = isakmp_plist_append(plist, 
+		    natd[1], iph1->natt_options->payload_nat_d);
+	}
+#endif
+
+	iph1->sendbuf = isakmp_plist_set_all(&plist, iph1);
+
+#ifdef HAVE_PRINT_ISAKMP_C
+	isakmp_printpacket(iph1->sendbuf, iph1->local, iph1->remote, 0);
+#endif
+
+	/* send HDR;KE;NONCE to responder */
+	if (isakmp_send(iph1, iph1->sendbuf) < 0)
+		goto end;
+
+	/* the sending message is added to the received-list. */
+	if (add_recvdpkt(iph1->remote, iph1->local, iph1->sendbuf, msg) == -1) {
+		plog(LLV_ERROR , LOCATION, NULL,
+			"failed to add a response packet to the tree.\n");
+		goto end;
+	}
+
+	/* generate SKEYIDs & IV & final cipher key */
+	if (oakley_skeyid_dae(iph1) < 0)
+		goto end;
+	if (oakley_compute_enckey(iph1) < 0)
+		goto end;
+	if (oakley_newiv(iph1) < 0)
+		goto end;
+
+	/* set encryption flag */
+	iph1->flags |= ISAKMP_FLAG_E;
+
+	iph1->status = PHASE1ST_ESTABLISHED;
+
+	error = 0;
+
+end:
+	if (vid)
+		vfree(vid);
+	return error;
+}
diff --git a/src/racoon/isakmp_base.h b/src/racoon/isakmp_base.h
new file mode 100644
index 0000000..560880e
--- /dev/null
+++ b/src/racoon/isakmp_base.h
@@ -0,0 +1,48 @@
+/*	$NetBSD: isakmp_base.h,v 1.4 2006/09/09 16:22:09 manu Exp $	*/
+
+/* Id: isakmp_base.h,v 1.3 2004/06/11 16:00:16 ludvigm Exp */
+
+/*
+ * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _ISAKMP_BASE_H
+#define _ISAKMP_BASE_H
+
+extern int base_i1send __P((struct ph1handle *, vchar_t *));
+extern int base_i2recv __P((struct ph1handle *, vchar_t *));
+extern int base_i2send __P((struct ph1handle *, vchar_t *));
+extern int base_i3recv __P((struct ph1handle *, vchar_t *));
+extern int base_i3send __P((struct ph1handle *, vchar_t *));
+
+extern int base_r1recv __P((struct ph1handle *, vchar_t *));
+extern int base_r1send __P((struct ph1handle *, vchar_t *));
+extern int base_r2recv __P((struct ph1handle *, vchar_t *));
+extern int base_r2send __P((struct ph1handle *, vchar_t *));
+
+#endif /* _ISAKMP_BASE_H */
diff --git a/src/racoon/isakmp_cfg.c b/src/racoon/isakmp_cfg.c
new file mode 100644
index 0000000..547cbf0
--- /dev/null
+++ b/src/racoon/isakmp_cfg.c
@@ -0,0 +1,2157 @@
+/*	$NetBSD: isakmp_cfg.c,v 1.12.6.3 2008/07/15 02:18:52 mgrooms Exp $	*/
+
+/* Id: isakmp_cfg.c,v 1.55 2006/08/22 18:17:17 manubsd Exp */
+
+/*
+ * Copyright (C) 2004-2006 Emmanuel Dreyfus
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <sys/queue.h>
+
+#include <utmp.h>
+#if defined(__APPLE__) && defined(__MACH__)
+#include <util.h>
+#endif
+
+#ifdef __FreeBSD__
+# include <libutil.h>
+#endif
+#ifdef __NetBSD__
+#  include <util.h>
+#endif
+
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#if TIME_WITH_SYS_TIME
+# include <sys/time.h>
+# include <time.h>
+#else
+# if HAVE_SYS_TIME_H
+#  include <sys/time.h>
+# else
+#  include <time.h>
+# endif
+#endif
+#include <netdb.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#if HAVE_STDINT_H
+#include <stdint.h>
+#endif
+#include <ctype.h>
+#include <resolv.h>
+
+#ifdef HAVE_LIBRADIUS
+#include <sys/utsname.h>
+#include <radlib.h>
+#endif
+
+#include "var.h"
+#include "misc.h"
+#include "vmbuf.h"
+#include "plog.h"
+#include "sockmisc.h"
+#include "schedule.h"
+#include "debug.h"
+
+#include "isakmp_var.h"
+#include "isakmp.h"
+#include "handler.h"
+#include "evt.h"
+#include "throttle.h"
+#include "remoteconf.h"
+#include "crypto_openssl.h"
+#include "isakmp_inf.h"
+#include "isakmp_xauth.h"
+#include "isakmp_unity.h"
+#include "isakmp_cfg.h"
+#include "strnames.h"
+#include "admin.h"
+#include "privsep.h"
+
+struct isakmp_cfg_config isakmp_cfg_config;
+
+static vchar_t *buffer_cat(vchar_t *s, vchar_t *append);
+static vchar_t *isakmp_cfg_net(struct ph1handle *, struct isakmp_data *);
+#if 0
+static vchar_t *isakmp_cfg_void(struct ph1handle *, struct isakmp_data *);
+#endif
+static vchar_t *isakmp_cfg_addr4(struct ph1handle *, 
+				 struct isakmp_data *, in_addr_t *);
+static void isakmp_cfg_getaddr4(struct isakmp_data *, struct in_addr *);
+static vchar_t *isakmp_cfg_addr4_list(struct ph1handle *,
+				      struct isakmp_data *, in_addr_t *, int);
+static void isakmp_cfg_appendaddr4(struct isakmp_data *, 
+				   struct in_addr *, int *, int);
+static void isakmp_cfg_getstring(struct isakmp_data *,char *);
+void isakmp_cfg_iplist_to_str(char *, int, void *, int);
+
+#define ISAKMP_CFG_LOGIN	1
+#define ISAKMP_CFG_LOGOUT	2
+static int isakmp_cfg_accounting(struct ph1handle *, int);
+#ifdef HAVE_LIBRADIUS
+static int isakmp_cfg_accounting_radius(struct ph1handle *, int);
+#endif
+
+/* 
+ * Handle an ISAKMP config mode packet
+ * We expect HDR, HASH, ATTR
+ */
+void
+isakmp_cfg_r(iph1, msg)
+	struct ph1handle *iph1;
+	vchar_t *msg;
+{
+	struct isakmp *packet;
+	struct isakmp_gen *ph;
+	int tlen;
+	char *npp;
+	int np;
+	vchar_t *dmsg;
+	struct isakmp_ivm *ivm;
+
+	/* Check that the packet is long enough to have a header */
+	if (msg->l < sizeof(*packet)) {
+	     plog(LLV_ERROR, LOCATION, NULL, "Unexpected short packet\n");
+	     return;
+	}
+
+	packet = (struct isakmp *)msg->v;
+
+	/* Is it encrypted? It should be encrypted */
+	if ((packet->flags & ISAKMP_FLAG_E) == 0) {
+		plog(LLV_ERROR, LOCATION, NULL, 
+		    "User credentials sent in cleartext!\n");
+		return;
+	}
+
+	/* 
+	 * Decrypt the packet. If this is the beginning of a new
+	 * exchange, reinitialize the IV
+	 */
+	if (iph1->mode_cfg->ivm == NULL ||
+	    iph1->mode_cfg->last_msgid != packet->msgid )
+		iph1->mode_cfg->ivm = 
+		    isakmp_cfg_newiv(iph1, packet->msgid);
+	ivm = iph1->mode_cfg->ivm;
+
+	dmsg = oakley_do_decrypt(iph1, msg, ivm->iv, ivm->ive);
+	if (dmsg == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL, 
+		    "failed to decrypt message\n");
+		return;
+	}
+
+	plog(LLV_DEBUG, LOCATION, NULL, "MODE_CFG packet\n");
+	plogdump(LLV_DEBUG, dmsg->v, dmsg->l);
+
+	/* Now work with the decrypted packet */
+	packet = (struct isakmp *)dmsg->v;
+	tlen = dmsg->l - sizeof(*packet);
+	ph = (struct isakmp_gen *)(packet + 1);
+
+	np = packet->np;
+	while ((tlen > 0) && (np != ISAKMP_NPTYPE_NONE)) {
+		/* Check that the payload header fits in the packet */
+		if (tlen < sizeof(*ph)) {
+			 plog(LLV_WARNING, LOCATION, NULL, 
+			      "Short payload header\n");
+			 goto out;
+		}
+
+		/* Check that the payload fits in the packet */
+		if (tlen < ntohs(ph->len)) {
+			plog(LLV_WARNING, LOCATION, NULL, 
+			      "Short payload\n");
+			goto out;
+		}
+		
+		plog(LLV_DEBUG, LOCATION, NULL, "Seen payload %d\n", np);
+		plogdump(LLV_DEBUG, ph, ntohs(ph->len));
+
+		switch(np) {
+		case ISAKMP_NPTYPE_HASH: {
+			vchar_t *check;
+			vchar_t *payload;
+			size_t plen;
+			struct isakmp_gen *nph;
+
+			plen = ntohs(ph->len);
+			nph = (struct isakmp_gen *)((char *)ph + plen);
+			plen = ntohs(nph->len);
+
+			if ((payload = vmalloc(plen)) == NULL) {
+				plog(LLV_ERROR, LOCATION, NULL, 
+				    "Cannot allocate memory\n");
+				goto out;
+			}
+			memcpy(payload->v, nph, plen);
+
+			if ((check = oakley_compute_hash1(iph1, 
+			    packet->msgid, payload)) == NULL) {
+				plog(LLV_ERROR, LOCATION, NULL, 
+				    "Cannot compute hash\n");
+				vfree(payload);
+				goto out;
+			}
+
+			if (memcmp(ph + 1, check->v, check->l) != 0) {
+				plog(LLV_ERROR, LOCATION, NULL, 
+				    "Hash verification failed\n");
+				vfree(payload);
+				vfree(check);
+				goto out;
+			}
+			vfree(payload);
+			vfree(check);
+			break;
+		}
+		case ISAKMP_NPTYPE_ATTR: {
+			struct isakmp_pl_attr *attrpl;
+
+			attrpl = (struct isakmp_pl_attr *)ph;
+			isakmp_cfg_attr_r(iph1, packet->msgid, attrpl);
+
+			break;
+		}
+		default:
+			 plog(LLV_WARNING, LOCATION, NULL, 
+			      "Unexpected next payload %d\n", np);
+			 /* Skip to the next payload */
+			 break;
+		}
+
+		/* Move to the next payload */
+		np = ph->np;
+		tlen -= ntohs(ph->len);
+		npp = (char *)ph;
+		ph = (struct isakmp_gen *)(npp + ntohs(ph->len));
+	}
+
+out:
+	vfree(dmsg);
+}
+
+int
+isakmp_cfg_attr_r(iph1, msgid, attrpl) 
+	struct ph1handle *iph1;
+	u_int32_t msgid;
+	struct isakmp_pl_attr *attrpl;
+{
+	int type = attrpl->type;
+
+	plog(LLV_DEBUG, LOCATION, NULL,
+	     "Configuration exchange type %s\n", s_isakmp_cfg_ptype(type));
+	switch (type) {
+	case ISAKMP_CFG_ACK:
+		/* ignore, but this is the time to reinit the IV */
+		oakley_delivm(iph1->mode_cfg->ivm);
+		iph1->mode_cfg->ivm = NULL;
+		return 0;
+		break;
+
+	case ISAKMP_CFG_REPLY:
+		return isakmp_cfg_reply(iph1, attrpl);
+		break;
+
+	case ISAKMP_CFG_REQUEST:
+		iph1->msgid = msgid;
+		return isakmp_cfg_request(iph1, attrpl);
+		break;
+
+	case ISAKMP_CFG_SET:
+		iph1->msgid = msgid;
+		return isakmp_cfg_set(iph1, attrpl);
+		break;
+
+	default:
+		plog(LLV_WARNING, LOCATION, NULL,
+		     "Unepected configuration exchange type %d\n", type);
+		return -1;
+		break;
+	}
+
+	return 0;
+}
+
+int
+isakmp_cfg_reply(iph1, attrpl)
+	struct ph1handle *iph1;
+	struct isakmp_pl_attr *attrpl;
+{
+	struct isakmp_data *attr;
+	int tlen;
+	size_t alen;
+	char *npp;
+	int type;
+	struct sockaddr_in *sin;
+	int error;
+
+	tlen = ntohs(attrpl->h.len);
+	attr = (struct isakmp_data *)(attrpl + 1);
+	tlen -= sizeof(*attrpl);
+	
+	while (tlen > 0) {
+		type = ntohs(attr->type);
+
+		/* Handle short attributes */
+		if ((type & ISAKMP_GEN_MASK) == ISAKMP_GEN_TV) {
+			type &= ~ISAKMP_GEN_MASK;
+
+			plog(LLV_DEBUG, LOCATION, NULL,
+			     "Short attribute %s = %d\n", 
+			     s_isakmp_cfg_type(type), ntohs(attr->lorv));
+
+			switch (type) {
+			case XAUTH_TYPE:
+				if ((error = xauth_attr_reply(iph1, 
+				    attr, ntohs(attrpl->id))) != 0)
+					return error;
+				break;
+
+			default:
+				plog(LLV_WARNING, LOCATION, NULL,
+				     "Ignored short attribute %s\n",
+				     s_isakmp_cfg_type(type));
+				break;
+			}
+
+			tlen -= sizeof(*attr);
+			attr++;
+			continue;
+		}
+
+		type = ntohs(attr->type);
+		alen = ntohs(attr->lorv);
+
+		/* Check that the attribute fit in the packet */
+		if (tlen < alen) {
+			plog(LLV_ERROR, LOCATION, NULL,
+			     "Short attribute %s\n",
+			     s_isakmp_cfg_type(type));
+			return -1;
+		}
+
+		plog(LLV_DEBUG, LOCATION, NULL,
+		     "Attribute %s, len %zu\n", 
+		     s_isakmp_cfg_type(type), alen);
+
+		switch(type) {
+		case XAUTH_TYPE:
+		case XAUTH_USER_NAME:
+		case XAUTH_USER_PASSWORD:
+		case XAUTH_PASSCODE:
+		case XAUTH_MESSAGE:
+		case XAUTH_CHALLENGE:
+		case XAUTH_DOMAIN:
+		case XAUTH_STATUS:
+		case XAUTH_NEXT_PIN:
+		case XAUTH_ANSWER:
+			if ((error = xauth_attr_reply(iph1, 
+			    attr, ntohs(attrpl->id))) != 0)
+				return error;
+			break;
+		case INTERNAL_IP4_ADDRESS:
+			isakmp_cfg_getaddr4(attr, &iph1->mode_cfg->addr4);
+			iph1->mode_cfg->flags |= ISAKMP_CFG_GOT_ADDR4;
+			break;
+		case INTERNAL_IP4_NETMASK:
+			isakmp_cfg_getaddr4(attr, &iph1->mode_cfg->mask4);
+			iph1->mode_cfg->flags |= ISAKMP_CFG_GOT_MASK4;
+			break;
+		case INTERNAL_IP4_DNS:
+			isakmp_cfg_appendaddr4(attr, 
+			    &iph1->mode_cfg->dns4[iph1->mode_cfg->dns4_index],
+			    &iph1->mode_cfg->dns4_index, MAXNS);
+			iph1->mode_cfg->flags |= ISAKMP_CFG_GOT_DNS4;
+			break;
+		case INTERNAL_IP4_NBNS:
+			isakmp_cfg_appendaddr4(attr, 
+			    &iph1->mode_cfg->wins4[iph1->mode_cfg->wins4_index],
+			    &iph1->mode_cfg->wins4_index, MAXNS);
+			iph1->mode_cfg->flags |= ISAKMP_CFG_GOT_WINS4;
+			break;
+		case UNITY_DEF_DOMAIN:
+			isakmp_cfg_getstring(attr, 
+			    iph1->mode_cfg->default_domain);
+			iph1->mode_cfg->flags |= ISAKMP_CFG_GOT_DEFAULT_DOMAIN;
+			break;
+		case UNITY_SPLIT_INCLUDE:
+		case UNITY_LOCAL_LAN:
+		case UNITY_SPLITDNS_NAME:
+		case UNITY_BANNER:
+		case UNITY_SAVE_PASSWD:
+		case UNITY_NATT_PORT:
+		case UNITY_PFS:
+		case UNITY_FW_TYPE:
+		case UNITY_BACKUP_SERVERS:
+		case UNITY_DDNS_HOSTNAME:
+			isakmp_unity_reply(iph1, attr);
+			break;
+		case INTERNAL_IP4_SUBNET:
+		case INTERNAL_ADDRESS_EXPIRY:
+		default:
+			plog(LLV_WARNING, LOCATION, NULL,
+			     "Ignored attribute %s\n",
+			     s_isakmp_cfg_type(type));
+			break;
+		}
+
+		npp = (char *)attr;
+		attr = (struct isakmp_data *)(npp + sizeof(*attr) + alen);
+		tlen -= (sizeof(*attr) + alen);
+	}
+
+	/* 
+	 * Call the SA up script hook now that we have the configuration
+	 * It is done at the end of phase 1 if ISAKMP mode config is not
+	 * requested.
+	 */
+	
+	if ((iph1->status == PHASE1ST_ESTABLISHED) && 
+	    iph1->rmconf->mode_cfg) {
+		switch (AUTHMETHOD(iph1)) {
+		case FICTIVE_AUTH_METHOD_XAUTH_PSKEY_I:
+		case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_I:
+		/* Unimplemented */
+		case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_I: 
+		case OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_I: 
+		case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_I:
+		case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAENC_I: 
+		case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAREV_I: 
+			script_hook(iph1, SCRIPT_PHASE1_UP);
+			break;
+		default:
+			break;
+		}
+	}
+		
+
+#ifdef ENABLE_ADMINPORT
+	{
+		vchar_t *buf;
+
+		alen = ntohs(attrpl->h.len) - sizeof(*attrpl);
+		if ((buf = vmalloc(alen)) == NULL) {
+			plog(LLV_WARNING, LOCATION, NULL, 
+			    "Cannot allocate memory: %s\n", strerror(errno));
+		} else {
+			memcpy(buf->v, attrpl + 1, buf->l);
+			EVT_PUSH(iph1->local, iph1->remote, 
+			    EVTT_ISAKMP_CFG_DONE, buf);
+			vfree(buf);
+		}
+	}
+#endif
+
+	return 0;
+}
+
+int
+isakmp_cfg_request(iph1, attrpl)
+	struct ph1handle *iph1;
+	struct isakmp_pl_attr *attrpl;
+{
+	struct isakmp_data *attr;
+	int tlen;
+	size_t alen;
+	char *npp;
+	vchar_t *payload;
+	struct isakmp_pl_attr *reply;
+	vchar_t *reply_attr;
+	int type;
+	int error = -1;
+
+	if ((payload = vmalloc(sizeof(*reply))) == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL, "Cannot allocate memory\n");
+		return -1;
+	}
+	memset(payload->v, 0, sizeof(*reply));
+
+	tlen = ntohs(attrpl->h.len);
+	attr = (struct isakmp_data *)(attrpl + 1);
+	tlen -= sizeof(*attrpl);
+	
+	while (tlen > 0) {
+		reply_attr = NULL;
+		type = ntohs(attr->type);
+
+		/* Handle short attributes */
+		if ((type & ISAKMP_GEN_MASK) == ISAKMP_GEN_TV) {
+			type &= ~ISAKMP_GEN_MASK;
+
+			plog(LLV_DEBUG, LOCATION, NULL,
+			     "Short attribute %s = %d\n", 
+			     s_isakmp_cfg_type(type), ntohs(attr->lorv));
+
+			switch (type) {
+			case XAUTH_TYPE:
+				reply_attr = isakmp_xauth_req(iph1, attr);
+				break;
+			default:
+				plog(LLV_WARNING, LOCATION, NULL,
+				     "Ignored short attribute %s\n",
+				     s_isakmp_cfg_type(type));
+				break;
+			}
+
+			tlen -= sizeof(*attr);
+			attr++;
+
+			if (reply_attr != NULL) {
+				payload = buffer_cat(payload, reply_attr);
+				vfree(reply_attr);
+			}
+
+			continue;
+		}
+
+		type = ntohs(attr->type);
+		alen = ntohs(attr->lorv);
+
+		/* Check that the attribute fit in the packet */
+		if (tlen < alen) {
+			plog(LLV_ERROR, LOCATION, NULL,
+			     "Short attribute %s\n",
+			     s_isakmp_cfg_type(type));
+			goto end;
+		}
+
+		plog(LLV_DEBUG, LOCATION, NULL,
+		     "Attribute %s, len %zu\n",
+		     s_isakmp_cfg_type(type), alen);
+
+		switch(type) {
+		case INTERNAL_IP4_ADDRESS:
+		case INTERNAL_IP4_NETMASK:
+		case INTERNAL_IP4_DNS:
+		case INTERNAL_IP4_NBNS:
+		case INTERNAL_IP4_SUBNET:
+			reply_attr = isakmp_cfg_net(iph1, attr);
+			break;
+
+		case XAUTH_TYPE:
+		case XAUTH_USER_NAME:
+		case XAUTH_USER_PASSWORD:
+		case XAUTH_PASSCODE:
+		case XAUTH_MESSAGE:
+		case XAUTH_CHALLENGE:
+		case XAUTH_DOMAIN:
+		case XAUTH_STATUS:
+		case XAUTH_NEXT_PIN:
+		case XAUTH_ANSWER:
+			reply_attr = isakmp_xauth_req(iph1, attr);
+			break;
+
+		case APPLICATION_VERSION:
+			reply_attr = isakmp_cfg_string(iph1, 
+			    attr, ISAKMP_CFG_RACOON_VERSION);
+			break;
+
+		case UNITY_BANNER:
+		case UNITY_PFS:
+		case UNITY_SAVE_PASSWD:
+		case UNITY_DEF_DOMAIN:
+		case UNITY_DDNS_HOSTNAME:
+		case UNITY_FW_TYPE:
+		case UNITY_SPLITDNS_NAME:
+		case UNITY_SPLIT_INCLUDE:
+		case UNITY_LOCAL_LAN:
+		case UNITY_NATT_PORT:
+		case UNITY_BACKUP_SERVERS:
+			reply_attr = isakmp_unity_req(iph1, attr);
+			break;
+
+		case INTERNAL_ADDRESS_EXPIRY:
+		default:
+			plog(LLV_WARNING, LOCATION, NULL,
+			     "Ignored attribute %s\n",
+			     s_isakmp_cfg_type(type));
+			break;
+		}
+
+		npp = (char *)attr;
+		attr = (struct isakmp_data *)(npp + sizeof(*attr) + alen);
+		tlen -= (sizeof(*attr) + alen);
+
+		if (reply_attr != NULL) {
+			payload = buffer_cat(payload, reply_attr);
+			vfree(reply_attr);
+		}
+
+	}
+
+	reply = (struct isakmp_pl_attr *)payload->v;
+	reply->h.len = htons(payload->l);
+	reply->type = ISAKMP_CFG_REPLY;
+	reply->id = attrpl->id;
+
+	plog(LLV_DEBUG, LOCATION, NULL, 
+		    "Sending MODE_CFG REPLY\n");
+
+	error = isakmp_cfg_send(iph1, payload, 
+	    ISAKMP_NPTYPE_ATTR, ISAKMP_FLAG_E, 0);
+
+	if (iph1->status == PHASE1ST_ESTABLISHED) {
+		switch (AUTHMETHOD(iph1)) {
+		case OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_R:
+		case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_R:
+		/* Unimplemented */
+		case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_R: 
+		case OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_R: 
+		case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_R:
+		case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAENC_R: 
+		case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAREV_R: 
+			script_hook(iph1, SCRIPT_PHASE1_UP);
+			break;
+		default:
+			break;
+		}
+	}
+	
+end:
+	vfree(payload);
+
+	return error;
+}
+
+int
+isakmp_cfg_set(iph1, attrpl)
+	struct ph1handle *iph1;
+	struct isakmp_pl_attr *attrpl;
+{
+	struct isakmp_data *attr;
+	int tlen;
+	size_t alen;
+	char *npp;
+	vchar_t *payload;
+	struct isakmp_pl_attr *reply;
+	vchar_t *reply_attr;
+	int type;
+	int error = -1;
+
+	if ((payload = vmalloc(sizeof(*reply))) == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL, "Cannot allocate memory\n");
+		return -1;
+	}
+	memset(payload->v, 0, sizeof(*reply));
+
+	tlen = ntohs(attrpl->h.len);
+	attr = (struct isakmp_data *)(attrpl + 1);
+	tlen -= sizeof(*attrpl);
+	
+	/* 
+	 * We should send ack for the attributes we accepted 
+	 */
+	while (tlen > 0) {
+		reply_attr = NULL;
+		type = ntohs(attr->type);
+
+		plog(LLV_DEBUG, LOCATION, NULL,
+		     "Attribute %s\n", 
+		     s_isakmp_cfg_type(type & ~ISAKMP_GEN_MASK));
+		
+		switch (type & ~ISAKMP_GEN_MASK) {
+		case XAUTH_STATUS:
+			reply_attr = isakmp_xauth_set(iph1, attr);
+			break;
+		default:
+			plog(LLV_DEBUG, LOCATION, NULL,
+			     "Unexpected SET attribute %s\n", 
+		     	     s_isakmp_cfg_type(type & ~ISAKMP_GEN_MASK));
+			break;
+		}
+
+		if (reply_attr != NULL) {
+			payload = buffer_cat(payload, reply_attr);
+			vfree(reply_attr);
+		}
+
+		/* 
+		 * Move to next attribute. If we run out of the packet, 
+		 * tlen becomes negative and we exit. 
+		 */
+		if ((type & ISAKMP_GEN_MASK) == ISAKMP_GEN_TV) {
+			tlen -= sizeof(*attr);
+			attr++;
+		} else {
+			alen = ntohs(attr->lorv);
+			tlen -= (sizeof(*attr) + alen);
+			npp = (char *)attr;
+			attr = (struct isakmp_data *)
+			    (npp + sizeof(*attr) + alen);
+		}
+	}
+
+	reply = (struct isakmp_pl_attr *)payload->v;
+	reply->h.len = htons(payload->l);
+	reply->type = ISAKMP_CFG_ACK;
+	reply->id = attrpl->id;
+
+	plog(LLV_DEBUG, LOCATION, NULL,
+		     "Sending MODE_CFG ACK\n");
+
+	error = isakmp_cfg_send(iph1, payload, 
+	    ISAKMP_NPTYPE_ATTR, ISAKMP_FLAG_E, 0);
+
+	if (iph1->mode_cfg->flags & ISAKMP_CFG_DELETE_PH1) {
+		if (iph1->status == PHASE1ST_ESTABLISHED)
+			isakmp_info_send_d1(iph1);
+		remph1(iph1);
+		delph1(iph1);
+		iph1 = NULL;
+	}
+end:
+	vfree(payload);
+
+	/* 
+	 * If required, request ISAKMP mode config information
+	 */
+	if ((iph1 != NULL) && (iph1->rmconf->mode_cfg) && (error == 0))
+		error = isakmp_cfg_getconfig(iph1);
+
+	return error;
+}
+
+
+static vchar_t *
+buffer_cat(s, append)
+	vchar_t *s;
+	vchar_t *append;
+{
+	vchar_t *new;
+
+	new = vmalloc(s->l + append->l);
+	if (new == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL, 
+		    "Cannot allocate memory\n");
+		return s;
+	}
+
+	memcpy(new->v, s->v, s->l);
+	memcpy(new->v + s->l, append->v, append->l);
+
+	vfree(s);
+	return new;
+}
+
+static vchar_t *
+isakmp_cfg_net(iph1, attr)
+	struct ph1handle *iph1;
+	struct isakmp_data *attr;
+{
+	int type;
+	int confsource;
+	in_addr_t addr4;
+
+	type = ntohs(attr->type);
+
+	/* 
+	 * Don't give an address to a peer that did not succeed Xauth
+	 */
+	if (xauth_check(iph1) != 0) {
+		plog(LLV_ERROR, LOCATION, NULL,
+		    "Attempt to start phase config whereas Xauth failed\n");
+		return NULL;
+	}
+
+	confsource = isakmp_cfg_config.confsource;
+	/*
+	 * If we have to fall back to a local
+	 * configuration source, we will jump
+	 * back to this point.
+	 */
+retry_source:
+
+	switch(type) {
+	case INTERNAL_IP4_ADDRESS:
+		switch(confsource) {
+#ifdef HAVE_LIBLDAP
+		case ISAKMP_CFG_CONF_LDAP:
+			if (iph1->mode_cfg->flags & ISAKMP_CFG_ADDR4_EXTERN)
+			    break;
+			plog(LLV_INFO, LOCATION, NULL, 
+			    "No IP from LDAP, using local pool\n");
+			/* FALLTHROUGH */
+			confsource = ISAKMP_CFG_CONF_LOCAL;
+			goto retry_source;
+#endif
+#ifdef HAVE_LIBRADIUS
+		case ISAKMP_CFG_CONF_RADIUS:
+			if ((iph1->mode_cfg->flags & ISAKMP_CFG_ADDR4_EXTERN)
+			    && (iph1->mode_cfg->addr4.s_addr != htonl(-2)))
+			    /*
+			     * -2 is 255.255.255.254, RADIUS uses that
+			     * to instruct the NAS to use a local pool
+			     */
+			    break;
+			plog(LLV_INFO, LOCATION, NULL, 
+			    "No IP from RADIUS, using local pool\n");
+			/* FALLTHROUGH */
+			confsource = ISAKMP_CFG_CONF_LOCAL;
+			goto retry_source;
+#endif
+		case ISAKMP_CFG_CONF_LOCAL:
+			if (isakmp_cfg_getport(iph1) == -1) {
+				plog(LLV_ERROR, LOCATION, NULL, 
+				    "Port pool depleted\n");
+				break;
+			}
+
+			iph1->mode_cfg->addr4.s_addr = 
+			    htonl(ntohl(isakmp_cfg_config.network4) 
+			    + iph1->mode_cfg->port);
+			iph1->mode_cfg->flags |= ISAKMP_CFG_ADDR4_LOCAL;
+			break;
+
+		default:
+			plog(LLV_ERROR, LOCATION, NULL, 
+			    "Unexpected confsource\n");
+		}
+			
+		if (isakmp_cfg_accounting(iph1, ISAKMP_CFG_LOGIN) != 0)
+			plog(LLV_ERROR, LOCATION, NULL, "Accounting failed\n");
+
+		return isakmp_cfg_addr4(iph1, 
+		    attr, &iph1->mode_cfg->addr4.s_addr);
+		break;
+
+	case INTERNAL_IP4_NETMASK:
+		switch(confsource) {
+#ifdef HAVE_LIBLDAP
+		case ISAKMP_CFG_CONF_LDAP:
+			if (iph1->mode_cfg->flags & ISAKMP_CFG_MASK4_EXTERN)
+				break;
+			plog(LLV_INFO, LOCATION, NULL, 
+			    "No mask from LDAP, using local pool\n");
+			/* FALLTHROUGH */
+			confsource = ISAKMP_CFG_CONF_LOCAL;
+			goto retry_source;
+#endif
+#ifdef HAVE_LIBRADIUS
+		case ISAKMP_CFG_CONF_RADIUS:
+			if (iph1->mode_cfg->flags & ISAKMP_CFG_MASK4_EXTERN)
+				break;
+			plog(LLV_INFO, LOCATION, NULL, 
+			    "No mask from RADIUS, using local pool\n");
+			/* FALLTHROUGH */
+			confsource = ISAKMP_CFG_CONF_LOCAL;
+			goto retry_source;
+#endif
+		case ISAKMP_CFG_CONF_LOCAL:
+			iph1->mode_cfg->mask4.s_addr 
+			    = isakmp_cfg_config.netmask4;
+			iph1->mode_cfg->flags |= ISAKMP_CFG_MASK4_LOCAL;
+			break;
+
+		default:
+			plog(LLV_ERROR, LOCATION, NULL, 
+			    "Unexpected confsource\n");
+		}
+		return isakmp_cfg_addr4(iph1, attr, 
+		    &iph1->mode_cfg->mask4.s_addr);
+		break;
+
+	case INTERNAL_IP4_DNS:
+		return isakmp_cfg_addr4_list(iph1, 
+		    attr, &isakmp_cfg_config.dns4[0], 
+		    isakmp_cfg_config.dns4_index);
+		break;
+
+	case INTERNAL_IP4_NBNS:
+		return isakmp_cfg_addr4_list(iph1, 
+		    attr, &isakmp_cfg_config.nbns4[0], 
+		    isakmp_cfg_config.nbns4_index);
+		break;
+
+	case INTERNAL_IP4_SUBNET:
+		return isakmp_cfg_addr4(iph1, 
+		    attr, &isakmp_cfg_config.network4);
+		break;
+
+	default:
+		plog(LLV_ERROR, LOCATION, NULL, "Unexpected type %d\n", type);
+		break;
+	}
+	return NULL;
+}
+
+#if 0
+static vchar_t *
+isakmp_cfg_void(iph1, attr)
+	struct ph1handle *iph1;
+	struct isakmp_data *attr;
+{
+	vchar_t *buffer;
+	struct isakmp_data *new;
+
+	if ((buffer = vmalloc(sizeof(*attr))) == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL, "Cannot allocate memory\n");
+		return NULL;
+	}
+
+	new = (struct isakmp_data *)buffer->v;
+
+	new->type = attr->type;
+	new->lorv = htons(0);
+
+	return buffer;
+}
+#endif
+
+vchar_t *
+isakmp_cfg_copy(iph1, attr)
+	struct ph1handle *iph1;
+	struct isakmp_data *attr;
+{
+	vchar_t *buffer;
+	size_t len = 0;
+
+	if ((ntohs(attr->type) & ISAKMP_GEN_MASK) == ISAKMP_GEN_TLV)
+		len = ntohs(attr->lorv);
+
+	if ((buffer = vmalloc(sizeof(*attr) + len)) == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL, "Cannot allocate memory\n");
+		return NULL;
+	}
+
+	memcpy(buffer->v, attr, sizeof(*attr) + ntohs(attr->lorv));
+
+	return buffer;
+}
+
+vchar_t *
+isakmp_cfg_short(iph1, attr, value)
+	struct ph1handle *iph1;
+	struct isakmp_data *attr;
+	int value;
+{
+	vchar_t *buffer;
+	struct isakmp_data *new;
+	int type;
+
+	if ((buffer = vmalloc(sizeof(*attr))) == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL, "Cannot allocate memory\n");
+		return NULL;
+	}
+
+	new = (struct isakmp_data *)buffer->v;
+	type = ntohs(attr->type) & ~ISAKMP_GEN_MASK;
+
+	new->type = htons(type | ISAKMP_GEN_TV);
+	new->lorv = htons(value);
+
+	return buffer;
+}
+
+vchar_t *
+isakmp_cfg_varlen(iph1, attr, string, len)
+	struct ph1handle *iph1;
+	struct isakmp_data *attr;
+	char *string;
+	size_t len;
+{
+	vchar_t *buffer;
+	struct isakmp_data *new;
+	char *data;
+
+	if ((buffer = vmalloc(sizeof(*attr) + len)) == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL, "Cannot allocate memory\n");
+		return NULL;
+	}
+
+	new = (struct isakmp_data *)buffer->v;
+
+	new->type = attr->type;
+	new->lorv = htons(len);
+	data = (char *)(new + 1);
+
+	memcpy(data, string, len);
+	
+	return buffer;
+}
+vchar_t *
+isakmp_cfg_string(iph1, attr, string)
+	struct ph1handle *iph1;
+	struct isakmp_data *attr;
+	char *string;
+{
+	size_t len = strlen(string);
+	return isakmp_cfg_varlen(iph1, attr, string, len);
+}
+
+static vchar_t *
+isakmp_cfg_addr4(iph1, attr, addr)
+	struct ph1handle *iph1;
+	struct isakmp_data *attr;
+	in_addr_t *addr;
+{
+	vchar_t *buffer;
+	struct isakmp_data *new;
+	size_t len;
+
+	len = sizeof(*addr);
+	if ((buffer = vmalloc(sizeof(*attr) + len)) == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL, "Cannot allocate memory\n");
+		return NULL;
+	}
+
+	new = (struct isakmp_data *)buffer->v;
+
+	new->type = attr->type;
+	new->lorv = htons(len);
+	memcpy(new + 1, addr, len);
+	
+	return buffer;
+}
+
+static vchar_t *
+isakmp_cfg_addr4_list(iph1, attr, addr, nbr)
+	struct ph1handle *iph1;
+	struct isakmp_data *attr;
+	in_addr_t *addr;
+	int nbr;
+{
+	int error = -1;
+	vchar_t *buffer = NULL;
+	vchar_t *bufone = NULL;
+	struct isakmp_data *new;
+	size_t len;
+	int i;
+
+	len = sizeof(*addr);
+	if ((buffer = vmalloc(0)) == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL, "Cannot allocate memory\n");
+		goto out;
+	}
+	for(i = 0; i < nbr; i++) {
+		if ((bufone = vmalloc(sizeof(*attr) + len)) == NULL) {
+			plog(LLV_ERROR, LOCATION, NULL, 
+			    "Cannot allocate memory\n");
+			goto out;
+		}
+		new = (struct isakmp_data *)bufone->v;
+		new->type = attr->type;
+		new->lorv = htons(len);
+		memcpy(new + 1, &addr[i], len);
+		new += (len + sizeof(*attr));
+		buffer = buffer_cat(buffer, bufone);
+		vfree(bufone);
+	}
+
+	error = 0;
+
+out:
+	if ((error != 0) && (buffer != NULL)) {
+		vfree(buffer);
+		buffer = NULL;
+	}
+
+	return buffer;
+}
+
+struct isakmp_ivm *
+isakmp_cfg_newiv(iph1, msgid)
+	struct ph1handle *iph1;
+	u_int32_t msgid;
+{
+	struct isakmp_cfg_state *ics = iph1->mode_cfg;
+
+	if (ics == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL,
+		    "isakmp_cfg_newiv called without mode config state\n");
+		return NULL;
+	}
+
+	if (ics->ivm != NULL)
+		oakley_delivm(ics->ivm);
+
+	ics->ivm = oakley_newiv2(iph1, msgid);
+	ics->last_msgid = msgid;
+
+	return ics->ivm;
+}
+
+/* Derived from isakmp_info_send_common */
+int
+isakmp_cfg_send(iph1, payload, np, flags, new_exchange)
+	struct ph1handle *iph1;
+	vchar_t *payload;
+	u_int32_t np;
+	int flags;
+	int new_exchange;
+{
+	struct ph2handle *iph2 = NULL;
+	vchar_t *hash = NULL;
+	struct isakmp *isakmp;
+	struct isakmp_gen *gen;
+	char *p;
+	int tlen;
+	int error = -1;
+	struct isakmp_cfg_state *ics = iph1->mode_cfg;
+
+	/* Check if phase 1 is established */
+	if ((iph1->status != PHASE1ST_ESTABLISHED) || 
+	    (iph1->local == NULL) ||
+	    (iph1->remote == NULL)) {
+		plog(LLV_ERROR, LOCATION, NULL, 
+		    "ISAKMP mode config exchange with immature phase 1\n");
+		goto end;
+	}
+
+	/* add new entry to isakmp status table */
+	iph2 = newph2();
+	if (iph2 == NULL)
+		goto end;
+
+	iph2->dst = dupsaddr(iph1->remote);
+	if (iph2->dst == NULL) {
+		delph2(iph2);
+		goto end;
+	}
+	iph2->src = dupsaddr(iph1->local);
+	if (iph2->src == NULL) {
+		delph2(iph2);
+		goto end;
+	}
+
+#if (!defined(ENABLE_NATT)) || (defined(BROKEN_NATT))
+	if (set_port(iph2->dst, 0) == NULL ||
+	    set_port(iph2->src, 0) == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL,
+		     "invalid family: %d\n", iph1->remote->sa_family);
+		delph2(iph2);
+		goto end;
+	}
+#endif
+	iph2->ph1 = iph1;
+	iph2->side = INITIATOR;
+	iph2->status = PHASE2ST_START;
+
+	if (new_exchange)
+		iph2->msgid = isakmp_newmsgid2(iph1);
+	else
+		iph2->msgid = iph1->msgid;
+
+	/* get IV and HASH(1) if skeyid_a was generated. */
+	if (iph1->skeyid_a != NULL) {
+		if (new_exchange) {
+			if (isakmp_cfg_newiv(iph1, iph2->msgid) == NULL) {
+				delph2(iph2);
+				goto end;
+			}
+		}
+
+		/* generate HASH(1) */
+		hash = oakley_compute_hash1(iph2->ph1, iph2->msgid, payload);
+		if (hash == NULL) {
+			delph2(iph2);
+			goto end;
+		}
+
+		/* initialized total buffer length */
+		tlen = hash->l;
+		tlen += sizeof(*gen);
+	} else {
+		/* IKE-SA is not established */
+		hash = NULL;
+
+		/* initialized total buffer length */
+		tlen = 0;
+	}
+	if ((flags & ISAKMP_FLAG_A) == 0)
+		iph2->flags = (hash == NULL ? 0 : ISAKMP_FLAG_E);
+	else
+		iph2->flags = (hash == NULL ? 0 : ISAKMP_FLAG_A);
+
+	insph2(iph2);
+	bindph12(iph1, iph2);
+
+	tlen += sizeof(*isakmp) + payload->l;
+
+	/* create buffer for isakmp payload */
+	iph2->sendbuf = vmalloc(tlen);
+	if (iph2->sendbuf == NULL) { 
+		plog(LLV_ERROR, LOCATION, NULL,
+			"failed to get buffer to send.\n");
+		goto err;
+	}
+
+	/* create isakmp header */
+	isakmp = (struct isakmp *)iph2->sendbuf->v;
+	memcpy(&isakmp->i_ck, &iph1->index.i_ck, sizeof(cookie_t));
+	memcpy(&isakmp->r_ck, &iph1->index.r_ck, sizeof(cookie_t));
+	isakmp->np = hash == NULL ? (np & 0xff) : ISAKMP_NPTYPE_HASH;
+	isakmp->v = iph1->version;
+	isakmp->etype = ISAKMP_ETYPE_CFG;
+	isakmp->flags = iph2->flags;
+	memcpy(&isakmp->msgid, &iph2->msgid, sizeof(isakmp->msgid));
+	isakmp->len = htonl(tlen);
+	p = (char *)(isakmp + 1);
+
+	/* create HASH payload */
+	if (hash != NULL) {
+		gen = (struct isakmp_gen *)p;
+		gen->np = np & 0xff;
+		gen->len = htons(sizeof(*gen) + hash->l);
+		p += sizeof(*gen);
+		memcpy(p, hash->v, hash->l);
+		p += hash->l;
+	}
+
+	/* add payload */
+	memcpy(p, payload->v, payload->l);
+	p += payload->l;
+
+#ifdef HAVE_PRINT_ISAKMP_C
+	isakmp_printpacket(iph2->sendbuf, iph1->local, iph1->remote, 1);
+#endif
+	
+	plog(LLV_DEBUG, LOCATION, NULL, "MODE_CFG packet to send\n");
+	plogdump(LLV_DEBUG, iph2->sendbuf->v, iph2->sendbuf->l);
+
+	/* encoding */
+	if (ISSET(isakmp->flags, ISAKMP_FLAG_E)) {
+		vchar_t *tmp;
+
+		tmp = oakley_do_encrypt(iph2->ph1, iph2->sendbuf, 
+			ics->ivm->ive, ics->ivm->iv);
+		VPTRINIT(iph2->sendbuf);
+		if (tmp == NULL)
+			goto err;
+		iph2->sendbuf = tmp;
+	}
+
+	/* HDR*, HASH(1), ATTR */
+	if (isakmp_send(iph2->ph1, iph2->sendbuf) < 0) {
+		VPTRINIT(iph2->sendbuf);
+		goto err;
+	}
+
+	plog(LLV_DEBUG, LOCATION, NULL,
+		"sendto mode config %s.\n", s_isakmp_nptype(np));
+
+	/*
+	 * XXX We might need to resend the message...
+	 */
+
+	error = 0;
+	VPTRINIT(iph2->sendbuf);
+
+err:
+	if (iph2->sendbuf != NULL)
+		vfree(iph2->sendbuf);
+
+	unbindph12(iph2);
+	remph2(iph2);
+	delph2(iph2);
+end:
+	if (hash)
+		vfree(hash);
+	return error;
+}
+
+
+void 
+isakmp_cfg_rmstate(iph1)
+	struct ph1handle *iph1;
+{
+	struct isakmp_cfg_state *state = iph1->mode_cfg;
+
+	if (isakmp_cfg_accounting(iph1, ISAKMP_CFG_LOGOUT) != 0)
+		plog(LLV_ERROR, LOCATION, NULL, "Accounting failed\n");
+
+	if (state->flags & ISAKMP_CFG_PORT_ALLOCATED)
+		isakmp_cfg_putport(iph1, state->port);	
+
+	/* Delete the IV if it's still there */
+	if(iph1->mode_cfg->ivm) {
+		oakley_delivm(iph1->mode_cfg->ivm);
+		iph1->mode_cfg->ivm = NULL;
+	}
+
+	/* Free any allocated splitnet lists */
+	if(iph1->mode_cfg->split_include != NULL)
+		splitnet_list_free(iph1->mode_cfg->split_include,
+			&iph1->mode_cfg->include_count);
+	if(iph1->mode_cfg->split_local != NULL)
+		splitnet_list_free(iph1->mode_cfg->split_local,
+			&iph1->mode_cfg->local_count);
+
+	xauth_rmstate(&state->xauth);
+
+	racoon_free(state);
+	iph1->mode_cfg = NULL;
+
+	return;
+}
+
+struct isakmp_cfg_state *
+isakmp_cfg_mkstate(void) 
+{
+	struct isakmp_cfg_state *state;
+
+	if ((state = racoon_malloc(sizeof(*state))) == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL,
+		    "Cannot allocate memory for mode config state\n");
+		return NULL;
+	}
+	memset(state, 0, sizeof(*state));
+
+	return state;
+}
+
+int 
+isakmp_cfg_getport(iph1)
+	struct ph1handle *iph1;
+{
+	unsigned int i;
+	size_t size = isakmp_cfg_config.pool_size;
+
+	if (iph1->mode_cfg->flags & ISAKMP_CFG_PORT_ALLOCATED)
+		return iph1->mode_cfg->port;
+
+	if (isakmp_cfg_config.port_pool == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL,
+		    "isakmp_cfg_config.port_pool == NULL\n");
+		return -1;
+	}
+
+	for (i = 0; i < size; i++) {
+		if (isakmp_cfg_config.port_pool[i].used == 0)
+			break;
+	}
+
+	if (i == size) {
+		plog(LLV_ERROR, LOCATION, NULL, 
+		    "No more addresses available\n");
+			return -1;
+	}
+
+	isakmp_cfg_config.port_pool[i].used = 1;
+
+	plog(LLV_INFO, LOCATION, NULL, "Using port %d\n", i);
+
+	iph1->mode_cfg->flags |= ISAKMP_CFG_PORT_ALLOCATED;
+	iph1->mode_cfg->port = i;
+
+	return i;
+}
+
+int 
+isakmp_cfg_putport(iph1, index)
+	struct ph1handle *iph1;
+	unsigned int index;
+{
+	if (isakmp_cfg_config.port_pool == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL, 
+		    "isakmp_cfg_config.port_pool == NULL\n");
+		return -1;
+	}
+
+	if (isakmp_cfg_config.port_pool[index].used == 0) {
+		plog(LLV_ERROR, LOCATION, NULL, 
+		    "Attempt to release an unallocated address (port %d)\n",
+		    index);
+		return -1;
+	}
+
+#ifdef HAVE_LIBPAM
+	/* Cleanup PAM status associated with the port */
+	if (isakmp_cfg_config.authsource == ISAKMP_CFG_AUTH_PAM)
+		privsep_cleanup_pam(index);
+#endif
+	isakmp_cfg_config.port_pool[index].used = 0;
+	iph1->mode_cfg->flags &= ISAKMP_CFG_PORT_ALLOCATED;
+
+	plog(LLV_INFO, LOCATION, NULL, "Released port %d\n", index);
+
+	return 0;
+}
+
+#ifdef HAVE_LIBPAM
+void
+cleanup_pam(port)
+	int port;
+{
+	if (isakmp_cfg_config.port_pool[port].pam != NULL) {
+		pam_end(isakmp_cfg_config.port_pool[port].pam, PAM_SUCCESS);
+		isakmp_cfg_config.port_pool[port].pam = NULL;
+	}
+
+	return;
+}
+#endif
+
+/* Accounting, only for RADIUS or PAM */
+static int
+isakmp_cfg_accounting(iph1, inout)
+	struct ph1handle *iph1;
+	int inout;
+{
+#ifdef HAVE_LIBPAM
+	if (isakmp_cfg_config.accounting == ISAKMP_CFG_ACCT_PAM)
+		return privsep_accounting_pam(iph1->mode_cfg->port, 
+		    inout);
+#endif 
+#ifdef HAVE_LIBRADIUS
+	if (isakmp_cfg_config.accounting == ISAKMP_CFG_ACCT_RADIUS)
+		return isakmp_cfg_accounting_radius(iph1, inout);
+#endif
+	if (isakmp_cfg_config.accounting == ISAKMP_CFG_ACCT_SYSTEM)
+		return privsep_accounting_system(iph1->mode_cfg->port,
+			iph1->remote, iph1->mode_cfg->login, inout);
+	return 0;
+}
+
+#ifdef HAVE_LIBPAM
+int 
+isakmp_cfg_accounting_pam(port, inout)
+	int port;
+	int inout;
+{
+	int error = 0;
+	pam_handle_t *pam;
+
+	if (isakmp_cfg_config.port_pool == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL, 
+		    "isakmp_cfg_config.port_pool == NULL\n");
+		return -1;
+	}
+	
+	pam = isakmp_cfg_config.port_pool[port].pam;
+	if (pam == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL, "pam handle is NULL\n");
+		return -1;
+	}
+
+	switch (inout) {
+	case ISAKMP_CFG_LOGIN:
+		error = pam_open_session(pam, 0);
+		break;
+	case ISAKMP_CFG_LOGOUT:
+		error = pam_close_session(pam, 0);
+		pam_end(pam, error);
+		isakmp_cfg_config.port_pool[port].pam = NULL;
+		break;
+	default:
+		plog(LLV_ERROR, LOCATION, NULL, "Unepected inout\n");
+		break;
+	}
+	
+	if (error != 0) {
+		plog(LLV_ERROR, LOCATION, NULL,
+		    "pam_open_session/pam_close_session failed: %s\n",
+		    pam_strerror(pam, error)); 
+		return -1;
+        }
+
+	return 0;
+}
+#endif /* HAVE_LIBPAM */
+
+#ifdef HAVE_LIBRADIUS
+static int
+isakmp_cfg_accounting_radius(iph1, inout)
+	struct ph1handle *iph1;
+	int inout;
+{
+	/* For first time use, initialize Radius */
+	if (radius_acct_state == NULL) {
+		if ((radius_acct_state = rad_acct_open()) == NULL) {
+			plog(LLV_ERROR, LOCATION, NULL,
+			    "Cannot init librradius\n");
+			return -1;
+		}
+
+		if (rad_config(radius_acct_state, NULL) != 0) {
+			 plog(LLV_ERROR, LOCATION, NULL,
+			     "Cannot open librarius config file: %s\n",
+			     rad_strerror(radius_acct_state));
+			  rad_close(radius_acct_state);
+			  radius_acct_state = NULL;
+			  return -1;
+		}
+	}
+
+	if (rad_create_request(radius_acct_state, 
+	    RAD_ACCOUNTING_REQUEST) != 0) {
+		plog(LLV_ERROR, LOCATION, NULL,
+		    "rad_create_request failed: %s\n",
+		    rad_strerror(radius_acct_state));
+		return -1;
+	}
+
+	if (rad_put_string(radius_acct_state, RAD_USER_NAME, 
+	    iph1->mode_cfg->login) != 0) {
+		plog(LLV_ERROR, LOCATION, NULL,
+		    "rad_put_string failed: %s\n",
+		    rad_strerror(radius_acct_state));
+		return -1;
+	}
+
+	switch (inout) {
+	case ISAKMP_CFG_LOGIN:
+		inout = RAD_START;
+		break;
+	case ISAKMP_CFG_LOGOUT:
+		inout = RAD_STOP;
+		break;
+	default:
+		plog(LLV_ERROR, LOCATION, NULL, "Unepected inout\n");
+		break;
+	}
+
+	if (rad_put_addr(radius_acct_state, 
+	    RAD_FRAMED_IP_ADDRESS, iph1->mode_cfg->addr4) != 0) {
+		plog(LLV_ERROR, LOCATION, NULL,
+		    "rad_put_addr failed: %s\n",
+		    rad_strerror(radius_acct_state));
+		return -1;
+	}
+
+	if (rad_put_addr(radius_acct_state, 
+	    RAD_LOGIN_IP_HOST, iph1->mode_cfg->addr4) != 0) {
+		plog(LLV_ERROR, LOCATION, NULL,
+		    "rad_put_addr failed: %s\n",
+		    rad_strerror(radius_acct_state));
+		return -1;
+	}
+
+	if (rad_put_int(radius_acct_state, RAD_ACCT_STATUS_TYPE, inout) != 0) {
+		plog(LLV_ERROR, LOCATION, NULL,
+		    "rad_put_int failed: %s\n",
+		    rad_strerror(radius_acct_state));
+		return -1;
+	}
+
+	if (isakmp_cfg_radius_common(radius_acct_state, 
+	    iph1->mode_cfg->port) != 0)
+		return -1;
+
+	if (rad_send_request(radius_acct_state) != RAD_ACCOUNTING_RESPONSE) {
+		plog(LLV_ERROR, LOCATION, NULL,
+		    "rad_send_request failed: %s\n",
+		    rad_strerror(radius_acct_state));
+		return -1;
+	}
+
+	return 0;
+}
+#endif /* HAVE_LIBRADIUS */
+
+/*
+ * Attributes common to all RADIUS requests
+ */
+#ifdef HAVE_LIBRADIUS
+int
+isakmp_cfg_radius_common(radius_state, port)
+	struct rad_handle *radius_state;
+	int port;
+{ 
+	struct utsname name;
+	static struct hostent *host = NULL;
+	struct in_addr nas_addr;
+
+	/* 
+	 * Find our own IP by resolving our nodename
+	 */
+	if (host == NULL) {
+		if (uname(&name) != 0) {
+			plog(LLV_ERROR, LOCATION, NULL,
+			    "uname failed: %s\n", strerror(errno));
+			return -1;
+		}
+
+		if ((host = gethostbyname(name.nodename)) == NULL) {
+			plog(LLV_ERROR, LOCATION, NULL,
+			    "gethostbyname failed: %s\n", strerror(errno));
+			return -1;
+		}
+	}
+
+	memcpy(&nas_addr, host->h_addr, sizeof(nas_addr));
+	if (rad_put_addr(radius_state, RAD_NAS_IP_ADDRESS, nas_addr) != 0) {
+		plog(LLV_ERROR, LOCATION, NULL,
+		    "rad_put_addr failed: %s\n",
+		    rad_strerror(radius_state));
+		return -1;
+	}
+
+	if (rad_put_int(radius_state, RAD_NAS_PORT, port) != 0) {
+		plog(LLV_ERROR, LOCATION, NULL,
+		    "rad_put_int failed: %s\n",
+		    rad_strerror(radius_state));
+		return -1;
+	}
+
+	if (rad_put_int(radius_state, RAD_NAS_PORT_TYPE, RAD_VIRTUAL) != 0) {
+		plog(LLV_ERROR, LOCATION, NULL,
+		    "rad_put_int failed: %s\n",
+		    rad_strerror(radius_state));
+		return -1;
+	}
+
+	if (rad_put_int(radius_state, RAD_SERVICE_TYPE, RAD_FRAMED) != 0) {
+		plog(LLV_ERROR, LOCATION, NULL,
+		    "rad_put_int failed: %s\n",
+		    rad_strerror(radius_state));
+		return -1;
+	}
+	
+	return 0;
+}
+#endif
+
+/*
+	Logs the user into the utmp system files.
+*/
+
+int
+isakmp_cfg_accounting_system(port, raddr, usr, inout)
+	int port;
+	struct sockaddr *raddr;
+	char *usr;
+	int inout;
+{
+	int error = 0;
+	struct utmp ut;
+	char term[UT_LINESIZE];
+	char addr[NI_MAXHOST];
+	
+	if (usr == NULL || usr[0]=='\0') {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"system accounting : no login found\n");
+		return -1;
+	}
+
+	sprintf(term, TERMSPEC, port);
+
+	switch (inout) {
+	case ISAKMP_CFG_LOGIN:
+		strncpy(ut.ut_name, usr, UT_NAMESIZE);
+		ut.ut_name[UT_NAMESIZE - 1] = '\0';
+
+		strncpy(ut.ut_line, term, UT_LINESIZE);
+		ut.ut_line[UT_LINESIZE - 1] = '\0';
+
+		GETNAMEINFO_NULL(raddr, addr);
+		strncpy(ut.ut_host, addr, UT_HOSTSIZE);
+		ut.ut_host[UT_HOSTSIZE - 1] = '\0';
+
+		ut.ut_time = time(NULL);
+ 
+		plog(LLV_INFO, LOCATION, NULL,
+			"Accounting : '%s' logging on '%s' from %s.\n",
+			ut.ut_name, ut.ut_line, ut.ut_host);
+
+		login(&ut);
+
+		break;
+	case ISAKMP_CFG_LOGOUT:	
+
+		plog(LLV_INFO, LOCATION, NULL,
+			"Accounting : '%s' unlogging from '%s'.\n",
+			usr, term);
+
+		logout(term);
+
+		break;
+	default:
+		plog(LLV_ERROR, LOCATION, NULL, "Unepected inout\n");
+		break;
+	}
+
+	return 0;
+}
+	
+int 
+isakmp_cfg_getconfig(iph1)
+	struct ph1handle *iph1;
+{
+	vchar_t *buffer;
+	struct isakmp_pl_attr *attrpl;
+	struct isakmp_data *attr;
+	size_t len;
+	int error;
+	int attrcount;
+	int i;
+	int attrlist[] = {
+		INTERNAL_IP4_ADDRESS,
+		INTERNAL_IP4_NETMASK,
+		INTERNAL_IP4_DNS,
+		INTERNAL_IP4_NBNS,
+		UNITY_BANNER,
+		UNITY_DEF_DOMAIN,
+		UNITY_SPLITDNS_NAME,
+		UNITY_SPLIT_INCLUDE,
+		UNITY_LOCAL_LAN,
+		APPLICATION_VERSION,
+	};
+
+	attrcount = sizeof(attrlist) / sizeof(*attrlist);
+	len = sizeof(*attrpl) + sizeof(*attr) * attrcount;
+	    
+	if ((buffer = vmalloc(len)) == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL, "Cannot allocate memory\n");
+		return -1;
+	}
+
+	attrpl = (struct isakmp_pl_attr *)buffer->v;
+	attrpl->h.len = htons(len);
+	attrpl->type = ISAKMP_CFG_REQUEST;
+	attrpl->id = htons((u_int16_t)(eay_random() & 0xffff));
+
+	attr = (struct isakmp_data *)(attrpl + 1);
+
+	for (i = 0; i < attrcount; i++) {
+		attr->type = htons(attrlist[i]);
+		attr->lorv = htons(0);
+		attr++;
+	}
+
+	plog(LLV_DEBUG, LOCATION, NULL, 
+		    "Sending MODE_CFG REQUEST\n");
+
+	error = isakmp_cfg_send(iph1, buffer,
+	    ISAKMP_NPTYPE_ATTR, ISAKMP_FLAG_E, 1);
+
+	vfree(buffer);
+
+	return error;
+}
+
+static void
+isakmp_cfg_getaddr4(attr, ip)
+	struct isakmp_data *attr;
+	struct in_addr *ip;
+{
+	size_t alen = ntohs(attr->lorv);
+	in_addr_t *addr;
+
+	if (alen != sizeof(*ip)) {
+		plog(LLV_ERROR, LOCATION, NULL, "Bad IPv4 address len\n");
+		return;
+	}
+
+	addr = (in_addr_t *)(attr + 1);
+	ip->s_addr = *addr;
+
+	return;
+}
+
+static void
+isakmp_cfg_appendaddr4(attr, ip, num, max)
+	struct isakmp_data *attr;
+	struct in_addr *ip;
+	int *num;
+	int max;
+{
+	size_t alen = ntohs(attr->lorv);
+	in_addr_t *addr;
+
+	if (alen != sizeof(*ip)) {
+		plog(LLV_ERROR, LOCATION, NULL, "Bad IPv4 address len\n");
+		return;
+	}
+	if (*num == max) {
+		plog(LLV_ERROR, LOCATION, NULL, "Too many addresses given\n");
+		return;
+	}
+
+	addr = (in_addr_t *)(attr + 1);
+	ip->s_addr = *addr;
+	(*num)++;
+
+	return;
+}
+
+static void
+isakmp_cfg_getstring(attr, str)
+	struct isakmp_data *attr;
+	char *str;
+{
+	size_t alen = ntohs(attr->lorv);
+	char *src;
+	src = (char *)(attr + 1);
+
+	memcpy(str, src, (alen > MAXPATHLEN ? MAXPATHLEN : alen));
+
+	return;
+}
+
+#define IP_MAX 40
+
+void
+isakmp_cfg_iplist_to_str(dest, count, addr, withmask)
+	char *dest;
+	int count;
+	void *addr;
+	int withmask;
+{
+	int i;
+	int p;
+	int l;
+	struct unity_network tmp;
+	for(i = 0, p = 0; i < count; i++) {
+		if(withmask == 1)
+			l = sizeof(struct unity_network);
+		else
+			l = sizeof(struct in_addr);
+		memcpy(&tmp, addr, l);
+		addr += l;
+		if((uint32_t)tmp.addr4.s_addr == 0)
+			break;
+	
+		inet_ntop(AF_INET, &tmp.addr4, dest + p, IP_MAX);
+		p += strlen(dest + p);
+		if(withmask == 1) {
+			dest[p] = '/';
+			p++;
+			inet_ntop(AF_INET, &tmp.mask4, dest + p, IP_MAX);
+			p += strlen(dest + p);
+		}
+		dest[p] = ' ';
+		p++;
+	}
+	if(p > 0)
+		dest[p-1] = '\0';
+	else
+		dest[0] = '\0';
+}
+
+int
+isakmp_cfg_setenv(iph1, envp, envc)
+	struct ph1handle *iph1; 
+	char ***envp;
+	int *envc;
+{
+	char addrstr[IP_MAX];
+	char addrlist[IP_MAX * MAXNS + MAXNS];
+	char *splitlist = addrlist;
+	char defdom[MAXPATHLEN + 1];
+	int cidr, tmp;
+	char cidrstr[4];
+	int i, p;
+	int test;
+
+	plog(LLV_DEBUG, LOCATION, NULL, "Starting a script.\n");
+
+	/* 
+	 * Internal IPv4 address, either if 
+	 * we are a client or a server.
+	 */
+	if ((iph1->mode_cfg->flags & ISAKMP_CFG_GOT_ADDR4) ||
+#ifdef HAVE_LIBLDAP
+	    (iph1->mode_cfg->flags & ISAKMP_CFG_ADDR4_EXTERN) ||
+#endif
+#ifdef HAVE_LIBRADIUS
+	    (iph1->mode_cfg->flags & ISAKMP_CFG_ADDR4_EXTERN) ||
+#endif
+	    (iph1->mode_cfg->flags & ISAKMP_CFG_ADDR4_LOCAL)) {
+		inet_ntop(AF_INET, &iph1->mode_cfg->addr4, 
+		    addrstr, IP_MAX);
+	} else
+		addrstr[0] = '\0';
+
+	if (script_env_append(envp, envc, "INTERNAL_ADDR4", addrstr) != 0) {
+		plog(LLV_ERROR, LOCATION, NULL, "Cannot set INTERNAL_ADDR4\n");
+		return -1;
+	}
+
+	if (iph1->mode_cfg->xauth.authdata.generic.usr != NULL) {
+		if (script_env_append(envp, envc, "XAUTH_USER", 
+		    iph1->mode_cfg->xauth.authdata.generic.usr) != 0) {
+			plog(LLV_ERROR, LOCATION, NULL, 
+			    "Cannot set XAUTH_USER\n");
+			return -1;
+		}
+	}
+
+	/* Internal IPv4 mask */
+	if (iph1->mode_cfg->flags & ISAKMP_CFG_GOT_MASK4) 
+		inet_ntop(AF_INET, &iph1->mode_cfg->mask4, 
+		    addrstr, IP_MAX);
+	else
+		addrstr[0] = '\0';
+
+	/* 	
+	 * During several releases, documentation adverised INTERNAL_NETMASK4
+	 * while code was using INTERNAL_MASK4. We now do both.
+	 */
+
+	if (script_env_append(envp, envc, "INTERNAL_MASK4", addrstr) != 0) { 
+		plog(LLV_ERROR, LOCATION, NULL, "Cannot set INTERNAL_MASK4\n");
+		return -1;
+	}
+
+	if (script_env_append(envp, envc, "INTERNAL_NETMASK4", addrstr) != 0) { 
+		plog(LLV_ERROR, LOCATION, NULL, 
+		    "Cannot set INTERNAL_NETMASK4\n");
+		return -1;
+	}
+
+	tmp = ntohl(iph1->mode_cfg->mask4.s_addr);
+	for (cidr = 0; tmp != 0; cidr++)
+		tmp <<= 1;
+	snprintf(cidrstr, 3, "%d", cidr);
+
+	if (script_env_append(envp, envc, "INTERNAL_CIDR4", cidrstr) != 0) {
+		plog(LLV_ERROR, LOCATION, NULL, "Cannot set INTERNAL_CIDR4\n");
+		return -1;
+	}
+
+	/* Internal IPv4 DNS */
+	if (iph1->mode_cfg->flags & ISAKMP_CFG_GOT_DNS4) {
+		/* First Internal IPv4 DNS (for compatibilty with older code */
+		inet_ntop(AF_INET, &iph1->mode_cfg->dns4[0], 
+		    addrstr, IP_MAX);
+
+		/* Internal IPv4 DNS - all */
+		isakmp_cfg_iplist_to_str(addrlist, iph1->mode_cfg->dns4_index,
+			(void *)iph1->mode_cfg->dns4, 0);
+	} else {
+		addrstr[0] = '\0';
+		addrlist[0] = '\0';
+	}
+
+	if (script_env_append(envp, envc, "INTERNAL_DNS4", addrstr) != 0) {
+		plog(LLV_ERROR, LOCATION, NULL, "Cannot set INTERNAL_DNS4\n");
+		return -1;
+	}
+	if (script_env_append(envp, envc, "INTERNAL_DNS4_LIST", addrlist) != 0) {
+		plog(LLV_ERROR, LOCATION, NULL, 
+		    "Cannot set INTERNAL_DNS4_LIST\n");
+		return -1;
+	}
+	
+	/* Internal IPv4 WINS */
+	if (iph1->mode_cfg->flags & ISAKMP_CFG_GOT_WINS4) {
+		/* 
+		 * First Internal IPv4 WINS 
+		 * (for compatibilty with older code 
+		 */
+		inet_ntop(AF_INET, &iph1->mode_cfg->wins4[0], 
+		    addrstr, IP_MAX);
+
+		/* Internal IPv4 WINS - all */
+		isakmp_cfg_iplist_to_str(addrlist, iph1->mode_cfg->wins4_index,
+			(void *)iph1->mode_cfg->wins4, 0);
+	} else {
+		addrstr[0] = '\0';
+		addrlist[0] = '\0';
+	}
+
+	if (script_env_append(envp, envc, "INTERNAL_WINS4", addrstr) != 0) {
+		plog(LLV_ERROR, LOCATION, NULL, 
+		    "Cannot set INTERNAL_WINS4\n");
+		return -1;
+	}
+	if (script_env_append(envp, envc, 
+	    "INTERNAL_WINS4_LIST", addrlist) != 0) {
+		plog(LLV_ERROR, LOCATION, NULL, 
+		    "Cannot set INTERNAL_WINS4_LIST\n");
+		return -1;
+	}
+
+	/* Deault domain */
+	if(iph1->mode_cfg->flags & ISAKMP_CFG_GOT_DEFAULT_DOMAIN) 
+		strncpy(defdom, 
+		    iph1->mode_cfg->default_domain, 
+		    MAXPATHLEN + 1);
+	else
+		defdom[0] = '\0';
+	
+	if (script_env_append(envp, envc, "DEFAULT_DOMAIN", defdom) != 0) { 
+		plog(LLV_ERROR, LOCATION, NULL, 
+		    "Cannot set DEFAULT_DOMAIN\n");
+		return -1;
+	}
+
+	/* Split networks */
+	if (iph1->mode_cfg->flags & ISAKMP_CFG_GOT_SPLIT_INCLUDE)
+		splitlist = splitnet_list_2str(iph1->mode_cfg->split_include);
+	else {
+		splitlist = addrlist;
+		addrlist[0] = '\0';
+	}
+
+	if (script_env_append(envp, envc, "SPLIT_INCLUDE", splitlist) != 0) {
+		plog(LLV_ERROR, LOCATION, NULL, "Cannot set SPLIT_INCLUDE\n");
+		return -1;
+	}
+	if (splitlist != addrlist)
+		racoon_free(splitlist);
+
+	if (iph1->mode_cfg->flags & ISAKMP_CFG_GOT_SPLIT_LOCAL)
+		splitlist = splitnet_list_2str(iph1->mode_cfg->split_local);
+	else {
+		splitlist = addrlist;
+		addrlist[0] = '\0';
+	}
+
+	if (script_env_append(envp, envc, "SPLIT_LOCAL", splitlist) != 0) {
+		plog(LLV_ERROR, LOCATION, NULL, "Cannot set SPLIT_LOCAL\n");
+		return -1;
+	}
+	if (splitlist != addrlist)
+		racoon_free(splitlist);
+	
+	return 0;
+}
+
+int
+isakmp_cfg_resize_pool(size)
+	int size;
+{
+	struct isakmp_cfg_port *new_pool;
+	size_t len;
+	int i;
+
+	if (size == isakmp_cfg_config.pool_size)
+		return 0;
+
+	plog(LLV_INFO, LOCATION, NULL,
+	    "Resize address pool from %zu to %d\n",
+	    isakmp_cfg_config.pool_size, size);
+
+	/* If a pool already exists, check if we can shrink it */
+	if ((isakmp_cfg_config.port_pool != NULL) &&
+	    (size < isakmp_cfg_config.pool_size)) {
+		for (i = isakmp_cfg_config.pool_size; i >= size; --i) {
+			if (isakmp_cfg_config.port_pool[i].used) {
+				plog(LLV_ERROR, LOCATION, NULL, 
+				    "resize pool from %zu to %d impossible "
+				    "port %d is in use\n", 
+				    isakmp_cfg_config.pool_size, size, i);
+				size = i;
+				break;
+			}	
+		}
+	}
+
+	len = size * sizeof(*isakmp_cfg_config.port_pool);
+	new_pool = racoon_realloc(isakmp_cfg_config.port_pool, len);
+	if (new_pool == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL, 
+		    "resize pool from %zu to %d impossible: %s",
+		    isakmp_cfg_config.pool_size, size, strerror(errno));
+		return -1;
+	}
+
+	/* If size increase, intialize correctly the new records */
+	if (size > isakmp_cfg_config.pool_size) {
+		size_t unit;
+		size_t old_size;
+
+		unit =  sizeof(*isakmp_cfg_config.port_pool);
+		old_size = isakmp_cfg_config.pool_size;
+
+		bzero((char *)new_pool + (old_size * unit), 
+		    (size - old_size) * unit);
+	}
+
+	isakmp_cfg_config.port_pool = new_pool;
+	isakmp_cfg_config.pool_size = size;
+
+	return 0;
+}
+
+int
+isakmp_cfg_init(cold) 
+	int cold;
+{
+	int i;
+	int error;
+
+	isakmp_cfg_config.network4 = (in_addr_t)0x00000000;
+	isakmp_cfg_config.netmask4 = (in_addr_t)0x00000000;
+	for (i = 0; i < MAXNS; i++)
+		isakmp_cfg_config.dns4[i] = (in_addr_t)0x00000000;
+	isakmp_cfg_config.dns4_index = 0;
+	for (i = 0; i < MAXWINS; i++)
+		isakmp_cfg_config.nbns4[i] = (in_addr_t)0x00000000;
+	isakmp_cfg_config.nbns4_index = 0;
+	if (cold == ISAKMP_CFG_INIT_COLD)
+		isakmp_cfg_config.port_pool = NULL;
+	isakmp_cfg_config.authsource = ISAKMP_CFG_AUTH_SYSTEM;
+	isakmp_cfg_config.groupsource = ISAKMP_CFG_GROUP_SYSTEM;
+	if (cold == ISAKMP_CFG_INIT_COLD) {
+		if (isakmp_cfg_config.grouplist != NULL) {
+			for (i = 0; i < isakmp_cfg_config.groupcount; i++)
+				racoon_free(isakmp_cfg_config.grouplist[i]);
+			racoon_free(isakmp_cfg_config.grouplist);
+		}
+	}
+	isakmp_cfg_config.grouplist = NULL;
+	isakmp_cfg_config.groupcount = 0;
+	isakmp_cfg_config.confsource = ISAKMP_CFG_CONF_LOCAL;
+	isakmp_cfg_config.accounting = ISAKMP_CFG_ACCT_NONE;
+	if (cold == ISAKMP_CFG_INIT_COLD)
+		isakmp_cfg_config.pool_size = 0;
+	isakmp_cfg_config.auth_throttle = THROTTLE_PENALTY;
+	strlcpy(isakmp_cfg_config.default_domain, ISAKMP_CFG_DEFAULT_DOMAIN,
+	    MAXPATHLEN);
+	strlcpy(isakmp_cfg_config.motd, ISAKMP_CFG_MOTD, MAXPATHLEN);
+
+	if (cold != ISAKMP_CFG_INIT_COLD )
+		if (isakmp_cfg_config.splitnet_list != NULL)
+			splitnet_list_free(isakmp_cfg_config.splitnet_list,
+				&isakmp_cfg_config.splitnet_count);
+	isakmp_cfg_config.splitnet_list = NULL;
+	isakmp_cfg_config.splitnet_count = 0;
+	isakmp_cfg_config.splitnet_type = 0;
+
+	isakmp_cfg_config.pfs_group = 0;
+	isakmp_cfg_config.save_passwd = 0;
+
+	if (cold != ISAKMP_CFG_INIT_COLD )
+		if (isakmp_cfg_config.splitdns_list != NULL)
+			racoon_free(isakmp_cfg_config.splitdns_list);
+	isakmp_cfg_config.splitdns_list = NULL;
+	isakmp_cfg_config.splitdns_len = 0;
+
+	if (cold == ISAKMP_CFG_INIT_COLD) {
+		if ((error = isakmp_cfg_resize_pool(ISAKMP_CFG_MAX_CNX)) != 0)
+			return error;
+	}
+
+	return 0;
+}
+
diff --git a/src/racoon/isakmp_cfg.h b/src/racoon/isakmp_cfg.h
new file mode 100644
index 0000000..63fe459
--- /dev/null
+++ b/src/racoon/isakmp_cfg.h
@@ -0,0 +1,222 @@
+/*	$NetBSD: isakmp_cfg.h,v 1.6 2006/09/09 16:22:09 manu Exp $	*/
+
+/*	$KAME$ */
+
+/*
+ * Copyright (C) 2004 Emmanuel Dreyfus
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef HAVE_LIBPAM
+#include <security/pam_appl.h>
+#endif
+
+/* 
+ * XXX don't forget to update 
+ * src/racoon/handler.c:exclude_cfg_addr()
+ * if you add IPv6 capability
+ */
+
+/* Attribute types */
+#define INTERNAL_IP4_ADDRESS        1
+#define INTERNAL_IP4_NETMASK        2
+#define INTERNAL_IP4_DNS            3
+#define INTERNAL_IP4_NBNS           4
+#define INTERNAL_ADDRESS_EXPIRY     5
+#define INTERNAL_IP4_DHCP           6
+#define APPLICATION_VERSION         7
+#define INTERNAL_IP6_ADDRESS        8
+#define INTERNAL_IP6_NETMASK        9
+#define INTERNAL_IP6_DNS           10
+#define INTERNAL_IP6_NBNS          11
+#define INTERNAL_IP6_DHCP          12
+#define INTERNAL_IP4_SUBNET        13
+#define SUPPORTED_ATTRIBUTES       14
+#define INTERNAL_IP6_SUBNET        15
+
+/* For APPLICATION_VERSION */
+#define ISAKMP_CFG_RACOON_VERSION "racoon / IPsec-tools"
+
+/* For the wins servers -- XXX find the value somewhere ? */
+#define MAXWINS 4
+
+/* 
+ * Global configuration for ISAKMP mode confiration address allocation 
+ * Read from the mode_cfg section of racoon.conf
+ */
+struct isakmp_cfg_port {
+	char	used;
+#ifdef HAVE_LIBPAM
+	pam_handle_t *pam;
+#endif
+};
+
+struct isakmp_cfg_config {
+	in_addr_t		network4;
+	in_addr_t		netmask4;
+	in_addr_t		dns4[MAXNS];
+	int			dns4_index;
+	in_addr_t		nbns4[MAXWINS];
+	int			nbns4_index;
+	struct isakmp_cfg_port 	*port_pool;
+	int			authsource;
+	int			groupsource;
+	char			**grouplist;
+	int			groupcount;
+	int			confsource;
+	int			accounting;
+	size_t			pool_size;
+	int			auth_throttle;
+	/* XXX move this to a unity specific sub-structure */
+	char			default_domain[MAXPATHLEN + 1];
+	char			motd[MAXPATHLEN + 1];
+	struct unity_netentry	*splitnet_list;
+	int			splitnet_count;
+	int			splitnet_type;
+	char 			*splitdns_list;
+	int			splitdns_len;
+	int			pfs_group;
+	int			save_passwd;
+};
+
+/* For utmp updating */
+#define TERMSPEC	"vpn%d"
+
+/* For authsource */
+#define ISAKMP_CFG_AUTH_SYSTEM	0
+#define ISAKMP_CFG_AUTH_RADIUS	1
+#define ISAKMP_CFG_AUTH_PAM	2
+#define ISAKMP_CFG_AUTH_LDAP	4
+
+/* For groupsource */
+#define ISAKMP_CFG_GROUP_SYSTEM	0
+#define ISAKMP_CFG_GROUP_LDAP	1
+
+/* For confsource */
+#define ISAKMP_CFG_CONF_LOCAL	0
+#define ISAKMP_CFG_CONF_RADIUS	1
+#define ISAKMP_CFG_CONF_LDAP	2
+
+/* For accounting */
+#define ISAKMP_CFG_ACCT_NONE	0
+#define ISAKMP_CFG_ACCT_RADIUS	1
+#define ISAKMP_CFG_ACCT_PAM	2
+#define ISAKMP_CFG_ACCT_LDAP	3
+#define ISAKMP_CFG_ACCT_SYSTEM	4
+
+/* For pool_size */
+#define ISAKMP_CFG_MAX_CNX	255
+
+/* For motd */
+#define ISAKMP_CFG_MOTD	"/etc/motd"
+
+/* For default domain */
+#define ISAKMP_CFG_DEFAULT_DOMAIN ""
+
+extern struct isakmp_cfg_config isakmp_cfg_config;
+
+/*
+ * ISAKMP mode config state 
+ */
+#define LOGINLEN 31
+struct isakmp_cfg_state {
+	int flags;			/* See below */
+	unsigned int port;		/* address index */
+	char login[LOGINLEN + 1];	/* login */
+	struct in_addr addr4;		/* IPv4 address */
+	struct in_addr mask4;		/* IPv4 netmask */
+	struct in_addr dns4[MAXNS];	/* IPv4 DNS (when client only) */
+	int dns4_index;			/* Number of IPv4 DNS (client only) */
+	struct in_addr wins4[MAXWINS];	/* IPv4 WINS (when client only) */
+	int wins4_index;		/* Number of IPv4 WINS (client only) */
+	char default_domain[MAXPATHLEN + 1];	/* Default domain recieved */
+	struct unity_netentry 
+	    *split_include; 		/* UNITY_SPLIT_INCLUDE */
+	int include_count;		/* Number of SPLIT_INCLUDES */
+	struct unity_netentry 
+	    *split_local;		/* UNITY_LOCAL_LAN */
+	int local_count;		/* Number of SPLIT_LOCAL */
+	struct xauth_state xauth;	/* Xauth state, if revelant */		
+	struct isakmp_ivm *ivm;		/* XXX Use iph1's ivm? */
+	u_int32_t last_msgid;           /* Last message-ID */
+};
+
+/* flags */
+#define ISAKMP_CFG_VENDORID_XAUTH	0x01	/* Supports Xauth */
+#define ISAKMP_CFG_VENDORID_UNITY	0x02	/* Cisco Unity compliant */
+#define ISAKMP_CFG_PORT_ALLOCATED	0x04	/* Port allocated */
+#define ISAKMP_CFG_ADDR4_EXTERN		0x08	/* Address from external config  */
+#define ISAKMP_CFG_MASK4_EXTERN		0x10	/* Netmask from external config */
+#define ISAKMP_CFG_ADDR4_LOCAL		0x20	/* Address from local pool */
+#define ISAKMP_CFG_MASK4_LOCAL		0x40	/* Netmask from local pool */
+#define ISAKMP_CFG_GOT_ADDR4		0x80	/* Client got address */
+#define ISAKMP_CFG_GOT_MASK4		0x100	/* Client got mask */
+#define ISAKMP_CFG_GOT_DNS4		0x200	/* Client got DNS */
+#define ISAKMP_CFG_GOT_WINS4		0x400	/* Client got WINS */
+#define ISAKMP_CFG_DELETE_PH1		0x800	/* phase 1 should be deleted */
+#define ISAKMP_CFG_GOT_DEFAULT_DOMAIN	0x1000	/* Client got default domain */
+#define ISAKMP_CFG_GOT_SPLIT_INCLUDE	0x2000	/* Client got a split network config */
+#define ISAKMP_CFG_GOT_SPLIT_LOCAL	0x4000	/* Client got a split LAN config */
+
+struct isakmp_pl_attr;
+struct ph1handle;
+struct isakmp_ivm;
+void isakmp_cfg_r(struct ph1handle *, vchar_t *);
+int isakmp_cfg_attr_r(struct ph1handle *, u_int32_t, struct isakmp_pl_attr *);
+int isakmp_cfg_reply(struct ph1handle *, struct isakmp_pl_attr *);
+int isakmp_cfg_request(struct ph1handle *, struct isakmp_pl_attr *);
+int isakmp_cfg_set(struct ph1handle *, struct isakmp_pl_attr *);
+int isakmp_cfg_send(struct ph1handle *, vchar_t *, u_int32_t, int, int);
+struct isakmp_ivm *isakmp_cfg_newiv(struct ph1handle *, u_int32_t);
+void isakmp_cfg_rmstate(struct ph1handle *);
+struct isakmp_cfg_state *isakmp_cfg_mkstate(void);
+vchar_t *isakmp_cfg_copy(struct ph1handle *, struct isakmp_data *);
+vchar_t *isakmp_cfg_short(struct ph1handle *, struct isakmp_data *, int);
+vchar_t *isakmp_cfg_varlen(struct ph1handle *, struct isakmp_data *, char *, size_t);
+vchar_t *isakmp_cfg_string(struct ph1handle *, struct isakmp_data *, char *);
+int isakmp_cfg_getconfig(struct ph1handle *);
+int isakmp_cfg_setenv(struct ph1handle *, char ***, int *);
+
+int isakmp_cfg_resize_pool(int);
+int isakmp_cfg_getport(struct ph1handle *);
+int isakmp_cfg_putport(struct ph1handle *, unsigned int);
+int isakmp_cfg_init(int);
+#define ISAKMP_CFG_INIT_COLD	1
+#define ISAKMP_CFG_INIT_WARM	0
+
+#ifdef HAVE_LIBRADIUS
+struct rad_handle;
+extern struct rad_handle *radius_acct_state;
+int isakmp_cfg_radius_common(struct rad_handle *, int); 
+#endif
+
+#ifdef HAVE_LIBPAM
+int isakmp_cfg_accounting_pam(int, int);
+void cleanup_pam(int);
+#endif
+
+int isakmp_cfg_accounting_system(int, struct sockaddr *, char *, int);
diff --git a/src/racoon/isakmp_frag.c b/src/racoon/isakmp_frag.c
new file mode 100644
index 0000000..76f22af
--- /dev/null
+++ b/src/racoon/isakmp_frag.c
@@ -0,0 +1,355 @@
+/*	$NetBSD: isakmp_frag.c,v 1.4 2006/09/09 16:22:09 manu Exp $	*/
+
+/* Id: isakmp_frag.c,v 1.4 2004/11/13 17:31:36 manubsd Exp */
+
+/*
+ * Copyright (C) 2004 Emmanuel Dreyfus
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <sys/queue.h>
+
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include <openssl/md5.h> 
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <string.h>
+#include <errno.h>
+#if TIME_WITH_SYS_TIME
+# include <sys/time.h>
+# include <time.h>
+#else
+# if HAVE_SYS_TIME_H
+#  include <sys/time.h>
+# else
+#  include <time.h>
+# endif
+#endif
+#include <netdb.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <ctype.h>
+
+#include "var.h"
+#include "misc.h"
+#include "vmbuf.h"
+#include "plog.h"
+#include "sockmisc.h"
+#include "schedule.h"
+#include "debug.h"
+
+#include "isakmp_var.h"
+#include "isakmp.h"
+#include "handler.h"
+#include "isakmp_frag.h"
+#include "strnames.h"
+
+int
+isakmp_sendfrags(iph1, buf) 
+	struct ph1handle *iph1;
+	vchar_t *buf;
+{
+	struct isakmp *hdr;
+	struct isakmp_frag *fraghdr;
+	caddr_t data;
+	caddr_t sdata;
+	size_t datalen;
+	size_t max_datalen;
+	size_t fraglen;
+	vchar_t *frag;
+	unsigned int trailer;
+	unsigned int fragnum = 0;
+	size_t len;
+	int etype;
+
+	/*
+	 * Catch the exchange type for later: the fragments and the
+	 * fragmented packet must have the same exchange type.
+	 */
+	hdr = (struct isakmp *)buf->v;
+	etype = hdr->etype;
+
+	/*
+	 * We want to send a a packet smaller than ISAKMP_FRAG_MAXLEN
+	 * First compute the maximum data length that will fit in it
+	 */
+	max_datalen = ISAKMP_FRAG_MAXLEN - 
+	    (sizeof(*hdr) + sizeof(*fraghdr) + sizeof(trailer));
+
+	sdata = buf->v;
+	len = buf->l;
+
+	while (len > 0) {
+		fragnum++;
+
+		if (len > max_datalen)
+			datalen = max_datalen;
+		else
+			datalen = len;
+
+		fraglen = sizeof(*hdr) 
+			+ sizeof(*fraghdr) 
+			+ datalen;
+
+		if ((frag = vmalloc(fraglen)) == NULL) {
+			plog(LLV_ERROR, LOCATION, NULL, 
+			    "Cannot allocate memory\n");
+			return -1;
+		}
+
+		set_isakmp_header1(frag, iph1, ISAKMP_NPTYPE_FRAG);
+		hdr = (struct isakmp *)frag->v;
+		hdr->etype = etype;
+
+		fraghdr = (struct isakmp_frag *)(hdr + 1);
+		fraghdr->unknown0 = htons(0);
+		fraghdr->len = htons(fraglen - sizeof(*hdr));
+		fraghdr->unknown1 = htons(1);
+		fraghdr->index = fragnum;
+		if (len == datalen)
+			fraghdr->flags = ISAKMP_FRAG_LAST;
+		else
+			fraghdr->flags = 0;
+
+		data = (caddr_t)(fraghdr + 1);
+		memcpy(data, sdata, datalen);
+
+		if (isakmp_send(iph1, frag) < 0) {
+			plog(LLV_ERROR, LOCATION, NULL, "isakmp_send failed\n");
+			return -1;
+		}
+
+		vfree(frag);
+
+		len -= datalen;
+		sdata += datalen;
+	}
+		
+	return fragnum;
+}
+
+unsigned int 
+vendorid_frag_cap(gen)
+	struct isakmp_gen *gen;
+{
+	int *hp;
+
+	hp = (int *)(gen + 1);
+
+	return ntohl(hp[MD5_DIGEST_LENGTH / sizeof(*hp)]);
+}
+
+int 
+isakmp_frag_extract(iph1, msg)
+	struct ph1handle *iph1;
+	vchar_t *msg;
+{
+	struct isakmp *isakmp;
+	struct isakmp_frag *frag;
+	struct isakmp_frag_item *item;
+	vchar_t *buf;
+	size_t len;
+	int last_frag = 0;
+	char *data;
+	int i;
+
+	if (msg->l < sizeof(*isakmp) + sizeof(*frag)) {
+		plog(LLV_ERROR, LOCATION, NULL, "Message too short\n");
+		return -1;
+	}
+
+	isakmp = (struct isakmp *)msg->v;
+	frag = (struct isakmp_frag *)(isakmp + 1);
+
+	/* 
+	 * frag->len is the frag payload data plus the frag payload header,
+	 * whose size is sizeof(*frag) 
+	 */
+	if (msg->l < sizeof(*isakmp) + ntohs(frag->len)) {
+		plog(LLV_ERROR, LOCATION, NULL, "Fragment too short\n");
+		return -1;
+	}
+
+	if ((buf = vmalloc(ntohs(frag->len) - sizeof(*frag))) == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL, "Cannot allocate memory\n");
+		return -1;
+	}
+
+	if ((item = racoon_malloc(sizeof(*item))) == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL, "Cannot allocate memory\n");
+		vfree(buf);
+		return -1;
+	}
+
+	data = (char *)(frag + 1);
+	memcpy(buf->v, data, buf->l);
+
+	item->frag_num = frag->index;
+	item->frag_last = (frag->flags & ISAKMP_FRAG_LAST);
+	item->frag_next = NULL;
+	item->frag_packet = buf;
+
+	/* Look for the last frag while inserting the new item in the chain */
+	if (item->frag_last)
+		last_frag = item->frag_num;
+
+	if (iph1->frag_chain == NULL) {
+		iph1->frag_chain = item;
+	} else {
+		struct isakmp_frag_item *current;
+
+		current = iph1->frag_chain;
+		while (current->frag_next) {
+			if (current->frag_last)
+				last_frag = item->frag_num;
+			current = current->frag_next;
+		}
+		current->frag_next = item;
+	}
+
+	/* If we saw the last frag, check if the chain is complete */
+	if (last_frag != 0) {
+		for (i = 1; i <= last_frag; i++) {
+			item = iph1->frag_chain;
+			do {
+				if (item->frag_num == i)
+					break;
+				item = item->frag_next;
+			} while (item != NULL);
+
+			if (item == NULL) /* Not found */
+				break;
+		}
+
+		if (item != NULL) /* It is complete */
+			return 1;
+	}
+		
+	return 0;
+}
+
+vchar_t *
+isakmp_frag_reassembly(iph1)
+	struct ph1handle *iph1;
+{
+	struct isakmp_frag_item *item;
+	size_t len = 0;
+	vchar_t *buf = NULL;
+	int frag_count = 0;
+	int i;
+	char *data;
+
+	if ((item = iph1->frag_chain) == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL, "No fragment to reassemble\n");
+		goto out;
+	}
+
+	do {
+		frag_count++;
+		len += item->frag_packet->l;
+		item = item->frag_next;
+	} while (item != NULL);
+	
+	if ((buf = vmalloc(len)) == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL, "Cannot allocate memory\n");
+		goto out;
+	}
+	data = buf->v;
+
+	for (i = 1; i <= frag_count; i++) {
+		item = iph1->frag_chain;
+		do {
+			if (item->frag_num == i)
+				break;
+			item = item->frag_next;
+		} while (item != NULL);
+
+		if (item == NULL) {
+			plog(LLV_ERROR, LOCATION, NULL, 
+			    "Missing fragment #%d\n", i);
+			vfree(buf);
+			buf = NULL;
+			goto out;
+		}
+		memcpy(data, item->frag_packet->v, item->frag_packet->l);
+		data += item->frag_packet->l;
+	}
+
+out:
+	item = iph1->frag_chain;		
+	do {
+		struct isakmp_frag_item *next_item;
+
+		next_item = item->frag_next;
+
+		vfree(item->frag_packet);
+		racoon_free(item);
+
+		item = next_item;
+	} while (item != NULL);
+
+	iph1->frag_chain = NULL;
+
+	return buf;
+}
+
+vchar_t *
+isakmp_frag_addcap(buf, cap)
+	vchar_t *buf;
+	int cap;
+{
+	int *capp;
+	size_t len;
+
+	/* If the capability has not been added, add room now */
+	len = buf->l;
+	if (len == MD5_DIGEST_LENGTH) {
+		if ((buf = vrealloc(buf, len + sizeof(cap))) == NULL) {
+			plog(LLV_ERROR, LOCATION, NULL, 
+			    "Cannot allocate memory\n");
+			return NULL;
+		}
+		capp = (int *)(buf->v + len);
+		*capp = htonl(0);
+	}
+
+	capp = (int *)(buf->v + MD5_DIGEST_LENGTH);
+	*capp |= htonl(cap);
+
+	return buf;
+}
+
diff --git a/src/racoon/isakmp_frag.h b/src/racoon/isakmp_frag.h
new file mode 100644
index 0000000..f2d4c33
--- /dev/null
+++ b/src/racoon/isakmp_frag.h
@@ -0,0 +1,58 @@
+/*	$NetBSD: isakmp_frag.h,v 1.5 2006/09/18 20:32:40 manu Exp $	*/
+
+/*	Id: isakmp_frag.h,v 1.3 2005/04/09 16:25:24 manubsd Exp */
+
+/*
+ * Copyright (C) 2004 Emmanuel Dreyfus 
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* These are the values from parsing "remote {}"
+   block of the config file. */
+#define ISAKMP_FRAG_OFF		FLASE   /* = 0 */
+#define ISAKMP_FRAG_ON		TRUE    /* = 1 */
+#define ISAKMP_FRAG_FORCE	2
+
+/* IKE fragmentation capabilities */
+#define VENDORID_FRAG_IDENT 	0x80000000
+#define VENDORID_FRAG_BASE 	0x40000000
+#define VENDORID_FRAG_AGG 	0x80000000
+
+#define ISAKMP_FRAG_MAXLEN 552
+
+struct isakmp_frag_item {
+	int	frag_num;
+	int	frag_last;
+	struct isakmp_frag_item *frag_next;
+	vchar_t *frag_packet;
+};
+
+int isakmp_sendfrags(struct ph1handle *, vchar_t *);
+unsigned int vendorid_frag_cap(struct isakmp_gen *);
+int isakmp_frag_extract(struct ph1handle *, vchar_t *);
+vchar_t *isakmp_frag_reassembly(struct ph1handle *);
+vchar_t *isakmp_frag_addcap(vchar_t *, int);
diff --git a/src/racoon/isakmp_ident.c b/src/racoon/isakmp_ident.c
new file mode 100644
index 0000000..1e00dc4
--- /dev/null
+++ b/src/racoon/isakmp_ident.c
@@ -0,0 +1,1959 @@
+/*	$NetBSD: isakmp_ident.c,v 1.6 2006/10/02 21:41:59 manu Exp $	*/
+
+/* Id: isakmp_ident.c,v 1.21 2006/04/06 16:46:08 manubsd Exp */
+
+/*
+ * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* Identity Protecion Exchange (Main Mode) */
+
+#include "config.h"
+
+#include <sys/types.h>
+#include <sys/param.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#if TIME_WITH_SYS_TIME
+# include <sys/time.h>
+# include <time.h>
+#else
+# if HAVE_SYS_TIME_H
+#  include <sys/time.h>
+# else
+#  include <time.h>
+# endif
+#endif
+
+#include "var.h"
+#include "misc.h"
+#include "vmbuf.h"
+#include "plog.h"
+#include "sockmisc.h"
+#include "schedule.h"
+#include "debug.h"
+
+#include "localconf.h"
+#include "remoteconf.h"
+#include "isakmp_var.h"
+#include "isakmp.h"
+#include "evt.h"
+#include "oakley.h"
+#include "handler.h"
+#include "ipsec_doi.h"
+#include "crypto_openssl.h"
+#include "pfkey.h"
+#include "isakmp_ident.h"
+#include "isakmp_inf.h"
+#include "vendorid.h"
+
+#ifdef ENABLE_NATT
+#include "nattraversal.h"
+#endif
+#ifdef HAVE_GSSAPI
+#include "gssapi.h"
+#endif
+#ifdef ENABLE_HYBRID
+#include <resolv.h>
+#include "isakmp_xauth.h"
+#include "isakmp_cfg.h"
+#endif
+#ifdef ENABLE_FRAG 
+#include "isakmp_frag.h"
+#endif
+
+static vchar_t *ident_ir2mx __P((struct ph1handle *));
+static vchar_t *ident_ir3mx __P((struct ph1handle *));
+
+/* %%%
+ * begin Identity Protection Mode as initiator.
+ */
+/*
+ * send to responder
+ * 	psk: HDR, SA
+ * 	sig: HDR, SA
+ * 	rsa: HDR, SA
+ * 	rev: HDR, SA
+ */
+int
+ident_i1send(iph1, msg)
+	struct ph1handle *iph1;
+	vchar_t *msg; /* must be null */
+{
+	struct payload_list *plist = NULL;
+	int error = -1;
+#ifdef ENABLE_NATT
+	vchar_t *vid_natt[MAX_NATT_VID_COUNT] = { NULL };
+	int i;
+#endif
+#ifdef ENABLE_HYBRID  
+	vchar_t *vid_xauth = NULL;
+	vchar_t *vid_unity = NULL;
+#endif
+#ifdef ENABLE_FRAG 
+	vchar_t *vid_frag = NULL;
+#endif 
+#ifdef ENABLE_DPD
+	vchar_t *vid_dpd = NULL;
+#endif
+	/* validity check */
+	if (msg != NULL) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"msg has to be NULL in this function.\n");
+		goto end;
+	}
+	if (iph1->status != PHASE1ST_START) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"status mismatched %d.\n", iph1->status);
+		goto end;
+	}
+
+	/* create isakmp index */
+	memset(&iph1->index, 0, sizeof(iph1->index));
+	isakmp_newcookie((caddr_t)&iph1->index, iph1->remote, iph1->local);
+
+	/* create SA payload for my proposal */
+	iph1->sa = ipsecdoi_setph1proposal(iph1->rmconf->proposal);
+	if (iph1->sa == NULL)
+		goto end;
+
+	/* set SA payload to propose */
+	plist = isakmp_plist_append(plist, iph1->sa, ISAKMP_NPTYPE_SA);
+
+#ifdef ENABLE_NATT
+	/* set VID payload for NAT-T if NAT-T support allowed in the config file */
+	if (iph1->rmconf->nat_traversal) 
+		plist = isakmp_plist_append_natt_vids(plist, vid_natt);
+#endif
+#ifdef ENABLE_HYBRID
+	/* Do we need Xauth VID? */
+	switch (RMAUTHMETHOD(iph1)) {
+	case FICTIVE_AUTH_METHOD_XAUTH_PSKEY_I:
+	case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_I:
+	case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_I:
+	case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_I:
+	case OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_I:
+	case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAENC_I:
+	case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAREV_I:
+		if ((vid_xauth = set_vendorid(VENDORID_XAUTH)) == NULL)
+			plog(LLV_ERROR, LOCATION, NULL,
+			     "Xauth vendor ID generation failed\n");
+		else
+			plist = isakmp_plist_append(plist,
+			    vid_xauth, ISAKMP_NPTYPE_VID);
+			
+		if ((vid_unity = set_vendorid(VENDORID_UNITY)) == NULL)
+			plog(LLV_ERROR, LOCATION, NULL,
+			     "Unity vendor ID generation failed\n");
+		else
+                	plist = isakmp_plist_append(plist,
+			    vid_unity, ISAKMP_NPTYPE_VID);
+		break;
+	default:
+		break;
+	}
+#endif
+#ifdef ENABLE_FRAG
+	if (iph1->rmconf->ike_frag) {
+		if ((vid_frag = set_vendorid(VENDORID_FRAG)) == NULL) {
+			plog(LLV_ERROR, LOCATION, NULL,
+			    "Frag vendorID construction failed\n");
+		} else {
+			vid_frag = isakmp_frag_addcap(vid_frag,
+			    VENDORID_FRAG_IDENT);
+			plist = isakmp_plist_append(plist, 
+			    vid_frag, ISAKMP_NPTYPE_VID);
+		}
+	}
+#endif
+#ifdef ENABLE_DPD
+	if(iph1->rmconf->dpd){
+		vid_dpd = set_vendorid(VENDORID_DPD);
+		if (vid_dpd != NULL)
+			plist = isakmp_plist_append(plist, vid_dpd,
+			    ISAKMP_NPTYPE_VID);
+	}
+#endif
+
+	iph1->sendbuf = isakmp_plist_set_all (&plist, iph1);
+
+#ifdef HAVE_PRINT_ISAKMP_C
+	isakmp_printpacket(iph1->sendbuf, iph1->local, iph1->remote, 0);
+#endif
+
+	/* send the packet, add to the schedule to resend */
+	iph1->retry_counter = iph1->rmconf->retry_counter;
+	if (isakmp_ph1resend(iph1) == -1)
+		goto end;
+
+	iph1->status = PHASE1ST_MSG1SENT;
+
+	error = 0;
+
+end:
+#ifdef ENABLE_FRAG
+	if (vid_frag) 
+		vfree(vid_frag);
+#endif  
+#ifdef ENABLE_NATT
+	for (i = 0; i < MAX_NATT_VID_COUNT && vid_natt[i] != NULL; i++)
+		vfree(vid_natt[i]);
+#endif
+#ifdef ENABLE_HYBRID
+	if (vid_xauth != NULL)
+		vfree(vid_xauth);
+	if (vid_unity != NULL)
+		vfree(vid_unity);
+#endif
+#ifdef ENABLE_DPD
+	if (vid_dpd != NULL)
+		vfree(vid_dpd);
+#endif
+
+	return error;
+}
+
+/*
+ * receive from responder
+ * 	psk: HDR, SA
+ * 	sig: HDR, SA
+ * 	rsa: HDR, SA
+ * 	rev: HDR, SA
+ */
+int
+ident_i2recv(iph1, msg)
+	struct ph1handle *iph1;
+	vchar_t *msg;
+{
+	vchar_t *pbuf = NULL;
+	struct isakmp_parse_t *pa;
+	vchar_t *satmp = NULL;
+	int error = -1;
+	int vid_numeric;
+
+	/* validity check */
+	if (iph1->status != PHASE1ST_MSG1SENT) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"status mismatched %d.\n", iph1->status);
+		goto end;
+	}
+
+	/* validate the type of next payload */
+	/*
+	 * NOTE: RedCreek(as responder) attaches N[responder-lifetime] here,
+	 *	if proposal-lifetime > lifetime-redcreek-wants.
+	 *	(see doi-08 4.5.4)
+	 *	=> According to the seciton 4.6.3 in RFC 2407, This is illegal.
+	 * NOTE: we do not really care about ordering of VID and N.
+	 *	does it matters?
+	 * NOTE: even if there's multiple VID/N, we'll ignore them.
+	 */
+	pbuf = isakmp_parse(msg);
+	if (pbuf == NULL)
+		goto end;
+	pa = (struct isakmp_parse_t *)pbuf->v;
+
+	/* SA payload is fixed postion */
+	if (pa->type != ISAKMP_NPTYPE_SA) {
+		plog(LLV_ERROR, LOCATION, iph1->remote,
+			"received invalid next payload type %d, "
+			"expecting %d.\n",
+			pa->type, ISAKMP_NPTYPE_SA);
+		goto end;
+	}
+	if (isakmp_p2ph(&satmp, pa->ptr) < 0)
+		goto end;
+	pa++;
+
+	for (/*nothing*/;
+	     pa->type != ISAKMP_NPTYPE_NONE;
+	     pa++) {
+
+		switch (pa->type) {
+		case ISAKMP_NPTYPE_VID:
+			vid_numeric = check_vendorid(pa->ptr);
+#ifdef ENABLE_NATT
+			if (iph1->rmconf->nat_traversal && natt_vendorid(vid_numeric))
+			  natt_handle_vendorid(iph1, vid_numeric);
+#endif
+#ifdef ENABLE_HYBRID
+			switch (vid_numeric) {
+			case VENDORID_XAUTH:
+				iph1->mode_cfg->flags |=
+				    ISAKMP_CFG_VENDORID_XAUTH;
+				break;
+	
+			case VENDORID_UNITY:
+				iph1->mode_cfg->flags |=
+				    ISAKMP_CFG_VENDORID_UNITY;
+				break;
+	
+			default:
+				break;
+			}
+#endif  
+#ifdef ENABLE_DPD
+			if (vid_numeric == VENDORID_DPD && iph1->rmconf->dpd)
+				iph1->dpd_support=1;
+#endif
+			break;
+		default:
+			/* don't send information, see ident_r1recv() */
+			plog(LLV_ERROR, LOCATION, iph1->remote,
+				"ignore the packet, "
+				"received unexpecting payload type %d.\n",
+				pa->type);
+			goto end;
+		}
+	}
+
+#ifdef ENABLE_NATT
+	if (NATT_AVAILABLE(iph1))
+		plog(LLV_INFO, LOCATION, iph1->remote,
+		     "Selected NAT-T version: %s\n",
+		     vid_string_by_id(iph1->natt_options->version));
+#endif
+
+	/* check SA payload and set approval SA for use */
+	if (ipsecdoi_checkph1proposal(satmp, iph1) < 0) {
+		plog(LLV_ERROR, LOCATION, iph1->remote,
+			"failed to get valid proposal.\n");
+		/* XXX send information */
+		goto end;
+	}
+	VPTRINIT(iph1->sa_ret);
+
+	iph1->status = PHASE1ST_MSG2RECEIVED;
+
+	error = 0;
+
+end:
+	if (pbuf)
+		vfree(pbuf);
+	if (satmp)
+		vfree(satmp);
+	return error;
+}
+
+/*
+ * send to responder
+ * 	psk: HDR, KE, Ni
+ * 	sig: HDR, KE, Ni
+ *   gssapi: HDR, KE, Ni, GSSi
+ * 	rsa: HDR, KE, [ HASH(1), ] <IDi1_b>PubKey_r, <Ni_b>PubKey_r
+ * 	rev: HDR, [ HASH(1), ] <Ni_b>Pubkey_r, <KE_b>Ke_i,
+ * 	          <IDi1_b>Ke_i, [<<Cert-I_b>Ke_i]
+ */
+int
+ident_i2send(iph1, msg)
+	struct ph1handle *iph1;
+	vchar_t *msg;
+{
+	int error = -1;
+
+	/* validity check */
+	if (iph1->status != PHASE1ST_MSG2RECEIVED) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"status mismatched %d.\n", iph1->status);
+		goto end;
+	}
+
+	/* fix isakmp index */
+	memcpy(&iph1->index.r_ck, &((struct isakmp *)msg->v)->r_ck,
+		sizeof(cookie_t));
+
+	/* generate DH public value */
+	if (oakley_dh_generate(iph1->approval->dhgrp,
+				&iph1->dhpub, &iph1->dhpriv) < 0)
+		goto end;
+
+	/* generate NONCE value */
+	iph1->nonce = eay_set_random(iph1->rmconf->nonce_size);
+	if (iph1->nonce == NULL)
+		goto end;
+
+#ifdef HAVE_GSSAPI
+	if (AUTHMETHOD(iph1) == OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB &&
+	    gssapi_get_itoken(iph1, NULL) < 0)
+		goto end;
+#endif
+
+	/* create buffer to send isakmp payload */
+	iph1->sendbuf = ident_ir2mx(iph1);
+	if (iph1->sendbuf == NULL)
+		goto end;
+
+#ifdef HAVE_PRINT_ISAKMP_C
+	isakmp_printpacket(iph1->sendbuf, iph1->local, iph1->remote, 0);
+#endif
+
+	/* send the packet, add to the schedule to resend */
+	iph1->retry_counter = iph1->rmconf->retry_counter;
+	if (isakmp_ph1resend(iph1) == -1)
+		goto end;
+
+	/* the sending message is added to the received-list. */
+	if (add_recvdpkt(iph1->remote, iph1->local, iph1->sendbuf, msg) == -1) {
+		plog(LLV_ERROR , LOCATION, NULL,
+			"failed to add a response packet to the tree.\n");
+		goto end;
+	}
+
+	iph1->status = PHASE1ST_MSG2SENT;
+
+	error = 0;
+
+end:
+	return error;
+}
+
+/*
+ * receive from responder
+ * 	psk: HDR, KE, Nr
+ * 	sig: HDR, KE, Nr [, CR ]
+ *   gssapi: HDR, KE, Nr, GSSr
+ * 	rsa: HDR, KE, <IDr1_b>PubKey_i, <Nr_b>PubKey_i
+ * 	rev: HDR, <Nr_b>PubKey_i, <KE_b>Ke_r, <IDr1_b>Ke_r,
+ */
+int
+ident_i3recv(iph1, msg)
+	struct ph1handle *iph1;
+	vchar_t *msg;
+{
+	vchar_t *pbuf = NULL;
+	struct isakmp_parse_t *pa;
+	int error = -1;
+#ifdef HAVE_GSSAPI
+	vchar_t *gsstoken = NULL;
+#endif
+#ifdef ENABLE_NATT
+	vchar_t	*natd_received;
+	int natd_seq = 0, natd_verified;
+#endif
+
+	/* validity check */
+	if (iph1->status != PHASE1ST_MSG2SENT) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"status mismatched %d.\n", iph1->status);
+		goto end;
+	}
+
+	/* validate the type of next payload */
+	pbuf = isakmp_parse(msg);
+	if (pbuf == NULL)
+		goto end;
+
+	for (pa = (struct isakmp_parse_t *)pbuf->v;
+	     pa->type != ISAKMP_NPTYPE_NONE;
+	     pa++) {
+
+		switch (pa->type) {
+		case ISAKMP_NPTYPE_KE:
+			if (isakmp_p2ph(&iph1->dhpub_p, pa->ptr) < 0)
+				goto end;
+			break;
+		case ISAKMP_NPTYPE_NONCE:
+			if (isakmp_p2ph(&iph1->nonce_p, pa->ptr) < 0)
+				goto end;
+			break;
+		case ISAKMP_NPTYPE_VID:
+			(void)check_vendorid(pa->ptr);
+			break;
+		case ISAKMP_NPTYPE_CR:
+			if (oakley_savecr(iph1, pa->ptr) < 0)
+				goto end;
+			break;
+#ifdef HAVE_GSSAPI
+		case ISAKMP_NPTYPE_GSS:
+			if (isakmp_p2ph(&gsstoken, pa->ptr) < 0)
+				goto end;
+			gssapi_save_received_token(iph1, gsstoken);
+			break;
+#endif
+
+#ifdef ENABLE_NATT
+		case ISAKMP_NPTYPE_NATD_DRAFT:
+		case ISAKMP_NPTYPE_NATD_RFC:
+			if (NATT_AVAILABLE(iph1) && iph1->natt_options != NULL &&
+			    pa->type == iph1->natt_options->payload_nat_d) {
+				natd_received = NULL;
+				if (isakmp_p2ph (&natd_received, pa->ptr) < 0)
+					goto end;
+                        
+				/* set both bits first so that we can clear them
+				   upon verifying hashes */
+				if (natd_seq == 0)
+					iph1->natt_flags |= NAT_DETECTED;
+                        
+				/* this function will clear appropriate bits bits 
+				   from iph1->natt_flags */
+				natd_verified = natt_compare_addr_hash (iph1,
+					natd_received, natd_seq++);
+                        
+				plog (LLV_INFO, LOCATION, NULL, "NAT-D payload #%d %s\n",
+					natd_seq - 1,
+					natd_verified ? "verified" : "doesn't match");
+                        
+				vfree (natd_received);
+				break;
+			}
+			/* passthrough to default... */
+#endif
+
+		default:
+			/* don't send information, see ident_r1recv() */
+			plog(LLV_ERROR, LOCATION, iph1->remote,
+				"ignore the packet, "
+				"received unexpecting payload type %d.\n",
+				pa->type);
+			goto end;
+		}
+	}
+
+#ifdef ENABLE_NATT
+	if (NATT_AVAILABLE(iph1)) {
+		plog (LLV_INFO, LOCATION, NULL, "NAT %s %s%s\n",
+		      iph1->natt_flags & NAT_DETECTED ? 
+		      		"detected:" : "not detected",
+		      iph1->natt_flags & NAT_DETECTED_ME ? "ME " : "",
+		      iph1->natt_flags & NAT_DETECTED_PEER ? "PEER" : "");
+		if (iph1->natt_flags & NAT_DETECTED)
+			natt_float_ports (iph1);
+	}
+#endif
+
+	/* payload existency check */
+	if (iph1->dhpub_p == NULL || iph1->nonce_p == NULL) {
+		plog(LLV_ERROR, LOCATION, iph1->remote,
+			"few isakmp message received.\n");
+		goto end;
+	}
+
+	if (oakley_checkcr(iph1) < 0) {
+		/* Ignore this error in order to be interoperability. */
+		;
+	}
+
+	iph1->status = PHASE1ST_MSG3RECEIVED;
+
+	error = 0;
+
+end:
+#ifdef HAVE_GSSAPI
+	if (gsstoken)
+		vfree(gsstoken);
+#endif
+	if (pbuf)
+		vfree(pbuf);
+	if (error) {
+		VPTRINIT(iph1->dhpub_p);
+		VPTRINIT(iph1->nonce_p);
+		VPTRINIT(iph1->id_p);
+		oakley_delcert(iph1->cr_p);
+		iph1->cr_p = NULL;
+	}
+
+	return error;
+}
+
+/*
+ * send to responder
+ * 	psk: HDR*, IDi1, HASH_I
+ * 	sig: HDR*, IDi1, [ CR, ] [ CERT, ] SIG_I
+ *   gssapi: HDR*, IDi1, < Gssi(n) | HASH_I >
+ * 	rsa: HDR*, HASH_I
+ * 	rev: HDR*, HASH_I
+ */
+int
+ident_i3send(iph1, msg0)
+	struct ph1handle *iph1;
+	vchar_t *msg0;
+{
+	int error = -1;
+	int dohash = 1;
+#ifdef HAVE_GSSAPI
+	int len;
+#endif
+
+	/* validity check */
+	if (iph1->status != PHASE1ST_MSG3RECEIVED) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"status mismatched %d.\n", iph1->status);
+		goto end;
+	}
+
+	/* compute sharing secret of DH */
+	if (oakley_dh_compute(iph1->approval->dhgrp, iph1->dhpub,
+				iph1->dhpriv, iph1->dhpub_p, &iph1->dhgxy) < 0)
+		goto end;
+
+	/* generate SKEYIDs & IV & final cipher key */
+	if (oakley_skeyid(iph1) < 0)
+		goto end;
+	if (oakley_skeyid_dae(iph1) < 0)
+		goto end;
+	if (oakley_compute_enckey(iph1) < 0)
+		goto end;
+	if (oakley_newiv(iph1) < 0)
+		goto end;
+
+	/* make ID payload into isakmp status */
+	if (ipsecdoi_setid1(iph1) < 0)
+		goto end;
+
+#ifdef HAVE_GSSAPI
+	if (AUTHMETHOD(iph1) == OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB &&
+	    gssapi_more_tokens(iph1)) {
+		plog(LLV_DEBUG, LOCATION, NULL, "calling get_itoken\n");
+		if (gssapi_get_itoken(iph1, &len) < 0)
+			goto end;
+		if (len != 0)
+			dohash = 0;
+	}
+#endif
+
+	/* generate HASH to send */
+	if (dohash) {
+		iph1->hash = oakley_ph1hash_common(iph1, GENERATE);
+		if (iph1->hash == NULL)
+			goto end;
+	} else
+		iph1->hash = NULL;
+
+	/* set encryption flag */
+	iph1->flags |= ISAKMP_FLAG_E;
+
+	/* create HDR;ID;HASH payload */
+	iph1->sendbuf = ident_ir3mx(iph1);
+	if (iph1->sendbuf == NULL)
+		goto end;
+
+	/* send the packet, add to the schedule to resend */
+	iph1->retry_counter = iph1->rmconf->retry_counter;
+	if (isakmp_ph1resend(iph1) == -1)
+		goto end;
+
+	/* the sending message is added to the received-list. */
+	if (add_recvdpkt(iph1->remote, iph1->local, iph1->sendbuf, msg0) == -1) {
+		plog(LLV_ERROR , LOCATION, NULL,
+			"failed to add a response packet to the tree.\n");
+		goto end;
+	}
+
+	/* see handler.h about IV synchronization. */
+	memcpy(iph1->ivm->ive->v, iph1->ivm->iv->v, iph1->ivm->iv->l);
+
+	iph1->status = PHASE1ST_MSG3SENT;
+
+	error = 0;
+
+end:
+	return error;
+}
+
+/*
+ * receive from responder
+ * 	psk: HDR*, IDr1, HASH_R
+ * 	sig: HDR*, IDr1, [ CERT, ] SIG_R
+ *   gssapi: HDR*, IDr1, < GSSr(n) | HASH_R >
+ * 	rsa: HDR*, HASH_R
+ * 	rev: HDR*, HASH_R
+ */
+int
+ident_i4recv(iph1, msg0)
+	struct ph1handle *iph1;
+	vchar_t *msg0;
+{
+	vchar_t *pbuf = NULL;
+	struct isakmp_parse_t *pa;
+	vchar_t *msg = NULL;
+	int error = -1;
+	int type;
+#ifdef HAVE_GSSAPI
+	vchar_t *gsstoken = NULL;
+#endif
+
+	/* validity check */
+	if (iph1->status != PHASE1ST_MSG3SENT) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"status mismatched %d.\n", iph1->status);
+		goto end;
+	}
+
+	/* decrypting */
+	if (!ISSET(((struct isakmp *)msg0->v)->flags, ISAKMP_FLAG_E)) {
+		plog(LLV_ERROR, LOCATION, iph1->remote,
+			"ignore the packet, "
+			"expecting the packet encrypted.\n");
+		goto end;
+	}
+	msg = oakley_do_decrypt(iph1, msg0, iph1->ivm->iv, iph1->ivm->ive);
+	if (msg == NULL)
+		goto end;
+
+	/* validate the type of next payload */
+	pbuf = isakmp_parse(msg);
+	if (pbuf == NULL)
+		goto end;
+
+	iph1->pl_hash = NULL;
+
+	for (pa = (struct isakmp_parse_t *)pbuf->v;
+	     pa->type != ISAKMP_NPTYPE_NONE;
+	     pa++) {
+
+		switch (pa->type) {
+		case ISAKMP_NPTYPE_ID:
+			if (isakmp_p2ph(&iph1->id_p, pa->ptr) < 0)
+				goto end;
+			break;
+		case ISAKMP_NPTYPE_HASH:
+			iph1->pl_hash = (struct isakmp_pl_hash *)pa->ptr;
+			break;
+		case ISAKMP_NPTYPE_CERT:
+			if (oakley_savecert(iph1, pa->ptr) < 0)
+				goto end;
+			break;
+		case ISAKMP_NPTYPE_SIG:
+			if (isakmp_p2ph(&iph1->sig_p, pa->ptr) < 0)
+				goto end;
+			break;
+#ifdef HAVE_GSSAPI
+		case ISAKMP_NPTYPE_GSS:
+			if (isakmp_p2ph(&gsstoken, pa->ptr) < 0)
+				goto end;
+			gssapi_save_received_token(iph1, gsstoken);
+			break;
+#endif
+		case ISAKMP_NPTYPE_VID:
+			(void)check_vendorid(pa->ptr);
+			break;
+		case ISAKMP_NPTYPE_N:
+			isakmp_check_notify(pa->ptr, iph1);
+			break;
+		default:
+			/* don't send information, see ident_r1recv() */
+			plog(LLV_ERROR, LOCATION, iph1->remote,
+				"ignore the packet, "
+				"received unexpecting payload type %d.\n",
+				pa->type);
+			goto end;
+		}
+	}
+
+	/* payload existency check */
+
+	/* verify identifier */
+	if (ipsecdoi_checkid1(iph1) != 0) {
+		plog(LLV_ERROR, LOCATION, iph1->remote,
+			"invalid ID payload.\n");
+		goto end;
+	}
+
+	/* validate authentication value */
+#ifdef HAVE_GSSAPI
+	if (gsstoken == NULL) {
+#endif
+		type = oakley_validate_auth(iph1);
+		if (type != 0) {
+			if (type == -1) {
+				/* msg printed inner oakley_validate_auth() */
+				goto end;
+			}
+			EVT_PUSH(iph1->local, iph1->remote, 
+			    EVTT_PEERPH1AUTH_FAILED, NULL);
+			isakmp_info_send_n1(iph1, type, NULL);
+			goto end;
+		}
+#ifdef HAVE_GSSAPI
+	}
+#endif
+
+	/*
+	 * XXX: Should we do compare two addresses, ph1handle's and ID
+	 * payload's.
+	 */
+
+	plog(LLV_DEBUG, LOCATION, iph1->remote, "peer's ID:");
+	plogdump(LLV_DEBUG, iph1->id_p->v, iph1->id_p->l);
+
+	/* see handler.h about IV synchronization. */
+	memcpy(iph1->ivm->iv->v, iph1->ivm->ive->v, iph1->ivm->ive->l);
+
+	/*
+	 * If we got a GSS token, we need to this roundtrip again.
+	 */
+#ifdef HAVE_GSSAPI
+	iph1->status = gsstoken != 0 ? PHASE1ST_MSG3RECEIVED : 
+	    PHASE1ST_MSG4RECEIVED;
+#else
+	iph1->status = PHASE1ST_MSG4RECEIVED;
+#endif
+
+	error = 0;
+
+end:
+	if (pbuf)
+		vfree(pbuf);
+	if (msg)
+		vfree(msg);
+#ifdef HAVE_GSSAPI
+	if (gsstoken)
+		vfree(gsstoken);
+#endif
+
+	if (error) {
+		VPTRINIT(iph1->id_p);
+		oakley_delcert(iph1->cert_p);
+		iph1->cert_p = NULL;
+		oakley_delcert(iph1->crl_p);
+		iph1->crl_p = NULL;
+		VPTRINIT(iph1->sig_p);
+	}
+
+	return error;
+}
+
+/*
+ * status update and establish isakmp sa.
+ */
+int
+ident_i4send(iph1, msg)
+	struct ph1handle *iph1;
+	vchar_t *msg;
+{
+	int error = -1;
+
+	/* validity check */
+	if (iph1->status != PHASE1ST_MSG4RECEIVED) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"status mismatched %d.\n", iph1->status);
+		goto end;
+	}
+
+	/* see handler.h about IV synchronization. */
+	memcpy(iph1->ivm->iv->v, iph1->ivm->ive->v, iph1->ivm->iv->l);
+
+	iph1->status = PHASE1ST_ESTABLISHED;
+
+	error = 0;
+
+end:
+	return error;
+}
+
+/*
+ * receive from initiator
+ * 	psk: HDR, SA
+ * 	sig: HDR, SA
+ * 	rsa: HDR, SA
+ * 	rev: HDR, SA
+ */
+int
+ident_r1recv(iph1, msg)
+	struct ph1handle *iph1;
+	vchar_t *msg;
+{
+	vchar_t *pbuf = NULL;
+	struct isakmp_parse_t *pa;
+	int error = -1;
+	int vid_numeric;
+
+	/* validity check */
+	if (iph1->status != PHASE1ST_START) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"status mismatched %d.\n", iph1->status);
+		goto end;
+	}
+
+	/* validate the type of next payload */
+	/*
+	 * NOTE: XXX even if multiple VID, we'll silently ignore those.
+	 */
+	pbuf = isakmp_parse(msg);
+	if (pbuf == NULL)
+		goto end;
+	pa = (struct isakmp_parse_t *)pbuf->v;
+
+	/* check the position of SA payload */
+	if (pa->type != ISAKMP_NPTYPE_SA) {
+		plog(LLV_ERROR, LOCATION, iph1->remote,
+			"received invalid next payload type %d, "
+			"expecting %d.\n",
+			pa->type, ISAKMP_NPTYPE_SA);
+		goto end;
+	}
+	if (isakmp_p2ph(&iph1->sa, pa->ptr) < 0)
+		goto end;
+	pa++;
+
+	for (/*nothing*/;
+	     pa->type != ISAKMP_NPTYPE_NONE;
+	     pa++) {
+
+		switch (pa->type) {
+		case ISAKMP_NPTYPE_VID:
+			vid_numeric = check_vendorid(pa->ptr);
+#ifdef ENABLE_NATT
+			if (iph1->rmconf->nat_traversal && natt_vendorid(vid_numeric))
+				natt_handle_vendorid(iph1, vid_numeric);
+#endif
+#ifdef ENABLE_FRAG
+			if ((vid_numeric == VENDORID_FRAG) &&
+			    (vendorid_frag_cap(pa->ptr) & VENDORID_FRAG_IDENT))
+				iph1->frag = 1;
+#endif   
+#ifdef ENABLE_HYBRID
+			switch (vid_numeric) {
+			case VENDORID_XAUTH:
+				iph1->mode_cfg->flags |=
+				    ISAKMP_CFG_VENDORID_XAUTH;
+				break;
+		
+			case VENDORID_UNITY:
+				iph1->mode_cfg->flags |=
+				    ISAKMP_CFG_VENDORID_UNITY;
+				break;
+	
+			default:  
+				break;
+			}
+#endif
+#ifdef ENABLE_DPD
+			if (vid_numeric == VENDORID_DPD && iph1->rmconf->dpd)
+				iph1->dpd_support=1;
+#endif
+			break;
+		default:
+			/*
+			 * We don't send information to the peer even
+			 * if we received malformed packet.  Because we
+			 * can't distinguish the malformed packet and
+			 * the re-sent packet.  And we do same behavior
+			 * when we expect encrypted packet.
+			 */
+			plog(LLV_ERROR, LOCATION, iph1->remote,
+				"ignore the packet, "
+				"received unexpecting payload type %d.\n",
+				pa->type);
+			goto end;
+		}
+	}
+
+#ifdef ENABLE_NATT
+	if (NATT_AVAILABLE(iph1))
+		plog(LLV_INFO, LOCATION, iph1->remote,
+		     "Selected NAT-T version: %s\n",
+		     vid_string_by_id(iph1->natt_options->version));
+#endif
+
+	/* check SA payload and set approval SA for use */
+	if (ipsecdoi_checkph1proposal(iph1->sa, iph1) < 0) {
+		plog(LLV_ERROR, LOCATION, iph1->remote,
+			"failed to get valid proposal.\n");
+		/* XXX send information */
+		goto end;
+	}
+
+	iph1->status = PHASE1ST_MSG1RECEIVED;
+
+	error = 0;
+
+end:
+	if (pbuf)
+		vfree(pbuf);
+	if (error) {
+		VPTRINIT(iph1->sa);
+	}
+
+	return error;
+}
+
+/*
+ * send to initiator
+ * 	psk: HDR, SA
+ * 	sig: HDR, SA
+ * 	rsa: HDR, SA
+ * 	rev: HDR, SA
+ */
+int
+ident_r1send(iph1, msg)
+	struct ph1handle *iph1;
+	vchar_t *msg;
+{
+	struct payload_list *plist = NULL;
+	int error = -1;
+	vchar_t *gss_sa = NULL;
+#ifdef HAVE_GSSAPI
+	int free_gss_sa = 0;
+#endif
+#ifdef ENABLE_NATT
+	vchar_t *vid_natt = NULL;
+#endif
+#ifdef ENABLE_HYBRID
+        vchar_t *vid_xauth = NULL;
+        vchar_t *vid_unity = NULL;
+#endif  
+#ifdef ENABLE_DPD
+	vchar_t *vid_dpd = NULL;
+#endif
+#ifdef ENABLE_FRAG          
+	vchar_t *vid_frag = NULL;
+#endif 
+
+	/* validity check */
+	if (iph1->status != PHASE1ST_MSG1RECEIVED) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"status mismatched %d.\n", iph1->status);
+		goto end;
+	}
+
+	/* set responder's cookie */
+	isakmp_newcookie((caddr_t)&iph1->index.r_ck, iph1->remote, iph1->local);
+
+#ifdef HAVE_GSSAPI
+	if (iph1->approval->gssid != NULL) {
+		gss_sa = ipsecdoi_setph1proposal(iph1->approval);
+		if (gss_sa != iph1->sa_ret)
+			free_gss_sa = 1;
+	} else 
+#endif
+		gss_sa = iph1->sa_ret;
+
+	/* set SA payload to reply */
+	plist = isakmp_plist_append(plist, gss_sa, ISAKMP_NPTYPE_SA);
+
+#ifdef ENABLE_HYBRID
+	if (iph1->mode_cfg->flags & ISAKMP_CFG_VENDORID_XAUTH) {
+		plog (LLV_INFO, LOCATION, NULL, "Adding xauth VID payload.\n");
+		if ((vid_xauth = set_vendorid(VENDORID_XAUTH)) == NULL) {
+			plog(LLV_ERROR, LOCATION, NULL,
+			    "Cannot create Xauth vendor ID\n");
+			goto end;
+		}
+		plist = isakmp_plist_append(plist,
+		    vid_xauth, ISAKMP_NPTYPE_VID);
+	}
+
+	if (iph1->mode_cfg->flags & ISAKMP_CFG_VENDORID_UNITY) {
+		if ((vid_unity = set_vendorid(VENDORID_UNITY)) == NULL) {
+			plog(LLV_ERROR, LOCATION, NULL,
+			    "Cannot create Unity vendor ID\n");
+			goto end;
+		}
+		plist = isakmp_plist_append(plist,
+		    vid_unity, ISAKMP_NPTYPE_VID);
+	}
+#endif
+#ifdef ENABLE_NATT
+	/* Has the peer announced NAT-T? */
+	if (NATT_AVAILABLE(iph1))
+		vid_natt = set_vendorid(iph1->natt_options->version);
+
+	if (vid_natt)
+		plist = isakmp_plist_append(plist, vid_natt, ISAKMP_NPTYPE_VID);
+#endif
+#ifdef ENABLE_DPD
+	/* XXX only send DPD VID if remote sent it ? */
+	if(iph1->rmconf->dpd){
+		vid_dpd = set_vendorid(VENDORID_DPD);
+		if (vid_dpd != NULL)
+			plist = isakmp_plist_append(plist, vid_dpd, ISAKMP_NPTYPE_VID);
+	}
+#endif
+#ifdef ENABLE_FRAG
+	if (iph1->frag) {
+		vid_frag = set_vendorid(VENDORID_FRAG);
+		if (vid_frag != NULL)
+			vid_frag = isakmp_frag_addcap(vid_frag,
+			    VENDORID_FRAG_IDENT);
+		if (vid_frag == NULL)
+			plog(LLV_ERROR, LOCATION, NULL,
+			    "Frag vendorID construction failed\n");
+		else
+			plist = isakmp_plist_append(plist, 
+			     vid_frag, ISAKMP_NPTYPE_VID);
+	}
+#endif
+
+	iph1->sendbuf = isakmp_plist_set_all (&plist, iph1);
+
+#ifdef HAVE_PRINT_ISAKMP_C
+	isakmp_printpacket(iph1->sendbuf, iph1->local, iph1->remote, 0);
+#endif
+
+	/* send the packet, add to the schedule to resend */
+	iph1->retry_counter = iph1->rmconf->retry_counter;
+	if (isakmp_ph1resend(iph1) == -1) {
+		goto end;
+	}
+
+	/* the sending message is added to the received-list. */
+	if (add_recvdpkt(iph1->remote, iph1->local, iph1->sendbuf, msg) == -1) {
+		plog(LLV_ERROR , LOCATION, NULL,
+			"failed to add a response packet to the tree.\n");
+		goto end;
+	}
+
+	iph1->status = PHASE1ST_MSG1SENT;
+
+	error = 0;
+
+end:
+#ifdef HAVE_GSSAPI
+	if (free_gss_sa)
+		vfree(gss_sa);
+#endif
+#ifdef ENABLE_NATT
+	if (vid_natt)
+		vfree(vid_natt);
+#endif
+#ifdef ENABLE_HYBRID
+	if (vid_xauth != NULL)
+		vfree(vid_xauth);
+	if (vid_unity != NULL)
+		vfree(vid_unity);
+#endif
+#ifdef ENABLE_DPD
+	if (vid_dpd != NULL)
+		vfree(vid_dpd);
+#endif
+#ifdef ENABLE_FRAG
+	if (vid_frag != NULL)
+		vfree(vid_frag);
+#endif
+
+	return error;
+}
+
+/*
+ * receive from initiator
+ * 	psk: HDR, KE, Ni
+ * 	sig: HDR, KE, Ni
+ *   gssapi: HDR, KE, Ni, GSSi
+ * 	rsa: HDR, KE, [ HASH(1), ] <IDi1_b>PubKey_r, <Ni_b>PubKey_r
+ * 	rev: HDR, [ HASH(1), ] <Ni_b>Pubkey_r, <KE_b>Ke_i,
+ * 	          <IDi1_b>Ke_i, [<<Cert-I_b>Ke_i]
+ */
+int
+ident_r2recv(iph1, msg)
+	struct ph1handle *iph1;
+	vchar_t *msg;
+{
+	vchar_t *pbuf = NULL;
+	struct isakmp_parse_t *pa;
+	int error = -1;
+#ifdef HAVE_GSSAPI
+	vchar_t *gsstoken = NULL;
+#endif
+#ifdef ENABLE_NATT
+	int natd_seq = 0;
+#endif
+
+	/* validity check */
+	if (iph1->status != PHASE1ST_MSG1SENT) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"status mismatched %d.\n", iph1->status);
+		goto end;
+	}
+
+	/* validate the type of next payload */
+	pbuf = isakmp_parse(msg);
+	if (pbuf == NULL)
+		goto end;
+
+	for (pa = (struct isakmp_parse_t *)pbuf->v;
+	     pa->type != ISAKMP_NPTYPE_NONE;
+	     pa++) {
+		switch (pa->type) {
+		case ISAKMP_NPTYPE_KE:
+			if (isakmp_p2ph(&iph1->dhpub_p, pa->ptr) < 0)
+				goto end;
+			break;
+		case ISAKMP_NPTYPE_NONCE:
+			if (isakmp_p2ph(&iph1->nonce_p, pa->ptr) < 0)
+				goto end;
+			break;
+		case ISAKMP_NPTYPE_VID:
+			(void)check_vendorid(pa->ptr);
+			break;
+		case ISAKMP_NPTYPE_CR:
+			plog(LLV_WARNING, LOCATION, iph1->remote,
+				"CR received, ignore it. "
+				"It should be in other exchange.\n");
+			break;
+#ifdef HAVE_GSSAPI
+		case ISAKMP_NPTYPE_GSS:
+			if (isakmp_p2ph(&gsstoken, pa->ptr) < 0)
+				goto end;
+			gssapi_save_received_token(iph1, gsstoken);
+			break;
+#endif
+
+#ifdef ENABLE_NATT
+		case ISAKMP_NPTYPE_NATD_DRAFT:
+		case ISAKMP_NPTYPE_NATD_RFC:
+			if (NATT_AVAILABLE(iph1) && iph1->natt_options != NULL &&
+				pa->type == iph1->natt_options->payload_nat_d)
+			{
+				vchar_t *natd_received = NULL;
+				int natd_verified;
+				
+				if (isakmp_p2ph (&natd_received, pa->ptr) < 0)
+					goto end;
+				
+				if (natd_seq == 0)
+					iph1->natt_flags |= NAT_DETECTED;
+				
+				natd_verified = natt_compare_addr_hash (iph1,
+					natd_received, natd_seq++);
+				
+				plog (LLV_INFO, LOCATION, NULL, "NAT-D payload #%d %s\n",
+					natd_seq - 1,
+					natd_verified ? "verified" : "doesn't match");
+				
+				vfree (natd_received);
+				break;
+			}
+			/* passthrough to default... */
+#endif
+
+		default:
+			/* don't send information, see ident_r1recv() */
+			plog(LLV_ERROR, LOCATION, iph1->remote,
+				"ignore the packet, "
+				"received unexpecting payload type %d.\n",
+				pa->type);
+			goto end;
+		}
+	}
+
+#ifdef ENABLE_NATT
+	if (NATT_AVAILABLE(iph1))
+		plog (LLV_INFO, LOCATION, NULL, "NAT %s %s%s\n",
+		      iph1->natt_flags & NAT_DETECTED ? 
+		      		"detected:" : "not detected",
+		      iph1->natt_flags & NAT_DETECTED_ME ? "ME " : "",
+		      iph1->natt_flags & NAT_DETECTED_PEER ? "PEER" : "");
+#endif
+
+	/* payload existency check */
+	if (iph1->dhpub_p == NULL || iph1->nonce_p == NULL) {
+		plog(LLV_ERROR, LOCATION, iph1->remote,
+			"few isakmp message received.\n");
+		goto end;
+	}
+
+	iph1->status = PHASE1ST_MSG2RECEIVED;
+
+	error = 0;
+
+end:
+	if (pbuf)
+		vfree(pbuf);
+#ifdef HAVE_GSSAPI
+	if (gsstoken)
+		vfree(gsstoken);
+#endif
+
+	if (error) {
+		VPTRINIT(iph1->dhpub_p);
+		VPTRINIT(iph1->nonce_p);
+		VPTRINIT(iph1->id_p);
+	}
+
+	return error;
+}
+
+/*
+ * send to initiator
+ * 	psk: HDR, KE, Nr
+ * 	sig: HDR, KE, Nr [, CR ]
+ *   gssapi: HDR, KE, Nr, GSSr
+ * 	rsa: HDR, KE, <IDr1_b>PubKey_i, <Nr_b>PubKey_i
+ * 	rev: HDR, <Nr_b>PubKey_i, <KE_b>Ke_r, <IDr1_b>Ke_r,
+ */
+int
+ident_r2send(iph1, msg)
+	struct ph1handle *iph1;
+	vchar_t *msg;
+{
+	int error = -1;
+
+	/* validity check */
+	if (iph1->status != PHASE1ST_MSG2RECEIVED) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"status mismatched %d.\n", iph1->status);
+		goto end;
+	}
+
+	/* generate DH public value */
+	if (oakley_dh_generate(iph1->approval->dhgrp,
+				&iph1->dhpub, &iph1->dhpriv) < 0)
+		goto end;
+
+	/* generate NONCE value */
+	iph1->nonce = eay_set_random(iph1->rmconf->nonce_size);
+	if (iph1->nonce == NULL)
+		goto end;
+
+#ifdef HAVE_GSSAPI
+	if (AUTHMETHOD(iph1) == OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB)
+		gssapi_get_rtoken(iph1, NULL);
+#endif
+
+	/* create HDR;KE;NONCE payload */
+	iph1->sendbuf = ident_ir2mx(iph1);
+	if (iph1->sendbuf == NULL)
+		goto end;
+
+#ifdef HAVE_PRINT_ISAKMP_C
+	isakmp_printpacket(iph1->sendbuf, iph1->local, iph1->remote, 0);
+#endif
+
+	/* send the packet, add to the schedule to resend */
+	iph1->retry_counter = iph1->rmconf->retry_counter;
+	if (isakmp_ph1resend(iph1) == -1)
+		goto end;
+
+	/* the sending message is added to the received-list. */
+	if (add_recvdpkt(iph1->remote, iph1->local, iph1->sendbuf, msg) == -1) {
+		plog(LLV_ERROR , LOCATION, NULL,
+			"failed to add a response packet to the tree.\n");
+		goto end;
+	}
+
+	/* compute sharing secret of DH */
+	if (oakley_dh_compute(iph1->approval->dhgrp, iph1->dhpub,
+				iph1->dhpriv, iph1->dhpub_p, &iph1->dhgxy) < 0)
+		goto end;
+
+	/* generate SKEYIDs & IV & final cipher key */
+	if (oakley_skeyid(iph1) < 0)
+		goto end;
+	if (oakley_skeyid_dae(iph1) < 0)
+		goto end;
+	if (oakley_compute_enckey(iph1) < 0)
+		goto end;
+	if (oakley_newiv(iph1) < 0)
+		goto end;
+
+	iph1->status = PHASE1ST_MSG2SENT;
+
+	error = 0;
+
+end:
+	return error;
+}
+
+/*
+ * receive from initiator
+ * 	psk: HDR*, IDi1, HASH_I
+ * 	sig: HDR*, IDi1, [ CR, ] [ CERT, ] SIG_I
+ *   gssapi: HDR*, [ IDi1, ] < GSSi(n) | HASH_I >
+ * 	rsa: HDR*, HASH_I
+ * 	rev: HDR*, HASH_I
+ */
+int
+ident_r3recv(iph1, msg0)
+	struct ph1handle *iph1;
+	vchar_t *msg0;
+{
+	vchar_t *msg = NULL;
+	vchar_t *pbuf = NULL;
+	struct isakmp_parse_t *pa;
+	int error = -1;
+	int type;
+#ifdef HAVE_GSSAPI
+	vchar_t *gsstoken = NULL;
+#endif
+
+	/* validity check */
+	if (iph1->status != PHASE1ST_MSG2SENT) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"status mismatched %d.\n", iph1->status);
+		goto end;
+	}
+
+	/* decrypting */
+	if (!ISSET(((struct isakmp *)msg0->v)->flags, ISAKMP_FLAG_E)) {
+		plog(LLV_ERROR, LOCATION, iph1->remote,
+			"reject the packet, "
+			"expecting the packet encrypted.\n");
+		goto end;
+	}
+	msg = oakley_do_decrypt(iph1, msg0, iph1->ivm->iv, iph1->ivm->ive);
+	if (msg == NULL)
+		goto end;
+
+	/* validate the type of next payload */
+	pbuf = isakmp_parse(msg);
+	if (pbuf == NULL)
+		goto end;
+
+	iph1->pl_hash = NULL;
+
+	for (pa = (struct isakmp_parse_t *)pbuf->v;
+	     pa->type != ISAKMP_NPTYPE_NONE;
+	     pa++) {
+
+		switch (pa->type) {
+		case ISAKMP_NPTYPE_ID:
+			if (isakmp_p2ph(&iph1->id_p, pa->ptr) < 0)
+				goto end;
+			break;
+		case ISAKMP_NPTYPE_HASH:
+			iph1->pl_hash = (struct isakmp_pl_hash *)pa->ptr;
+			break;
+		case ISAKMP_NPTYPE_CR:
+			if (oakley_savecr(iph1, pa->ptr) < 0)
+				goto end;
+			break;
+		case ISAKMP_NPTYPE_CERT:
+			if (oakley_savecert(iph1, pa->ptr) < 0)
+				goto end;
+			break;
+		case ISAKMP_NPTYPE_SIG:
+			if (isakmp_p2ph(&iph1->sig_p, pa->ptr) < 0)
+				goto end;
+			break;
+#ifdef HAVE_GSSAPI
+		case ISAKMP_NPTYPE_GSS:
+			if (isakmp_p2ph(&gsstoken, pa->ptr) < 0)
+				goto end;
+			gssapi_save_received_token(iph1, gsstoken);
+			break;
+#endif
+		case ISAKMP_NPTYPE_VID:
+			(void)check_vendorid(pa->ptr);
+			break;
+		case ISAKMP_NPTYPE_N:
+			isakmp_check_notify(pa->ptr, iph1);
+			break;
+		default:
+			/* don't send information, see ident_r1recv() */
+			plog(LLV_ERROR, LOCATION, iph1->remote,
+				"ignore the packet, "
+				"received unexpecting payload type %d.\n",
+				pa->type);
+			goto end;
+		}
+	}
+
+	/* payload existency check */
+	/* XXX same as ident_i4recv(), should be merged. */
+    {
+	int ng = 0;
+
+	switch (AUTHMETHOD(iph1)) {
+	case OAKLEY_ATTR_AUTH_METHOD_PSKEY:
+#ifdef ENABLE_HYBRID
+	case OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_R:
+	case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_R:
+	case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_R:
+#endif
+		if (iph1->id_p == NULL || iph1->pl_hash == NULL)
+			ng++;
+		break;
+	case OAKLEY_ATTR_AUTH_METHOD_DSSSIG:
+	case OAKLEY_ATTR_AUTH_METHOD_RSASIG:
+#ifdef ENABLE_HYBRID
+	case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_R:
+	case OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_R:
+#endif
+		if (iph1->id_p == NULL || iph1->sig_p == NULL)
+			ng++;
+		break;
+	case OAKLEY_ATTR_AUTH_METHOD_RSAENC:
+	case OAKLEY_ATTR_AUTH_METHOD_RSAREV:
+#ifdef ENABLE_HYBRID
+	case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAENC_R:
+	case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAREV_R:
+#endif
+		if (iph1->pl_hash == NULL)
+			ng++;
+		break;
+#ifdef HAVE_GSSAPI
+	case OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB:
+		if (gsstoken == NULL && iph1->pl_hash == NULL)
+			ng++;
+		break;
+#endif
+	default:
+		plog(LLV_ERROR, LOCATION, iph1->remote,
+			"invalid authmethod %d why ?\n",
+			iph1->approval->authmethod);
+		goto end;
+	}
+	if (ng) {
+		plog(LLV_ERROR, LOCATION, iph1->remote,
+			"few isakmp message received.\n");
+		goto end;
+	}
+    }
+
+	/* verify identifier */
+	if (ipsecdoi_checkid1(iph1) != 0) {
+		plog(LLV_ERROR, LOCATION, iph1->remote,
+			"invalid ID payload.\n");
+		goto end;
+	}
+
+	/* validate authentication value */
+#ifdef HAVE_GSSAPI
+	if (gsstoken == NULL) {
+#endif
+		type = oakley_validate_auth(iph1);
+		if (type != 0) {
+			if (type == -1) {
+				/* msg printed inner oakley_validate_auth() */
+				goto end;
+			}
+			EVT_PUSH(iph1->local, iph1->remote, 
+			    EVTT_PEERPH1AUTH_FAILED, NULL);
+			isakmp_info_send_n1(iph1, type, NULL);
+			goto end;
+		}
+#ifdef HAVE_GSSAPI
+	}
+#endif
+
+	if (oakley_checkcr(iph1) < 0) {
+		/* Ignore this error in order to be interoperability. */
+		;
+	}
+
+	/*
+	 * XXX: Should we do compare two addresses, ph1handle's and ID
+	 * payload's.
+	 */
+
+	plog(LLV_DEBUG, LOCATION, iph1->remote, "peer's ID\n");
+	plogdump(LLV_DEBUG, iph1->id_p->v, iph1->id_p->l);
+
+	/* see handler.h about IV synchronization. */
+	memcpy(iph1->ivm->iv->v, iph1->ivm->ive->v, iph1->ivm->ive->l);
+
+#ifdef HAVE_GSSAPI
+	iph1->status = gsstoken != NULL ? PHASE1ST_MSG2RECEIVED :
+	    PHASE1ST_MSG3RECEIVED;
+#else
+	iph1->status = PHASE1ST_MSG3RECEIVED;
+#endif
+
+	error = 0;
+
+end:
+	if (pbuf)
+		vfree(pbuf);
+	if (msg)
+		vfree(msg);
+#ifdef HAVE_GSSAPI
+	if (gsstoken)
+		vfree(gsstoken);
+#endif
+
+	if (error) {
+		VPTRINIT(iph1->id_p);
+		oakley_delcert(iph1->cert_p);
+		iph1->cert_p = NULL;
+		oakley_delcert(iph1->crl_p);
+		iph1->crl_p = NULL;
+		VPTRINIT(iph1->sig_p);
+		oakley_delcert(iph1->cr_p);
+		iph1->cr_p = NULL;
+	}
+
+	return error;
+}
+
+/*
+ * send to initiator
+ * 	psk: HDR*, IDr1, HASH_R
+ * 	sig: HDR*, IDr1, [ CERT, ] SIG_R
+ *   gssapi: HDR*, IDr1, < GSSr(n) | HASH_R >
+ * 	rsa: HDR*, HASH_R
+ * 	rev: HDR*, HASH_R
+ */
+int
+ident_r3send(iph1, msg)
+	struct ph1handle *iph1;
+	vchar_t *msg;
+{
+	int error = -1;
+	int dohash = 1;
+#ifdef HAVE_GSSAPI
+	int len;
+#endif
+
+	/* validity check */
+	if (iph1->status != PHASE1ST_MSG3RECEIVED) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"status mismatched %d.\n", iph1->status);
+		goto end;
+	}
+
+	/* make ID payload into isakmp status */
+	if (ipsecdoi_setid1(iph1) < 0)
+		goto end;
+
+#ifdef HAVE_GSSAPI
+	if (AUTHMETHOD(iph1) == OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB &&
+	    gssapi_more_tokens(iph1)) {
+		gssapi_get_rtoken(iph1, &len);
+		if (len != 0)
+			dohash = 0;
+	}
+#endif
+
+	if (dohash) {
+		/* generate HASH to send */
+		plog(LLV_DEBUG, LOCATION, NULL, "generate HASH_R\n");
+		iph1->hash = oakley_ph1hash_common(iph1, GENERATE);
+		if (iph1->hash == NULL)
+			goto end;
+	} else
+		iph1->hash = NULL;
+
+	/* set encryption flag */
+	iph1->flags |= ISAKMP_FLAG_E;
+
+	/* create HDR;ID;HASH payload */
+	iph1->sendbuf = ident_ir3mx(iph1);
+	if (iph1->sendbuf == NULL)
+		goto end;
+
+	/* send HDR;ID;HASH to responder */
+	if (isakmp_send(iph1, iph1->sendbuf) < 0)
+		goto end;
+
+	/* the sending message is added to the received-list. */
+	if (add_recvdpkt(iph1->remote, iph1->local, iph1->sendbuf, msg) == -1) {
+		plog(LLV_ERROR , LOCATION, NULL,
+			"failed to add a response packet to the tree.\n");
+		goto end;
+	}
+
+	/* see handler.h about IV synchronization. */
+	memcpy(iph1->ivm->ive->v, iph1->ivm->iv->v, iph1->ivm->iv->l);
+
+	iph1->status = PHASE1ST_ESTABLISHED;
+
+	error = 0;
+
+end:
+
+	return error;
+}
+
+/*
+ * This is used in main mode for:
+ * initiator's 3rd exchange send to responder
+ * 	psk: HDR, KE, Ni
+ * 	sig: HDR, KE, Ni
+ * 	rsa: HDR, KE, [ HASH(1), ] <IDi1_b>PubKey_r, <Ni_b>PubKey_r
+ * 	rev: HDR, [ HASH(1), ] <Ni_b>Pubkey_r, <KE_b>Ke_i,
+ * 	          <IDi1_b>Ke_i, [<<Cert-I_b>Ke_i]
+ * responders 2nd exchnage send to initiator
+ * 	psk: HDR, KE, Nr
+ * 	sig: HDR, KE, Nr [, CR ]
+ * 	rsa: HDR, KE, <IDr1_b>PubKey_i, <Nr_b>PubKey_i
+ * 	rev: HDR, <Nr_b>PubKey_i, <KE_b>Ke_r, <IDr1_b>Ke_r,
+ */
+static vchar_t *
+ident_ir2mx(iph1)
+	struct ph1handle *iph1;
+{
+	vchar_t *buf = 0;
+	struct payload_list *plist = NULL;
+	int need_cr = 0;
+	vchar_t *cr = NULL;
+	vchar_t *vid = NULL;
+	int error = -1;
+#ifdef HAVE_GSSAPI
+	vchar_t *gsstoken = NULL;
+#endif
+#ifdef ENABLE_NATT
+	vchar_t *natd[2] = { NULL, NULL };
+#endif
+
+	/* create CR if need */
+	if (iph1->side == RESPONDER
+	 && iph1->rmconf->send_cr
+	 && oakley_needcr(iph1->approval->authmethod)
+	 && iph1->rmconf->peerscertfile == NULL) {
+		need_cr = 1;
+		cr = oakley_getcr(iph1);
+		if (cr == NULL) {
+			plog(LLV_ERROR, LOCATION, NULL,
+				"failed to get cr buffer.\n");
+			goto end;
+		}
+	}
+
+#ifdef HAVE_GSSAPI
+	if (AUTHMETHOD(iph1) == OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB)
+		gssapi_get_token_to_send(iph1, &gsstoken);
+#endif
+
+	/* create isakmp KE payload */
+	plist = isakmp_plist_append(plist, iph1->dhpub, ISAKMP_NPTYPE_KE);
+
+	/* create isakmp NONCE payload */
+	plist = isakmp_plist_append(plist, iph1->nonce, ISAKMP_NPTYPE_NONCE);
+
+#ifdef HAVE_GSSAPI
+	if (AUTHMETHOD(iph1) == OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB)
+		plist = isakmp_plist_append(plist, gsstoken, ISAKMP_NPTYPE_GSS);
+#endif
+
+	/* append vendor id, if needed */
+	if (vid)
+		plist = isakmp_plist_append(plist, vid, ISAKMP_NPTYPE_VID);
+
+	/* create isakmp CR payload if needed */
+	if (need_cr)
+		plist = isakmp_plist_append(plist, cr, ISAKMP_NPTYPE_CR);
+
+#ifdef ENABLE_NATT
+	/* generate and append NAT-D payloads */
+	if (NATT_AVAILABLE(iph1) && iph1->status == PHASE1ST_MSG2RECEIVED)
+	{
+		if ((natd[0] = natt_hash_addr (iph1, iph1->remote)) == NULL) {
+			plog(LLV_ERROR, LOCATION, NULL,
+				"NAT-D hashing failed for %s\n", saddr2str(iph1->remote));
+			goto end;
+		}
+
+		if ((natd[1] = natt_hash_addr (iph1, iph1->local)) == NULL) {
+			plog(LLV_ERROR, LOCATION, NULL,
+				"NAT-D hashing failed for %s\n", saddr2str(iph1->local));
+			goto end;
+		}
+
+		plog (LLV_INFO, LOCATION, NULL, "Adding remote and local NAT-D payloads.\n");
+		plist = isakmp_plist_append(plist, natd[0], iph1->natt_options->payload_nat_d);
+		plist = isakmp_plist_append(plist, natd[1], iph1->natt_options->payload_nat_d);
+	}
+#endif
+	
+	buf = isakmp_plist_set_all (&plist, iph1);
+	
+	error = 0;
+
+end:
+	if (error && buf != NULL) {
+		vfree(buf);
+		buf = NULL;
+	}
+	if (cr)
+		vfree(cr);
+#ifdef HAVE_GSSAPI
+	if (gsstoken)
+		vfree(gsstoken);
+#endif
+	if (vid)
+		vfree(vid);
+
+#ifdef ENABLE_NATT
+	if (natd[0])
+		vfree(natd[0]);
+	if (natd[1])
+		vfree(natd[1]);
+#endif
+
+	return buf;
+}
+
+/*
+ * This is used in main mode for:
+ * initiator's 4th exchange send to responder
+ * 	psk: HDR*, IDi1, HASH_I
+ * 	sig: HDR*, IDi1, [ CR, ] [ CERT, ] SIG_I
+ *   gssapi: HDR*, [ IDi1, ] < GSSi(n) | HASH_I >
+ * 	rsa: HDR*, HASH_I
+ * 	rev: HDR*, HASH_I
+ * responders 3rd exchnage send to initiator
+ * 	psk: HDR*, IDr1, HASH_R
+ * 	sig: HDR*, IDr1, [ CERT, ] SIG_R
+ *   gssapi: HDR*, [ IDr1, ] < GSSr(n) | HASH_R >
+ * 	rsa: HDR*, HASH_R
+ * 	rev: HDR*, HASH_R
+ */
+static vchar_t *
+ident_ir3mx(iph1)
+	struct ph1handle *iph1;
+{
+	struct payload_list *plist = NULL;
+	vchar_t *buf = NULL, *new = NULL;
+	int need_cr = 0;
+	int need_cert = 0;
+	vchar_t *cr = NULL;
+	int error = -1;
+#ifdef HAVE_GSSAPI
+	int nptype;
+	vchar_t *gsstoken = NULL;
+	vchar_t *gsshash = NULL;
+#endif
+
+	switch (AUTHMETHOD(iph1)) {
+	case OAKLEY_ATTR_AUTH_METHOD_PSKEY:
+#ifdef ENABLE_HYBRID
+	case FICTIVE_AUTH_METHOD_XAUTH_PSKEY_I:
+	case OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_R:
+	case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_I:
+	case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_I:
+#endif
+		/* create isakmp ID payload */
+		plist = isakmp_plist_append(plist, iph1->id, ISAKMP_NPTYPE_ID);
+
+		/* create isakmp HASH payload */
+		plist = isakmp_plist_append(plist, iph1->hash, ISAKMP_NPTYPE_HASH);
+		break;
+	case OAKLEY_ATTR_AUTH_METHOD_DSSSIG:
+	case OAKLEY_ATTR_AUTH_METHOD_RSASIG:
+#ifdef ENABLE_HYBRID
+	case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_R:
+	case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_R:
+	case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_I:
+	case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_R:
+	case OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_I:
+	case OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_R:
+#endif 
+		if (oakley_getmycert(iph1) < 0)
+			goto end;
+
+		if (oakley_getsign(iph1) < 0)
+			goto end;
+
+		/* create CR if need */
+		if (iph1->side == INITIATOR
+		 && iph1->rmconf->send_cr
+	 	 && oakley_needcr(iph1->approval->authmethod)
+		 && iph1->rmconf->peerscertfile == NULL) {
+			need_cr = 1;
+			cr = oakley_getcr(iph1);
+			if (cr == NULL) {
+				plog(LLV_ERROR, LOCATION, NULL,
+					"failed to get cr buffer.\n");
+				goto end;
+			}
+		}
+
+		if (iph1->cert != NULL && iph1->rmconf->send_cert)
+			need_cert = 1;
+
+		/* add ID payload */
+		plist = isakmp_plist_append(plist, iph1->id, ISAKMP_NPTYPE_ID);
+
+		/* add CERT payload if there */
+		if (need_cert)
+			plist = isakmp_plist_append(plist, iph1->cert->pl, ISAKMP_NPTYPE_CERT);
+		/* add SIG payload */
+		plist = isakmp_plist_append(plist, iph1->sig, ISAKMP_NPTYPE_SIG);
+
+		/* create isakmp CR payload */
+		if (need_cr)
+			plist = isakmp_plist_append(plist, cr, ISAKMP_NPTYPE_CR);
+		break;
+#ifdef HAVE_GSSAPI
+	case OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB:
+		if (iph1->hash != NULL) {
+			gsshash = gssapi_wraphash(iph1);
+			if (gsshash == NULL)
+				goto end;
+		} else {
+			gssapi_get_token_to_send(iph1, &gsstoken);
+		}
+
+		if (!gssapi_id_sent(iph1)) {
+			/* create isakmp ID payload */
+			plist = isakmp_plist_append(plist, iph1->id, ISAKMP_NPTYPE_ID);
+			gssapi_set_id_sent(iph1);
+		}
+
+		if (iph1->hash != NULL)
+			/* create isakmp HASH payload */
+			plist = isakmp_plist_append(plist, gsshash, ISAKMP_NPTYPE_HASH);
+		else
+			plist = isakmp_plist_append(plist, gsstoken, ISAKMP_NPTYPE_GSS);
+		break;
+#endif
+	case OAKLEY_ATTR_AUTH_METHOD_RSAENC:
+	case OAKLEY_ATTR_AUTH_METHOD_RSAREV:
+#ifdef ENABLE_HYBRID
+	case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAENC_I:
+	case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAENC_R:
+	case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAREV_I:
+	case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAREV_R:
+#endif
+		plog(LLV_ERROR, LOCATION, NULL,
+			"not supported authentication type %d\n",
+			iph1->approval->authmethod);
+		goto end;
+	default:
+		plog(LLV_ERROR, LOCATION, NULL,
+			"invalid authentication type %d\n",
+			iph1->approval->authmethod);
+		goto end;
+	}
+
+	buf = isakmp_plist_set_all (&plist, iph1);
+	
+#ifdef HAVE_PRINT_ISAKMP_C
+	isakmp_printpacket(buf, iph1->local, iph1->remote, 1);
+#endif
+
+	/* encoding */
+	new = oakley_do_encrypt(iph1, buf, iph1->ivm->ive, iph1->ivm->iv);
+	if (new == NULL)
+		goto end;
+
+	vfree(buf);
+
+	buf = new;
+
+	error = 0;
+
+end:
+#ifdef HAVE_GSSAPI
+	if (gsstoken)
+		vfree(gsstoken);
+#endif
+	if (cr)
+		vfree(cr);
+	if (error && buf != NULL) {
+		vfree(buf);
+		buf = NULL;
+	}
+
+	return buf;
+}
diff --git a/src/racoon/isakmp_ident.h b/src/racoon/isakmp_ident.h
new file mode 100644
index 0000000..ea5595d
--- /dev/null
+++ b/src/racoon/isakmp_ident.h
@@ -0,0 +1,52 @@
+/*	$NetBSD: isakmp_ident.h,v 1.4 2006/09/09 16:22:09 manu Exp $	*/
+
+/* Id: isakmp_ident.h,v 1.3 2004/06/11 16:00:16 ludvigm Exp */
+
+/*
+ * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _ISAKMP_IDENT_H
+#define _ISAKMP_IDENT_H
+
+extern int ident_i1send __P((struct ph1handle *, vchar_t *));
+extern int ident_i2recv __P((struct ph1handle *, vchar_t *));
+extern int ident_i2send __P((struct ph1handle *, vchar_t *));
+extern int ident_i3recv __P((struct ph1handle *, vchar_t *));
+extern int ident_i3send __P((struct ph1handle *, vchar_t *));
+extern int ident_i4recv __P((struct ph1handle *, vchar_t *));
+extern int ident_i4send __P((struct ph1handle *, vchar_t *));
+
+extern int ident_r1recv __P((struct ph1handle *, vchar_t *));
+extern int ident_r1send __P((struct ph1handle *, vchar_t *));
+extern int ident_r2recv __P((struct ph1handle *, vchar_t *));
+extern int ident_r2send __P((struct ph1handle *, vchar_t *));
+extern int ident_r3recv __P((struct ph1handle *, vchar_t *));
+extern int ident_r3send __P((struct ph1handle *, vchar_t *));
+
+#endif /* _ISAKMP_IDENT_H */
diff --git a/src/racoon/isakmp_inf.c b/src/racoon/isakmp_inf.c
new file mode 100644
index 0000000..75f367d
--- /dev/null
+++ b/src/racoon/isakmp_inf.c
@@ -0,0 +1,1705 @@
+/*	$NetBSD: isakmp_inf.c,v 1.14.4.14 2008/07/11 08:08:42 tteras Exp $	*/
+
+/* Id: isakmp_inf.c,v 1.44 2006/05/06 20:45:52 manubsd Exp */
+
+/*
+ * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+
+#include <net/pfkeyv2.h>
+#include <netinet/in.h>
+#include <sys/queue.h>
+#include PATH_IPSEC_H
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#if TIME_WITH_SYS_TIME
+# include <sys/time.h>
+# include <time.h>
+#else
+# if HAVE_SYS_TIME_H
+#  include <sys/time.h>
+# else
+#  include <time.h>
+# endif
+#endif
+#ifdef ENABLE_HYBRID
+#include <resolv.h>
+#endif
+
+#include "libpfkey.h"
+
+#include "var.h"
+#include "vmbuf.h"
+#include "schedule.h"
+#include "str2val.h"
+#include "misc.h"
+#include "plog.h"
+#include "debug.h"
+
+#include "localconf.h"
+#include "remoteconf.h"
+#include "sockmisc.h"
+#include "handler.h"
+#include "policy.h"
+#include "proposal.h"
+#include "isakmp_var.h"
+#include "evt.h"
+#include "isakmp.h"
+#ifdef ENABLE_HYBRID
+#include "isakmp_xauth.h"
+#include "isakmp_unity.h"
+#include "isakmp_cfg.h" 
+#endif
+#include "isakmp_inf.h"
+#include "oakley.h"
+#include "ipsec_doi.h"
+#include "crypto_openssl.h"
+#include "pfkey.h"
+#include "policy.h"
+#include "algorithm.h"
+#include "proposal.h"
+#include "admin.h"
+#include "strnames.h"
+#ifdef ENABLE_NATT
+#include "nattraversal.h"
+#endif
+
+/* information exchange */
+static int isakmp_info_recv_n (struct ph1handle *, struct isakmp_pl_n *, u_int32_t, int);
+static int isakmp_info_recv_d (struct ph1handle *, struct isakmp_pl_d *, u_int32_t, int);
+
+#ifdef ENABLE_DPD
+static int isakmp_info_recv_r_u __P((struct ph1handle *,
+	struct isakmp_pl_ru *, u_int32_t));
+static int isakmp_info_recv_r_u_ack __P((struct ph1handle *,
+	struct isakmp_pl_ru *, u_int32_t));
+static void isakmp_info_send_r_u __P((void *));
+#endif
+
+static void purge_isakmp_spi __P((int, isakmp_index *, size_t));
+static void info_recv_initialcontact __P((struct ph1handle *));
+
+/* %%%
+ * Information Exchange
+ */
+/*
+ * receive Information
+ */
+int
+isakmp_info_recv(iph1, msg0)
+	struct ph1handle *iph1;
+	vchar_t *msg0;
+{
+	vchar_t *msg = NULL;
+	vchar_t *pbuf = NULL;
+	u_int32_t msgid = 0;
+	int error = -1;
+	struct isakmp *isakmp;
+	struct isakmp_gen *gen;
+	struct isakmp_parse_t *pa, *pap;
+	void *p;
+	vchar_t *hash, *payload;
+	struct isakmp_gen *nd;
+	u_int8_t np;
+	int encrypted;
+	int flag;
+
+	plog(LLV_DEBUG, LOCATION, NULL, "receive Information.\n");
+
+	encrypted = ISSET(((struct isakmp *)msg0->v)->flags, ISAKMP_FLAG_E);
+	msgid = ((struct isakmp *)msg0->v)->msgid;
+
+	/* Use new IV to decrypt Informational message. */
+	if (encrypted) {
+		struct isakmp_ivm *ivm;
+
+		if (iph1->ivm == NULL) {
+			plog(LLV_ERROR, LOCATION, NULL, "iph1->ivm == NULL\n");
+			return -1;
+		}
+
+		/* compute IV */
+		ivm = oakley_newiv2(iph1, ((struct isakmp *)msg0->v)->msgid);
+		if (ivm == NULL)
+			return -1;
+
+		msg = oakley_do_decrypt(iph1, msg0, ivm->iv, ivm->ive);
+		oakley_delivm(ivm);
+		if (msg == NULL)
+			return -1;
+
+	} else
+		msg = vdup(msg0);
+
+	/* Safety check */
+	if (msg->l < sizeof(*isakmp) + sizeof(*gen)) {
+		plog(LLV_ERROR, LOCATION, NULL, 
+			"ignore information because the "
+			"message is way too short - %zu byte(s).\n", msg->l);
+		goto end;
+	}
+
+	isakmp = (struct isakmp *)msg->v;
+	gen = (struct isakmp_gen *)((caddr_t)isakmp + sizeof(struct isakmp));
+	np = gen->np;
+
+	if (encrypted) {
+		if (isakmp->np != ISAKMP_NPTYPE_HASH) {
+			plog(LLV_ERROR, LOCATION, NULL,
+			    "ignore information because the"
+			    "message has no hash payload.\n");
+			goto end;
+		}
+
+		if (iph1->status != PHASE1ST_ESTABLISHED) {
+			plog(LLV_ERROR, LOCATION, NULL,
+			    "ignore information because ISAKMP-SA"
+			    "has not been established yet.\n");
+			goto end;
+		}
+		
+		/* Safety check */
+		if (msg->l < sizeof(*isakmp) + ntohs(gen->len) + sizeof(*nd)) {
+			plog(LLV_ERROR, LOCATION, NULL, 
+				"ignore information because the "
+				"message is too short - %zu byte(s).\n", msg->l);
+			goto end;
+		}
+
+		p = (caddr_t) gen + sizeof(struct isakmp_gen);
+		nd = (struct isakmp_gen *) ((caddr_t) gen + ntohs(gen->len));
+
+		/* nd length check */
+		if (ntohs(nd->len) > msg->l - (sizeof(struct isakmp) +
+		    ntohs(gen->len))) {
+			plog(LLV_ERROR, LOCATION, NULL,
+				 "too long payload length (broken message?)\n");
+			goto end;
+		}
+
+		if (ntohs(nd->len) < sizeof(*nd)) {
+			plog(LLV_ERROR, LOCATION, NULL,
+				"too short payload length (broken message?)\n");
+			goto end;
+		}
+
+		payload = vmalloc(ntohs(nd->len));
+		if (payload == NULL) {
+			plog(LLV_ERROR, LOCATION, NULL,
+			    "cannot allocate memory\n");
+			goto end;
+		}
+
+		memcpy(payload->v, (caddr_t) nd, ntohs(nd->len));
+
+		/* compute HASH */
+		hash = oakley_compute_hash1(iph1, isakmp->msgid, payload);
+		if (hash == NULL) {
+			plog(LLV_ERROR, LOCATION, NULL,
+			    "cannot compute hash\n");
+
+			vfree(payload);
+			goto end;
+		}
+		
+		if (ntohs(gen->len) - sizeof(struct isakmp_gen) != hash->l) {
+			plog(LLV_ERROR, LOCATION, NULL,
+			    "ignore information due to hash length mismatch\n");
+
+			vfree(hash);
+			vfree(payload);
+			goto end;
+		}
+
+		if (memcmp(p, hash->v, hash->l) != 0) {
+			plog(LLV_ERROR, LOCATION, NULL,
+			    "ignore information due to hash mismatch\n");
+
+			vfree(hash);
+			vfree(payload);
+			goto end;
+		}
+
+		plog(LLV_DEBUG, LOCATION, NULL, "hash validated.\n");
+
+		vfree(hash);
+		vfree(payload);
+	} else {
+		/* make sure the packet was encrypted after the beginning of phase 1. */
+		switch (iph1->etype) {
+		case ISAKMP_ETYPE_AGG:
+		case ISAKMP_ETYPE_BASE:
+		case ISAKMP_ETYPE_IDENT:
+			if ((iph1->side == INITIATOR && iph1->status < PHASE1ST_MSG3SENT)
+			 || (iph1->side == RESPONDER && iph1->status < PHASE1ST_MSG2SENT)) {
+				break;
+			}
+			/*FALLTHRU*/
+		default:
+			plog(LLV_ERROR, LOCATION, iph1->remote,
+				"%s message must be encrypted\n",
+				s_isakmp_nptype(np));
+			error = 0;
+			goto end;
+		}
+	}
+
+	if (!(pbuf = isakmp_parse(msg))) {
+		error = -1;
+		goto end;
+	}
+
+	error = 0;
+	for (pa = (struct isakmp_parse_t *)pbuf->v; pa->type; pa++) {
+		switch (pa->type) {
+		case ISAKMP_NPTYPE_HASH:
+			/* Handled above */
+			break;
+		case ISAKMP_NPTYPE_N:
+			error = isakmp_info_recv_n(iph1,
+				(struct isakmp_pl_n *)pa->ptr,
+				msgid, encrypted);
+			break;
+		case ISAKMP_NPTYPE_D:
+			error = isakmp_info_recv_d(iph1,
+				(struct isakmp_pl_d *)pa->ptr,
+				msgid, encrypted);
+			break;
+		case ISAKMP_NPTYPE_NONCE:
+			/* XXX to be 6.4.2 ike-01.txt */
+			/* XXX IV is to be synchronized. */
+			plog(LLV_ERROR, LOCATION, iph1->remote,
+				"ignore Acknowledged Informational\n");
+			break;
+		default:
+			/* don't send information, see isakmp_ident_r1() */
+			error = 0;
+			plog(LLV_ERROR, LOCATION, iph1->remote,
+				"reject the packet, "
+				"received unexpected payload type %s.\n",
+				s_isakmp_nptype(gen->np));
+		}
+		if(error < 0) {
+			break;
+		} else {
+			flag |= error;
+		}
+	}
+    end:
+	if (msg != NULL)
+		vfree(msg);
+	if (pbuf != NULL)
+		vfree(pbuf);
+	return error;
+}
+
+/*
+ * handling of Notification payload
+ */
+static int
+isakmp_info_recv_n(iph1, notify, msgid, encrypted)
+	struct ph1handle *iph1;
+	struct isakmp_pl_n *notify;
+	u_int32_t msgid;
+	int encrypted;
+{
+	u_int type;
+	vchar_t *pbuf;
+	vchar_t *ndata;
+	char *nraw;
+	size_t l;
+	char *spi;
+
+	type = ntohs(notify->type);
+
+	switch (type) {
+	case ISAKMP_NTYPE_CONNECTED:
+	case ISAKMP_NTYPE_RESPONDER_LIFETIME:
+	case ISAKMP_NTYPE_REPLAY_STATUS:
+#ifdef ENABLE_HYBRID
+	case ISAKMP_NTYPE_UNITY_HEARTBEAT:
+#endif
+		/* do something */
+		break;
+	case ISAKMP_NTYPE_INITIAL_CONTACT:
+		if (encrypted)
+			info_recv_initialcontact(iph1);
+			return 0;
+		break;
+#ifdef ENABLE_DPD
+	case ISAKMP_NTYPE_R_U_THERE:
+		if (encrypted)
+			return isakmp_info_recv_r_u(iph1,
+				(struct isakmp_pl_ru *)notify, msgid);
+		break;
+	case ISAKMP_NTYPE_R_U_THERE_ACK:
+		if (encrypted)
+			return isakmp_info_recv_r_u_ack(iph1,
+				(struct isakmp_pl_ru *)notify, msgid);
+		break;
+#endif
+	default:
+	    {
+		/* XXX there is a potential of dos attack. */
+		if(type >= ISAKMP_NTYPE_MINERROR &&
+		   type <= ISAKMP_NTYPE_MAXERROR) {
+			if (msgid == 0) {
+				/* don't think this realy deletes ph1 ? */
+				plog(LLV_ERROR, LOCATION, iph1->remote,
+					"delete phase1 handle.\n");
+				return -1;
+			} else {
+				if (getph2bymsgid(iph1, msgid) == NULL) {
+					plog(LLV_ERROR, LOCATION, iph1->remote,
+						"fatal %s notify messsage, "
+						"phase1 should be deleted.\n",
+						s_isakmp_notify_msg(type));
+				} else {
+					plog(LLV_ERROR, LOCATION, iph1->remote,
+						"fatal %s notify messsage, "
+						"phase2 should be deleted.\n",
+						s_isakmp_notify_msg(type));
+				}
+			}
+		} else {
+			plog(LLV_ERROR, LOCATION, iph1->remote,
+				"unhandled notify message %s, "
+				"no phase2 handle found.\n",
+				s_isakmp_notify_msg(type));
+		}
+	    }
+	    break;
+	}
+
+	/* get spi if specified and allocate */
+	if(notify->spi_size > 0) {
+		if (ntohs(notify->h.len) < sizeof(*notify) + notify->spi_size) {
+			plog(LLV_ERROR, LOCATION, iph1->remote,
+				"invalid spi_size in notification payload.\n");
+			return -1;
+		}
+		spi = val2str((char *)(notify + 1), notify->spi_size);
+
+		plog(LLV_DEBUG, LOCATION, iph1->remote,
+			"notification message %d:%s, "
+			"doi=%d proto_id=%d spi=%s(size=%d).\n",
+			type, s_isakmp_notify_msg(type),
+			ntohl(notify->doi), notify->proto_id, spi, notify->spi_size);
+
+		racoon_free(spi);
+	}
+
+	/* Send the message data to the logs */
+	if(type >= ISAKMP_NTYPE_MINERROR &&
+	   type <= ISAKMP_NTYPE_MAXERROR) {
+		l = ntohs(notify->h.len) - sizeof(*notify) - notify->spi_size;
+		if (l > 0) {
+			nraw = (char*)notify;	
+			nraw += sizeof(*notify) + notify->spi_size;
+			if ((ndata = vmalloc(l)) != NULL) {
+				memcpy(ndata->v, nraw, ndata->l);
+				plog(LLV_ERROR, LOCATION, iph1->remote,
+				    "Message: '%s'.\n", 
+				    binsanitize(ndata->v, ndata->l));
+				vfree(ndata);
+			} else {
+				plog(LLV_ERROR, LOCATION, iph1->remote,
+				    "Cannot allocate memory\n");
+			}
+		}
+	}
+	return 0;
+}
+
+/*
+ * handling of Deletion payload
+ */
+static int
+isakmp_info_recv_d(iph1, delete, msgid, encrypted)
+	struct ph1handle *iph1;
+	struct isakmp_pl_d *delete;
+	u_int32_t msgid;
+	int encrypted;
+{
+	int tlen, num_spi;
+	vchar_t *pbuf;
+	int protected = 0;
+	struct ph1handle *del_ph1;
+	struct ph2handle *iph2;
+	union {
+		u_int32_t spi32;
+		u_int16_t spi16[2];
+	} spi;
+
+	if (ntohl(delete->doi) != IPSEC_DOI) {
+		plog(LLV_ERROR, LOCATION, iph1->remote,
+			"delete payload with invalid doi:%d.\n",
+			ntohl(delete->doi));
+#ifdef ENABLE_HYBRID
+		/*
+		 * At deconnexion time, Cisco VPN client does this
+		 * with a zero DOI. Don't give up in that situation.
+		 */
+		if (((iph1->mode_cfg->flags &
+		    ISAKMP_CFG_VENDORID_UNITY) == 0) || (delete->doi != 0))
+			return 0;
+#else
+		return 0;
+#endif
+	}
+
+	num_spi = ntohs(delete->num_spi);
+	tlen = ntohs(delete->h.len) - sizeof(struct isakmp_pl_d);
+
+	if (tlen != num_spi * delete->spi_size) {
+		plog(LLV_ERROR, LOCATION, iph1->remote,
+			"deletion payload with invalid length.\n");
+		return 0;
+	}
+
+	plog(LLV_DEBUG, LOCATION, iph1->remote,
+		"delete payload for protocol %s\n",
+		s_ipsecdoi_proto(delete->proto_id));
+
+	if(!iph1->rmconf->weak_phase1_check && !encrypted) {
+		plog(LLV_WARNING, LOCATION, iph1->remote,
+			"Ignoring unencrypted delete payload "
+			"(check the weak_phase1_check option)\n");
+		return 0;
+	}
+
+	switch (delete->proto_id) {
+	case IPSECDOI_PROTO_ISAKMP:
+		if (delete->spi_size != sizeof(isakmp_index)) {
+			plog(LLV_ERROR, LOCATION, iph1->remote,
+				"delete payload with strange spi "
+				"size %d(proto_id:%d)\n",
+				delete->spi_size, delete->proto_id);
+			return 0;
+		}
+
+		del_ph1=getph1byindex((isakmp_index *)(delete + 1));
+		if(del_ph1 != NULL){
+
+			EVT_PUSH(del_ph1->local, del_ph1->remote,
+			EVTT_PEERPH1_NOPROP, NULL);
+			if (del_ph1->scr)
+				SCHED_KILL(del_ph1->scr);
+
+			/*
+			 * Do not delete IPsec SAs when receiving an IKE delete notification.
+			 * Just delete the IKE SA.
+			 */
+			isakmp_ph1expire(del_ph1);
+		}
+		break;
+
+	case IPSECDOI_PROTO_IPSEC_AH:
+	case IPSECDOI_PROTO_IPSEC_ESP:
+		if (delete->spi_size != sizeof(u_int32_t)) {
+			plog(LLV_ERROR, LOCATION, iph1->remote,
+				"delete payload with strange spi "
+				"size %d(proto_id:%d)\n",
+				delete->spi_size, delete->proto_id);
+			return 0;
+		}
+		EVT_PUSH(iph1->local, iph1->remote, 
+		    EVTT_PEER_DELETE, NULL);
+		purge_ipsec_spi(iph1->remote, delete->proto_id,
+		    (u_int32_t *)(delete + 1), num_spi);
+		break;
+
+	case IPSECDOI_PROTO_IPCOMP:
+		/* need to handle both 16bit/32bit SPI */
+		memset(&spi, 0, sizeof(spi));
+		if (delete->spi_size == sizeof(spi.spi16[1])) {
+			memcpy(&spi.spi16[1], delete + 1,
+			    sizeof(spi.spi16[1]));
+		} else if (delete->spi_size == sizeof(spi.spi32))
+			memcpy(&spi.spi32, delete + 1, sizeof(spi.spi32));
+		else {
+			plog(LLV_ERROR, LOCATION, iph1->remote,
+				"delete payload with strange spi "
+				"size %d(proto_id:%d)\n",
+				delete->spi_size, delete->proto_id);
+			return 0;
+		}
+		purge_ipsec_spi(iph1->remote, delete->proto_id,
+		    &spi.spi32, num_spi);
+		break;
+
+	default:
+		plog(LLV_ERROR, LOCATION, iph1->remote,
+			"deletion message received, "
+			"invalid proto_id: %d\n",
+			delete->proto_id);
+		return 0;
+	}
+
+	plog(LLV_DEBUG, LOCATION, NULL, "purged SAs.\n");
+
+	return 0;
+}
+
+/*
+ * send Delete payload (for ISAKMP SA) in Informational exchange.
+ */
+int
+isakmp_info_send_d1(iph1)
+	struct ph1handle *iph1;
+{
+	struct isakmp_pl_d *d;
+	vchar_t *payload = NULL;
+	int tlen;
+	int error = 0;
+
+	if (iph1->status != PHASE2ST_ESTABLISHED)
+		return 0;
+
+	/* create delete payload */
+
+	/* send SPIs of inbound SAs. */
+	/* XXX should send outbound SAs's ? */
+	tlen = sizeof(*d) + sizeof(isakmp_index);
+	payload = vmalloc(tlen);
+	if (payload == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL, 
+			"failed to get buffer for payload.\n");
+		return errno;
+	}
+
+	d = (struct isakmp_pl_d *)payload->v;
+	d->h.np = ISAKMP_NPTYPE_NONE;
+	d->h.len = htons(tlen);
+	d->doi = htonl(IPSEC_DOI);
+	d->proto_id = IPSECDOI_PROTO_ISAKMP;
+	d->spi_size = sizeof(isakmp_index);
+	d->num_spi = htons(1);
+	memcpy(d + 1, &iph1->index, sizeof(isakmp_index));
+
+	error = isakmp_info_send_common(iph1, payload,
+					ISAKMP_NPTYPE_D, 0);
+	vfree(payload);
+
+	return error;
+}
+
+/*
+ * send Delete payload (for IPsec SA) in Informational exchange, based on
+ * pfkey msg.  It sends always single SPI.
+ */
+int
+isakmp_info_send_d2(iph2)
+	struct ph2handle *iph2;
+{
+	struct ph1handle *iph1;
+	struct saproto *pr;
+	struct isakmp_pl_d *d;
+	vchar_t *payload = NULL;
+	int tlen;
+	int error = 0;
+	u_int8_t *spi;
+
+	if (iph2->status != PHASE2ST_ESTABLISHED)
+		return 0;
+
+	/*
+	 * don't send delete information if there is no phase 1 handler.
+	 * It's nonsensical to negotiate phase 1 to send the information.
+	 */
+	iph1 = getph1byaddr(iph2->src, iph2->dst, 0);
+	if (iph1 == NULL){
+		plog(LLV_DEBUG2, LOCATION, NULL,
+			 "No ph1 handler found, could not send DELETE_SA\n");
+		return 0;
+	}
+
+	/* create delete payload */
+	for (pr = iph2->approval->head; pr != NULL; pr = pr->next) {
+
+		/* send SPIs of inbound SAs. */
+		/*
+		 * XXX should I send outbound SAs's ?
+		 * I send inbound SAs's SPI only at the moment because I can't
+		 * decode any more if peer send encoded packet without aware of
+		 * deletion of SA.  Outbound SAs don't come under the situation.
+		 */
+		tlen = sizeof(*d) + pr->spisize;
+		payload = vmalloc(tlen);
+		if (payload == NULL) {
+			plog(LLV_ERROR, LOCATION, NULL, 
+				"failed to get buffer for payload.\n");
+			return errno;
+		}
+
+		d = (struct isakmp_pl_d *)payload->v;
+		d->h.np = ISAKMP_NPTYPE_NONE;
+		d->h.len = htons(tlen);
+		d->doi = htonl(IPSEC_DOI);
+		d->proto_id = pr->proto_id;
+		d->spi_size = pr->spisize;
+		d->num_spi = htons(1);
+		/*
+		 * XXX SPI bits are left-filled, for use with IPComp.
+		 * we should be switching to variable-length spi field...
+		 */
+		spi = (u_int8_t *)&pr->spi;
+		spi += sizeof(pr->spi);
+		spi -= pr->spisize;
+		memcpy(d + 1, spi, pr->spisize);
+
+		error = isakmp_info_send_common(iph1, payload,
+						ISAKMP_NPTYPE_D, 0);
+		vfree(payload);
+	}
+
+	return error;
+}
+
+/*
+ * send Notification payload (for without ISAKMP SA) in Informational exchange
+ */
+int
+isakmp_info_send_nx(isakmp, remote, local, type, data)
+	struct isakmp *isakmp;
+	struct sockaddr *remote, *local;
+	int type;
+	vchar_t *data;
+{
+	struct ph1handle *iph1 = NULL;
+	struct remoteconf *rmconf;
+	vchar_t *payload = NULL;
+	int tlen;
+	int error = -1;
+	struct isakmp_pl_n *n;
+	int spisiz = 0;		/* see below */
+
+	/* search appropreate configuration */
+	rmconf = getrmconf(remote);
+	if (rmconf == NULL) {
+		plog(LLV_ERROR, LOCATION, remote,
+			"no configuration found for peer address.\n");
+		goto end;
+	}
+
+	/* add new entry to isakmp status table. */
+	iph1 = newph1();
+	if (iph1 == NULL)
+		return -1;
+
+	memcpy(&iph1->index.i_ck, &isakmp->i_ck, sizeof(cookie_t));
+	isakmp_newcookie((char *)&iph1->index.r_ck, remote, local);
+	iph1->status = PHASE1ST_START;
+	iph1->rmconf = rmconf;
+	iph1->side = INITIATOR;
+	iph1->version = isakmp->v;
+	iph1->flags = 0;
+	iph1->msgid = 0;	/* XXX */
+#ifdef ENABLE_HYBRID
+	if ((iph1->mode_cfg = isakmp_cfg_mkstate()) == NULL)
+		goto end;
+#endif
+#ifdef ENABLE_FRAG
+	iph1->frag = 0;
+	iph1->frag_chain = NULL;
+#endif
+
+	/* copy remote address */
+	if (copy_ph1addresses(iph1, rmconf, remote, local) < 0)
+		goto end;
+
+	tlen = sizeof(*n) + spisiz;
+	if (data)
+		tlen += data->l;
+	payload = vmalloc(tlen);
+	if (payload == NULL) { 
+		plog(LLV_ERROR, LOCATION, NULL,
+			"failed to get buffer to send.\n");
+		goto end;
+	}
+
+	n = (struct isakmp_pl_n *)payload->v;
+	n->h.np = ISAKMP_NPTYPE_NONE;
+	n->h.len = htons(tlen);
+	n->doi = htonl(IPSEC_DOI);
+	n->proto_id = IPSECDOI_KEY_IKE;
+	n->spi_size = spisiz;
+	n->type = htons(type);
+	if (spisiz)
+		memset(n + 1, 0, spisiz);	/* XXX spisiz is always 0 */
+	if (data)
+		memcpy((caddr_t)(n + 1) + spisiz, data->v, data->l);
+
+	error = isakmp_info_send_common(iph1, payload, ISAKMP_NPTYPE_N, 0);
+	vfree(payload);
+
+    end:
+	if (iph1 != NULL)
+		delph1(iph1);
+
+	return error;
+}
+
+/*
+ * send Notification payload (for ISAKMP SA) in Informational exchange
+ */
+int
+isakmp_info_send_n1(iph1, type, data)
+	struct ph1handle *iph1;
+	int type;
+	vchar_t *data;
+{
+	vchar_t *payload = NULL;
+	int tlen;
+	int error = 0;
+	struct isakmp_pl_n *n;
+	int spisiz;
+
+	/*
+	 * note on SPI size: which description is correct?  I have chosen
+	 * this to be 0.
+	 *
+	 * RFC2408 3.1, 2nd paragraph says: ISAKMP SA is identified by
+	 * Initiator/Responder cookie and SPI has no meaning, SPI size = 0.
+	 * RFC2408 3.1, first paragraph on page 40: ISAKMP SA is identified
+	 * by cookie and SPI has no meaning, 0 <= SPI size <= 16.
+	 * RFC2407 4.6.3.3, INITIAL-CONTACT is required to set to 16.
+	 */
+	if (type == ISAKMP_NTYPE_INITIAL_CONTACT)
+		spisiz = sizeof(isakmp_index);
+	else
+		spisiz = 0;
+
+	tlen = sizeof(*n) + spisiz;
+	if (data)
+		tlen += data->l;
+	payload = vmalloc(tlen);
+	if (payload == NULL) { 
+		plog(LLV_ERROR, LOCATION, NULL,
+			"failed to get buffer to send.\n");
+		return errno;
+	}
+
+	n = (struct isakmp_pl_n *)payload->v;
+	n->h.np = ISAKMP_NPTYPE_NONE;
+	n->h.len = htons(tlen);
+	n->doi = htonl(iph1->rmconf->doitype);
+	n->proto_id = IPSECDOI_PROTO_ISAKMP; /* XXX to be configurable ? */
+	n->spi_size = spisiz;
+	n->type = htons(type);
+	if (spisiz)
+		memcpy(n + 1, &iph1->index, sizeof(isakmp_index));
+	if (data)
+		memcpy((caddr_t)(n + 1) + spisiz, data->v, data->l);
+
+	error = isakmp_info_send_common(iph1, payload, ISAKMP_NPTYPE_N, iph1->flags);
+	vfree(payload);
+
+	return error;
+}
+
+/*
+ * send Notification payload (for IPsec SA) in Informational exchange
+ */
+int
+isakmp_info_send_n2(iph2, type, data)
+	struct ph2handle *iph2;
+	int type;
+	vchar_t *data;
+{
+	struct ph1handle *iph1 = iph2->ph1;
+	vchar_t *payload = NULL;
+	int tlen;
+	int error = 0;
+	struct isakmp_pl_n *n;
+	struct saproto *pr;
+
+	if (!iph2->approval)
+		return EINVAL;
+
+	pr = iph2->approval->head;
+
+	/* XXX must be get proper spi */
+	tlen = sizeof(*n) + pr->spisize;
+	if (data)
+		tlen += data->l;
+	payload = vmalloc(tlen);
+	if (payload == NULL) { 
+		plog(LLV_ERROR, LOCATION, NULL,
+			"failed to get buffer to send.\n");
+		return errno;
+	}
+
+	n = (struct isakmp_pl_n *)payload->v;
+	n->h.np = ISAKMP_NPTYPE_NONE;
+	n->h.len = htons(tlen);
+	n->doi = htonl(IPSEC_DOI);		/* IPSEC DOI (1) */
+	n->proto_id = pr->proto_id;		/* IPSEC AH/ESP/whatever*/
+	n->spi_size = pr->spisize;
+	n->type = htons(type);
+	*(u_int32_t *)(n + 1) = pr->spi;
+	if (data)
+		memcpy((caddr_t)(n + 1) + pr->spisize, data->v, data->l);
+
+	iph2->flags |= ISAKMP_FLAG_E;	/* XXX Should we do FLAG_A ? */
+	error = isakmp_info_send_common(iph1, payload, ISAKMP_NPTYPE_N, iph2->flags);
+	vfree(payload);
+
+	return error;
+}
+
+/*
+ * send Information
+ * When ph1->skeyid_a == NULL, send message without encoding.
+ */
+int
+isakmp_info_send_common(iph1, payload, np, flags)
+	struct ph1handle *iph1;
+	vchar_t *payload;
+	u_int32_t np;
+	int flags;
+{
+	struct ph2handle *iph2 = NULL;
+	vchar_t *hash = NULL;
+	struct isakmp *isakmp;
+	struct isakmp_gen *gen;
+	char *p;
+	int tlen;
+	int error = -1;
+
+	/* add new entry to isakmp status table */
+	iph2 = newph2();
+	if (iph2 == NULL)
+		goto end;
+
+	iph2->dst = dupsaddr(iph1->remote);
+	if (iph2->dst == NULL) {
+		delph2(iph2);
+		goto end;
+	}
+	iph2->src = dupsaddr(iph1->local);
+	if (iph2->src == NULL) {
+		delph2(iph2);
+		goto end;
+	}
+#if (!defined(ENABLE_NATT)) || (defined(BROKEN_NATT))
+	if (set_port(iph2->dst, 0) == NULL ||
+	    set_port(iph2->src, 0) == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL,
+		     "invalid family: %d\n", iph1->remote->sa_family);
+		delph2(iph2);
+		goto end;
+	}
+#endif
+	iph2->ph1 = iph1;
+	iph2->side = INITIATOR;
+	iph2->status = PHASE2ST_START;
+	iph2->msgid = isakmp_newmsgid2(iph1);
+
+	/* get IV and HASH(1) if skeyid_a was generated. */
+	if (iph1->skeyid_a != NULL) {
+		iph2->ivm = oakley_newiv2(iph1, iph2->msgid);
+		if (iph2->ivm == NULL) {
+			delph2(iph2);
+			goto end;
+		}
+
+		/* generate HASH(1) */
+		hash = oakley_compute_hash1(iph2->ph1, iph2->msgid, payload);
+		if (hash == NULL) {
+			delph2(iph2);
+			goto end;
+		}
+
+		/* initialized total buffer length */
+		tlen = hash->l;
+		tlen += sizeof(*gen);
+	} else {
+		/* IKE-SA is not established */
+		hash = NULL;
+
+		/* initialized total buffer length */
+		tlen = 0;
+	}
+	if ((flags & ISAKMP_FLAG_A) == 0)
+		iph2->flags = (hash == NULL ? 0 : ISAKMP_FLAG_E);
+	else
+		iph2->flags = (hash == NULL ? 0 : ISAKMP_FLAG_A);
+
+	insph2(iph2);
+	bindph12(iph1, iph2);
+
+	tlen += sizeof(*isakmp) + payload->l;
+
+	/* create buffer for isakmp payload */
+	iph2->sendbuf = vmalloc(tlen);
+	if (iph2->sendbuf == NULL) { 
+		plog(LLV_ERROR, LOCATION, NULL,
+			"failed to get buffer to send.\n");
+		goto err;
+	}
+
+	/* create isakmp header */
+	isakmp = (struct isakmp *)iph2->sendbuf->v;
+	memcpy(&isakmp->i_ck, &iph1->index.i_ck, sizeof(cookie_t));
+	memcpy(&isakmp->r_ck, &iph1->index.r_ck, sizeof(cookie_t));
+	isakmp->np = hash == NULL ? (np & 0xff) : ISAKMP_NPTYPE_HASH;
+	isakmp->v = iph1->version;
+	isakmp->etype = ISAKMP_ETYPE_INFO;
+	isakmp->flags = iph2->flags;
+	memcpy(&isakmp->msgid, &iph2->msgid, sizeof(isakmp->msgid));
+	isakmp->len   = htonl(tlen);
+	p = (char *)(isakmp + 1);
+
+	/* create HASH payload */
+	if (hash != NULL) {
+		gen = (struct isakmp_gen *)p;
+		gen->np = np & 0xff;
+		gen->len = htons(sizeof(*gen) + hash->l);
+		p += sizeof(*gen);
+		memcpy(p, hash->v, hash->l);
+		p += hash->l;
+	}
+
+	/* add payload */
+	memcpy(p, payload->v, payload->l);
+	p += payload->l;
+
+#ifdef HAVE_PRINT_ISAKMP_C
+	isakmp_printpacket(iph2->sendbuf, iph1->local, iph1->remote, 1);
+#endif
+
+	/* encoding */
+	if (ISSET(isakmp->flags, ISAKMP_FLAG_E)) {
+		vchar_t *tmp;
+
+		tmp = oakley_do_encrypt(iph2->ph1, iph2->sendbuf, iph2->ivm->ive,
+				iph2->ivm->iv);
+		VPTRINIT(iph2->sendbuf);
+		if (tmp == NULL)
+			goto err;
+		iph2->sendbuf = tmp;
+	}
+
+	/* HDR*, HASH(1), N */
+	if (isakmp_send(iph2->ph1, iph2->sendbuf) < 0) {
+		VPTRINIT(iph2->sendbuf);
+		goto err;
+	}
+
+	plog(LLV_DEBUG, LOCATION, NULL,
+		"sendto Information %s.\n", s_isakmp_nptype(np));
+
+	/*
+	 * don't resend notify message because peer can use Acknowledged
+	 * Informational if peer requires the reply of the notify message.
+	 */
+
+	/* XXX If Acknowledged Informational required, don't delete ph2handle */
+	error = 0;
+	VPTRINIT(iph2->sendbuf);
+	goto err;	/* XXX */
+
+end:
+	if (hash)
+		vfree(hash);
+	return error;
+
+err:
+	unbindph12(iph2);
+	remph2(iph2);
+	delph2(iph2);
+	goto end;
+}
+
+/*
+ * add a notify payload to buffer by reallocating buffer.
+ * If buf == NULL, the function only create a notify payload.
+ *
+ * XXX Which is SPI to be included, inbound or outbound ?
+ */
+vchar_t *
+isakmp_add_pl_n(buf0, np_p, type, pr, data)
+	vchar_t *buf0;
+	u_int8_t **np_p;
+	int type;
+	struct saproto *pr;
+	vchar_t *data;
+{
+	vchar_t *buf = NULL;
+	struct isakmp_pl_n *n;
+	int tlen;
+	int oldlen = 0;
+
+	if (*np_p)
+		**np_p = ISAKMP_NPTYPE_N;
+
+	tlen = sizeof(*n) + pr->spisize;
+
+	if (data)
+		tlen += data->l;
+	if (buf0) {
+		oldlen = buf0->l;
+		buf = vrealloc(buf0, buf0->l + tlen);
+	} else
+		buf = vmalloc(tlen);
+	if (!buf) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"failed to get a payload buffer.\n");
+		return NULL;
+	}
+
+	n = (struct isakmp_pl_n *)(buf->v + oldlen);
+	n->h.np = ISAKMP_NPTYPE_NONE;
+	n->h.len = htons(tlen);
+	n->doi = htonl(IPSEC_DOI);		/* IPSEC DOI (1) */
+	n->proto_id = pr->proto_id;		/* IPSEC AH/ESP/whatever*/
+	n->spi_size = pr->spisize;
+	n->type = htons(type);
+	*(u_int32_t *)(n + 1) = pr->spi;	/* XXX */
+	if (data)
+		memcpy((caddr_t)(n + 1) + pr->spisize, data->v, data->l);
+
+	/* save the pointer of next payload type */
+	*np_p = &n->h.np;
+
+	return buf;
+}
+
+static void
+purge_isakmp_spi(proto, spi, n)
+	int proto;
+	isakmp_index *spi;	/*network byteorder*/
+	size_t n;
+{
+	struct ph1handle *iph1;
+	size_t i;
+
+	for (i = 0; i < n; i++) {
+		iph1 = getph1byindex(&spi[i]);
+		if (!iph1)
+			continue;
+
+		plog(LLV_INFO, LOCATION, NULL,
+			"purged ISAKMP-SA proto_id=%s spi=%s.\n",
+			s_ipsecdoi_proto(proto),
+			isakmp_pindex(&spi[i], 0));
+
+		SCHED_KILL(iph1->sce);
+		iph1->status = PHASE1ST_EXPIRED;
+		iph1->sce = sched_new(1, isakmp_ph1delete_stub, iph1);
+	}
+}
+
+
+
+void
+purge_ipsec_spi(dst0, proto, spi, n)
+	struct sockaddr *dst0;
+	int proto;
+	u_int32_t *spi;	/*network byteorder*/
+	size_t n;
+{
+	vchar_t *buf = NULL;
+	struct sadb_msg *msg, *next, *end;
+	struct sadb_sa *sa;
+	struct sadb_lifetime *lt;
+	struct sockaddr *src, *dst;
+	struct ph2handle *iph2;
+	u_int64_t created;
+	size_t i;
+	caddr_t mhp[SADB_EXT_MAX + 1];
+#ifdef ENABLE_NATT
+	struct sadb_x_nat_t_type *natt_type;
+	struct sadb_x_nat_t_port *natt_port;
+#endif
+
+	plog(LLV_DEBUG2, LOCATION, NULL,
+		 "purge_ipsec_spi:\n");
+	plog(LLV_DEBUG2, LOCATION, NULL, "dst0: %s\n", saddr2str(dst0));
+	plog(LLV_DEBUG2, LOCATION, NULL, "SPI: %08X\n", ntohl(spi[0]));
+
+	buf = pfkey_dump_sadb(ipsecdoi2pfkey_proto(proto));
+	if (buf == NULL) {
+		plog(LLV_DEBUG, LOCATION, NULL,
+			"pfkey_dump_sadb returned nothing.\n");
+		return;
+	}
+
+	msg = (struct sadb_msg *)buf->v;
+	end = (struct sadb_msg *)(buf->v + buf->l);
+
+	while (msg < end) {
+		if ((msg->sadb_msg_len << 3) < sizeof(*msg))
+			break;
+		next = (struct sadb_msg *)((caddr_t)msg + (msg->sadb_msg_len << 3));
+		if (msg->sadb_msg_type != SADB_DUMP) {
+			msg = next;
+			continue;
+		}
+
+		if (pfkey_align(msg, mhp) || pfkey_check(mhp)) {
+			plog(LLV_ERROR, LOCATION, NULL,
+				"pfkey_check (%s)\n", ipsec_strerror());
+			msg = next;
+			continue;
+		}
+
+		sa = (struct sadb_sa *)(mhp[SADB_EXT_SA]);
+		if (!sa
+		 || !mhp[SADB_EXT_ADDRESS_SRC]
+		 || !mhp[SADB_EXT_ADDRESS_DST]) {
+			msg = next;
+			continue;
+		}
+		src = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_SRC]);
+		dst = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_DST]);
+		lt = (struct sadb_lifetime*)mhp[SADB_EXT_LIFETIME_HARD];
+		if(lt != NULL)
+			created = lt->sadb_lifetime_addtime;
+		else
+			created = 0;
+
+		if (sa->sadb_sa_state != SADB_SASTATE_MATURE
+		 && sa->sadb_sa_state != SADB_SASTATE_DYING) {
+			msg = next;
+			continue;
+		}
+#ifdef ENABLE_NATT
+		natt_type = (void *)mhp[SADB_X_EXT_NAT_T_TYPE];
+		if (natt_type && natt_type->sadb_x_nat_t_type_type) {
+			/* NAT-T is enabled for this SADB entry; copy
+			 * the ports from NAT-T extensions */
+			natt_port = (void *)mhp[SADB_X_EXT_NAT_T_SPORT];
+			if (extract_port(src) == 0 && natt_port != NULL)
+				set_port(src, ntohs(natt_port->sadb_x_nat_t_port_port));
+
+			natt_port = (void *)mhp[SADB_X_EXT_NAT_T_DPORT];
+			if (extract_port(dst) == 0 && natt_port != NULL)
+				set_port(dst, ntohs(natt_port->sadb_x_nat_t_port_port));
+		}
+#endif
+		plog(LLV_DEBUG2, LOCATION, NULL, "src: %s\n", saddr2str(src));
+		plog(LLV_DEBUG2, LOCATION, NULL, "dst: %s\n", saddr2str(dst));
+
+		/* XXX n^2 algorithm, inefficient */
+
+		/* don't delete inbound SAs at the moment */
+		/* XXX should we remove SAs with opposite direction as well? */
+		if (CMPSADDR(dst0, dst)) {
+			msg = next;
+			continue;
+		}
+
+		for (i = 0; i < n; i++) {
+			plog(LLV_DEBUG, LOCATION, NULL,
+				"check spi(packet)=%u spi(db)=%u.\n",
+				ntohl(spi[i]), ntohl(sa->sadb_sa_spi));
+			if (spi[i] != sa->sadb_sa_spi)
+				continue;
+
+			pfkey_send_delete(lcconf->sock_pfkey,
+				msg->sadb_msg_satype,
+				IPSEC_MODE_ANY,
+				src, dst, sa->sadb_sa_spi);
+
+			/*
+			 * delete a relative phase 2 handler.
+			 * continue to process if no relative phase 2 handler
+			 * exists.
+			 */
+			iph2 = getph2bysaidx(src, dst, proto, spi[i]);
+			if(iph2 != NULL){
+				delete_spd(iph2, created);
+				unbindph12(iph2);
+				remph2(iph2);
+				delph2(iph2);
+			}
+
+			plog(LLV_INFO, LOCATION, NULL,
+				"purged IPsec-SA proto_id=%s spi=%u.\n",
+				s_ipsecdoi_proto(proto),
+				ntohl(spi[i]));
+		}
+
+		msg = next;
+	}
+
+	if (buf)
+		vfree(buf);
+}
+
+/*
+ * delete all phase2 sa relatived to the destination address.
+ * Don't delete Phase 1 handlers on INITIAL-CONTACT, and don't ignore
+ * an INITIAL-CONTACT if we have contacted the peer.  This matches the
+ * Sun IKE behavior, and makes rekeying work much better when the peer
+ * restarts.
+ */
+static void
+info_recv_initialcontact(iph1)
+	struct ph1handle *iph1;
+{
+	vchar_t *buf = NULL;
+	struct sadb_msg *msg, *next, *end;
+	struct sadb_sa *sa;
+	struct sockaddr *src, *dst;
+	caddr_t mhp[SADB_EXT_MAX + 1];
+	int proto_id, i;
+	struct ph2handle *iph2;
+#if 0
+	char *loc, *rem;
+#endif
+
+	if (f_local)
+		return;
+
+#if 0
+	loc = racoon_strdup(saddrwop2str(iph1->local));
+	rem = racoon_strdup(saddrwop2str(iph1->remote));
+	STRDUP_FATAL(loc);
+	STRDUP_FATAL(rem);
+
+	/*
+	 * Purge all IPSEC-SAs for the peer.  We can do this
+	 * the easy way (using a PF_KEY SADB_DELETE extension)
+	 * or we can do it the hard way.
+	 */
+	for (i = 0; i < pfkey_nsatypes; i++) {
+		proto_id = pfkey2ipsecdoi_proto(pfkey_satypes[i].ps_satype);
+
+		plog(LLV_INFO, LOCATION, NULL,
+		    "purging %s SAs for %s -> %s\n",
+		    pfkey_satypes[i].ps_name, loc, rem);
+		if (pfkey_send_delete_all(lcconf->sock_pfkey,
+		    pfkey_satypes[i].ps_satype, IPSEC_MODE_ANY,
+		    iph1->local, iph1->remote) == -1) {
+			plog(LLV_ERROR, LOCATION, NULL,
+			    "delete_all %s -> %s failed for %s (%s)\n",
+			    loc, rem,
+			    pfkey_satypes[i].ps_name, ipsec_strerror());
+			goto the_hard_way;
+		}
+
+		deleteallph2(iph1->local, iph1->remote, proto_id);
+
+		plog(LLV_INFO, LOCATION, NULL,
+		    "purging %s SAs for %s -> %s\n",
+		    pfkey_satypes[i].ps_name, rem, loc);
+		if (pfkey_send_delete_all(lcconf->sock_pfkey,
+		    pfkey_satypes[i].ps_satype, IPSEC_MODE_ANY,
+		    iph1->remote, iph1->local) == -1) {
+			plog(LLV_ERROR, LOCATION, NULL,
+			    "delete_all %s -> %s failed for %s (%s)\n",
+			    rem, loc,
+			    pfkey_satypes[i].ps_name, ipsec_strerror());
+			goto the_hard_way;
+		}
+
+		deleteallph2(iph1->remote, iph1->local, proto_id);
+	}
+
+	racoon_free(loc);
+	racoon_free(rem);
+	return;
+
+ the_hard_way:
+	racoon_free(loc);
+	racoon_free(rem);
+#endif
+
+	buf = pfkey_dump_sadb(SADB_SATYPE_UNSPEC);
+	if (buf == NULL) {
+		plog(LLV_DEBUG, LOCATION, NULL,
+			"pfkey_dump_sadb returned nothing.\n");
+		return;
+	}
+
+	msg = (struct sadb_msg *)buf->v;
+	end = (struct sadb_msg *)(buf->v + buf->l);
+
+	while (msg < end) {
+		if ((msg->sadb_msg_len << 3) < sizeof(*msg))
+			break;
+		next = (struct sadb_msg *)((caddr_t)msg + (msg->sadb_msg_len << 3));
+		if (msg->sadb_msg_type != SADB_DUMP) {
+			msg = next;
+			continue;
+		}
+
+		if (pfkey_align(msg, mhp) || pfkey_check(mhp)) {
+			plog(LLV_ERROR, LOCATION, NULL,
+				"pfkey_check (%s)\n", ipsec_strerror());
+			msg = next;
+			continue;
+		}
+
+		if (mhp[SADB_EXT_SA] == NULL
+		 || mhp[SADB_EXT_ADDRESS_SRC] == NULL
+		 || mhp[SADB_EXT_ADDRESS_DST] == NULL) {
+			msg = next;
+			continue;
+		}
+		sa = (struct sadb_sa *)mhp[SADB_EXT_SA];
+		src = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_SRC]);
+		dst = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_DST]);
+
+		if (sa->sadb_sa_state != SADB_SASTATE_MATURE
+		 && sa->sadb_sa_state != SADB_SASTATE_DYING) {
+			msg = next;
+			continue;
+		}
+
+		/*
+		 * RFC2407 4.6.3.3 INITIAL-CONTACT is the message that
+		 * announces the sender of the message was rebooted.
+		 * it is interpreted to delete all SAs which source address
+		 * is the sender of the message.
+		 * racoon only deletes SA which is matched both the
+		 * source address and the destination accress.
+		 */
+#ifdef ENABLE_NATT
+		/* 
+		 * XXX RFC 3947 says that whe MUST NOT use IP+port to find old SAs
+		 * from this peer !
+		 */
+		if(iph1->natt_flags & NAT_DETECTED){
+			if (CMPSADDR(iph1->local, src) == 0 &&
+				CMPSADDR(iph1->remote, dst) == 0)
+				;
+			else if (CMPSADDR(iph1->remote, src) == 0 &&
+					 CMPSADDR(iph1->local, dst) == 0)
+				;
+			else {
+				msg = next;
+				continue;
+			}
+		} else
+#endif
+		/* If there is no NAT-T, we don't have to check addr + port...
+		 * XXX what about a configuration with a remote peers which is not
+		 * NATed, but which NATs some other peers ?
+		 * Here, the INITIAl-CONTACT would also flush all those NATed peers !!
+		 */
+		if (cmpsaddrwop(iph1->local, src) == 0 &&
+		    cmpsaddrwop(iph1->remote, dst) == 0)
+			;
+		else if (cmpsaddrwop(iph1->remote, src) == 0 &&
+		    cmpsaddrwop(iph1->local, dst) == 0)
+			;
+		else {
+			msg = next;
+			continue;
+		}
+
+		/*
+		 * Make sure this is an SATYPE that we manage.
+		 * This is gross; too bad we couldn't do it the
+		 * easy way.
+		 */
+		for (i = 0; i < pfkey_nsatypes; i++) {
+			if (pfkey_satypes[i].ps_satype ==
+			    msg->sadb_msg_satype)
+				break;
+		}
+		if (i == pfkey_nsatypes) {
+			msg = next;
+			continue;
+		}
+
+		plog(LLV_INFO, LOCATION, NULL,
+			"purging spi=%u.\n", ntohl(sa->sadb_sa_spi));
+		pfkey_send_delete(lcconf->sock_pfkey,
+			msg->sadb_msg_satype,
+			IPSEC_MODE_ANY, src, dst, sa->sadb_sa_spi);
+
+		/*
+		 * delete a relative phase 2 handler.
+		 * continue to process if no relative phase 2 handler
+		 * exists.
+		 */
+		proto_id = pfkey2ipsecdoi_proto(msg->sadb_msg_satype);
+		iph2 = getph2bysaidx(src, dst, proto_id, sa->sadb_sa_spi);
+		if (iph2) {
+			delete_spd(iph2, 0);
+			unbindph12(iph2);
+			remph2(iph2);
+			delph2(iph2);
+		}
+
+		msg = next;
+	}
+
+	vfree(buf);
+}
+
+void
+isakmp_check_notify(gen, iph1)
+	struct isakmp_gen *gen;		/* points to Notify payload */
+	struct ph1handle *iph1;
+{
+	struct isakmp_pl_n *notify = (struct isakmp_pl_n *)gen;
+
+	plog(LLV_DEBUG, LOCATION, iph1->remote,
+		"Notify Message received\n");
+
+	switch (ntohs(notify->type)) {
+	case ISAKMP_NTYPE_CONNECTED:
+	case ISAKMP_NTYPE_RESPONDER_LIFETIME:
+	case ISAKMP_NTYPE_REPLAY_STATUS:
+	case ISAKMP_NTYPE_HEARTBEAT:
+#ifdef ENABLE_HYBRID
+	case ISAKMP_NTYPE_UNITY_HEARTBEAT:
+#endif
+		plog(LLV_WARNING, LOCATION, iph1->remote,
+			"ignore %s notification.\n",
+			s_isakmp_notify_msg(ntohs(notify->type)));
+		break;
+	case ISAKMP_NTYPE_INITIAL_CONTACT:
+		plog(LLV_WARNING, LOCATION, iph1->remote,
+			"ignore INITIAL-CONTACT notification, "
+			"because it is only accepted after phase1.\n");
+		break;
+	default:
+		isakmp_info_send_n1(iph1, ISAKMP_NTYPE_INVALID_PAYLOAD_TYPE, NULL);
+		plog(LLV_ERROR, LOCATION, iph1->remote,
+			"received unknown notification type %s.\n",
+			s_isakmp_notify_msg(ntohs(notify->type)));
+	}
+
+	return;
+}
+
+
+#ifdef ENABLE_DPD
+static int
+isakmp_info_recv_r_u (iph1, ru, msgid)
+	struct ph1handle *iph1;
+	struct isakmp_pl_ru *ru;
+	u_int32_t msgid;
+{
+	struct isakmp_pl_ru *ru_ack;
+	vchar_t *payload = NULL;
+	int tlen;
+	int error = 0;
+
+	plog(LLV_DEBUG, LOCATION, iph1->remote,
+		 "DPD R-U-There received\n");
+
+	/* XXX should compare cookies with iph1->index?
+	   Or is this already done by calling function?  */
+	tlen = sizeof(*ru_ack);
+	payload = vmalloc(tlen);
+	if (payload == NULL) { 
+		plog(LLV_ERROR, LOCATION, NULL,
+			"failed to get buffer to send.\n");
+		return errno;
+	}
+
+	ru_ack = (struct isakmp_pl_ru *)payload->v;
+	ru_ack->h.np = ISAKMP_NPTYPE_NONE;
+	ru_ack->h.len = htons(tlen);
+	ru_ack->doi = htonl(IPSEC_DOI);
+	ru_ack->type = htons(ISAKMP_NTYPE_R_U_THERE_ACK);
+	ru_ack->proto_id = IPSECDOI_PROTO_ISAKMP; /* XXX ? */
+	ru_ack->spi_size = sizeof(isakmp_index);
+	memcpy(ru_ack->i_ck, ru->i_ck, sizeof(cookie_t));
+	memcpy(ru_ack->r_ck, ru->r_ck, sizeof(cookie_t));	
+	ru_ack->data = ru->data;
+
+	/* XXX Should we do FLAG_A ?  */
+	error = isakmp_info_send_common(iph1, payload, ISAKMP_NPTYPE_N,
+					ISAKMP_FLAG_E);
+	vfree(payload);
+
+	plog(LLV_DEBUG, LOCATION, NULL, "received a valid R-U-THERE, ACK sent\n");
+
+	/* Should we mark tunnel as active ? */
+	return error;
+}
+
+static int
+isakmp_info_recv_r_u_ack (iph1, ru, msgid)
+	struct ph1handle *iph1;
+	struct isakmp_pl_ru *ru;
+	u_int32_t msgid;
+{
+
+	plog(LLV_DEBUG, LOCATION, iph1->remote,
+		 "DPD R-U-There-Ack received\n");
+
+	/* XXX Maintain window of acceptable sequence numbers ?
+	 * => ru->data <= iph2->dpd_seq &&
+	 *    ru->data >= iph2->dpd_seq - iph2->dpd_fails ? */
+	if (ntohl(ru->data) != iph1->dpd_seq-1) {
+		plog(LLV_ERROR, LOCATION, iph1->remote,
+			 "Wrong DPD sequence number (%d, %d expected).\n", 
+			 ntohl(ru->data), iph1->dpd_seq-1);
+		return 0;
+	}
+
+	if (memcmp(ru->i_ck, iph1->index.i_ck, sizeof(cookie_t)) ||
+	    memcmp(ru->r_ck, iph1->index.r_ck, sizeof(cookie_t))) {
+		plog(LLV_ERROR, LOCATION, iph1->remote,
+			 "Cookie mismatch in DPD ACK!.\n");
+		return 0;
+	}
+
+	iph1->dpd_fails = 0;
+
+	/* Useless ??? */
+	iph1->dpd_lastack = time(NULL);
+
+	SCHED_KILL(iph1->dpd_r_u);
+
+	isakmp_sched_r_u(iph1, 0);
+
+	plog(LLV_DEBUG, LOCATION, NULL, "received an R-U-THERE-ACK\n");
+
+	return 0;
+}
+
+
+
+
+/*
+ * send DPD R-U-THERE payload in Informational exchange.
+ */
+static void
+isakmp_info_send_r_u(arg)
+	void *arg;
+{
+	struct ph1handle *iph1 = arg;
+
+	/* create R-U-THERE payload */
+	struct isakmp_pl_ru *ru;
+	vchar_t *payload = NULL;
+	int tlen;
+	int error = 0;
+
+	plog(LLV_DEBUG, LOCATION, iph1->remote, "DPD monitoring....\n");
+
+	iph1->dpd_r_u=NULL;
+
+	if (iph1->dpd_fails >= iph1->rmconf->dpd_maxfails) {
+
+		plog(LLV_INFO, LOCATION, iph1->remote,
+			"DPD: remote (ISAKMP-SA spi=%s) seems to be dead.\n",
+			isakmp_pindex(&iph1->index, 0));
+
+		EVT_PUSH(iph1->local, iph1->remote, EVTT_DPD_TIMEOUT, NULL);
+		purge_remote(iph1);
+
+		/* Do not reschedule here: phase1 is deleted,
+		 * DPD will be reactivated when a new ph1 will be negociated
+		 */
+		return;
+	}
+
+	/* TODO: check recent activity to avoid useless sends... */
+
+	tlen = sizeof(*ru);
+	payload = vmalloc(tlen);
+	if (payload == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL, 
+			 "failed to get buffer for payload.\n");
+		return;
+	}
+	ru = (struct isakmp_pl_ru *)payload->v;
+	ru->h.np = ISAKMP_NPTYPE_NONE;
+	ru->h.len = htons(tlen);
+	ru->doi = htonl(IPSEC_DOI);
+	ru->type = htons(ISAKMP_NTYPE_R_U_THERE);
+	ru->proto_id = IPSECDOI_PROTO_ISAKMP; /* XXX ?*/
+	ru->spi_size = sizeof(isakmp_index);
+
+	memcpy(ru->i_ck, iph1->index.i_ck, sizeof(cookie_t));
+	memcpy(ru->r_ck, iph1->index.r_ck, sizeof(cookie_t));
+
+	if (iph1->dpd_seq == 0){
+		/* generate a random seq which is not too big */
+		srand(time(NULL));
+		iph1->dpd_seq = rand() & 0x0fff;
+	}
+
+	ru->data = htonl(iph1->dpd_seq);
+
+	error = isakmp_info_send_common(iph1, payload, ISAKMP_NPTYPE_N, 0);
+	vfree(payload);
+
+	plog(LLV_DEBUG, LOCATION, iph1->remote,
+		 "DPD R-U-There sent (%d)\n", error);
+
+	/* will be decreased if ACK received... */
+	iph1->dpd_fails++;
+
+	/* XXX should be increased only when ACKed ? */
+	iph1->dpd_seq++;
+
+	/* Reschedule the r_u_there with a short delay,
+	 * will be deleted/rescheduled if ACK received before */
+	isakmp_sched_r_u(iph1, 1);
+
+	plog(LLV_DEBUG, LOCATION, iph1->remote,
+		 "rescheduling send_r_u (%d).\n", iph1->rmconf->dpd_retry);
+}
+
+/* Schedule a new R-U-THERE */
+int
+isakmp_sched_r_u(iph1, retry)
+	struct ph1handle *iph1;
+	int retry;
+{
+	if(iph1 == NULL ||
+	   iph1->rmconf == NULL)
+		return 1;
+
+
+	if(iph1->dpd_support == 0 ||
+	   iph1->rmconf->dpd_interval == 0)
+		return 0;
+
+	if(retry)
+		iph1->dpd_r_u = sched_new(iph1->rmconf->dpd_retry,
+								  isakmp_info_send_r_u, iph1);
+	else
+		iph1->dpd_r_u = sched_new(iph1->rmconf->dpd_interval,
+								  isakmp_info_send_r_u, iph1);
+
+	return 0;
+}
+#endif
diff --git a/src/racoon/isakmp_inf.h b/src/racoon/isakmp_inf.h
new file mode 100644
index 0000000..c7682d9
--- /dev/null
+++ b/src/racoon/isakmp_inf.h
@@ -0,0 +1,60 @@
+/*	$NetBSD: isakmp_inf.h,v 1.4 2006/09/09 16:22:09 manu Exp $	*/
+
+/* Id: isakmp_inf.h,v 1.6 2005/05/07 14:15:59 manubsd Exp */
+
+/*
+ * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _ISAKMP_INF_H
+#define _ISAKMP_INF_H
+
+struct saproto;
+extern int isakmp_info_recv __P((struct ph1handle *, vchar_t *));
+extern int isakmp_info_send_d1 __P((struct ph1handle *));
+extern int isakmp_info_send_d2 __P((struct ph2handle *));
+extern int isakmp_info_send_nx __P((struct isakmp *,
+	struct sockaddr *, struct sockaddr *, int, vchar_t *));
+extern int isakmp_info_send_n1 __P((struct ph1handle *, int, vchar_t *));
+extern int isakmp_info_send_n2 __P((struct ph2handle *, int, vchar_t *));
+extern int isakmp_info_send_common __P((struct ph1handle *,
+	vchar_t *, u_int32_t, int));
+
+extern vchar_t * isakmp_add_pl_n __P((vchar_t *, u_int8_t **, int,
+	struct saproto *, vchar_t *));
+
+extern void isakmp_check_notify __P((struct isakmp_gen *, struct ph1handle *));
+
+#ifdef ENABLE_DPD
+extern int isakmp_sched_r_u __P((struct ph1handle *, int));
+#endif
+
+extern void purge_ipsec_spi __P((struct sockaddr *, int,	u_int32_t *, size_t));
+extern int tunnel_mode_prop __P((struct saprop *));
+
+#endif /* _ISAKMP_INF_H */
diff --git a/src/racoon/isakmp_newg.c b/src/racoon/isakmp_newg.c
new file mode 100644
index 0000000..211e632
--- /dev/null
+++ b/src/racoon/isakmp_newg.c
@@ -0,0 +1,232 @@
+/*	$NetBSD: isakmp_newg.c,v 1.4 2006/09/09 16:22:09 manu Exp $	*/
+
+/*	$KAME: isakmp_newg.c,v 1.10 2002/09/27 05:55:52 itojun Exp $	*/
+
+/*
+ * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include <sys/types.h>
+#include <sys/param.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+
+#include "var.h"
+#include "misc.h"
+#include "vmbuf.h"
+#include "plog.h"
+#include "sockmisc.h"
+#include "debug.h"
+
+#include "schedule.h"
+#include "cfparse_proto.h"
+#include "isakmp_var.h"
+#include "isakmp.h"
+#include "isakmp_newg.h"
+#include "oakley.h"
+#include "ipsec_doi.h"
+#include "crypto_openssl.h"
+#include "handler.h"
+#include "pfkey.h"
+#include "admin.h"
+#include "str2val.h"
+#include "vendorid.h"
+
+/*
+ * New group mode as responder
+ */
+int
+isakmp_newgroup_r(iph1, msg)
+	struct ph1handle *iph1;
+	vchar_t *msg;
+{
+#if 0
+	struct isakmp *isakmp = (struct isakmp *)msg->v;
+	struct isakmp_pl_hash *hash = NULL;
+	struct isakmp_pl_sa *sa = NULL;
+	int error = -1;
+	vchar_t *buf;
+	struct oakley_sa *osa;
+	int len;
+
+	/* validate the type of next payload */
+	/*
+	 * ISAKMP_ETYPE_NEWGRP,
+	 * ISAKMP_NPTYPE_HASH, (ISAKMP_NPTYPE_VID), ISAKMP_NPTYPE_SA,
+	 * ISAKMP_NPTYPE_NONE
+	 */
+    {
+	vchar_t *pbuf = NULL;
+	struct isakmp_parse_t *pa;
+
+	if ((pbuf = isakmp_parse(msg)) == NULL)
+		goto end;
+
+	for (pa = (struct isakmp_parse_t *)pbuf->v;
+	     pa->type != ISAKMP_NPTYPE_NONE;
+	     pa++) {
+
+		switch (pa->type) {
+		case ISAKMP_NPTYPE_HASH:
+			if (hash) {
+				isakmp_info_send_n1(iph1, ISAKMP_NTYPE_INVALID_PAYLOAD_TYPE, NULL);
+				plog(LLV_ERROR, LOCATION, iph1->remote,
+					"received multiple payload type %d.\n",
+					pa->type);
+				vfree(pbuf);
+				goto end;
+			}
+			hash = (struct isakmp_pl_hash *)pa->ptr;
+			break;
+		case ISAKMP_NPTYPE_SA:
+			if (sa) {
+				isakmp_info_send_n1(iph1, ISAKMP_NTYPE_INVALID_PAYLOAD_TYPE, NULL);
+				plog(LLV_ERROR, LOCATION, iph1->remote,
+					"received multiple payload type %d.\n",
+					pa->type);
+				vfree(pbuf);
+				goto end;
+			}
+			sa = (struct isakmp_pl_sa *)pa->ptr;
+			break;
+		case ISAKMP_NPTYPE_VID:
+			(void)check_vendorid(pa->ptr);
+			break;
+		default:
+			isakmp_info_send_n1(iph1, ISAKMP_NTYPE_INVALID_PAYLOAD_TYPE, NULL);
+			plog(LLV_ERROR, LOCATION, iph1->remote,
+				"ignore the packet, "
+				"received unexpecting payload type %d.\n",
+				pa->type);
+			vfree(pbuf);
+			goto end;
+		}
+	}
+	vfree(pbuf);
+
+	if (!hash || !sa) {
+		isakmp_info_send_n1(iph1, ISAKMP_NTYPE_INVALID_PAYLOAD_TYPE, NULL);
+		plog(LLV_ERROR, LOCATION, iph1->remote,
+			"no HASH, or no SA payload.\n");
+		goto end;
+	}
+    }
+
+	/* validate HASH */
+    {
+	char *r_hash;
+	vchar_t *my_hash = NULL;
+	int result;
+
+	plog(LLV_DEBUG, LOCATION, NULL, "validate HASH\n");
+
+	len = sizeof(isakmp->msgid) + ntohs(sa->h.len);
+	buf = vmalloc(len);
+	if (buf == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"failed to get buffer to send.\n");
+		goto end;
+	}
+	memcpy(buf->v, &isakmp->msgid, sizeof(isakmp->msgid));
+	memcpy(buf->v + sizeof(isakmp->msgid), sa, ntohs(sa->h.len));
+
+	plog(LLV_DEBUG, LOCATION, NULL, "hash source\n");
+	plogdump(LLV_DEBUG, buf->v, buf->l);
+
+	my_hash = isakmp_prf(iph1->skeyid_a, buf, iph1);
+	vfree(buf);
+	if (my_hash == NULL)
+		goto end;
+
+	plog(LLV_DEBUG, LOCATION, NULL, "hash result\n");
+	plogdump(LLV_DEBUG, my_hash->v, my_hash->l);
+
+	r_hash = (char *)hash + sizeof(*hash);
+
+	plog(LLV_DEBUG, LOCATION, NULL, "original hash\n"));
+	plogdump(LLV_DEBUG, r_hash, ntohs(hash->h.len) - sizeof(*hash)));
+
+	result = memcmp(my_hash->v, r_hash, my_hash->l);
+	vfree(my_hash);
+
+	if (result) {
+		plog(LLV_ERROR, LOCATION, iph1->remote,
+			"HASH mismatch.\n");
+		isakmp_info_send_n1(iph1, ISAKMP_NTYPE_INVALID_HASH_INFORMATION, NULL);
+		goto end;
+	}
+    }
+
+	/* check SA payload and get new one for use */
+	buf = ipsecdoi_get_proposal((struct ipsecdoi_sa *)sa,
+					OAKLEY_NEWGROUP_MODE);
+	if (buf == NULL) {
+		isakmp_info_send_n1(iph1, ISAKMP_NTYPE_ATTRIBUTES_NOT_SUPPORTED, NULL);
+		goto end;
+	}
+
+	/* save sa parameters */
+	osa = ipsecdoi_get_oakley(buf);
+	if (osa == NULL) {
+		isakmp_info_send_n1(iph1, ISAKMP_NTYPE_ATTRIBUTES_NOT_SUPPORTED, NULL);
+		goto end;
+	}
+	vfree(buf);
+
+	switch (osa->dhgrp) {
+	case OAKLEY_ATTR_GRP_DESC_MODP768:
+	case OAKLEY_ATTR_GRP_DESC_MODP1024:
+	case OAKLEY_ATTR_GRP_DESC_MODP1536:
+		/*XXX*/
+	default:
+		isakmp_info_send_n1(iph1, ISAKMP_NTYPE_ATTRIBUTES_NOT_SUPPORTED, NULL);
+		plog(LLV_ERROR, LOCATION, NULL,
+			"dh group %d isn't supported.\n", osa->dhgrp);
+		goto end;
+	}
+
+	plog(LLV_INFO, LOCATION, iph1->remote,
+		"got new dh group %s.\n", isakmp_pindex(&iph1->index, 0));
+
+	error = 0;
+
+end:
+	if (error) {
+		if (iph1 != NULL)
+			(void)isakmp_free_ph1(iph1);
+	}
+	return error;
+#endif
+	return 0;
+}
+
diff --git a/src/racoon/isakmp_newg.h b/src/racoon/isakmp_newg.h
new file mode 100644
index 0000000..1562c41
--- /dev/null
+++ b/src/racoon/isakmp_newg.h
@@ -0,0 +1,39 @@
+/*	$NetBSD: isakmp_newg.h,v 1.4 2006/09/09 16:22:09 manu Exp $	*/
+
+/* Id: isakmp_newg.h,v 1.3 2004/06/11 16:00:16 ludvigm Exp */
+
+/*
+ * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _ISAKMP_NEWG_H
+#define _ISAKMP_NEWG_H
+
+extern int isakmp_newgroup_r __P((struct ph1handle *, vchar_t *));
+
+#endif /* _ISAKMP_NEWG_H */
diff --git a/src/racoon/isakmp_quick.c b/src/racoon/isakmp_quick.c
new file mode 100644
index 0000000..2ff7639
--- /dev/null
+++ b/src/racoon/isakmp_quick.c
@@ -0,0 +1,2188 @@
+/*	$NetBSD: isakmp_quick.c,v 1.11.4.1 2007/08/01 11:52:21 vanhu Exp $	*/
+
+/* Id: isakmp_quick.c,v 1.29 2006/08/22 18:17:17 manubsd Exp */
+
+/*
+ * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+
+#include <netinet/in.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#if TIME_WITH_SYS_TIME
+# include <sys/time.h>
+# include <time.h>
+#else
+# if HAVE_SYS_TIME_H
+#  include <sys/time.h>
+# else
+#  include <time.h>
+# endif
+#endif
+#ifdef ENABLE_HYBRID
+#include <resolv.h>
+#endif
+
+#include PATH_IPSEC_H
+
+#include "var.h"
+#include "vmbuf.h"
+#include "schedule.h"
+#include "misc.h"
+#include "plog.h"
+#include "debug.h"
+
+#include "localconf.h"
+#include "remoteconf.h"
+#include "handler.h"
+#include "policy.h"
+#include "proposal.h"
+#include "isakmp_var.h"
+#include "isakmp.h"
+#include "isakmp_inf.h"
+#include "isakmp_quick.h"
+#include "oakley.h"
+#include "ipsec_doi.h"
+#include "crypto_openssl.h"
+#include "pfkey.h"
+#include "policy.h"
+#include "algorithm.h"
+#include "sockmisc.h"
+#include "proposal.h"
+#include "sainfo.h"
+#include "admin.h"
+#include "strnames.h"
+
+/* quick mode */
+static vchar_t *quick_ir1mx __P((struct ph2handle *, vchar_t *, vchar_t *));
+static int get_sainfo_r __P((struct ph2handle *));
+static int get_proposal_r __P((struct ph2handle *));
+
+/* %%%
+ * Quick Mode
+ */
+/*
+ * begin Quick Mode as initiator.  send pfkey getspi message to kernel.
+ */
+int
+quick_i1prep(iph2, msg)
+	struct ph2handle *iph2;
+	vchar_t *msg; /* must be null pointer */
+{
+	int error = ISAKMP_INTERNAL_ERROR;
+
+	/* validity check */
+	if (iph2->status != PHASE2ST_STATUS2) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"status mismatched %d.\n", iph2->status);
+		goto end;
+	}
+
+	iph2->msgid = isakmp_newmsgid2(iph2->ph1);
+	iph2->ivm = oakley_newiv2(iph2->ph1, iph2->msgid);
+	if (iph2->ivm == NULL)
+		return 0;
+
+	iph2->status = PHASE2ST_GETSPISENT;
+
+	/* don't anything if local test mode. */
+	if (f_local) {
+		error = 0;
+		goto end;
+	}
+
+	/* send getspi message */
+	if (pk_sendgetspi(iph2) < 0)
+		goto end;
+
+	plog(LLV_DEBUG, LOCATION, NULL, "pfkey getspi sent.\n");
+
+	iph2->sce = sched_new(lcconf->wait_ph2complete,
+		pfkey_timeover_stub, iph2);
+
+	error = 0;
+
+end:
+	return error;
+}
+
+/*
+ * send to responder
+ * 	HDR*, HASH(1), SA, Ni [, KE ] [, IDi2, IDr2 ]
+ */
+int
+quick_i1send(iph2, msg)
+	struct ph2handle *iph2;
+	vchar_t *msg; /* must be null pointer */
+{
+	vchar_t *body = NULL;
+	vchar_t *hash = NULL;
+	struct isakmp_gen *gen;
+	char *p;
+	int tlen;
+	int error = ISAKMP_INTERNAL_ERROR;
+	int pfsgroup, idci, idcr;
+	int np;
+	struct ipsecdoi_id_b *id, *id_p;
+
+	/* validity check */
+	if (msg != NULL) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"msg has to be NULL in this function.\n");
+		goto end;
+	}
+	if (iph2->status != PHASE2ST_GETSPIDONE) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"status mismatched %d.\n", iph2->status);
+		goto end;
+	}
+
+	/* create SA payload for my proposal */
+	if (ipsecdoi_setph2proposal(iph2) < 0)
+		goto end;
+
+	/* generate NONCE value */
+	iph2->nonce = eay_set_random(iph2->ph1->rmconf->nonce_size);
+	if (iph2->nonce == NULL)
+		goto end;
+
+	/*
+	 * DH value calculation is kicked out into cfparse.y.
+	 * because pfs group can not be negotiated, it's only to be checked
+	 * acceptable.
+	 */
+	/* generate KE value if need */
+	pfsgroup = iph2->proposal->pfs_group;
+	if (pfsgroup) {
+		/* DH group settting if PFS is required. */
+		if (oakley_setdhgroup(pfsgroup, &iph2->pfsgrp) < 0) {
+			plog(LLV_ERROR, LOCATION, NULL,
+				"failed to set DH value.\n");
+			goto end;
+		}
+		if (oakley_dh_generate(iph2->pfsgrp,
+				&iph2->dhpub, &iph2->dhpriv) < 0) {
+			goto end;
+		}
+	}
+
+	/* generate ID value */
+	if (ipsecdoi_setid2(iph2) < 0) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"failed to get ID.\n");
+		goto end;
+	}
+	plog(LLV_DEBUG, LOCATION, NULL, "IDci:\n");
+	plogdump(LLV_DEBUG, iph2->id->v, iph2->id->l);
+	plog(LLV_DEBUG, LOCATION, NULL, "IDcr:\n");
+	plogdump(LLV_DEBUG, iph2->id_p->v, iph2->id_p->l);
+
+	/*
+	 * we do not attach IDci nor IDcr, under the following condition:
+	 * - all proposals are transport mode
+	 * - no MIP6 or proxy
+	 * - id payload suggests to encrypt all the traffic (no specific
+	 *   protocol type)
+	 */
+	id = (struct ipsecdoi_id_b *)iph2->id->v;
+	id_p = (struct ipsecdoi_id_b *)iph2->id_p->v;
+	if (id->proto_id == 0
+	 && id_p->proto_id == 0
+	 && iph2->ph1->rmconf->support_proxy == 0
+	 && ipsecdoi_transportmode(iph2->proposal)) {
+		idci = idcr = 0;
+	} else
+		idci = idcr = 1;
+
+	/* create SA;NONCE payload, and KE if need, and IDii, IDir. */
+	tlen = + sizeof(*gen) + iph2->sa->l
+		+ sizeof(*gen) + iph2->nonce->l;
+	if (pfsgroup)
+		tlen += (sizeof(*gen) + iph2->dhpub->l);
+	if (idci)
+		tlen += sizeof(*gen) + iph2->id->l;
+	if (idcr)
+		tlen += sizeof(*gen) + iph2->id_p->l;
+
+	body = vmalloc(tlen);
+	if (body == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"failed to get buffer to send.\n");
+		goto end;
+	}
+
+	p = body->v;
+
+	/* add SA payload */
+	p = set_isakmp_payload(p, iph2->sa, ISAKMP_NPTYPE_NONCE);
+
+	/* add NONCE payload */
+	if (pfsgroup)
+		np = ISAKMP_NPTYPE_KE;
+	else if (idci || idcr)
+		np = ISAKMP_NPTYPE_ID;
+	else
+		np = ISAKMP_NPTYPE_NONE;
+	p = set_isakmp_payload(p, iph2->nonce, np);
+
+	/* add KE payload if need. */
+	np = (idci || idcr) ? ISAKMP_NPTYPE_ID : ISAKMP_NPTYPE_NONE;
+	if (pfsgroup)
+		p = set_isakmp_payload(p, iph2->dhpub, np);
+
+	/* IDci */
+	np = (idcr) ? ISAKMP_NPTYPE_ID : ISAKMP_NPTYPE_NONE;
+	if (idci)
+		p = set_isakmp_payload(p, iph2->id, np);
+
+	/* IDcr */
+	if (idcr)
+		p = set_isakmp_payload(p, iph2->id_p, ISAKMP_NPTYPE_NONE);
+
+	/* generate HASH(1) */
+	hash = oakley_compute_hash1(iph2->ph1, iph2->msgid, body);
+	if (hash == NULL)
+		goto end;
+
+	/* send isakmp payload */
+	iph2->sendbuf = quick_ir1mx(iph2, body, hash);
+	if (iph2->sendbuf == NULL)
+		goto end;
+
+	/* send the packet, add to the schedule to resend */
+	iph2->retry_counter = iph2->ph1->rmconf->retry_counter;
+	if (isakmp_ph2resend(iph2) == -1)
+		goto end;
+
+	/* change status of isakmp status entry */
+	iph2->status = PHASE2ST_MSG1SENT;
+
+	error = 0;
+
+end:
+	if (body != NULL)
+		vfree(body);
+	if (hash != NULL)
+		vfree(hash);
+
+	return error;
+}
+
+/*
+ * receive from responder
+ * 	HDR*, HASH(2), SA, Nr [, KE ] [, IDi2, IDr2 ]
+ */
+int
+quick_i2recv(iph2, msg0)
+	struct ph2handle *iph2;
+	vchar_t *msg0;
+{
+	vchar_t *msg = NULL;
+	vchar_t *hbuf = NULL;	/* for hash computing. */
+	vchar_t *pbuf = NULL;	/* for payload parsing */
+	struct isakmp_parse_t *pa;
+	struct isakmp *isakmp = (struct isakmp *)msg0->v;
+	struct isakmp_pl_hash *hash = NULL;
+	int f_id;
+	char *p;
+	int tlen;
+	int error = ISAKMP_INTERNAL_ERROR;
+
+	/* validity check */
+	if (iph2->status != PHASE2ST_MSG1SENT) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"status mismatched %d.\n", iph2->status);
+		goto end;
+	}
+
+	/* decrypt packet */
+	if (!ISSET(((struct isakmp *)msg0->v)->flags, ISAKMP_FLAG_E)) {
+		plog(LLV_ERROR, LOCATION, iph2->ph1->remote,
+			"Packet wasn't encrypted.\n");
+		goto end;
+	}
+	msg = oakley_do_decrypt(iph2->ph1, msg0, iph2->ivm->iv, iph2->ivm->ive);
+	if (msg == NULL)
+		goto end;
+
+	/* create buffer for validating HASH(2) */
+	/*
+	 * ordering rule:
+	 *	1. the first one must be HASH
+	 *	2. the second one must be SA (added in isakmp-oakley-05!)
+	 *	3. two IDs must be considered as IDci, then IDcr
+	 */
+	pbuf = isakmp_parse(msg);
+	if (pbuf == NULL)
+		goto end;
+	pa = (struct isakmp_parse_t *)pbuf->v;
+
+	/* HASH payload is fixed postion */
+	if (pa->type != ISAKMP_NPTYPE_HASH) {
+		plog(LLV_ERROR, LOCATION, iph2->ph1->remote,
+			"received invalid next payload type %d, "
+			"expecting %d.\n",
+			pa->type, ISAKMP_NPTYPE_HASH);
+		goto end;
+	}
+	hash = (struct isakmp_pl_hash *)pa->ptr;
+	pa++;
+
+	/*
+	 * this restriction was introduced in isakmp-oakley-05.
+	 * we do not check this for backward compatibility.
+	 * TODO: command line/config file option to enable/disable this code
+	 */
+	/* HASH payload is fixed postion */
+	if (pa->type != ISAKMP_NPTYPE_SA) {
+		plog(LLV_WARNING, LOCATION, iph2->ph1->remote,
+			"received invalid next payload type %d, "
+			"expecting %d.\n",
+			pa->type, ISAKMP_NPTYPE_HASH);
+	}
+
+	/* allocate buffer for computing HASH(2) */
+	tlen = iph2->nonce->l
+		+ ntohl(isakmp->len) - sizeof(*isakmp);
+	hbuf = vmalloc(tlen);
+	if (hbuf == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"failed to get hash buffer.\n");
+		goto end;
+	}
+	p = hbuf->v + iph2->nonce->l;	/* retain the space for Ni_b */
+
+	/*
+	 * parse the payloads.
+	 * copy non-HASH payloads into hbuf, so that we can validate HASH.
+	 */
+	iph2->sa_ret = NULL;
+	f_id = 0;	/* flag to use checking ID */
+	tlen = 0;	/* count payload length except of HASH payload. */
+	for (; pa->type; pa++) {
+
+		/* copy to buffer for HASH */
+		/* Don't modify the payload */
+		memcpy(p, pa->ptr, pa->len);
+
+		switch (pa->type) {
+		case ISAKMP_NPTYPE_SA:
+			if (iph2->sa_ret != NULL) {
+				plog(LLV_ERROR, LOCATION, NULL,
+					"Ignored, multiple SA "
+					"isn't supported.\n");
+				break;
+			}
+			if (isakmp_p2ph(&iph2->sa_ret, pa->ptr) < 0)
+				goto end;
+			break;
+
+		case ISAKMP_NPTYPE_NONCE:
+			if (isakmp_p2ph(&iph2->nonce_p, pa->ptr) < 0)
+				goto end;
+			break;
+
+		case ISAKMP_NPTYPE_KE:
+			if (isakmp_p2ph(&iph2->dhpub_p, pa->ptr) < 0)
+				goto end;
+			break;
+
+		case ISAKMP_NPTYPE_ID:
+		    {
+			vchar_t *vp;
+
+			/* check ID value */
+			if (f_id == 0) {
+				/* for IDci */
+				f_id = 1;
+				vp = iph2->id;
+			} else {
+				/* for IDcr */
+				vp = iph2->id_p;
+			}
+#ifndef ANDROID_CHANGES	// This block of code wont allow us to talk to Microsoft L2TP/IPSEC server
+			if (memcmp(vp->v, (caddr_t)pa->ptr + sizeof(struct isakmp_gen), vp->l)) {
+
+				plog(LLV_ERROR, LOCATION, NULL,
+					"mismatched ID was returned.\n");
+				error = ISAKMP_NTYPE_ATTRIBUTES_NOT_SUPPORTED;
+				goto end;
+			}
+#endif			
+		    }
+			break;
+
+		case ISAKMP_NPTYPE_N:
+			isakmp_check_notify(pa->ptr, iph2->ph1);
+			break;
+
+#ifdef ENABLE_NATT
+		case ISAKMP_NPTYPE_NATOA_DRAFT:
+		case ISAKMP_NPTYPE_NATOA_RFC:
+			/* Ignore original source/destination messages */
+			break;
+#endif
+
+		default:
+			/* don't send information, see ident_r1recv() */
+			plog(LLV_ERROR, LOCATION, iph2->ph1->remote,
+				"ignore the packet, "
+				"received unexpecting payload type %d.\n",
+				pa->type);
+			goto end;
+		}
+
+		p += pa->len;
+
+		/* compute true length of payload. */
+		tlen += pa->len;
+	}
+
+	/* payload existency check */
+	if (hash == NULL || iph2->sa_ret == NULL || iph2->nonce_p == NULL) {
+		plog(LLV_ERROR, LOCATION, iph2->ph1->remote,
+			"few isakmp message received.\n");
+		goto end;
+	}
+
+	/* Fixed buffer for calculating HASH */
+	memcpy(hbuf->v, iph2->nonce->v, iph2->nonce->l);
+	plog(LLV_DEBUG, LOCATION, NULL,
+		"HASH allocated:hbuf->l=%zu actual:tlen=%zu\n",
+		hbuf->l, tlen + iph2->nonce->l);
+	/* adjust buffer length for HASH */
+	hbuf->l = iph2->nonce->l + tlen;
+
+	/* validate HASH(2) */
+    {
+	char *r_hash;
+	vchar_t *my_hash = NULL;
+	int result;
+
+	r_hash = (char *)hash + sizeof(*hash);
+
+	plog(LLV_DEBUG, LOCATION, NULL, "HASH(2) received:");
+	plogdump(LLV_DEBUG, r_hash, ntohs(hash->h.len) - sizeof(*hash));
+
+	my_hash = oakley_compute_hash1(iph2->ph1, iph2->msgid, hbuf);
+	if (my_hash == NULL)
+		goto end;
+
+	result = memcmp(my_hash->v, r_hash, my_hash->l);
+	vfree(my_hash);
+
+	if (result) {
+		plog(LLV_DEBUG, LOCATION, iph2->ph1->remote,
+			"HASH(2) mismatch.\n");
+		error = ISAKMP_NTYPE_INVALID_HASH_INFORMATION;
+		goto end;
+	}
+    }
+
+	/* validity check SA payload sent from responder */
+	if (ipsecdoi_checkph2proposal(iph2) < 0) {
+		error = ISAKMP_NTYPE_NO_PROPOSAL_CHOSEN;
+		goto end;
+	}
+
+	/* change status of isakmp status entry */
+	iph2->status = PHASE2ST_STATUS6;
+
+	error = 0;
+
+end:
+	if (hbuf)
+		vfree(hbuf);
+	if (pbuf)
+		vfree(pbuf);
+	if (msg)
+		vfree(msg);
+
+	if (error) {
+		VPTRINIT(iph2->sa_ret);
+		VPTRINIT(iph2->nonce_p);
+		VPTRINIT(iph2->dhpub_p);
+		VPTRINIT(iph2->id);
+		VPTRINIT(iph2->id_p);
+	}
+
+	return error;
+}
+
+/*
+ * send to responder
+ * 	HDR*, HASH(3)
+ */
+int
+quick_i2send(iph2, msg0)
+	struct ph2handle *iph2;
+	vchar_t *msg0;
+{
+	vchar_t *msg = NULL;
+	vchar_t *buf = NULL;
+	vchar_t *hash = NULL;
+	char *p = NULL;
+	int tlen;
+	int error = ISAKMP_INTERNAL_ERROR;
+
+	/* validity check */
+	if (iph2->status != PHASE2ST_STATUS6) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"status mismatched %d.\n", iph2->status);
+		goto end;
+	}
+
+	/* generate HASH(3) */
+    {
+	vchar_t *tmp = NULL;
+
+	plog(LLV_DEBUG, LOCATION, NULL, "HASH(3) generate\n");
+
+	tmp = vmalloc(iph2->nonce->l + iph2->nonce_p->l);
+	if (tmp == NULL) { 
+		plog(LLV_ERROR, LOCATION, NULL,
+			"failed to get hash buffer.\n");
+		goto end;
+	}
+	memcpy(tmp->v, iph2->nonce->v, iph2->nonce->l);
+	memcpy(tmp->v + iph2->nonce->l, iph2->nonce_p->v, iph2->nonce_p->l);
+
+	hash = oakley_compute_hash3(iph2->ph1, iph2->msgid, tmp);
+	vfree(tmp);
+
+	if (hash == NULL)
+		goto end;
+    }
+
+	/* create buffer for isakmp payload */
+	tlen = sizeof(struct isakmp)
+		+ sizeof(struct isakmp_gen) + hash->l;
+	buf = vmalloc(tlen);
+	if (buf == NULL) { 
+		plog(LLV_ERROR, LOCATION, NULL,
+			"failed to get buffer to send.\n");
+		goto end;
+	}
+
+	/* create isakmp header */
+	p = set_isakmp_header2(buf, iph2, ISAKMP_NPTYPE_HASH);
+	if (p == NULL)
+		goto end;
+
+	/* add HASH(3) payload */
+	p = set_isakmp_payload(p, hash, ISAKMP_NPTYPE_NONE);
+
+#ifdef HAVE_PRINT_ISAKMP_C
+	isakmp_printpacket(buf, iph2->ph1->local, iph2->ph1->remote, 1);
+#endif
+
+	/* encoding */
+	iph2->sendbuf = oakley_do_encrypt(iph2->ph1, buf, iph2->ivm->ive, iph2->ivm->iv);
+	if (iph2->sendbuf == NULL)
+		goto end;
+
+	/* if there is commit bit, need resending */
+	if (ISSET(iph2->flags, ISAKMP_FLAG_C)) {
+		/* send the packet, add to the schedule to resend */
+		iph2->retry_counter = iph2->ph1->rmconf->retry_counter;
+		if (isakmp_ph2resend(iph2) == -1)
+			goto end;
+	} else {
+		/* send the packet */
+		if (isakmp_send(iph2->ph1, iph2->sendbuf) < 0)
+			goto end;
+	}
+
+	/* the sending message is added to the received-list. */
+	if (add_recvdpkt(iph2->ph1->remote, iph2->ph1->local,
+			iph2->sendbuf, msg0) == -1) {
+		plog(LLV_ERROR , LOCATION, NULL,
+			"failed to add a response packet to the tree.\n");
+		goto end;
+	}
+
+	/* compute both of KEYMATs */
+	if (oakley_compute_keymat(iph2, INITIATOR) < 0)
+		goto end;
+
+	iph2->status = PHASE2ST_ADDSA;
+
+	/* don't anything if local test mode. */
+	if (f_local) {
+		error = 0;
+		goto end;
+	}
+
+	/* if there is commit bit don't set up SA now. */
+	if (ISSET(iph2->flags, ISAKMP_FLAG_C)) {
+		iph2->status = PHASE2ST_COMMIT;
+		error = 0;
+		goto end;
+	}
+
+	/* Do UPDATE for initiator */
+	plog(LLV_DEBUG, LOCATION, NULL, "call pk_sendupdate\n");
+	if (pk_sendupdate(iph2) < 0) {
+		plog(LLV_ERROR, LOCATION, NULL, "pfkey update failed.\n");
+		goto end;
+	}
+	plog(LLV_DEBUG, LOCATION, NULL, "pfkey update sent.\n");
+
+	/* Do ADD for responder */
+	if (pk_sendadd(iph2) < 0) {
+		plog(LLV_ERROR, LOCATION, NULL, "pfkey add failed.\n");
+		goto end;
+	}
+	plog(LLV_DEBUG, LOCATION, NULL, "pfkey add sent.\n");
+
+	error = 0;
+
+end:
+	if (buf != NULL)
+		vfree(buf);
+	if (msg != NULL)
+		vfree(msg);
+	if (hash != NULL)
+		vfree(hash);
+
+	return error;
+}
+
+/*
+ * receive from responder
+ * 	HDR#*, HASH(4), notify
+ */
+int
+quick_i3recv(iph2, msg0)
+	struct ph2handle *iph2;
+	vchar_t *msg0;
+{
+	vchar_t *msg = NULL;
+	vchar_t *pbuf = NULL;	/* for payload parsing */
+	struct isakmp_parse_t *pa;
+	struct isakmp_pl_hash *hash = NULL;
+	vchar_t *notify = NULL;
+	int error = ISAKMP_INTERNAL_ERROR;
+
+	/* validity check */
+	if (iph2->status != PHASE2ST_COMMIT) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"status mismatched %d.\n", iph2->status);
+		goto end;
+	}
+
+	/* decrypt packet */
+	if (!ISSET(((struct isakmp *)msg0->v)->flags, ISAKMP_FLAG_E)) {
+		plog(LLV_ERROR, LOCATION, iph2->ph1->remote,
+			"Packet wasn't encrypted.\n");
+		goto end;
+	}
+	msg = oakley_do_decrypt(iph2->ph1, msg0, iph2->ivm->iv, iph2->ivm->ive);
+	if (msg == NULL)
+		goto end;
+
+	/* validate the type of next payload */
+	pbuf = isakmp_parse(msg);
+	if (pbuf == NULL)
+		goto end;
+
+	for (pa = (struct isakmp_parse_t *)pbuf->v;
+	     pa->type != ISAKMP_NPTYPE_NONE;
+	     pa++) {
+
+		switch (pa->type) {
+		case ISAKMP_NPTYPE_HASH:
+			hash = (struct isakmp_pl_hash *)pa->ptr;
+			break;
+		case ISAKMP_NPTYPE_N:
+			if (notify != NULL) {
+				plog(LLV_WARNING, LOCATION, NULL,
+				    "Ignoring multiples notifications\n");
+				break;
+			}
+			isakmp_check_notify(pa->ptr, iph2->ph1);
+			notify = vmalloc(pa->len);
+			if (notify == NULL) {
+				plog(LLV_ERROR, LOCATION, NULL,
+					"failed to get notify buffer.\n");
+				goto end;
+			}
+			memcpy(notify->v, pa->ptr, notify->l);
+			break;
+		default:
+			/* don't send information, see ident_r1recv() */
+			plog(LLV_ERROR, LOCATION, iph2->ph1->remote,
+				"ignore the packet, "
+				"received unexpecting payload type %d.\n",
+				pa->type);
+			goto end;
+		}
+	}
+
+	/* payload existency check */
+	if (hash == NULL) {
+		plog(LLV_ERROR, LOCATION, iph2->ph1->remote,
+			"few isakmp message received.\n");
+		goto end;
+	}
+
+	/* validate HASH(4) */
+    {
+	char *r_hash;
+	vchar_t *my_hash = NULL;
+	vchar_t *tmp = NULL;
+	int result;
+
+	r_hash = (char *)hash + sizeof(*hash);
+
+	plog(LLV_DEBUG, LOCATION, NULL, "HASH(4) validate:");
+	plogdump(LLV_DEBUG, r_hash, ntohs(hash->h.len) - sizeof(*hash));
+
+	my_hash = oakley_compute_hash1(iph2->ph1, iph2->msgid, notify);
+	vfree(tmp);
+	if (my_hash == NULL)
+		goto end;
+
+	result = memcmp(my_hash->v, r_hash, my_hash->l);
+	vfree(my_hash);
+
+	if (result) {
+		plog(LLV_DEBUG, LOCATION, iph2->ph1->remote,
+			"HASH(4) mismatch.\n");
+		error = ISAKMP_NTYPE_INVALID_HASH_INFORMATION;
+		goto end;
+	}
+    }
+
+	iph2->status = PHASE2ST_ADDSA;
+	iph2->flags ^= ISAKMP_FLAG_C;	/* reset bit */
+
+	/* don't anything if local test mode. */
+	if (f_local) {
+		error = 0;
+		goto end;
+	}
+
+	/* Do UPDATE for initiator */
+	plog(LLV_DEBUG, LOCATION, NULL, "call pk_sendupdate\n");
+	if (pk_sendupdate(iph2) < 0) {
+		plog(LLV_ERROR, LOCATION, NULL, "pfkey update failed.\n");
+		goto end;
+	}
+	plog(LLV_DEBUG, LOCATION, NULL, "pfkey update sent.\n");
+
+	/* Do ADD for responder */
+	if (pk_sendadd(iph2) < 0) {
+		plog(LLV_ERROR, LOCATION, NULL, "pfkey add failed.\n");
+		goto end;
+	}
+	plog(LLV_DEBUG, LOCATION, NULL, "pfkey add sent.\n");
+
+	error = 0;
+
+end:
+	if (msg != NULL)
+		vfree(msg);
+	if (pbuf != NULL)
+		vfree(pbuf);
+	if (notify != NULL)
+		vfree(notify);
+
+	return error;
+}
+
+/*
+ * receive from initiator
+ * 	HDR*, HASH(1), SA, Ni [, KE ] [, IDi2, IDr2 ]
+ */
+int
+quick_r1recv(iph2, msg0)
+	struct ph2handle *iph2;
+	vchar_t *msg0;
+{
+	vchar_t *msg = NULL;
+	vchar_t *hbuf = NULL;	/* for hash computing. */
+	vchar_t *pbuf = NULL;	/* for payload parsing */
+	struct isakmp_parse_t *pa;
+	struct isakmp *isakmp = (struct isakmp *)msg0->v;
+	struct isakmp_pl_hash *hash = NULL;
+	char *p;
+	int tlen;
+	int f_id_order;	/* for ID payload detection */
+	int error = ISAKMP_INTERNAL_ERROR;
+
+	/* validity check */
+	if (iph2->status != PHASE2ST_START) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"status mismatched %d.\n", iph2->status);
+		goto end;
+	}
+
+	/* decrypting */
+	if (!ISSET(((struct isakmp *)msg0->v)->flags, ISAKMP_FLAG_E)) {
+		plog(LLV_ERROR, LOCATION, iph2->ph1->remote,
+			"Packet wasn't encrypted.\n");
+		error = ISAKMP_NTYPE_PAYLOAD_MALFORMED;
+		goto end;
+	}
+	/* decrypt packet */
+	msg = oakley_do_decrypt(iph2->ph1, msg0, iph2->ivm->iv, iph2->ivm->ive);
+	if (msg == NULL)
+		goto end;
+
+	/* create buffer for using to validate HASH(1) */
+	/*
+	 * ordering rule:
+	 *	1. the first one must be HASH
+	 *	2. the second one must be SA (added in isakmp-oakley-05!)
+	 *	3. two IDs must be considered as IDci, then IDcr
+	 */
+	pbuf = isakmp_parse(msg);
+	if (pbuf == NULL)
+		goto end;
+	pa = (struct isakmp_parse_t *)pbuf->v;
+
+	/* HASH payload is fixed postion */
+	if (pa->type != ISAKMP_NPTYPE_HASH) {
+		plog(LLV_ERROR, LOCATION, iph2->ph1->remote,
+			"received invalid next payload type %d, "
+			"expecting %d.\n",
+			pa->type, ISAKMP_NPTYPE_HASH);
+		error = ISAKMP_NTYPE_BAD_PROPOSAL_SYNTAX;
+		goto end;
+	}
+	hash = (struct isakmp_pl_hash *)pa->ptr;
+	pa++;
+
+	/*
+	 * this restriction was introduced in isakmp-oakley-05.
+	 * we do not check this for backward compatibility.
+	 * TODO: command line/config file option to enable/disable this code
+	 */
+	/* HASH payload is fixed postion */
+	if (pa->type != ISAKMP_NPTYPE_SA) {
+		plog(LLV_WARNING, LOCATION, iph2->ph1->remote,
+			"received invalid next payload type %d, "
+			"expecting %d.\n",
+			pa->type, ISAKMP_NPTYPE_SA);
+		error = ISAKMP_NTYPE_BAD_PROPOSAL_SYNTAX;
+	}
+
+	/* allocate buffer for computing HASH(1) */
+	tlen = ntohl(isakmp->len) - sizeof(*isakmp);
+	hbuf = vmalloc(tlen);
+	if (hbuf == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"failed to get hash buffer.\n");
+		goto end;
+	}
+	p = hbuf->v;
+
+	/*
+	 * parse the payloads.
+	 * copy non-HASH payloads into hbuf, so that we can validate HASH.
+	 */
+	iph2->sa = NULL;	/* we don't support multi SAs. */
+	iph2->nonce_p = NULL;
+	iph2->dhpub_p = NULL;
+	iph2->id_p = NULL;
+	iph2->id = NULL;
+	tlen = 0;	/* count payload length except of HASH payload. */
+
+	/*
+	 * IDi2 MUST be immediatelly followed by IDr2.  We allowed the
+	 * illegal case, but logged.  First ID payload is to be IDi2.
+	 * And next ID payload is to be IDr2.
+	 */
+	f_id_order = 0;
+
+	for (; pa->type; pa++) {
+
+		/* copy to buffer for HASH */
+		/* Don't modify the payload */
+		memcpy(p, pa->ptr, pa->len);
+
+		if (pa->type != ISAKMP_NPTYPE_ID)
+			f_id_order = 0;
+
+		switch (pa->type) {
+		case ISAKMP_NPTYPE_SA:
+			if (iph2->sa != NULL) {
+				plog(LLV_ERROR, LOCATION, NULL,
+					"Multi SAs isn't supported.\n");
+				goto end;
+			}
+			if (isakmp_p2ph(&iph2->sa, pa->ptr) < 0)
+				goto end;
+			break;
+
+		case ISAKMP_NPTYPE_NONCE:
+			if (isakmp_p2ph(&iph2->nonce_p, pa->ptr) < 0)
+				goto end;
+			break;
+
+		case ISAKMP_NPTYPE_KE:
+			if (isakmp_p2ph(&iph2->dhpub_p, pa->ptr) < 0)
+				goto end;
+			break;
+
+		case ISAKMP_NPTYPE_ID:
+			if (iph2->id_p == NULL) {
+				/* for IDci */
+				f_id_order++;
+
+				if (isakmp_p2ph(&iph2->id_p, pa->ptr) < 0)
+					goto end;
+
+			} else if (iph2->id == NULL) {
+				/* for IDcr */
+				if (f_id_order == 0) {
+					plog(LLV_ERROR, LOCATION, NULL,
+						"IDr2 payload is not "
+						"immediatelly followed "
+						"by IDi2. We allowed.\n");
+					/* XXX we allowed in this case. */
+				}
+
+				if (isakmp_p2ph(&iph2->id, pa->ptr) < 0)
+					goto end;
+			} else {
+				plog(LLV_ERROR, LOCATION, NULL,
+					"received too many ID payloads.\n");
+				plogdump(LLV_ERROR, iph2->id->v, iph2->id->l);
+				error = ISAKMP_NTYPE_INVALID_ID_INFORMATION;
+				goto end;
+			}
+			break;
+
+		case ISAKMP_NPTYPE_N:
+			isakmp_check_notify(pa->ptr, iph2->ph1);
+			break;
+
+#ifdef ENABLE_NATT
+		case ISAKMP_NPTYPE_NATOA_DRAFT:
+		case ISAKMP_NPTYPE_NATOA_RFC:
+			/* Ignore original source/destination messages */
+			break;
+#endif
+
+		default:
+			plog(LLV_ERROR, LOCATION, iph2->ph1->remote,
+				"ignore the packet, "
+				"received unexpecting payload type %d.\n",
+				pa->type);
+			error = ISAKMP_NTYPE_PAYLOAD_MALFORMED;
+			goto end;
+		}
+
+		p += pa->len;
+
+		/* compute true length of payload. */
+		tlen += pa->len;
+	}
+
+	/* payload existency check */
+	if (hash == NULL || iph2->sa == NULL || iph2->nonce_p == NULL) {
+		plog(LLV_ERROR, LOCATION, iph2->ph1->remote,
+			"few isakmp message received.\n");
+		error = ISAKMP_NTYPE_PAYLOAD_MALFORMED;
+		goto end;
+	}
+
+	if (iph2->id_p) {
+		plog(LLV_DEBUG, LOCATION, NULL, "received IDci2:");
+		plogdump(LLV_DEBUG, iph2->id_p->v, iph2->id_p->l);
+	}
+	if (iph2->id) {
+		plog(LLV_DEBUG, LOCATION, NULL, "received IDcr2:");
+		plogdump(LLV_DEBUG, iph2->id->v, iph2->id->l);
+	}
+
+	/* adjust buffer length for HASH */
+	hbuf->l = tlen;
+
+	/* validate HASH(1) */
+    {
+	char *r_hash;
+	vchar_t *my_hash = NULL;
+	int result;
+
+	r_hash = (caddr_t)hash + sizeof(*hash);
+
+	plog(LLV_DEBUG, LOCATION, NULL, "HASH(1) validate:");
+	plogdump(LLV_DEBUG, r_hash, ntohs(hash->h.len) - sizeof(*hash));
+
+	my_hash = oakley_compute_hash1(iph2->ph1, iph2->msgid, hbuf);
+	if (my_hash == NULL)
+		goto end;
+
+	result = memcmp(my_hash->v, r_hash, my_hash->l);
+	vfree(my_hash);
+
+	if (result) {
+		plog(LLV_DEBUG, LOCATION, iph2->ph1->remote,
+			"HASH(1) mismatch.\n");
+		error = ISAKMP_NTYPE_INVALID_HASH_INFORMATION;
+		goto end;
+	}
+    }
+
+	/* get sainfo */
+	error = get_sainfo_r(iph2);
+	if (error) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"failed to get sainfo.\n");
+		goto end;
+	}
+
+
+	/* check the existence of ID payload and create responder's proposal */
+	error = get_proposal_r(iph2);
+	switch (error) {
+	case -2:
+		/* generate a policy template from peer's proposal */
+		if (set_proposal_from_proposal(iph2)) {
+			plog(LLV_ERROR, LOCATION, NULL,
+				"failed to generate a proposal template "
+				"from client's proposal.\n");
+			return ISAKMP_INTERNAL_ERROR;
+		}
+		/*FALLTHROUGH*/
+	case 0:
+		/* select single proposal or reject it. */
+		if (ipsecdoi_selectph2proposal(iph2) < 0) {
+			error = ISAKMP_NTYPE_NO_PROPOSAL_CHOSEN;
+			goto end;
+		}
+		break;
+	default:
+		plog(LLV_ERROR, LOCATION, NULL,
+			"failed to get proposal for responder.\n");
+		goto end;
+	}
+
+	/* check KE and attribute of PFS */
+	if (iph2->dhpub_p != NULL && iph2->approval->pfs_group == 0) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"no PFS is specified, but peer sends KE.\n");
+		error = ISAKMP_NTYPE_NO_PROPOSAL_CHOSEN;
+		goto end;
+	}
+	if (iph2->dhpub_p == NULL && iph2->approval->pfs_group != 0) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"PFS is specified, but peer doesn't sends KE.\n");
+		error = ISAKMP_NTYPE_NO_PROPOSAL_CHOSEN;
+		goto end;
+	}
+
+	/*
+	 * save the packet from the initiator in order to resend the
+	 * responder's first packet against this packet.
+	 */
+	iph2->msg1 = vdup(msg0);
+
+	/* change status of isakmp status entry */
+	iph2->status = PHASE2ST_STATUS2;
+
+	error = 0;
+
+end:
+	if (hbuf)
+		vfree(hbuf);
+	if (msg)
+		vfree(msg);
+	if (pbuf)
+		vfree(pbuf);
+
+	if (error) {
+		VPTRINIT(iph2->sa);
+		VPTRINIT(iph2->nonce_p);
+		VPTRINIT(iph2->dhpub_p);
+		VPTRINIT(iph2->id);
+		VPTRINIT(iph2->id_p);
+	}
+
+	return error;
+}
+
+/*
+ * call pfkey_getspi.
+ */
+int
+quick_r1prep(iph2, msg)
+	struct ph2handle *iph2;
+	vchar_t *msg;
+{
+	int error = ISAKMP_INTERNAL_ERROR;
+
+	/* validity check */
+	if (iph2->status != PHASE2ST_STATUS2) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"status mismatched %d.\n", iph2->status);
+		goto end;
+	}
+
+	iph2->status = PHASE2ST_GETSPISENT;
+
+	/* send getspi message */
+	if (pk_sendgetspi(iph2) < 0)
+		goto end;
+
+	plog(LLV_DEBUG, LOCATION, NULL, "pfkey getspi sent.\n");
+
+	iph2->sce = sched_new(lcconf->wait_ph2complete,
+		pfkey_timeover_stub, iph2);
+
+	error = 0;
+
+end:
+	return error;
+}
+
+/*
+ * send to initiator
+ * 	HDR*, HASH(2), SA, Nr [, KE ] [, IDi2, IDr2 ]
+ */
+int
+quick_r2send(iph2, msg)
+	struct ph2handle *iph2;
+	vchar_t *msg;
+{
+	vchar_t *body = NULL;
+	vchar_t *hash = NULL;
+	struct isakmp_gen *gen;
+	char *p;
+	int tlen;
+	int error = ISAKMP_INTERNAL_ERROR;
+	int pfsgroup;
+	u_int8_t *np_p = NULL;
+
+	/* validity check */
+	if (msg != NULL) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"msg has to be NULL in this function.\n");
+		goto end;
+	}
+	if (iph2->status != PHASE2ST_GETSPIDONE) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"status mismatched %d.\n", iph2->status);
+		goto end;
+	}
+
+	/* update responders SPI */
+	if (ipsecdoi_updatespi(iph2) < 0) {
+		plog(LLV_ERROR, LOCATION, NULL, "failed to update spi.\n");
+		goto end;
+	}
+
+	/* generate NONCE value */
+	iph2->nonce = eay_set_random(iph2->ph1->rmconf->nonce_size);
+	if (iph2->nonce == NULL)
+		goto end;
+
+	/* generate KE value if need */
+	pfsgroup = iph2->approval->pfs_group;
+	if (iph2->dhpub_p != NULL && pfsgroup != 0) {
+		/* DH group settting if PFS is required. */
+		if (oakley_setdhgroup(pfsgroup, &iph2->pfsgrp) < 0) {
+			plog(LLV_ERROR, LOCATION, NULL,
+				"failed to set DH value.\n");
+			goto end;
+		}
+		/* generate DH public value */
+		if (oakley_dh_generate(iph2->pfsgrp,
+				&iph2->dhpub, &iph2->dhpriv) < 0) {
+			goto end;
+		}
+	}
+
+	/* create SA;NONCE payload, and KE and ID if need */
+	tlen = sizeof(*gen) + iph2->sa_ret->l
+		+ sizeof(*gen) + iph2->nonce->l;
+	if (iph2->dhpub_p != NULL && pfsgroup != 0)
+		tlen += (sizeof(*gen) + iph2->dhpub->l);
+	if (iph2->id_p != NULL)
+		tlen += (sizeof(*gen) + iph2->id_p->l
+			+ sizeof(*gen) + iph2->id->l);
+
+	body = vmalloc(tlen);
+	if (body == NULL) { 
+		plog(LLV_ERROR, LOCATION, NULL,
+			"failed to get buffer to send.\n");
+		goto end;
+	}
+	p = body->v;
+
+	/* make SA payload */ 
+	p = set_isakmp_payload(body->v, iph2->sa_ret, ISAKMP_NPTYPE_NONCE);
+
+	/* add NONCE payload */
+	np_p = &((struct isakmp_gen *)p)->np;	/* XXX */
+	p = set_isakmp_payload(p, iph2->nonce,
+		(iph2->dhpub_p != NULL && pfsgroup != 0)
+				? ISAKMP_NPTYPE_KE
+				: (iph2->id_p != NULL
+					? ISAKMP_NPTYPE_ID
+					: ISAKMP_NPTYPE_NONE));
+
+	/* add KE payload if need. */
+	if (iph2->dhpub_p != NULL && pfsgroup != 0) {
+		np_p = &((struct isakmp_gen *)p)->np;	/* XXX */
+		p = set_isakmp_payload(p, iph2->dhpub,
+			(iph2->id_p == NULL)
+				? ISAKMP_NPTYPE_NONE
+				: ISAKMP_NPTYPE_ID);
+	}
+
+	/* add ID payloads received. */
+	if (iph2->id_p != NULL) {
+		/* IDci */
+		p = set_isakmp_payload(p, iph2->id_p, ISAKMP_NPTYPE_ID);
+		/* IDcr */
+		np_p = &((struct isakmp_gen *)p)->np;	/* XXX */
+		p = set_isakmp_payload(p, iph2->id, ISAKMP_NPTYPE_NONE);
+	}
+
+	/* add a RESPONDER-LIFETIME notify payload if needed */
+    {
+	vchar_t *data = NULL;
+	struct saprop *pp = iph2->approval;
+	struct saproto *pr;
+
+	if (pp->claim & IPSECDOI_ATTR_SA_LD_TYPE_SEC) {
+		u_int32_t v = htonl((u_int32_t)pp->lifetime);
+		data = isakmp_add_attr_l(data, IPSECDOI_ATTR_SA_LD_TYPE,
+					IPSECDOI_ATTR_SA_LD_TYPE_SEC);
+		if (!data)
+			goto end;
+		data = isakmp_add_attr_v(data, IPSECDOI_ATTR_SA_LD,
+					(caddr_t)&v, sizeof(v));
+		if (!data)
+			goto end;
+	}
+	if (pp->claim & IPSECDOI_ATTR_SA_LD_TYPE_KB) {
+		u_int32_t v = htonl((u_int32_t)pp->lifebyte);
+		data = isakmp_add_attr_l(data, IPSECDOI_ATTR_SA_LD_TYPE,
+					IPSECDOI_ATTR_SA_LD_TYPE_KB);
+		if (!data)
+			goto end;
+		data = isakmp_add_attr_v(data, IPSECDOI_ATTR_SA_LD,
+					(caddr_t)&v, sizeof(v));
+		if (!data)
+			goto end;
+	}
+
+	/*
+	 * XXX Is there only single RESPONDER-LIFETIME payload in a IKE message
+	 * in the case of SA bundle ?
+	 */
+	if (data) {
+		for (pr = pp->head; pr; pr = pr->next) {
+			body = isakmp_add_pl_n(body, &np_p,
+					ISAKMP_NTYPE_RESPONDER_LIFETIME, pr, data);
+			if (!body) {
+				vfree(data);
+				return error;	/* XXX */
+			}
+		}
+		vfree(data);
+	}
+    }
+
+	/* generate HASH(2) */
+    {
+	vchar_t *tmp;
+
+	tmp = vmalloc(iph2->nonce_p->l + body->l);
+	if (tmp == NULL) { 
+		plog(LLV_ERROR, LOCATION, NULL,
+			"failed to get hash buffer.\n");
+		goto end;
+	}
+	memcpy(tmp->v, iph2->nonce_p->v, iph2->nonce_p->l);
+	memcpy(tmp->v + iph2->nonce_p->l, body->v, body->l);
+
+	hash = oakley_compute_hash1(iph2->ph1, iph2->msgid, tmp);
+	vfree(tmp);
+
+	if (hash == NULL)
+		goto end;
+    }
+
+	/* send isakmp payload */
+	iph2->sendbuf = quick_ir1mx(iph2, body, hash);
+	if (iph2->sendbuf == NULL)
+		goto end;
+
+	/* send the packet, add to the schedule to resend */
+	iph2->retry_counter = iph2->ph1->rmconf->retry_counter;
+	if (isakmp_ph2resend(iph2) == -1)
+		goto end;
+
+	/* the sending message is added to the received-list. */
+	if (add_recvdpkt(iph2->ph1->remote, iph2->ph1->local, iph2->sendbuf, iph2->msg1) == -1) {
+		plog(LLV_ERROR , LOCATION, NULL,
+			"failed to add a response packet to the tree.\n");
+		goto end;
+	}
+
+	/* change status of isakmp status entry */
+	iph2->status = PHASE2ST_MSG1SENT;
+
+	error = 0;
+
+end:
+	if (body != NULL)
+		vfree(body);
+	if (hash != NULL)
+		vfree(hash);
+
+	return error;
+}
+
+/*
+ * receive from initiator
+ * 	HDR*, HASH(3)
+ */
+int
+quick_r3recv(iph2, msg0)
+	struct ph2handle *iph2;
+	vchar_t *msg0;
+{
+	vchar_t *msg = NULL;
+	vchar_t *pbuf = NULL;	/* for payload parsing */
+	struct isakmp_parse_t *pa;
+	struct isakmp_pl_hash *hash = NULL;
+	int error = ISAKMP_INTERNAL_ERROR;
+
+	/* validity check */
+	if (iph2->status != PHASE2ST_MSG1SENT) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"status mismatched %d.\n", iph2->status);
+		goto end;
+	}
+
+	/* decrypt packet */
+	if (!ISSET(((struct isakmp *)msg0->v)->flags, ISAKMP_FLAG_E)) {
+		plog(LLV_ERROR, LOCATION, iph2->ph1->remote,
+			"Packet wasn't encrypted.\n");
+		goto end;
+	}
+	msg = oakley_do_decrypt(iph2->ph1, msg0, iph2->ivm->iv, iph2->ivm->ive);
+	if (msg == NULL)
+		goto end;
+
+	/* validate the type of next payload */
+	pbuf = isakmp_parse(msg);
+	if (pbuf == NULL)
+		goto end;
+
+	for (pa = (struct isakmp_parse_t *)pbuf->v;
+	     pa->type != ISAKMP_NPTYPE_NONE;
+	     pa++) {
+
+		switch (pa->type) {
+		case ISAKMP_NPTYPE_HASH:
+			hash = (struct isakmp_pl_hash *)pa->ptr;
+			break;
+		case ISAKMP_NPTYPE_N:
+			isakmp_check_notify(pa->ptr, iph2->ph1);
+			break;
+		default:
+			/* don't send information, see ident_r1recv() */
+			plog(LLV_ERROR, LOCATION, iph2->ph1->remote,
+				"ignore the packet, "
+				"received unexpecting payload type %d.\n",
+				pa->type);
+			goto end;
+		}
+	}
+
+	/* payload existency check */
+	if (hash == NULL) {
+		plog(LLV_ERROR, LOCATION, iph2->ph1->remote,
+			"few isakmp message received.\n");
+		goto end;
+	}
+
+	/* validate HASH(3) */
+	/* HASH(3) = prf(SKEYID_a, 0 | M-ID | Ni_b | Nr_b) */
+    {
+	char *r_hash;
+	vchar_t *my_hash = NULL;
+	vchar_t *tmp = NULL;
+	int result;
+
+	r_hash = (char *)hash + sizeof(*hash);
+
+	plog(LLV_DEBUG, LOCATION, NULL, "HASH(3) validate:");
+	plogdump(LLV_DEBUG, r_hash, ntohs(hash->h.len) - sizeof(*hash));
+
+	tmp = vmalloc(iph2->nonce_p->l + iph2->nonce->l);
+	if (tmp == NULL) { 
+		plog(LLV_ERROR, LOCATION, NULL,
+			"failed to get hash buffer.\n");
+		goto end;
+	}
+	memcpy(tmp->v, iph2->nonce_p->v, iph2->nonce_p->l);
+	memcpy(tmp->v + iph2->nonce_p->l, iph2->nonce->v, iph2->nonce->l);
+
+	my_hash = oakley_compute_hash3(iph2->ph1, iph2->msgid, tmp);
+	vfree(tmp);
+	if (my_hash == NULL)
+		goto end;
+
+	result = memcmp(my_hash->v, r_hash, my_hash->l);
+	vfree(my_hash);
+
+	if (result) {
+		plog(LLV_ERROR, LOCATION, iph2->ph1->remote,
+			"HASH(3) mismatch.\n");
+		error = ISAKMP_NTYPE_INVALID_HASH_INFORMATION;
+		goto end;
+	}
+    }
+
+	/* if there is commit bit, don't set up SA now. */
+	if (ISSET(iph2->flags, ISAKMP_FLAG_C)) {
+		iph2->status = PHASE2ST_COMMIT;
+	} else
+		iph2->status = PHASE2ST_STATUS6;
+
+	error = 0;
+
+end:
+	if (pbuf != NULL)
+		vfree(pbuf);
+	if (msg != NULL)
+		vfree(msg);
+
+	return error;
+}
+
+/*
+ * send to initiator
+ * 	HDR#*, HASH(4), notify
+ */
+int
+quick_r3send(iph2, msg0)
+	struct ph2handle *iph2;
+	vchar_t *msg0;
+{
+	vchar_t *buf = NULL;
+	vchar_t *myhash = NULL;
+	struct isakmp_pl_n *n;
+	vchar_t *notify = NULL;
+	char *p;
+	int tlen;
+	int error = ISAKMP_INTERNAL_ERROR;
+
+	/* validity check */
+	if (iph2->status != PHASE2ST_COMMIT) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"status mismatched %d.\n", iph2->status);
+		goto end;
+	}
+
+	/* generate HASH(4) */
+	/* XXX What can I do in the case of multiple different SA */
+	plog(LLV_DEBUG, LOCATION, NULL, "HASH(4) generate\n");
+
+	/* XXX What should I do if there are multiple SAs ? */
+	tlen = sizeof(struct isakmp_pl_n) + iph2->approval->head->spisize;
+	notify = vmalloc(tlen);
+	if (notify == NULL) { 
+		plog(LLV_ERROR, LOCATION, NULL,
+			"failed to get notify buffer.\n");
+		goto end;
+	}
+	n = (struct isakmp_pl_n *)notify->v;
+	n->h.np = ISAKMP_NPTYPE_NONE;
+	n->h.len = htons(tlen);
+	n->doi = htonl(IPSEC_DOI);
+	n->proto_id = iph2->approval->head->proto_id;
+	n->spi_size = sizeof(iph2->approval->head->spisize);
+	n->type = htons(ISAKMP_NTYPE_CONNECTED);
+	memcpy(n + 1, &iph2->approval->head->spi, iph2->approval->head->spisize);
+
+	myhash = oakley_compute_hash1(iph2->ph1, iph2->msgid, notify);
+	if (myhash == NULL)
+		goto end;
+
+	/* create buffer for isakmp payload */
+	tlen = sizeof(struct isakmp)
+		+ sizeof(struct isakmp_gen) + myhash->l
+		+ notify->l;
+	buf = vmalloc(tlen);
+	if (buf == NULL) { 
+		plog(LLV_ERROR, LOCATION, NULL,
+			"failed to get buffer to send.\n");
+		goto end;
+	}
+
+	/* create isakmp header */
+	p = set_isakmp_header2(buf, iph2, ISAKMP_NPTYPE_HASH);
+	if (p == NULL)
+		goto end;
+
+	/* add HASH(4) payload */
+	p = set_isakmp_payload(p, myhash, ISAKMP_NPTYPE_N);
+
+	/* add notify payload */
+	memcpy(p, notify->v, notify->l);
+
+#ifdef HAVE_PRINT_ISAKMP_C
+	isakmp_printpacket(buf, iph2->ph1->local, iph2->ph1->remote, 1);
+#endif
+
+	/* encoding */
+	iph2->sendbuf = oakley_do_encrypt(iph2->ph1, buf, iph2->ivm->ive, iph2->ivm->iv);
+	if (iph2->sendbuf == NULL)
+		goto end;
+
+	/* send the packet */
+	if (isakmp_send(iph2->ph1, iph2->sendbuf) < 0)
+		goto end;
+
+	/* the sending message is added to the received-list. */
+	if (add_recvdpkt(iph2->ph1->remote, iph2->ph1->local, iph2->sendbuf, msg0) == -1) {
+		plog(LLV_ERROR , LOCATION, NULL,
+			"failed to add a response packet to the tree.\n");
+		goto end;
+	}
+
+	iph2->status = PHASE2ST_COMMIT;
+
+	error = 0;
+
+end:
+	if (buf != NULL)
+		vfree(buf);
+	if (myhash != NULL)
+		vfree(myhash);
+	if (notify != NULL)
+		vfree(notify);
+
+	return error;
+}
+
+int
+tunnel_mode_prop(p)
+	struct saprop *p;
+{
+	struct saproto *pr;
+
+	for (pr = p->head; pr; pr = pr->next)
+		if (pr->encmode == IPSECDOI_ATTR_ENC_MODE_TUNNEL)
+			return 1;
+	return 0;
+}
+
+/*
+ * set SA to kernel.
+ */
+int
+quick_r3prep(iph2, msg0)
+	struct ph2handle *iph2;
+	vchar_t *msg0;
+{
+	int error = ISAKMP_INTERNAL_ERROR;
+
+	/* validity check */
+	if (iph2->status != PHASE2ST_STATUS6) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"status mismatched %d.\n", iph2->status);
+		goto end;
+	}
+
+	/* compute both of KEYMATs */
+	if (oakley_compute_keymat(iph2, RESPONDER) < 0)
+		goto end;
+
+	iph2->status = PHASE2ST_ADDSA;
+	iph2->flags ^= ISAKMP_FLAG_C;	/* reset bit */
+
+	/* don't anything if local test mode. */
+	if (f_local) {
+		error = 0;
+		goto end;
+	}
+
+	/* Do UPDATE as responder */
+	plog(LLV_DEBUG, LOCATION, NULL, "call pk_sendupdate\n");
+	if (pk_sendupdate(iph2) < 0) {
+		plog(LLV_ERROR, LOCATION, NULL, "pfkey update failed.\n");
+		goto end;
+	}
+	plog(LLV_DEBUG, LOCATION, NULL, "pfkey update sent.\n");
+
+	/* Do ADD for responder */
+	if (pk_sendadd(iph2) < 0) {
+		plog(LLV_ERROR, LOCATION, NULL, "pfkey add failed.\n");
+		goto end;
+	}
+	plog(LLV_DEBUG, LOCATION, NULL, "pfkey add sent.\n");
+
+	/*
+	 * set policies into SPD if the policy is generated
+	 * from peer's policy.
+	 */
+	if (iph2->spidx_gen) {
+
+		struct policyindex *spidx;
+		struct sockaddr_storage addr;
+		u_int8_t pref;
+		struct sockaddr *src = iph2->src;
+		struct sockaddr *dst = iph2->dst;
+
+		/* make inbound policy */
+		iph2->src = dst;
+		iph2->dst = src;
+		if (pk_sendspdupdate2(iph2) < 0) {
+			plog(LLV_ERROR, LOCATION, NULL,
+				"pfkey spdupdate2(inbound) failed.\n");
+			goto end;
+		}
+		plog(LLV_DEBUG, LOCATION, NULL,
+			"pfkey spdupdate2(inbound) sent.\n");
+
+		spidx = (struct policyindex *)iph2->spidx_gen;
+#ifdef HAVE_POLICY_FWD
+		/* make forward policy if required */
+		if (tunnel_mode_prop(iph2->approval)) {
+			spidx->dir = IPSEC_DIR_FWD;
+			if (pk_sendspdupdate2(iph2) < 0) {
+				plog(LLV_ERROR, LOCATION, NULL,
+					"pfkey spdupdate2(forward) failed.\n");
+				goto end;
+			}
+			plog(LLV_DEBUG, LOCATION, NULL,
+				"pfkey spdupdate2(forward) sent.\n");
+		}
+#endif
+
+		/* make outbound policy */
+		iph2->src = src;
+		iph2->dst = dst;
+		spidx->dir = IPSEC_DIR_OUTBOUND;
+		addr = spidx->src;
+		spidx->src = spidx->dst;
+		spidx->dst = addr;
+		pref = spidx->prefs;
+		spidx->prefs = spidx->prefd;
+		spidx->prefd = pref;
+
+		if (pk_sendspdupdate2(iph2) < 0) {
+			plog(LLV_ERROR, LOCATION, NULL,
+				"pfkey spdupdate2(outbound) failed.\n");
+			goto end;
+		}
+		plog(LLV_DEBUG, LOCATION, NULL,
+			"pfkey spdupdate2(outbound) sent.\n");
+
+		/* spidx_gen is unnecessary any more */
+		delsp_bothdir((struct policyindex *)iph2->spidx_gen);
+		racoon_free(iph2->spidx_gen);
+		iph2->spidx_gen = NULL;
+		iph2->generated_spidx=1;
+	}
+
+	error = 0;
+
+end:
+	return error;
+}
+
+/*
+ * create HASH, body (SA, NONCE) payload with isakmp header.
+ */
+static vchar_t *
+quick_ir1mx(iph2, body, hash)
+	struct ph2handle *iph2;
+	vchar_t *body, *hash;
+{
+	struct isakmp *isakmp;
+	vchar_t *buf = NULL, *new = NULL;
+	char *p;
+	int tlen;
+	struct isakmp_gen *gen;
+	int error = ISAKMP_INTERNAL_ERROR;
+
+	/* create buffer for isakmp payload */
+	tlen = sizeof(*isakmp)
+		+ sizeof(*gen) + hash->l
+		+ body->l;
+	buf = vmalloc(tlen);
+	if (buf == NULL) { 
+		plog(LLV_ERROR, LOCATION, NULL,
+			"failed to get buffer to send.\n");
+		goto end;
+	}
+
+	/* re-set encryption flag, for serurity. */
+	iph2->flags |= ISAKMP_FLAG_E;
+
+	/* set isakmp header */
+	p = set_isakmp_header2(buf, iph2, ISAKMP_NPTYPE_HASH);
+	if (p == NULL)
+		goto end;
+
+	/* add HASH payload */
+	/* XXX is next type always SA ? */
+	p = set_isakmp_payload(p, hash, ISAKMP_NPTYPE_SA);
+
+	/* add body payload */
+	memcpy(p, body->v, body->l);
+
+#ifdef HAVE_PRINT_ISAKMP_C
+	isakmp_printpacket(buf, iph2->ph1->local, iph2->ph1->remote, 1);
+#endif
+
+	/* encoding */
+	new = oakley_do_encrypt(iph2->ph1, buf, iph2->ivm->ive, iph2->ivm->iv);
+	
+	if (new == NULL)
+		goto end;
+
+	vfree(buf);
+
+	buf = new;
+
+	error = 0;
+
+end:
+	if (error && buf != NULL) {
+		vfree(buf);
+		buf = NULL;
+	}
+
+	return buf;
+}
+
+/*
+ * get remote's sainfo.
+ * NOTE: this function is for responder.
+ */
+static int
+get_sainfo_r(iph2)
+	struct ph2handle *iph2;
+{
+	vchar_t *idsrc = NULL, *iddst = NULL;
+	int prefixlen;
+	int error = ISAKMP_INTERNAL_ERROR;
+	int remoteid = 0;
+
+	if (iph2->id == NULL) {
+		switch (iph2->src->sa_family) {
+		case AF_INET:
+			prefixlen = sizeof(struct in_addr) << 3;
+			break;
+		case AF_INET6:
+			prefixlen = sizeof(struct in6_addr) << 3;
+			break;
+		default:
+			plog(LLV_ERROR, LOCATION, NULL,
+				"invalid family: %d\n", iph2->src->sa_family);
+			goto end;
+		}
+		idsrc = ipsecdoi_sockaddr2id(iph2->src, prefixlen,
+					IPSEC_ULPROTO_ANY);
+	} else {
+		idsrc = vdup(iph2->id);
+	}
+	if (idsrc == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"failed to set ID for source.\n");
+		goto end;
+	}
+
+	if (iph2->id_p == NULL) {
+		switch (iph2->dst->sa_family) {
+		case AF_INET:
+			prefixlen = sizeof(struct in_addr) << 3;
+			break;
+		case AF_INET6:
+			prefixlen = sizeof(struct in6_addr) << 3;
+			break;
+		default:
+			plog(LLV_ERROR, LOCATION, NULL,
+				"invalid family: %d\n", iph2->dst->sa_family);
+			goto end;
+		}
+		iddst = ipsecdoi_sockaddr2id(iph2->dst, prefixlen,
+					IPSEC_ULPROTO_ANY);
+	} else {
+		iddst = vdup(iph2->id_p);
+	}
+	if (iddst == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"failed to set ID for destination.\n");
+		goto end;
+	}
+
+	{
+		struct remoteconf *conf;
+		conf = getrmconf(iph2->dst);
+		if (conf != NULL)
+			remoteid=conf->ph1id;
+		else{
+			plog(LLV_DEBUG, LOCATION, NULL, "Warning: no valid rmconf !\n");
+			remoteid=0;
+		}
+		
+	}
+
+	iph2->sainfo = getsainfo(idsrc, iddst, iph2->ph1->id_p, remoteid);
+	if (iph2->sainfo == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"failed to get sainfo.\n");
+		goto end;
+	}
+
+#ifdef ENABLE_HYBRID
+	/* xauth group inclusion check */
+	if (iph2->sainfo->group != NULL)
+		if(group_check(iph2->ph1,&iph2->sainfo->group->v,1))
+			goto end;
+#endif
+
+	plog(LLV_DEBUG, LOCATION, NULL,
+		"selected sainfo: %s\n", sainfo2str(iph2->sainfo));
+
+	error = 0;
+end:
+	if (idsrc)
+		vfree(idsrc);
+	if (iddst)
+		vfree(iddst);
+
+	return error;
+}
+
+/*
+ * Copy both IP addresses in ID payloads into [src,dst]_id if both ID types
+ * are IP address and same address family.
+ * Then get remote's policy from SPD copied from kernel.
+ * If the type of ID payload is address or subnet type, then the index is
+ * made from the payload.  If there is no ID payload, or the type of ID
+ * payload is NOT address type, then the index is made from the address
+ * pair of phase 1.
+ * NOTE: This function is only for responder.
+ */
+static int
+get_proposal_r(iph2)
+	struct ph2handle *iph2;
+{
+	struct policyindex spidx;
+	struct secpolicy *sp_in, *sp_out;
+	int idi2type = 0;	/* switch whether copy IDs into id[src,dst]. */
+	int error = ISAKMP_INTERNAL_ERROR;
+
+	/* check the existence of ID payload */
+	if ((iph2->id_p != NULL && iph2->id == NULL)
+	 || (iph2->id_p == NULL && iph2->id != NULL)) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"Both IDs wasn't found in payload.\n");
+		return ISAKMP_NTYPE_INVALID_ID_INFORMATION;
+	}
+
+	/* make sure if id[src,dst] is null. */
+	if (iph2->src_id || iph2->dst_id) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"Why do ID[src,dst] exist already.\n");
+		return ISAKMP_INTERNAL_ERROR;
+	}
+
+	memset(&spidx, 0, sizeof(spidx));
+
+#define _XIDT(d) ((struct ipsecdoi_id_b *)(d)->v)->type
+
+	/* make a spidx; a key to search SPD */
+	spidx.dir = IPSEC_DIR_INBOUND;
+	spidx.ul_proto = 0;
+
+	/*
+	 * make destination address in spidx from either ID payload
+	 * or phase 1 address into a address in spidx.
+	 */
+	if (iph2->id != NULL
+	 && (_XIDT(iph2->id) == IPSECDOI_ID_IPV4_ADDR
+	  || _XIDT(iph2->id) == IPSECDOI_ID_IPV6_ADDR
+	  || _XIDT(iph2->id) == IPSECDOI_ID_IPV4_ADDR_SUBNET
+	  || _XIDT(iph2->id) == IPSECDOI_ID_IPV6_ADDR_SUBNET)) {
+		/* get a destination address of a policy */
+		error = ipsecdoi_id2sockaddr(iph2->id,
+				(struct sockaddr *)&spidx.dst,
+				&spidx.prefd, &spidx.ul_proto);
+		if (error)
+			return error;
+
+#ifdef INET6
+		/*
+		 * get scopeid from the SA address.
+		 * note that the phase 1 source address is used as
+		 * a destination address to search for a inbound policy entry
+		 * because rcoon is responder.
+		 */
+		if (_XIDT(iph2->id) == IPSECDOI_ID_IPV6_ADDR) {
+			error = setscopeid((struct sockaddr *)&spidx.dst,
+			                    iph2->src);
+			if (error)
+				return error;
+		}
+#endif
+
+		if (_XIDT(iph2->id) == IPSECDOI_ID_IPV4_ADDR
+		 || _XIDT(iph2->id) == IPSECDOI_ID_IPV6_ADDR)
+			idi2type = _XIDT(iph2->id);
+
+	} else {
+
+		plog(LLV_DEBUG, LOCATION, NULL,
+			"get a destination address of SP index "
+			"from phase1 address "
+			"due to no ID payloads found "
+			"OR because ID type is not address.\n");
+
+		/*
+		 * copy the SOURCE address of IKE into the DESTINATION address
+		 * of the key to search the SPD because the direction of policy
+		 * is inbound.
+		 */
+		memcpy(&spidx.dst, iph2->src, sysdep_sa_len(iph2->src));
+		switch (spidx.dst.ss_family) {
+		case AF_INET:
+			spidx.prefd = sizeof(struct in_addr) << 3;
+			break;
+#ifdef INET6
+		case AF_INET6:
+			spidx.prefd = sizeof(struct in6_addr) << 3;
+			break;
+#endif
+		default:
+			spidx.prefd = 0;
+			break;
+		}
+	}
+
+	/* make source address in spidx */
+	if (iph2->id_p != NULL
+	 && (_XIDT(iph2->id_p) == IPSECDOI_ID_IPV4_ADDR
+	  || _XIDT(iph2->id_p) == IPSECDOI_ID_IPV6_ADDR
+	  || _XIDT(iph2->id_p) == IPSECDOI_ID_IPV4_ADDR_SUBNET
+	  || _XIDT(iph2->id_p) == IPSECDOI_ID_IPV6_ADDR_SUBNET)) {
+		/* get a source address of inbound SA */
+		error = ipsecdoi_id2sockaddr(iph2->id_p,
+				(struct sockaddr *)&spidx.src,
+				&spidx.prefs, &spidx.ul_proto);
+		if (error)
+			return error;
+
+#ifdef INET6
+		/*
+		 * get scopeid from the SA address.
+		 * for more detail, see above of this function.
+		 */
+		if (_XIDT(iph2->id_p) == IPSECDOI_ID_IPV6_ADDR) {
+			error = setscopeid((struct sockaddr *)&spidx.src,
+			                    iph2->dst);
+			if (error)
+				return error;
+		}
+#endif
+
+		/* make id[src,dst] if both ID types are IP address and same */
+		if (_XIDT(iph2->id_p) == idi2type
+		 && spidx.dst.ss_family == spidx.src.ss_family) {
+			iph2->src_id = dupsaddr((struct sockaddr *)&spidx.dst);
+			if (iph2->src_id  == NULL) {
+				plog(LLV_ERROR, LOCATION, NULL,
+				    "buffer allocation failed.\n");
+				return ISAKMP_INTERNAL_ERROR;
+			}
+			iph2->dst_id = dupsaddr((struct sockaddr *)&spidx.src);
+			if (iph2->dst_id  == NULL) {
+				plog(LLV_ERROR, LOCATION, NULL,
+				    "buffer allocation failed.\n");
+				return ISAKMP_INTERNAL_ERROR;
+			}
+		}
+
+	} else {
+		plog(LLV_DEBUG, LOCATION, NULL,
+			"get a source address of SP index "
+			"from phase1 address "
+			"due to no ID payloads found "
+			"OR because ID type is not address.\n");
+
+		/* see above comment. */
+		memcpy(&spidx.src, iph2->dst, sysdep_sa_len(iph2->dst));
+		switch (spidx.src.ss_family) {
+		case AF_INET:
+			spidx.prefs = sizeof(struct in_addr) << 3;
+			break;
+#ifdef INET6
+		case AF_INET6:
+			spidx.prefs = sizeof(struct in6_addr) << 3;
+			break;
+#endif
+		default:
+			spidx.prefs = 0;
+			break;
+		}
+	}
+
+#undef _XIDT
+
+	plog(LLV_DEBUG, LOCATION, NULL,
+		"get a src address from ID payload "
+		"%s prefixlen=%u ul_proto=%u\n",
+		saddr2str((struct sockaddr *)&spidx.src),
+		spidx.prefs, spidx.ul_proto);
+	plog(LLV_DEBUG, LOCATION, NULL,
+		"get dst address from ID payload "
+		"%s prefixlen=%u ul_proto=%u\n",
+		saddr2str((struct sockaddr *)&spidx.dst),
+		spidx.prefd, spidx.ul_proto);
+
+	/*
+	 * convert the ul_proto if it is 0
+	 * because 0 in ID payload means a wild card.
+	 */
+	if (spidx.ul_proto == 0)
+		spidx.ul_proto = IPSEC_ULPROTO_ANY;
+
+#ifdef HAVE_SECCTX
+	/*
+	 * Need to use security context in spidx to ensure the correct
+	 * policy is selected. The only way to get the security context
+	 * is to look into the proposal sent by peer ahead of time.
+	 */
+	if (get_security_context(iph2->sa, &spidx)) {
+		plog(LLV_ERROR, LOCATION, NULL,
+		     "error occurred trying to get security context.\n");
+		return ISAKMP_INTERNAL_ERROR;
+	}
+#endif /* HAVE_SECCTX */
+
+	/* get inbound policy */
+	sp_in = getsp_r(&spidx);
+	if (sp_in == NULL) {
+		if (iph2->ph1->rmconf->gen_policy) {
+			plog(LLV_INFO, LOCATION, NULL,
+				"no policy found, "
+				"try to generate the policy : %s\n",
+				spidx2str(&spidx));
+			iph2->spidx_gen = racoon_malloc(sizeof(spidx));
+			if (!iph2->spidx_gen) {
+				plog(LLV_ERROR, LOCATION, NULL,
+					"buffer allocation failed.\n");
+				return ISAKMP_INTERNAL_ERROR;
+			}
+			memcpy(iph2->spidx_gen, &spidx, sizeof(spidx));
+			return -2;	/* special value */
+		}
+		plog(LLV_ERROR, LOCATION, NULL,
+			"no policy found: %s\n", spidx2str(&spidx));
+		return ISAKMP_INTERNAL_ERROR;
+	}
+	/* Refresh existing generated policies
+	 */
+	if (iph2->ph1->rmconf->gen_policy) {
+		plog(LLV_INFO, LOCATION, NULL,
+			 "Update the generated policy : %s\n",
+			 spidx2str(&spidx));
+		iph2->spidx_gen = racoon_malloc(sizeof(spidx));
+		if (!iph2->spidx_gen) {
+			plog(LLV_ERROR, LOCATION, NULL,
+				 "buffer allocation failed.\n");
+			return ISAKMP_INTERNAL_ERROR;
+		}
+		memcpy(iph2->spidx_gen, &spidx, sizeof(spidx));
+	}
+
+	/* get outbound policy */
+    {
+	struct sockaddr_storage addr;
+	u_int8_t pref;
+
+	spidx.dir = IPSEC_DIR_OUTBOUND;
+	addr = spidx.src;
+	spidx.src = spidx.dst;
+	spidx.dst = addr;
+	pref = spidx.prefs;
+	spidx.prefs = spidx.prefd;
+	spidx.prefd = pref;
+
+	sp_out = getsp_r(&spidx);
+	if (!sp_out) {
+		plog(LLV_WARNING, LOCATION, NULL,
+			"no outbound policy found: %s\n",
+			spidx2str(&spidx));
+	}
+    }
+
+	plog(LLV_DEBUG, LOCATION, NULL,
+		"suitable SP found:%s\n", spidx2str(&spidx));
+
+	/*
+	 * In the responder side, the inbound policy should be using IPsec.
+	 * outbound policy is not checked currently.
+	 */
+	if (sp_in->policy != IPSEC_POLICY_IPSEC) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"policy found, but no IPsec required: %s\n",
+			spidx2str(&spidx));
+		return ISAKMP_INTERNAL_ERROR;
+	}
+
+	/* set new proposal derived from a policy into the iph2->proposal. */
+	if (set_proposal_from_policy(iph2, sp_in, sp_out) < 0) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"failed to create saprop.\n");
+		return ISAKMP_INTERNAL_ERROR;
+	}
+
+#ifdef HAVE_SECCTX
+	if (spidx.sec_ctx.ctx_str) {
+		set_secctx_in_proposal(iph2, spidx);
+	}
+#endif /* HAVE_SECCTX */
+
+	return 0;
+}
+
diff --git a/src/racoon/isakmp_quick.h b/src/racoon/isakmp_quick.h
new file mode 100644
index 0000000..71eeecf
--- /dev/null
+++ b/src/racoon/isakmp_quick.h
@@ -0,0 +1,50 @@
+/*	$NetBSD: isakmp_quick.h,v 1.4 2006/09/09 16:22:09 manu Exp $	*/
+
+/* Id: isakmp_quick.h,v 1.3 2004/06/11 16:00:16 ludvigm Exp */
+
+/*
+ * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _ISAKMP_QUICK_H
+#define _ISAKMP_QUICK_H
+
+extern int quick_i1prep __P((struct ph2handle *, vchar_t *));
+extern int quick_i1send __P((struct ph2handle *, vchar_t *));
+extern int quick_i2recv __P((struct ph2handle *, vchar_t *));
+extern int quick_i2send __P((struct ph2handle *, vchar_t *));
+extern int quick_i3recv __P((struct ph2handle *, vchar_t *));
+
+extern int quick_r1recv __P((struct ph2handle *, vchar_t *));
+extern int quick_r1prep __P((struct ph2handle *, vchar_t *));
+extern int quick_r2send __P((struct ph2handle *, vchar_t *));
+extern int quick_r3recv __P((struct ph2handle *, vchar_t *));
+extern int quick_r3send __P((struct ph2handle *, vchar_t *));
+extern int quick_r3prep __P((struct ph2handle *, vchar_t *));
+
+#endif /* _ISAKMP_QUICK_H */
diff --git a/src/racoon/isakmp_unity.c b/src/racoon/isakmp_unity.c
new file mode 100644
index 0000000..9873f59
--- /dev/null
+++ b/src/racoon/isakmp_unity.c
@@ -0,0 +1,401 @@
+/*	$NetBSD: isakmp_unity.c,v 1.7 2006/10/09 06:17:20 manu Exp $	*/
+
+/* Id: isakmp_unity.c,v 1.10 2006/07/31 04:49:23 manubsd Exp */
+
+/*
+ * Copyright (C) 2004 Emmanuel Dreyfus
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <sys/queue.h>
+
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <string.h>
+#include <errno.h>
+#if TIME_WITH_SYS_TIME
+# include <sys/time.h>
+# include <time.h>
+#else
+# if HAVE_SYS_TIME_H
+#  include <sys/time.h>
+# else
+#  include <time.h>
+# endif
+#endif
+#include <netdb.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <ctype.h>
+#include <resolv.h>
+
+#include "var.h"
+#include "misc.h"
+#include "vmbuf.h"
+#include "plog.h"
+#include "sockmisc.h"
+#include "schedule.h"
+#include "debug.h"
+
+#include "isakmp_var.h"
+#include "isakmp.h"
+#include "handler.h"
+#include "isakmp_xauth.h"
+#include "isakmp_unity.h"
+#include "isakmp_cfg.h"
+#include "strnames.h"
+
+static vchar_t *isakmp_cfg_split(struct ph1handle *, 
+    struct isakmp_data *, struct unity_netentry*,int);
+
+vchar_t *
+isakmp_unity_req(iph1, attr)
+	struct ph1handle *iph1;
+	struct isakmp_data *attr;
+{
+	int type;
+	vchar_t *reply_attr = NULL;
+
+	if ((iph1->mode_cfg->flags & ISAKMP_CFG_VENDORID_UNITY) == 0) {
+		plog(LLV_ERROR, LOCATION, NULL, 
+		    "Unity mode config request but the peer "
+		    "did not declare itself as  unity compliant\n");
+		return NULL;
+	}
+
+	type = ntohs(attr->type);
+
+	/* Handle short attributes */
+	if ((type & ISAKMP_GEN_MASK) == ISAKMP_GEN_TV) {
+		type &= ~ISAKMP_GEN_MASK;
+
+		plog(LLV_DEBUG, LOCATION, NULL,
+		     "Short attribute %s = %d\n", 
+		     s_isakmp_cfg_type(type), ntohs(attr->lorv));
+
+		switch (type) {
+		default:
+			plog(LLV_DEBUG, LOCATION, NULL,
+			     "Ignored short attribute %s\n",
+			     s_isakmp_cfg_type(type));
+			break;
+		}
+
+		return reply_attr;
+	}
+
+	switch(type) {
+	case UNITY_BANNER: {
+#define MAXMOTD 65536
+		char buf[MAXMOTD + 1];
+		int fd;
+		char *filename = &isakmp_cfg_config.motd[0];
+		int len;
+
+		if ((fd = open(filename, O_RDONLY, 0)) == -1) {
+			plog(LLV_ERROR, LOCATION, NULL, 
+			    "Cannot open \"%s\"\n", filename);
+			return NULL;
+		}
+
+		if ((len = read(fd, buf, MAXMOTD)) == -1) {
+			plog(LLV_ERROR, LOCATION, NULL, 
+			    "Cannot read \"%s\"\n", filename);
+			close(fd);
+			return NULL;
+		}
+		close(fd);
+
+		buf[len] = '\0';
+		reply_attr = isakmp_cfg_string(iph1, attr, buf);
+
+		break;
+	}
+
+	case UNITY_PFS:
+		reply_attr = isakmp_cfg_short(iph1, attr, 
+		    isakmp_cfg_config.pfs_group);
+		break;
+
+	case UNITY_SAVE_PASSWD:
+		reply_attr = isakmp_cfg_short(iph1, attr, 
+		    isakmp_cfg_config.save_passwd);
+		break;
+
+	case UNITY_DDNS_HOSTNAME:
+		reply_attr = isakmp_cfg_copy(iph1, attr);
+		break;
+
+	case UNITY_DEF_DOMAIN:
+		reply_attr = isakmp_cfg_string(iph1, 
+		    attr, isakmp_cfg_config.default_domain);
+		break;
+
+	case UNITY_SPLIT_INCLUDE:
+		if(isakmp_cfg_config.splitnet_type == UNITY_SPLIT_INCLUDE)
+			reply_attr = isakmp_cfg_split(iph1, attr,
+			isakmp_cfg_config.splitnet_list,
+			isakmp_cfg_config.splitnet_count);
+		else
+			return NULL;
+		break;
+	case UNITY_LOCAL_LAN:
+		if(isakmp_cfg_config.splitnet_type == UNITY_LOCAL_LAN)
+			reply_attr = isakmp_cfg_split(iph1, attr,
+			isakmp_cfg_config.splitnet_list,
+			isakmp_cfg_config.splitnet_count);
+		else
+			return NULL;
+		break;
+	case UNITY_SPLITDNS_NAME:
+		reply_attr = isakmp_cfg_varlen(iph1, attr,
+				isakmp_cfg_config.splitdns_list,
+				isakmp_cfg_config.splitdns_len);
+		break;
+	case UNITY_FW_TYPE:
+	case UNITY_NATT_PORT:
+	case UNITY_BACKUP_SERVERS:
+	default:
+		plog(LLV_DEBUG, LOCATION, NULL,
+		     "Ignored attribute %s\n", s_isakmp_cfg_type(type));
+		return NULL;
+		break;
+	}
+
+	return reply_attr;
+}
+
+void
+isakmp_unity_reply(iph1, attr)
+	struct ph1handle *iph1;
+	struct isakmp_data *attr;
+{
+	int type = ntohs(attr->type);
+	int alen = ntohs(attr->lorv);
+
+	struct unity_network *network = (struct unity_network *)(attr + 1);
+	int index = 0;
+	int count = 0;
+
+	switch(type) {
+	case UNITY_SPLIT_INCLUDE:
+	{
+		if (alen)
+			count = alen / sizeof(struct unity_network);
+
+		for(;index < count; index++)
+			splitnet_list_add(
+				&iph1->mode_cfg->split_include,
+				&network[index],
+				&iph1->mode_cfg->include_count);
+
+		iph1->mode_cfg->flags |= ISAKMP_CFG_GOT_SPLIT_INCLUDE;
+		break;
+	}
+	case UNITY_LOCAL_LAN:
+	{
+		if (alen)
+			count = alen / sizeof(struct unity_network);
+
+		for(;index < count; index++)
+			splitnet_list_add(
+				&iph1->mode_cfg->split_local,
+				&network[index],
+				&iph1->mode_cfg->local_count);
+
+		iph1->mode_cfg->flags |= ISAKMP_CFG_GOT_SPLIT_LOCAL;
+		break;
+	}
+	case UNITY_SPLITDNS_NAME:
+	case UNITY_BANNER:
+	case UNITY_SAVE_PASSWD:
+	case UNITY_NATT_PORT:
+	case UNITY_PFS:
+	case UNITY_FW_TYPE:
+	case UNITY_BACKUP_SERVERS:
+	case UNITY_DDNS_HOSTNAME:
+	default:
+		plog(LLV_WARNING, LOCATION, NULL,
+		     "Ignored attribute %s\n",
+		     s_isakmp_cfg_type(type));
+		break;
+	}
+	return;
+}
+
+static vchar_t *
+isakmp_cfg_split(iph1, attr, netentry, count)
+	struct ph1handle *iph1;
+	struct isakmp_data *attr;
+	struct unity_netentry *netentry;
+	int count;
+{
+	vchar_t *buffer;
+	struct isakmp_data *new;
+	struct unity_network * network;
+	size_t len;
+	int index = 0;
+
+	char tmp1[40];
+	char tmp2[40];
+
+	len = sizeof(struct unity_network) * count;
+	if ((buffer = vmalloc(sizeof(*attr) + len)) == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL, "Cannot allocate memory\n");
+		return NULL;
+	}
+
+	new = (struct isakmp_data *)buffer->v;
+	new->type = attr->type;
+	new->lorv = htons(len);
+
+	network = (struct unity_network *)(new + 1);
+	for (; index < count; index++) {
+
+		memcpy(&network[index],
+			&netentry->network,
+			sizeof(struct unity_network));
+
+		inet_ntop(AF_INET, &netentry->network.addr4, tmp1, 40);
+		inet_ntop(AF_INET, &netentry->network.mask4, tmp2, 40);
+		plog(LLV_DEBUG, LOCATION, NULL, "splitnet: %s/%s\n", tmp1, tmp2);
+
+		netentry = netentry->next;
+	}
+
+	return buffer;
+}
+
+int  splitnet_list_add(list, network, count)
+	struct unity_netentry ** list;
+	struct unity_network * network;
+	int *count;
+{
+	struct unity_netentry * newentry;
+
+	/*
+	 * allocate new netentry and copy
+         * new splitnet network data
+	 */
+	newentry = (struct unity_netentry *)
+		racoon_malloc(sizeof(struct unity_netentry));
+	if (newentry == NULL)
+		return -1;
+
+	memcpy(&newentry->network,network,
+		sizeof(struct unity_network));
+	newentry->next = NULL;
+
+	/*
+	 * locate the last netentry in our
+	 * splitnet list and add our entry
+	 */
+	if (*list == NULL)
+		*list = newentry;
+	else {
+		struct unity_netentry * tmpentry = *list;
+		while (tmpentry->next != NULL)
+			tmpentry = tmpentry->next;
+		tmpentry->next = newentry;
+	}
+
+	(*count)++;
+
+	return 0;
+}
+
+void splitnet_list_free(list, count)
+	struct unity_netentry * list;
+	int *count;
+{
+	struct unity_netentry * netentry = list;
+	struct unity_netentry * delentry;
+
+	*count = 0;
+
+	while (netentry != NULL) {
+		delentry = netentry;
+		netentry = netentry->next;
+		racoon_free(delentry);
+	}
+}
+
+char * splitnet_list_2str(list)
+	struct unity_netentry * list;
+{
+	struct unity_netentry * netentry;
+	char tmp1[40];
+	char tmp2[40];
+	char * str;
+	int len;
+
+	/* determine string length */
+	len = 0;
+	netentry = list;
+	while (netentry != NULL) {
+
+		inet_ntop(AF_INET, &netentry->network.addr4, tmp1, 40);
+		inet_ntop(AF_INET, &netentry->network.mask4, tmp2, 40);
+		len += strlen(tmp1);
+		len += strlen(tmp2);
+		len += 2;
+
+		netentry = netentry->next;
+	}
+
+	/* allocate network list string */
+	str = racoon_malloc(len);
+	if (str == NULL)
+		return NULL;
+
+	/* create network list string */
+	len = 0;
+	netentry = list;
+	while (netentry != NULL) {
+
+		inet_ntop(AF_INET, &netentry->network.addr4, tmp1, 40);
+		inet_ntop(AF_INET, &netentry->network.mask4, tmp2, 40);
+
+		len += sprintf(str+len, "%s/%s ", tmp1, tmp2);
+
+		netentry = netentry->next;
+	}
+
+	str[len-1]=0;
+
+	return str;
+}
diff --git a/src/racoon/isakmp_unity.h b/src/racoon/isakmp_unity.h
new file mode 100644
index 0000000..b52f02c
--- /dev/null
+++ b/src/racoon/isakmp_unity.h
@@ -0,0 +1,72 @@
+/*	$NetBSD: isakmp_unity.h,v 1.4 2006/09/09 16:22:09 manu Exp $	*/
+
+/*	$KAME$ */
+
+/*
+ * Copyright (C) 2004 Emmanuel Dreyfus 
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* ISAKMP notifies specific to the Unity vendor Id */
+/* Sent during xauth if the user types his password too slowly */
+#define ISAKMP_NTYPE_UNITY_HEARTBEAT	40500
+
+/* ISAKMP mode config attributes specific to the Unity vendor Id */
+#define UNITY_BANNER		28672
+#define UNITY_SAVE_PASSWD	28673
+#define UNITY_DEF_DOMAIN	28674
+#define UNITY_SPLITDNS_NAME	28675
+#define UNITY_SPLIT_INCLUDE	28676
+#define UNITY_NATT_PORT		28677
+#define UNITY_LOCAL_LAN		28678
+#define UNITY_PFS		28679
+#define UNITY_FW_TYPE		28680
+#define UNITY_BACKUP_SERVERS	28681
+#define UNITY_DDNS_HOSTNAME	28682
+
+/*
+ * Unity adress/mask lists
+ * XXX : the padding is probably there for something !
+ */
+        
+struct unity_network {
+	struct in_addr addr4;
+	struct in_addr mask4;
+	char padding[6];
+} __attribute__((__packed__));
+        
+struct unity_netentry {
+	struct unity_network    network;       
+	struct unity_netentry   *next;
+};
+
+int	splitnet_list_add(struct unity_netentry **, struct unity_network *, int *);
+void	splitnet_list_free(struct unity_netentry *, int *);
+char *	splitnet_list_2str(struct unity_netentry *);
+
+vchar_t *isakmp_unity_req(struct ph1handle *, struct isakmp_data *);
+void isakmp_unity_reply(struct ph1handle *, struct isakmp_data *);
diff --git a/src/racoon/isakmp_var.h b/src/racoon/isakmp_var.h
new file mode 100644
index 0000000..f4ef45d
--- /dev/null
+++ b/src/racoon/isakmp_var.h
@@ -0,0 +1,132 @@
+/*	$NetBSD: isakmp_var.h,v 1.6.6.1 2007/02/20 09:08:49 vanhu Exp $	*/
+
+/* Id: isakmp_var.h,v 1.12 2005/05/07 14:45:31 manubsd Exp */
+
+/*
+ * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _ISAKMP_VAR_H
+#define _ISAKMP_VAR_H
+
+#include "vmbuf.h"
+
+#define PORT_ISAKMP 500
+#define PORT_ISAKMP_NATT 4500
+
+#define DEFAULT_NONCE_SIZE	16
+
+typedef u_char cookie_t[8];
+typedef u_char msgid_t[4];
+
+typedef struct { /* i_cookie + r_cookie */
+	cookie_t i_ck;
+	cookie_t r_ck;
+} isakmp_index;
+
+struct isakmp_gen;
+struct sched;
+
+struct sockaddr;
+struct ph1handle;
+struct ph2handle;
+struct remoteconf;
+struct isakmp_gen;
+struct ipsecdoi_pl_id;	/* XXX */
+struct isakmp_pl_ke;	/* XXX */
+struct isakmp_pl_nonce;	/* XXX */
+
+extern int isakmp_handler __P((int));
+extern int isakmp_ph1begin_i __P((struct remoteconf *, struct sockaddr *,
+	struct sockaddr *));
+
+extern vchar_t *isakmp_parsewoh __P((int, struct isakmp_gen *, int));
+extern vchar_t *isakmp_parse __P((vchar_t *));
+
+extern int isakmp_init __P((void));
+extern const char *isakmp_pindex __P((const isakmp_index *, const u_int32_t));
+extern int isakmp_open __P((void));
+extern void isakmp_close __P((void));
+extern int isakmp_send __P((struct ph1handle *, vchar_t *));
+
+extern void isakmp_ph1resend_stub __P((void *));
+extern int isakmp_ph1resend __P((struct ph1handle *));
+extern void isakmp_ph2resend_stub __P((void *));
+extern int isakmp_ph2resend __P((struct ph2handle *));
+extern void isakmp_ph1expire_stub __P((void *));
+extern void isakmp_ph1expire __P((struct ph1handle *));
+extern void isakmp_ph1delete_stub __P((void *));
+extern void isakmp_ph1delete __P((struct ph1handle *));
+extern void isakmp_ph2expire_stub __P((void *));
+extern void isakmp_ph2expire __P((struct ph2handle *));
+extern void isakmp_ph2delete_stub __P((void *));
+extern void isakmp_ph2delete __P((struct ph2handle *));
+
+extern int isakmp_post_acquire __P((struct ph2handle *));
+extern int isakmp_post_getspi __P((struct ph2handle *));
+extern void isakmp_chkph1there_stub __P((void *));
+extern void isakmp_chkph1there __P((struct ph2handle *));
+
+extern caddr_t isakmp_set_attr_v __P((caddr_t, int, caddr_t, int));
+extern caddr_t isakmp_set_attr_l __P((caddr_t, int, u_int32_t));
+extern vchar_t *isakmp_add_attr_v __P((vchar_t *, int, caddr_t, int));
+extern vchar_t *isakmp_add_attr_l __P((vchar_t *, int, u_int32_t));
+
+extern int isakmp_newcookie __P((caddr_t, struct sockaddr *, struct sockaddr *));
+
+extern int isakmp_p2ph __P((vchar_t **, struct isakmp_gen *));
+
+extern u_int32_t isakmp_newmsgid2 __P((struct ph1handle *));
+extern caddr_t set_isakmp_header1 __P((vchar_t *, struct ph1handle *, int));
+extern caddr_t set_isakmp_header2 __P((vchar_t *, struct ph2handle *, int));
+extern caddr_t set_isakmp_payload __P((caddr_t, vchar_t *, int));
+
+extern struct payload_list *isakmp_plist_append __P((struct payload_list *plist, 
+	vchar_t *payload, int payload_type));
+extern vchar_t *isakmp_plist_set_all __P((struct payload_list **plist,
+	struct ph1handle *iph1));
+
+#ifdef HAVE_PRINT_ISAKMP_C
+extern void isakmp_printpacket __P((vchar_t *, struct sockaddr *,
+	struct sockaddr *, int));
+#endif
+
+extern int copy_ph1addresses __P(( struct ph1handle *,
+	struct remoteconf *, struct sockaddr *, struct sockaddr *));
+extern void log_ph1established __P((const struct ph1handle *));
+
+extern void script_hook __P((struct ph1handle *, int)); 
+extern int script_env_append __P((char ***, int *, char *, char *));
+extern int script_exec __P((char *, int, char * const *));
+
+void purge_remote __P((struct ph1handle *));
+void delete_spd __P((struct ph2handle *, u_int64_t));
+#ifdef INET6
+u_int32_t setscopeid __P((struct sockaddr *, struct sockaddr *));
+#endif
+#endif /* _ISAKMP_VAR_H */
diff --git a/src/racoon/isakmp_xauth.c b/src/racoon/isakmp_xauth.c
new file mode 100644
index 0000000..f7b9c39
--- /dev/null
+++ b/src/racoon/isakmp_xauth.c
@@ -0,0 +1,1693 @@
+/*	$NetBSD: isakmp_xauth.c,v 1.11.6.1 2007/08/07 04:49:24 manu Exp $	*/
+
+/* Id: isakmp_xauth.c,v 1.38 2006/08/22 18:17:17 manubsd Exp */
+
+/*
+ * Copyright (C) 2004-2005 Emmanuel Dreyfus
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <sys/queue.h>
+
+#include <netinet/in.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <pwd.h>
+#include <grp.h>
+#if TIME_WITH_SYS_TIME
+# include <sys/time.h>
+# include <time.h>
+#else
+# if HAVE_SYS_TIME_H
+#  include <sys/time.h>
+# else
+#  include <time.h>
+# endif
+#endif
+#include <netdb.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <ctype.h>
+#include <resolv.h>
+
+#ifdef HAVE_SHADOW_H
+#include <shadow.h>
+#endif
+
+#include "var.h"
+#include "misc.h"
+#include "vmbuf.h"
+#include "plog.h"
+#include "sockmisc.h"
+#include "schedule.h"
+#include "debug.h"
+
+#include "crypto_openssl.h"
+#include "isakmp_var.h"
+#include "isakmp.h"
+#include "admin.h"
+#include "privsep.h"
+#include "evt.h"
+#include "handler.h"
+#include "throttle.h"
+#include "remoteconf.h"
+#include "isakmp_inf.h"
+#include "isakmp_xauth.h"
+#include "isakmp_unity.h"
+#include "isakmp_cfg.h"
+#include "strnames.h"
+#include "ipsec_doi.h"
+#include "remoteconf.h"
+#include "localconf.h"
+
+#ifdef HAVE_LIBRADIUS
+#include <radlib.h>
+
+struct rad_handle *radius_auth_state = NULL;
+struct rad_handle *radius_acct_state = NULL;
+#endif
+
+#ifdef HAVE_LIBPAM
+#include <security/pam_appl.h>
+
+static char *PAM_usr = NULL;
+static char *PAM_pwd = NULL;
+static int PAM_conv(int, const struct pam_message **, 
+    struct pam_response **, void *);
+static struct pam_conv PAM_chat = { &PAM_conv, NULL };
+#endif
+
+#ifdef HAVE_LIBLDAP
+#include "ldap.h"
+#include <arpa/inet.h>
+struct xauth_ldap_config xauth_ldap_config;
+#endif
+
+void 
+xauth_sendreq(iph1)
+	struct ph1handle *iph1;
+{
+	vchar_t *buffer;
+	struct isakmp_pl_attr *attr;
+	struct isakmp_data *typeattr;
+	struct isakmp_data *usrattr;
+	struct isakmp_data *pwdattr;
+	struct xauth_state *xst = &iph1->mode_cfg->xauth;
+	size_t tlen;
+
+	/* Status checks */
+	if (iph1->status != PHASE1ST_ESTABLISHED) {
+		plog(LLV_ERROR, LOCATION, NULL, 
+		    "Xauth request while phase 1 is not completed\n");
+		return;
+	}
+
+	if (xst->status != XAUTHST_NOTYET) {
+		plog(LLV_ERROR, LOCATION, NULL, 
+		    "Xauth request whith Xauth state %d\n", xst->status);
+		return;
+	}
+
+	plog(LLV_INFO, LOCATION, NULL, "Sending Xauth request\n");
+
+	tlen = sizeof(*attr) +
+	       + sizeof(*typeattr) +
+	       + sizeof(*usrattr) +
+	       + sizeof(*pwdattr);
+	
+	if ((buffer = vmalloc(tlen)) == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL, "Cannot allocate buffer\n");
+		return;
+	}
+	
+	attr = (struct isakmp_pl_attr *)buffer->v;
+	memset(attr, 0, tlen);
+
+	attr->h.len = htons(tlen);
+	attr->type = ISAKMP_CFG_REQUEST;
+	attr->id = htons(eay_random());
+
+	typeattr = (struct isakmp_data *)(attr + 1);
+	typeattr->type = htons(XAUTH_TYPE | ISAKMP_GEN_TV);
+	typeattr->lorv = htons(XAUTH_TYPE_GENERIC);
+
+	usrattr = (struct isakmp_data *)(typeattr + 1);
+	usrattr->type = htons(XAUTH_USER_NAME | ISAKMP_GEN_TLV);
+	usrattr->lorv = htons(0);
+
+	pwdattr = (struct isakmp_data *)(usrattr + 1);
+	pwdattr->type = htons(XAUTH_USER_PASSWORD | ISAKMP_GEN_TLV);
+	pwdattr->lorv = htons(0);
+
+	isakmp_cfg_send(iph1, buffer, 
+	    ISAKMP_NPTYPE_ATTR, ISAKMP_FLAG_E, 1);
+	
+	vfree(buffer);
+
+	xst->status = XAUTHST_REQSENT;
+
+	return;
+}
+
+int
+xauth_attr_reply(iph1, attr, id)
+	struct ph1handle *iph1;
+	struct isakmp_data *attr;
+	int id;
+{
+	char **outlet = NULL;
+	size_t alen = 0;
+	int type;
+	struct xauth_state *xst = &iph1->mode_cfg->xauth;
+
+	if ((iph1->mode_cfg->flags & ISAKMP_CFG_VENDORID_XAUTH) == 0) {
+		plog(LLV_ERROR, LOCATION, NULL, 
+		    "Xauth reply but peer did not declare "
+		    "itself as Xauth capable\n");
+		return -1;
+	}
+
+	if (xst->status != XAUTHST_REQSENT) {
+		plog(LLV_ERROR, LOCATION, NULL, 
+		    "Xauth reply while Xauth state is %d\n", xst->status);
+		return -1;
+	}
+
+	type = ntohs(attr->type) & ~ISAKMP_GEN_MASK;
+	switch (type) {
+	case XAUTH_TYPE:
+		switch (ntohs(attr->lorv)) {
+		case XAUTH_TYPE_GENERIC:
+			xst->authtype = XAUTH_TYPE_GENERIC;
+			break;
+		default:
+			plog(LLV_WARNING, LOCATION, NULL, 
+			    "Unexpected authentication type %d\n", 
+			    ntohs(type));
+			return -1;
+		}
+		break;
+
+	case XAUTH_USER_NAME:
+		outlet = &xst->authdata.generic.usr;
+		break;
+
+	case XAUTH_USER_PASSWORD:
+		outlet = &xst->authdata.generic.pwd; 
+		break;
+
+	default:
+		plog(LLV_WARNING, LOCATION, NULL, 
+		    "ignored Xauth attribute %d\n", type);
+		break;
+	}
+
+	if (outlet != NULL) {
+		alen = ntohs(attr->lorv);
+
+		if ((*outlet = racoon_malloc(alen + 1)) == NULL) {
+			plog(LLV_ERROR, LOCATION, NULL, 
+			    "Cannot allocate memory for Xauth Data\n");
+			return -1;
+		}
+
+		memcpy(*outlet, attr + 1, alen);
+		(*outlet)[alen] = '\0';
+		outlet = NULL;
+	}
+
+	
+	if ((xst->authdata.generic.usr != NULL) &&
+	   (xst->authdata.generic.pwd != NULL)) {
+		int port;
+		int res;
+		char *usr = xst->authdata.generic.usr;
+		char *pwd = xst->authdata.generic.pwd;
+		time_t throttle_delay = 0;
+
+#if 0	/* Real debug, don't do that at home */
+		plog(LLV_DEBUG, LOCATION, NULL, 
+		    "Got username \"%s\", password \"%s\"\n", usr, pwd);
+#endif
+		strncpy(iph1->mode_cfg->login, usr, LOGINLEN);
+		iph1->mode_cfg->login[LOGINLEN] = '\0';
+
+		res = -1;
+		if ((port = isakmp_cfg_getport(iph1)) == -1) {
+			plog(LLV_ERROR, LOCATION, NULL, 
+			    "Port pool depleted\n");
+			goto skip_auth;
+		}	
+
+		switch (isakmp_cfg_config.authsource) {
+		case ISAKMP_CFG_AUTH_SYSTEM:
+			res = privsep_xauth_login_system(usr, pwd);
+			break;
+#ifdef HAVE_LIBRADIUS
+		case ISAKMP_CFG_AUTH_RADIUS:
+			res = xauth_login_radius(iph1, usr, pwd);
+			break;
+#endif
+#ifdef HAVE_LIBPAM
+		case ISAKMP_CFG_AUTH_PAM:
+			res = privsep_xauth_login_pam(iph1->mode_cfg->port, 
+			    iph1->remote, usr, pwd);
+			break;
+#endif
+#ifdef HAVE_LIBLDAP
+		case ISAKMP_CFG_AUTH_LDAP:
+			res = xauth_login_ldap(iph1, usr, pwd);
+			break;
+#endif
+		default:
+			plog(LLV_ERROR, LOCATION, NULL, 
+			    "Unexpected authentication source\n");
+			res = -1;
+			break;
+		}
+
+		/*
+		 * Optional group authentication
+		 */
+		if (!res && (isakmp_cfg_config.groupcount))
+			res = group_check(iph1,
+				isakmp_cfg_config.grouplist,
+				isakmp_cfg_config.groupcount);
+
+		/*
+		 * On failure, throttle the connexion for the remote host
+		 * in order to make password attacks more difficult.
+		 */
+		throttle_delay = throttle_host(iph1->remote, res) - time(NULL);
+		if (throttle_delay > 0) {
+			char *str;
+
+			str = saddrwop2str(iph1->remote);
+
+			plog(LLV_ERROR, LOCATION, NULL, 
+			    "Throttling in action for %s: delay %lds\n",
+			    str, (unsigned long)throttle_delay);
+			res = -1;
+		} else {
+			throttle_delay = 0;
+		}
+
+skip_auth:
+		if (throttle_delay != 0) {
+			struct xauth_reply_arg *xra;
+
+			if ((xra = racoon_malloc(sizeof(*xra))) == NULL) {
+				plog(LLV_ERROR, LOCATION, NULL, 
+				    "malloc failed, bypass throttling\n");
+				return xauth_reply(iph1, port, id, res);
+			}
+
+			/*
+			 * We need to store the ph1, but it might have
+			 * disapeared when xauth_reply is called, so
+			 * store the index instead.
+			 */
+			xra->index = iph1->index;
+			xra->port = port;
+			xra->id = id;
+			xra->res = res;
+			sched_new(throttle_delay, xauth_reply_stub, xra);
+		} else {
+			return xauth_reply(iph1, port, id, res);
+		}
+	}
+
+	return 0;
+}
+
+void 
+xauth_reply_stub(args)
+	void *args;
+{
+	struct xauth_reply_arg *xra = (struct xauth_reply_arg *)args;
+	struct ph1handle *iph1;
+
+	if ((iph1 = getph1byindex(&xra->index)) != NULL)
+		(void)xauth_reply(iph1, xra->port, xra->id, xra->res);
+	else
+		plog(LLV_ERROR, LOCATION, NULL, 
+		    "Delayed Xauth reply: phase 1 no longer exists.\n"); 
+
+	racoon_free(xra);
+	return;
+}
+
+int
+xauth_reply(iph1, port, id, res)
+	struct ph1handle *iph1;
+	int port;
+	int id;
+{
+	struct xauth_state *xst = &iph1->mode_cfg->xauth;
+	char *usr = xst->authdata.generic.usr;
+
+	if (res != 0) {
+		if (port != -1)
+			isakmp_cfg_putport(iph1, port);
+
+		plog(LLV_INFO, LOCATION, NULL, 
+		    "login failed for user \"%s\"\n", usr);
+		
+		xauth_sendstatus(iph1, XAUTH_STATUS_FAIL, id);
+		xst->status = XAUTHST_NOTYET;
+
+		/* Delete Phase 1 SA */
+		if (iph1->status == PHASE1ST_ESTABLISHED)
+			isakmp_info_send_d1(iph1);
+		remph1(iph1);
+		delph1(iph1);
+
+		return -1;
+	}
+
+	xst->status = XAUTHST_OK;
+	plog(LLV_INFO, LOCATION, NULL, 
+	    "login succeeded for user \"%s\"\n", usr);
+
+	xauth_sendstatus(iph1, XAUTH_STATUS_OK, id);
+
+	return 0;
+}
+
+void
+xauth_sendstatus(iph1, status, id)
+	struct ph1handle *iph1;
+	int status;
+	int id;
+{
+	vchar_t *buffer;
+	struct isakmp_pl_attr *attr;
+	struct isakmp_data *stattr;
+	size_t tlen;
+
+	tlen = sizeof(*attr) +
+	       + sizeof(*stattr); 
+	
+	if ((buffer = vmalloc(tlen)) == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL, "Cannot allocate buffer\n");
+		return;
+	}
+	
+	attr = (struct isakmp_pl_attr *)buffer->v;
+	memset(attr, 0, tlen);
+
+	attr->h.len = htons(tlen);
+	attr->type = ISAKMP_CFG_SET;
+	attr->id = htons(id);
+
+	stattr = (struct isakmp_data *)(attr + 1);
+	stattr->type = htons(XAUTH_STATUS | ISAKMP_GEN_TV);
+	stattr->lorv = htons(status);
+
+	isakmp_cfg_send(iph1, buffer, 
+	    ISAKMP_NPTYPE_ATTR, ISAKMP_FLAG_E, 1);
+	
+	vfree(buffer);
+
+	return;	
+}
+
+#ifdef HAVE_LIBRADIUS
+int
+xauth_radius_init(void)
+{
+	/* For first time use, initialize Radius */
+	if ((isakmp_cfg_config.authsource == ISAKMP_CFG_AUTH_RADIUS) &&
+	    (radius_auth_state == NULL)) {
+		if ((radius_auth_state = rad_auth_open()) == NULL) {
+			plog(LLV_ERROR, LOCATION, NULL, 
+			    "Cannot init libradius\n");
+			return -1;
+		}
+
+		if (rad_config(radius_auth_state, NULL) != 0) {
+			plog(LLV_ERROR, LOCATION, NULL, 
+			    "Cannot open librarius config file: %s\n", 
+			    rad_strerror(radius_auth_state));
+			rad_close(radius_auth_state);
+			radius_auth_state = NULL;
+			return -1;
+		}
+	}
+
+	if ((isakmp_cfg_config.accounting == ISAKMP_CFG_ACCT_RADIUS) &&
+	    (radius_acct_state == NULL)) {
+		if ((radius_acct_state = rad_acct_open()) == NULL) {
+			plog(LLV_ERROR, LOCATION, NULL, 
+			    "Cannot init libradius\n");
+			return -1;
+		}
+
+		if (rad_config(radius_acct_state, NULL) != 0) {
+			plog(LLV_ERROR, LOCATION, NULL, 
+			    "Cannot open librarius config file: %s\n", 
+			    rad_strerror(radius_acct_state));
+			rad_close(radius_acct_state);
+			radius_acct_state = NULL;
+			return -1;
+		}
+	}
+
+	return 0;
+}
+
+int
+xauth_login_radius(iph1, usr, pwd)
+	struct ph1handle *iph1;
+	char *usr;
+	char *pwd;
+{
+	int res;
+	const void *data;
+	size_t len;
+	int type;
+
+	if (rad_create_request(radius_auth_state, RAD_ACCESS_REQUEST) != 0) {
+		plog(LLV_ERROR, LOCATION, NULL, 
+		    "rad_create_request failed: %s\n", 
+		    rad_strerror(radius_auth_state));
+		return -1;
+	}
+	
+	if (rad_put_string(radius_auth_state, RAD_USER_NAME, usr) != 0) {
+		plog(LLV_ERROR, LOCATION, NULL, 
+		    "rad_put_string failed: %s\n", 
+		    rad_strerror(radius_auth_state));
+		return -1;
+	}
+
+	if (rad_put_string(radius_auth_state, RAD_USER_PASSWORD, pwd) != 0) {
+		plog(LLV_ERROR, LOCATION, NULL, 
+		    "rad_put_string failed: %s\n", 
+		    rad_strerror(radius_auth_state));
+		return -1;
+	}
+
+	if (isakmp_cfg_radius_common(radius_auth_state, iph1->mode_cfg->port) != 0)
+		return -1;
+
+	switch (res = rad_send_request(radius_auth_state)) {
+	case RAD_ACCESS_ACCEPT:
+		while ((type = rad_get_attr(radius_auth_state, &data, &len)) != 0) {
+			switch (type) {
+			case RAD_FRAMED_IP_ADDRESS:
+				iph1->mode_cfg->addr4 = rad_cvt_addr(data);
+				iph1->mode_cfg->flags 
+				    |= ISAKMP_CFG_ADDR4_EXTERN;
+				break;
+
+			case RAD_FRAMED_IP_NETMASK:
+				iph1->mode_cfg->mask4 = rad_cvt_addr(data);
+				iph1->mode_cfg->flags 
+				    |= ISAKMP_CFG_MASK4_EXTERN;
+				break;
+
+			default:
+				plog(LLV_INFO, LOCATION, NULL,
+				    "Unexpected attribute: %d\n", type);
+				break;
+			}
+		}
+
+		return 0;
+		break;
+
+	case RAD_ACCESS_REJECT:
+		return -1;
+		break;
+
+	case -1:
+		plog(LLV_ERROR, LOCATION, NULL, 
+		    "rad_send_request failed: %s\n", 
+		    rad_strerror(radius_auth_state));
+		return -1;
+		break;
+	default:
+		plog(LLV_ERROR, LOCATION, NULL, 
+		    "rad_send_request returned %d\n", res);
+		return -1;
+		break;
+	}
+
+	return -1;
+}
+#endif
+
+#ifdef HAVE_LIBPAM
+static int 
+PAM_conv(msg_count, msg, rsp, dontcare)
+	int msg_count;
+	const struct pam_message **msg;
+	struct pam_response **rsp;
+	void *dontcare;
+{
+	int i;
+	int replies = 0;
+	struct pam_response *reply = NULL;
+
+	if ((reply = racoon_malloc(sizeof(*reply) * msg_count)) == NULL) 
+		return PAM_CONV_ERR;
+	bzero(reply, sizeof(*reply) * msg_count);
+
+	for (i = 0; i < msg_count; i++) {
+		switch (msg[i]->msg_style) {
+		case PAM_PROMPT_ECHO_ON:
+			/* Send the username, libpam frees resp */
+			reply[i].resp_retcode = PAM_SUCCESS;
+			if ((reply[i].resp = strdup(PAM_usr)) == NULL) {
+				plog(LLV_ERROR, LOCATION, 
+				    NULL, "strdup failed\n");
+				exit(1);
+			}
+			break;
+
+		case PAM_PROMPT_ECHO_OFF:
+			/* Send the password, libpam frees resp */
+			reply[i].resp_retcode = PAM_SUCCESS;
+			if ((reply[i].resp = strdup(PAM_pwd)) == NULL) {
+				plog(LLV_ERROR, LOCATION, 
+				    NULL, "strdup failed\n");
+				exit(1);
+			}
+			break;
+
+		case PAM_TEXT_INFO:
+		case PAM_ERROR_MSG:
+			reply[i].resp_retcode = PAM_SUCCESS;
+			reply[i].resp = NULL;
+			break;
+
+		default:
+			if (reply != NULL)
+				racoon_free(reply);
+			return PAM_CONV_ERR;
+			break;
+		}
+	}
+
+	if (reply != NULL)
+		*rsp = reply;
+
+	return PAM_SUCCESS;
+}
+
+int
+xauth_login_pam(port, raddr, usr, pwd)
+	int port;
+	struct sockaddr *raddr;
+	char *usr;
+	char *pwd;
+{
+	int error;
+	int res;
+	const void *data;
+	size_t len;
+	int type;
+	char *remote = NULL;
+	pam_handle_t *pam = NULL;
+
+	if (isakmp_cfg_config.port_pool == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL,
+		    "isakmp_cfg_config.port_pool == NULL\n");
+		return -1;
+	}
+
+	if ((error = pam_start("racoon", usr, 
+	    &PAM_chat, &isakmp_cfg_config.port_pool[port].pam)) != 0) {
+		if (isakmp_cfg_config.port_pool[port].pam == NULL) {
+			plog(LLV_ERROR, LOCATION, NULL, "pam_start failed\n");
+			return -1;
+		} else {
+			plog(LLV_ERROR, LOCATION, NULL, 
+			    "pam_start failed: %s\n", 
+			    pam_strerror(isakmp_cfg_config.port_pool[port].pam,
+			    error));
+			goto out;
+		}
+	}
+	pam = isakmp_cfg_config.port_pool[port].pam;
+
+	if ((remote = strdup(saddrwop2str(raddr))) == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL,
+		    "cannot allocate memory: %s\n", strerror(errno)); 
+		goto out;
+	}
+	
+	if ((error = pam_set_item(pam, PAM_RHOST, remote)) != 0) {
+		plog(LLV_ERROR, LOCATION, NULL, 
+		    "pam_set_item failed: %s\n", 
+		    pam_strerror(pam, error));
+		goto out;
+	}
+
+	PAM_usr = usr;
+	PAM_pwd = pwd;
+	error = pam_authenticate(pam, 0);
+	PAM_usr = NULL;
+	PAM_pwd = NULL;
+	if (error != 0) {
+		plog(LLV_ERROR, LOCATION, NULL, 
+		    "pam_authenticate failed: %s\n", 
+		    pam_strerror(pam, error));
+		goto out;
+	}
+
+	if ((error = pam_acct_mgmt(pam, 0)) != 0) {
+		plog(LLV_ERROR, LOCATION, NULL, 
+		    "pam_acct_mgmt failed: %s\n", 
+		    pam_strerror(pam, error));
+		goto out;
+	}
+
+	if ((error = pam_setcred(pam, 0)) != 0) {
+		plog(LLV_ERROR, LOCATION, NULL, 
+		    "pam_setcred failed: %s\n", 
+		    pam_strerror(pam, error));
+		goto out;
+	}
+
+	if (remote != NULL)
+		free(remote);
+
+	return 0;
+
+out:
+	pam_end(pam, error);
+	isakmp_cfg_config.port_pool[port].pam = NULL;
+	if (remote != NULL)
+		free(remote);
+	return -1;
+}
+#endif
+
+#ifdef HAVE_LIBLDAP
+int 
+xauth_ldap_init(void)
+{
+	int tmplen;
+	int error = -1;
+
+	xauth_ldap_config.pver = 3;
+	xauth_ldap_config.host = NULL;
+	xauth_ldap_config.port = LDAP_PORT;
+	xauth_ldap_config.base = NULL;
+	xauth_ldap_config.subtree = 0;
+	xauth_ldap_config.bind_dn = NULL;
+	xauth_ldap_config.bind_pw = NULL;
+	xauth_ldap_config.auth_type = LDAP_AUTH_SIMPLE;
+	xauth_ldap_config.attr_user = NULL;
+	xauth_ldap_config.attr_addr = NULL;
+	xauth_ldap_config.attr_mask = NULL;
+	xauth_ldap_config.attr_group = NULL;
+	xauth_ldap_config.attr_member = NULL;
+
+	/* set default host */
+	tmplen = strlen(LDAP_DFLT_HOST);
+	xauth_ldap_config.host = vmalloc(tmplen);
+	if (xauth_ldap_config.host == NULL)
+		goto out;
+	memcpy(xauth_ldap_config.host->v, LDAP_DFLT_HOST, tmplen);
+
+	/* set default user naming attribute */
+	tmplen = strlen(LDAP_DFLT_USER);
+	xauth_ldap_config.attr_user = vmalloc(tmplen);
+	if (xauth_ldap_config.attr_user == NULL)
+		goto out;	
+	memcpy(xauth_ldap_config.attr_user->v, LDAP_DFLT_USER, tmplen);
+
+	/* set default address attribute */
+	tmplen = strlen(LDAP_DFLT_ADDR);
+	xauth_ldap_config.attr_addr = vmalloc(tmplen);
+	if (xauth_ldap_config.attr_addr == NULL)
+		goto out;
+	memcpy(xauth_ldap_config.attr_addr->v, LDAP_DFLT_ADDR, tmplen);
+
+	/* set default netmask attribute */
+	tmplen = strlen(LDAP_DFLT_MASK);
+	xauth_ldap_config.attr_mask = vmalloc(tmplen);
+	if (xauth_ldap_config.attr_mask == NULL)
+		goto out;
+	memcpy(xauth_ldap_config.attr_mask->v, LDAP_DFLT_MASK, tmplen);
+
+	/* set default group naming attribute */
+	tmplen = strlen(LDAP_DFLT_GROUP);
+	xauth_ldap_config.attr_group = vmalloc(tmplen);
+	if (xauth_ldap_config.attr_group == NULL)
+		goto out;
+	memcpy(xauth_ldap_config.attr_group->v, LDAP_DFLT_GROUP, tmplen);
+
+	/* set default member attribute */
+	tmplen = strlen(LDAP_DFLT_MEMBER);
+	xauth_ldap_config.attr_member = vmalloc(tmplen);
+	if (xauth_ldap_config.attr_member == NULL)
+		goto out;
+	memcpy(xauth_ldap_config.attr_member->v, LDAP_DFLT_MEMBER, tmplen);
+
+	error = 0;
+out:
+	if (error != 0)
+		plog(LLV_ERROR, LOCATION, NULL, "cannot allocate memory\n");
+
+	return error;
+}
+
+int
+xauth_login_ldap(iph1, usr, pwd)
+	struct ph1handle *iph1;
+	char *usr;
+	char *pwd;
+{
+	int rtn = -1;
+	int res = -1;
+	LDAP *ld = NULL;
+	LDAPMessage *lr = NULL;
+	LDAPMessage *le = NULL;
+	struct berval cred;
+	struct berval **bv = NULL;
+	struct timeval timeout;
+	char *init = NULL;
+	char *filter = NULL;
+	char *atlist[3];
+	char *basedn = NULL;
+	char *userdn = NULL;
+	int tmplen = 0;
+	int ecount = 0;
+	int scope = LDAP_SCOPE_ONE;
+
+	atlist[0] = NULL;
+	atlist[1] = NULL;
+	atlist[2] = NULL;
+
+	/* build our initialization url */
+	tmplen = strlen("ldap://:") + 17;
+	tmplen += strlen(xauth_ldap_config.host->v);
+	init = racoon_malloc(tmplen);
+	if (init == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"unable to alloc ldap init url\n");
+		goto ldap_end;
+	}
+	sprintf(init,"ldap://%s:%d",
+		xauth_ldap_config.host->v,
+		xauth_ldap_config.port );
+
+	/* initialize the ldap handle */
+	res = ldap_initialize(&ld, init);
+	if (res != LDAP_SUCCESS) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"ldap_initialize failed: %s\n",
+			ldap_err2string(res));
+		goto ldap_end;
+	}
+
+	/* initialize the protocol version */
+	ldap_set_option(ld, LDAP_OPT_PROTOCOL_VERSION,
+		&xauth_ldap_config.pver);
+
+	/*
+	 * attempt to bind to the ldap server.
+         * default to anonymous bind unless a
+	 * user dn and password has been
+	 * specified in our configuration
+         */
+	if ((xauth_ldap_config.bind_dn != NULL)&&
+	    (xauth_ldap_config.bind_pw != NULL))
+	{
+		cred.bv_val = xauth_ldap_config.bind_pw->v;
+		cred.bv_len = strlen( cred.bv_val );
+		res = ldap_sasl_bind_s(ld,
+			xauth_ldap_config.bind_dn->v, NULL, &cred,
+			NULL, NULL, NULL);
+	}
+	else
+	{
+		res = ldap_sasl_bind_s(ld,
+			NULL, NULL, NULL,
+			NULL, NULL, NULL);
+	}
+	
+	if (res!=LDAP_SUCCESS) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"ldap_sasl_bind_s (search) failed: %s\n",
+			ldap_err2string(res));
+		goto ldap_end;
+	}
+
+	/* build an ldap user search filter */
+	tmplen = strlen(xauth_ldap_config.attr_user->v);
+	tmplen += 1;
+	tmplen += strlen(usr);
+	tmplen += 1;
+	filter = racoon_malloc(tmplen);
+	if (filter == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"unable to alloc ldap search filter buffer\n");
+		goto ldap_end;
+	}
+	sprintf(filter, "%s=%s",
+		xauth_ldap_config.attr_user->v, usr);
+
+	/* build our return attribute list */
+	tmplen = strlen(xauth_ldap_config.attr_addr->v) + 1;
+	atlist[0] = racoon_malloc(tmplen);
+	tmplen = strlen(xauth_ldap_config.attr_mask->v) + 1;
+	atlist[1] = racoon_malloc(tmplen);
+	if ((atlist[0] == NULL)||(atlist[1] == NULL)) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"unable to alloc ldap attrib list buffer\n");
+		goto ldap_end;
+	}
+	strcpy(atlist[0],xauth_ldap_config.attr_addr->v);
+	strcpy(atlist[1],xauth_ldap_config.attr_mask->v);
+
+	/* attempt to locate the user dn */
+	if (xauth_ldap_config.base != NULL)
+		basedn = xauth_ldap_config.base->v;
+	if (xauth_ldap_config.subtree)
+		scope = LDAP_SCOPE_SUBTREE;
+	timeout.tv_sec = 15;
+	timeout.tv_usec = 0;
+	res = ldap_search_ext_s(ld, basedn, scope,
+		filter, atlist, 0, NULL, NULL,
+		&timeout, 2, &lr);
+	if (res != LDAP_SUCCESS) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"ldap_search_ext_s failed: %s\n",
+			ldap_err2string(res));
+		goto ldap_end;
+	}
+
+	/* check the number of ldap entries returned */
+	ecount = ldap_count_entries(ld, lr);
+	if (ecount < 1) {
+		plog(LLV_WARNING, LOCATION, NULL, 
+			"no ldap results for filter \'%s\'\n", 
+			 filter);
+		goto ldap_end;
+	}
+	if (ecount > 1) {
+		plog(LLV_WARNING, LOCATION, NULL, 
+			"multiple (%i) ldap results for filter \'%s\'\n", 
+			ecount, filter);
+	}
+
+	/* obtain the dn from the first result */
+	le = ldap_first_entry(ld, lr);
+	if (le == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"ldap_first_entry failed: invalid entry returned\n");
+		goto ldap_end;
+	}
+	userdn = ldap_get_dn(ld, le);
+	if (userdn == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"ldap_get_dn failed: invalid string returned\n");
+		goto ldap_end;
+	}
+
+	/* cache the user dn in the xauth state */
+	iph1->mode_cfg->xauth.udn = racoon_malloc(strlen(userdn)+1);
+	strcpy(iph1->mode_cfg->xauth.udn,userdn);
+
+	/* retrieve modecfg address */
+	bv = ldap_get_values_len(ld, le, xauth_ldap_config.attr_addr->v);
+	if (bv != NULL)	{
+		char tmpaddr[16];
+		/* sanity check for address value */
+		if ((bv[0]->bv_len < 7)||(bv[0]->bv_len > 15)) {
+			plog(LLV_DEBUG, LOCATION, NULL,
+				"ldap returned invalid modecfg address\n");
+			ldap_value_free_len(bv);
+			goto ldap_end;
+		}
+		memcpy(tmpaddr,bv[0]->bv_val,bv[0]->bv_len);
+		tmpaddr[bv[0]->bv_len]=0;
+		iph1->mode_cfg->addr4.s_addr = inet_addr(tmpaddr);
+		iph1->mode_cfg->flags |= ISAKMP_CFG_ADDR4_EXTERN;
+		plog(LLV_INFO, LOCATION, NULL,
+			"ldap returned modecfg address %s\n", tmpaddr);
+		ldap_value_free_len(bv);
+	}
+
+	/* retrieve modecfg netmask */
+	bv = ldap_get_values_len(ld, le, xauth_ldap_config.attr_mask->v);
+	if (bv != NULL)	{
+		char tmpmask[16];
+		/* sanity check for netmask value */
+		if ((bv[0]->bv_len < 7)||(bv[0]->bv_len > 15)) {
+			plog(LLV_DEBUG, LOCATION, NULL,
+				"ldap returned invalid modecfg netmask\n");
+			ldap_value_free_len(bv);
+			goto ldap_end;
+		}
+		memcpy(tmpmask,bv[0]->bv_val,bv[0]->bv_len);
+		tmpmask[bv[0]->bv_len]=0;
+		iph1->mode_cfg->mask4.s_addr = inet_addr(tmpmask);
+		iph1->mode_cfg->flags |= ISAKMP_CFG_MASK4_EXTERN;
+		plog(LLV_INFO, LOCATION, NULL,
+			"ldap returned modecfg netmask %s\n", tmpmask);
+		ldap_value_free_len(bv);
+	}
+
+	/*
+	 * finally, use the dn and the xauth
+	 * password to check the users given
+	 * credentials by attempting to bind
+	 * to the ldap server
+	 */
+	plog(LLV_INFO, LOCATION, NULL,
+		"attempting ldap bind for dn \'%s\'\n", userdn);
+	cred.bv_val = pwd;
+	cred.bv_len = strlen( cred.bv_val );
+	res = ldap_sasl_bind_s(ld,
+		userdn, NULL, &cred,
+		NULL, NULL, NULL);
+        if(res==LDAP_SUCCESS)
+		rtn = 0;
+
+ldap_end:
+
+	/* free ldap resources */
+	if (userdn != NULL)
+		ldap_memfree(userdn);
+	if (atlist[0] != NULL)
+		racoon_free(atlist[0]);
+	if (atlist[1] != NULL)
+		racoon_free(atlist[1]);
+	if (filter != NULL)
+		racoon_free(filter);
+	if (lr != NULL)
+		ldap_msgfree(lr);
+	if (init != NULL)
+		racoon_free(init);
+
+	ldap_unbind_ext_s(ld, NULL, NULL);
+
+	return rtn;
+}
+
+int
+xauth_group_ldap(udn, grp)
+	char * udn;
+	char * grp;
+{
+	int rtn = -1;
+	int res = -1;
+	LDAP *ld = NULL;
+	LDAPMessage *lr = NULL;
+	LDAPMessage *le = NULL;
+	struct berval cred;
+	struct timeval timeout;
+	char *init = NULL;
+	char *filter = NULL;
+	char *basedn = NULL;
+	char *groupdn = NULL;
+	int tmplen = 0;
+	int ecount = 0;
+	int scope = LDAP_SCOPE_ONE;
+
+	/* build our initialization url */
+	tmplen = strlen("ldap://:") + 17;
+	tmplen += strlen(xauth_ldap_config.host->v);
+	init = racoon_malloc(tmplen);
+	if (init == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"unable to alloc ldap init url\n");
+		goto ldap_group_end;
+	}
+	sprintf(init,"ldap://%s:%d",
+		xauth_ldap_config.host->v,
+		xauth_ldap_config.port );
+
+	/* initialize the ldap handle */
+	res = ldap_initialize(&ld, init);
+	if (res != LDAP_SUCCESS) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"ldap_initialize failed: %s\n",
+			ldap_err2string(res));
+		goto ldap_group_end;
+	}
+
+	/* initialize the protocol version */
+	ldap_set_option(ld, LDAP_OPT_PROTOCOL_VERSION,
+		&xauth_ldap_config.pver);
+
+	/*
+	 * attempt to bind to the ldap server.
+         * default to anonymous bind unless a
+	 * user dn and password has been
+	 * specified in our configuration
+         */
+	if ((xauth_ldap_config.bind_dn != NULL)&&
+	    (xauth_ldap_config.bind_pw != NULL))
+	{
+		cred.bv_val = xauth_ldap_config.bind_pw->v;
+		cred.bv_len = strlen( cred.bv_val );
+		res = ldap_sasl_bind_s(ld,
+			xauth_ldap_config.bind_dn->v, NULL, &cred,
+			NULL, NULL, NULL);
+	}
+	else
+	{
+		res = ldap_sasl_bind_s(ld,
+			NULL, NULL, NULL,
+			NULL, NULL, NULL);
+	}
+
+	if (res!=LDAP_SUCCESS) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"ldap_sasl_bind_s (search) failed: %s\n",
+			ldap_err2string(res));
+		goto ldap_group_end;
+	}
+
+	/* build an ldap group search filter */
+	tmplen = strlen("(&(=)(=))") + 1;
+	tmplen += strlen(xauth_ldap_config.attr_group->v);
+	tmplen += strlen(grp);
+	tmplen += strlen(xauth_ldap_config.attr_member->v);
+	tmplen += strlen(udn);
+	filter = racoon_malloc(tmplen);
+	if (filter == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"unable to alloc ldap search filter buffer\n");
+		goto ldap_group_end;
+	}
+	sprintf(filter, "(&(%s=%s)(%s=%s))",
+		xauth_ldap_config.attr_group->v, grp,
+		xauth_ldap_config.attr_member->v, udn);
+
+	/* attempt to locate the group dn */
+	if (xauth_ldap_config.base != NULL)
+		basedn = xauth_ldap_config.base->v;
+	if (xauth_ldap_config.subtree)
+		scope = LDAP_SCOPE_SUBTREE;
+	timeout.tv_sec = 15;
+	timeout.tv_usec = 0;
+	res = ldap_search_ext_s(ld, basedn, scope,
+		filter, NULL, 0, NULL, NULL,
+		&timeout, 2, &lr);
+	if (res != LDAP_SUCCESS) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"ldap_search_ext_s failed: %s\n",
+			ldap_err2string(res));
+		goto ldap_group_end;
+	}
+
+	/* check the number of ldap entries returned */
+	ecount = ldap_count_entries(ld, lr);
+	if (ecount < 1) {
+		plog(LLV_WARNING, LOCATION, NULL, 
+			"no ldap results for filter \'%s\'\n", 
+			 filter);
+		goto ldap_group_end;
+	}
+
+	/* success */
+	rtn = 0;
+
+	/* obtain the dn from the first result */
+	le = ldap_first_entry(ld, lr);
+	if (le == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"ldap_first_entry failed: invalid entry returned\n");
+		goto ldap_group_end;
+	}
+	groupdn = ldap_get_dn(ld, le);
+	if (groupdn == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"ldap_get_dn failed: invalid string returned\n");
+		goto ldap_group_end;
+	}
+
+	plog(LLV_INFO, LOCATION, NULL,
+		"ldap membership group returned \'%s\'\n", groupdn);
+ldap_group_end:
+
+	/* free ldap resources */
+	if (groupdn != NULL)
+		ldap_memfree(groupdn);
+	if (filter != NULL)
+		racoon_free(filter);
+	if (lr != NULL)
+		ldap_msgfree(lr);
+	if (init != NULL)
+		racoon_free(init);
+
+	ldap_unbind_ext_s(ld, NULL, NULL);
+
+	return rtn;
+}
+
+#endif
+
+int
+xauth_login_system(usr, pwd)
+	char *usr;
+	char *pwd;
+{
+	struct passwd *pw;
+	char *cryptpwd;
+	char *syscryptpwd;
+#ifdef HAVE_SHADOW_H
+	struct spwd *spw;
+
+	if ((spw = getspnam(usr)) == NULL)
+		return -1;
+
+	syscryptpwd = spw->sp_pwdp;
+#endif
+
+	if ((pw = getpwnam(usr)) == NULL)
+		return -1;
+
+#ifndef HAVE_SHADOW_H
+	syscryptpwd = pw->pw_passwd;
+#endif
+
+	/* No root login. Ever. */
+	if (pw->pw_uid == 0)
+		return -1;
+
+	if ((cryptpwd = crypt(pwd, syscryptpwd)) == NULL)
+		return -1;
+
+	if (strcmp(cryptpwd, syscryptpwd) == 0)
+		return 0;
+
+	return -1;
+}
+
+int
+xauth_group_system(usr, grp)
+	char * usr;
+	char * grp;
+{
+	struct group * gr;
+	char * member;
+	int index = 0;
+
+	gr = getgrnam(grp);
+	if (gr == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"the system group name \'%s\' is unknown\n",
+			grp);
+		return -1;
+	}
+
+	while ((member = gr->gr_mem[index++])!=NULL) {
+		if (!strcmp(member,usr)) {
+			plog(LLV_INFO, LOCATION, NULL,
+		                "membership validated\n");
+			return 0;
+		}
+	}
+
+	return -1;
+}
+
+int 
+xauth_check(iph1)
+	struct ph1handle *iph1;
+{
+	struct xauth_state *xst = &iph1->mode_cfg->xauth;
+
+	/* 
+ 	 * Only the server side (edge device) really check for Xauth 
+	 * status. It does it if the chose authmethod is using Xauth.
+	 * On the client side (roadwarrior), we don't check anything.
+	 */
+	switch (AUTHMETHOD(iph1)) {
+	case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_R:
+	case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_R:
+	case OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_R:
+	/* The following are not yet implemented */
+	case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_R:
+	case OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_R:
+	case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAENC_R:
+	case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAREV_R:
+		if ((iph1->mode_cfg->flags & ISAKMP_CFG_VENDORID_XAUTH) == 0) {
+			plog(LLV_ERROR, LOCATION, NULL,
+			    "Hybrid auth negotiated but peer did not "
+			    "announced as Xauth capable\n");
+			return -1;
+		}
+
+		if (xst->status != XAUTHST_OK) {
+			plog(LLV_ERROR, LOCATION, NULL,
+			    "Hybrid auth negotiated but peer did not "
+			    "succeed Xauth exchange\n");
+			return -1;
+		}
+
+		return 0;
+		break;
+	default:
+		return 0;
+		break;
+	}
+
+	return 0;
+}
+
+int
+group_check(iph1, grp_list, grp_count)
+	struct ph1handle *iph1;
+	char **grp_list;
+	int grp_count;
+{
+	int res = -1;
+	int grp_index = 0;
+	char * usr = NULL;
+
+	/* check for presence of modecfg data */
+
+	if(iph1->mode_cfg == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"xauth group specified but modecfg not found\n");
+		return res;
+	}
+
+	/* loop through our group list */
+
+	for(; grp_index < grp_count; grp_index++) {
+
+		/* check for presence of xauth data */
+
+		usr = iph1->mode_cfg->xauth.authdata.generic.usr;
+
+		if(usr == NULL) {
+			plog(LLV_ERROR, LOCATION, NULL,
+				"xauth group specified but xauth not found\n");
+			return res;
+		}
+
+		/* call appropriate group validation funtion */
+
+		switch (isakmp_cfg_config.groupsource) {
+
+			case ISAKMP_CFG_GROUP_SYSTEM:
+				res = xauth_group_system(
+					usr,
+					grp_list[grp_index]);
+				break;
+
+#ifdef HAVE_LIBLDAP
+			case ISAKMP_CFG_GROUP_LDAP:
+				res = xauth_group_ldap(
+					iph1->mode_cfg->xauth.udn,
+					grp_list[grp_index]);
+				break;
+#endif
+
+			default:
+				/* we should never get here */
+				plog(LLV_ERROR, LOCATION, NULL,
+				    "Unknown group auth source\n");
+				break;
+		}
+
+		if( !res ) {
+			plog(LLV_INFO, LOCATION, NULL,
+				"user \"%s\" is a member of group \"%s\"\n",
+				usr,
+				grp_list[grp_index]);
+			break;
+		} else {
+			plog(LLV_INFO, LOCATION, NULL,
+				"user \"%s\" is not a member of group \"%s\"\n",
+				usr,
+				grp_list[grp_index]);
+		}
+	}
+
+	return res;
+}
+
+vchar_t *
+isakmp_xauth_req(iph1, attr)
+	struct ph1handle *iph1;
+	struct isakmp_data *attr;
+{
+	int type;
+	size_t dlen = 0;
+	int ashort = 0;
+	int value = 0;
+	vchar_t *buffer = NULL;
+	char* mraw = NULL;
+	vchar_t *mdata = NULL;
+	char *data;
+	vchar_t *usr = NULL;
+	vchar_t *pwd = NULL;
+	size_t skip = 0;
+	int freepwd = 0;
+
+	if ((iph1->mode_cfg->flags & ISAKMP_CFG_VENDORID_XAUTH) == 0) {
+		plog(LLV_ERROR, LOCATION, NULL, 
+		    "Xauth mode config request but peer "
+		    "did not declare itself as Xauth capable\n");
+		return NULL;
+	}
+
+	type = ntohs(attr->type) & ~ISAKMP_GEN_MASK;
+
+	/* Sanity checks */
+	switch(type) {
+	case XAUTH_TYPE:
+		if ((ntohs(attr->type) & ISAKMP_GEN_TV) == 0) {
+			plog(LLV_ERROR, LOCATION, NULL, 
+			    "Unexpected long XAUTH_TYPE attribute\n");
+			return NULL;
+		}
+		if (ntohs(attr->lorv) != XAUTH_TYPE_GENERIC) {
+			plog(LLV_ERROR, LOCATION, NULL, 
+			    "Unsupported Xauth authentication %d\n", 
+			    ntohs(attr->lorv));
+			return NULL;
+		}
+		ashort = 1;
+		dlen = 0;
+		value = XAUTH_TYPE_GENERIC;
+		break;
+
+	case XAUTH_USER_NAME:
+		if (!iph1->rmconf->xauth || !iph1->rmconf->xauth->login) {
+			plog(LLV_ERROR, LOCATION, NULL, "Xauth performed "
+			    "with no login supplied\n");
+			return NULL;
+		}
+
+		dlen = iph1->rmconf->xauth->login->l - 1;
+		iph1->rmconf->xauth->state |= XAUTH_SENT_USERNAME;
+		break;
+
+	case XAUTH_USER_PASSWORD:
+		if (!iph1->rmconf->xauth || !iph1->rmconf->xauth->login)
+			return NULL;
+
+		skip = sizeof(struct ipsecdoi_id_b);
+		usr = vmalloc(iph1->rmconf->xauth->login->l - 1 + skip);
+		if (usr == NULL) {
+			plog(LLV_ERROR, LOCATION, NULL, 
+			    "Cannot allocate memory\n");
+			return NULL;
+		}
+		memset(usr->v, 0, skip);
+		memcpy(usr->v + skip, 
+		    iph1->rmconf->xauth->login->v, 
+		    iph1->rmconf->xauth->login->l - 1);
+
+		if (iph1->rmconf->xauth->pass) {
+			/* A key given through racoonctl */
+			pwd = iph1->rmconf->xauth->pass;
+		} else {
+			if ((pwd = getpskbyname(usr)) == NULL) {
+				plog(LLV_ERROR, LOCATION, NULL, 
+				    "No password was found for login %s\n", 
+				    iph1->rmconf->xauth->login->v);
+				vfree(usr);
+				return NULL;
+			}
+			/* We have to free it before returning */
+			freepwd = 1;
+		}
+		vfree(usr);
+
+		iph1->rmconf->xauth->state |= XAUTH_SENT_PASSWORD;
+		dlen = pwd->l;
+
+		break;
+	case XAUTH_MESSAGE:
+		if ((ntohs(attr->type) & ISAKMP_GEN_TV) == 0) {
+			dlen = ntohs(attr->lorv);
+			if (dlen > 0) {
+				mraw = (char*)(attr + 1);
+				if ((mdata = vmalloc(dlen)) == NULL) {
+					plog(LLV_ERROR, LOCATION, iph1->remote,
+					    "Cannot allocate memory\n");
+					return NULL;
+				}
+				memcpy(mdata->v, mraw, mdata->l);
+				plog(LLV_NOTIFY,LOCATION, iph1->remote,
+					"XAUTH Message: '%s'.\n",
+					binsanitize(mdata->v, mdata->l));
+				vfree(mdata);
+			}
+		}
+		return NULL;
+	default:
+		plog(LLV_WARNING, LOCATION, NULL,
+		    "Ignored attribute %s\n", s_isakmp_cfg_type(type));
+		return NULL;
+		break;
+	}
+
+	if ((buffer = vmalloc(sizeof(*attr) + dlen)) == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL,
+		    "Cannot allocate memory\n");
+		goto out;
+	}
+
+	attr = (struct isakmp_data *)buffer->v;
+	if (ashort) {
+		attr->type = htons(type | ISAKMP_GEN_TV);
+		attr->lorv = htons(value);
+		goto out;
+	}
+
+	attr->type = htons(type | ISAKMP_GEN_TLV);
+	attr->lorv = htons(dlen);
+	data = (char *)(attr + 1);
+
+	switch(type) {
+	case XAUTH_USER_NAME:
+		/* 
+		 * iph1->rmconf->xauth->login->v is valid, 
+		 * we just checked it in the previous switch case 
+		 */
+		memcpy(data, iph1->rmconf->xauth->login->v, dlen);
+		break;
+	case XAUTH_USER_PASSWORD:
+		memcpy(data, pwd->v, dlen);
+		break;
+	default:
+		break;
+	}
+
+out:
+	if (freepwd)
+		vfree(pwd);
+
+	return buffer;
+}
+
+vchar_t *
+isakmp_xauth_set(iph1, attr)
+	struct ph1handle *iph1;
+	struct isakmp_data *attr;
+{
+	int type;
+	vchar_t *buffer = NULL;
+	char *data;
+	struct xauth_state *xst;
+	size_t dlen = 0;
+	char* mraw = NULL;
+	vchar_t *mdata = NULL;
+
+	if ((iph1->mode_cfg->flags & ISAKMP_CFG_VENDORID_XAUTH) == 0) {
+		plog(LLV_ERROR, LOCATION, NULL, 
+		    "Xauth mode config set but peer "
+		    "did not declare itself as Xauth capable\n");
+		return NULL;
+	}
+
+	type = ntohs(attr->type) & ~ISAKMP_GEN_MASK;
+
+	switch(type) {
+	case XAUTH_STATUS:
+		/* 
+		 * We should only receive ISAKMP mode_cfg SET XAUTH_STATUS
+		 * when running as a client (initiator).
+		 */
+		xst = &iph1->mode_cfg->xauth;
+		switch(AUTHMETHOD(iph1)) {
+		case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_I:
+		case FICTIVE_AUTH_METHOD_XAUTH_PSKEY_I:
+		case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_I:
+		/* Not implemented ... */
+		case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_I:
+		case OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_I:
+		case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAENC_I:
+		case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAREV_I:
+			break;
+		default:
+			plog(LLV_ERROR, LOCATION, NULL, 
+			    "Unexpected XAUTH_STATUS_OK\n");
+			return NULL;
+			break;
+		}
+
+		/* If we got a failure, delete iph1 */
+		if (ntohs(attr->lorv) != XAUTH_STATUS_OK) {
+			plog(LLV_ERROR, LOCATION, NULL, 
+			    "Xauth authentication failed\n");
+
+			EVT_PUSH(iph1->local, iph1->remote, 
+			    EVTT_XAUTH_FAILED, NULL);
+
+			iph1->mode_cfg->flags |= ISAKMP_CFG_DELETE_PH1;
+		} else {
+			EVT_PUSH(iph1->local, iph1->remote, 
+			    EVTT_XAUTH_SUCCESS, NULL);
+		}
+
+
+		/* We acknowledge it */
+		break;
+	case XAUTH_MESSAGE:
+		if ((ntohs(attr->type) & ISAKMP_GEN_TV) == 0) {
+			dlen = ntohs(attr->lorv);
+			if (dlen > 0) {
+				mraw = (char*)(attr + 1);
+				if ((mdata = vmalloc(dlen)) == NULL) {
+					plog(LLV_ERROR, LOCATION, iph1->remote,
+					    "Cannot allocate memory\n");
+					return NULL;
+				}
+				memcpy(mdata->v, mraw, mdata->l);
+				plog(LLV_NOTIFY,LOCATION, iph1->remote,
+					"XAUTH Message: '%s'.\n",
+					binsanitize(mdata->v, mdata->l));
+				vfree(mdata);
+			}
+		}
+
+	default:
+		plog(LLV_WARNING, LOCATION, NULL,
+		    "Ignored attribute %s\n", s_isakmp_cfg_type(type));
+		return NULL;
+		break;
+	}
+
+	if ((buffer = vmalloc(sizeof(*attr))) == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL,
+		    "Cannot allocate memory\n");
+		return NULL;
+	}
+
+	attr = (struct isakmp_data *)buffer->v;
+	attr->type = htons(type | ISAKMP_GEN_TV);
+	attr->lorv = htons(0);
+
+	return buffer;
+}
+
+
+void 
+xauth_rmstate(xst)
+	struct xauth_state *xst;
+{
+	switch (xst->authtype) {
+	case XAUTH_TYPE_GENERIC:
+		if (xst->authdata.generic.usr)
+			racoon_free(xst->authdata.generic.usr);
+
+		if (xst->authdata.generic.pwd)
+			racoon_free(xst->authdata.generic.pwd);
+
+		break;
+
+	case XAUTH_TYPE_CHAP:
+	case XAUTH_TYPE_OTP:
+	case XAUTH_TYPE_SKEY:
+		plog(LLV_WARNING, LOCATION, NULL, 
+		    "Unsupported authtype %d\n", xst->authtype);
+		break;
+
+	default:
+		plog(LLV_WARNING, LOCATION, NULL, 
+		    "Unexpected authtype %d\n", xst->authtype);
+		break;
+	}
+
+#ifdef HAVE_LIBLDAP
+	if (xst->udn != NULL)
+		racoon_free(xst->udn);
+#endif
+	return;
+}
+
+int
+xauth_rmconf_used(xauth_rmconf)
+	struct xauth_rmconf **xauth_rmconf;
+{
+	if (*xauth_rmconf == NULL) {
+		*xauth_rmconf = racoon_malloc(sizeof(**xauth_rmconf));
+		if (*xauth_rmconf == NULL) {
+			plog(LLV_ERROR, LOCATION, NULL, 
+			    "xauth_rmconf_used: malloc failed\n");
+			return -1;
+		}
+
+		(*xauth_rmconf)->login = NULL;
+		(*xauth_rmconf)->pass = NULL;
+		(*xauth_rmconf)->state = 0;
+	}
+
+	return 0;
+}
+
+void 
+xauth_rmconf_delete(xauth_rmconf)
+	struct xauth_rmconf **xauth_rmconf;
+{
+	if (*xauth_rmconf != NULL) { 
+		if ((*xauth_rmconf)->login != NULL)
+			vfree((*xauth_rmconf)->login);
+		if ((*xauth_rmconf)->pass != NULL)
+			vfree((*xauth_rmconf)->pass);
+
+		racoon_free(*xauth_rmconf);
+		*xauth_rmconf = NULL;
+	}
+
+	return;
+}
diff --git a/src/racoon/isakmp_xauth.h b/src/racoon/isakmp_xauth.h
new file mode 100644
index 0000000..ebb5214
--- /dev/null
+++ b/src/racoon/isakmp_xauth.h
@@ -0,0 +1,155 @@
+/*	$NetBSD: isakmp_xauth.h,v 1.4 2006/09/09 16:22:09 manu Exp $	*/
+
+/*	$KAME$ */
+
+/*
+ * Copyright (C) 2004 Emmanuel Dreyfus 
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _ISAKMP_XAUTH_H
+#define _ISAKMP_XAUTH_H
+
+/* ISAKMP mode config attribute types specific to the Xauth vendor ID */
+#define	XAUTH_TYPE                16520
+#define	XAUTH_USER_NAME           16521
+#define	XAUTH_USER_PASSWORD       16522
+#define	XAUTH_PASSCODE            16523
+#define	XAUTH_MESSAGE             16524
+#define	XAUTH_CHALLENGE           16525
+#define	XAUTH_DOMAIN              16526
+#define	XAUTH_STATUS              16527
+#define	XAUTH_NEXT_PIN            16528
+#define	XAUTH_ANSWER              16529
+
+/* Types for XAUTH_TYPE */
+#define	XAUTH_TYPE_GENERIC 	0
+#define	XAUTH_TYPE_CHAP    	1
+#define	XAUTH_TYPE_OTP     	2
+#define	XAUTH_TYPE_SKEY    	3
+
+/* Values for XAUTH_STATUS */
+#define	XAUTH_STATUS_FAIL       0
+#define	XAUTH_STATUS_OK         1
+
+/* For phase 1 Xauth status */
+struct xauth_state {
+	int status; /* authentication status, used only on server side */
+	int vendorid;
+	int authtype;
+	union {
+		struct authgeneric {
+			char *usr;
+			char *pwd;
+		} generic;
+	} authdata;
+#ifdef HAVE_LIBLDAP
+	char *udn; /* ldap user dn */
+#endif
+};
+
+/* What's been sent */
+#define XAUTH_SENT_USERNAME 1
+#define XAUTH_SENT_PASSWORD 2
+#define XAUTH_SENT_EVERYTHING (XAUTH_SENT_USERNAME | XAUTH_SENT_PASSWORD)
+
+/* For rmconf Xauth data */
+struct xauth_rmconf {
+	vchar_t *login;	/* xauth login */
+	vchar_t *pass;	/* xauth password */
+	int state;      /* what's been sent */
+};
+
+/* status */
+#define XAUTHST_NOTYET	0
+#define XAUTHST_REQSENT	1
+#define XAUTHST_OK	2
+
+struct xauth_reply_arg {
+	isakmp_index index;
+	int port;
+	int id;
+	int res;
+};
+
+struct ph1handle;
+struct isakmp_data;
+void xauth_sendreq(struct ph1handle *);
+int xauth_attr_reply(struct ph1handle *, struct isakmp_data *, int);
+int xauth_login_system(char *, char *);
+void xauth_sendstatus(struct ph1handle *, int, int);
+int xauth_check(struct ph1handle *);
+int group_check(struct ph1handle *, char **, int);
+vchar_t *isakmp_xauth_req(struct ph1handle *, struct isakmp_data *);
+vchar_t *isakmp_xauth_set(struct ph1handle *, struct isakmp_data *);
+void xauth_rmstate(struct xauth_state *);
+void xauth_reply_stub(void *);
+int xauth_reply(struct ph1handle *, int, int, int);
+int xauth_rmconf_used(struct xauth_rmconf **);
+void xauth_rmconf_delete(struct xauth_rmconf **);
+
+#ifdef HAVE_LIBRADIUS
+int xauth_login_radius(struct ph1handle *, char *, char *);
+int xauth_radius_init(void);
+#endif
+
+#ifdef HAVE_LIBPAM
+int xauth_login_pam(int, struct sockaddr *, char *, char *);
+#endif
+
+#ifdef HAVE_LIBLDAP
+
+#define LDAP_DFLT_HOST		"localhost"
+#define LDAP_DFLT_USER		"cn"
+#define LDAP_DFLT_ADDR		"racoon-address"
+#define LDAP_DFLT_MASK		"racoon-netmask"
+#define LDAP_DFLT_GROUP		"cn"
+#define LDAP_DFLT_MEMBER	"member"
+
+struct xauth_ldap_config {
+	int		pver;
+	vchar_t 	*host;
+	int		port;
+	vchar_t		*base;
+	int		subtree;
+	vchar_t		*bind_dn;
+	vchar_t		*bind_pw;
+	int		auth_type;
+	vchar_t		*attr_user;
+	vchar_t		*attr_addr;
+	vchar_t		*attr_mask;
+	vchar_t		*attr_group;
+	vchar_t		*attr_member;
+};
+
+extern struct xauth_ldap_config xauth_ldap_config;
+
+int xauth_ldap_init(void);
+int xauth_login_ldap(struct ph1handle *, char *, char *);
+#endif
+
+#endif /* _ISAKMP_XAUTH_H */
diff --git a/src/racoon/kmpstat.c b/src/racoon/kmpstat.c
new file mode 100644
index 0000000..c59e43a
--- /dev/null
+++ b/src/racoon/kmpstat.c
@@ -0,0 +1,227 @@
+/*	$NetBSD: kmpstat.c,v 1.4.6.2 2007/11/06 16:41:33 vanhu Exp $	*/
+
+/*	$KAME: kmpstat.c,v 1.33 2004/08/16 08:20:28 itojun Exp $	*/
+
+/*
+ * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <net/pfkeyv2.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#if TIME_WITH_SYS_TIME
+# include <sys/time.h>
+# include <time.h>
+#else
+# if HAVE_SYS_TIME_H
+#  include <sys/time.h>
+# else
+#  include <time.h>
+# endif
+#endif
+#include <netdb.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <err.h>
+#include <sys/ioctl.h> 
+#include <resolv.h>
+
+#include "libpfkey.h"
+
+#include "var.h"
+#include "misc.h"
+#include "vmbuf.h"
+#include "plog.h"
+#include "debug.h"
+#include "sockmisc.h"
+
+#include "racoonctl.h"
+#include "admin.h"
+#include "schedule.h"
+#include "isakmp_var.h"
+#include "isakmp.h"
+#include "isakmp_xauth.h"
+#include "isakmp_var.h"
+#include "isakmp_cfg.h"
+#include "oakley.h"
+#include "handler.h"
+#include "pfkey.h"
+#include "admin.h"
+#include "evt.h"
+#include "admin_var.h"
+#include "ipsec_doi.h"
+
+u_int32_t racoonctl_interface = RACOONCTL_INTERFACE;
+u_int32_t racoonctl_interface_major = RACOONCTL_INTERFACE_MAJOR;
+
+static int so;
+u_int32_t loglevel = 0;
+
+int
+com_init()
+{
+	struct sockaddr_un name;
+
+	memset(&name, 0, sizeof(name));
+	name.sun_family = AF_UNIX;
+	snprintf(name.sun_path, sizeof(name.sun_path),
+		"%s", adminsock_path);
+
+	so = socket(AF_UNIX, SOCK_STREAM, 0);
+	if (so < 0)
+		return -1;
+
+	if (connect(so, (struct sockaddr *)&name, sizeof(name)) < 0) {
+		(void)close(so);
+		return -1;
+	}
+
+	return 0;
+}
+
+int
+com_send(combuf)
+	vchar_t *combuf;
+{
+	int len;
+
+	if ((len = send(so, combuf->v, combuf->l, 0)) == -1) {
+		perror("send");
+		(void)close(so);
+		return -1;
+	}
+
+	return 0;
+}
+
+int
+com_recv(combufp) 
+	vchar_t **combufp;
+{
+	struct admin_com h, *com;
+	caddr_t buf;
+	int len;
+	int l = 0;
+	caddr_t p;
+
+	if (combufp == NULL)
+		return -1;
+
+	/* receive by PEEK */ 
+	if ((len = recv(so, &h, sizeof(h), MSG_PEEK)) == -1)
+		goto bad1;
+
+	/* sanity check */
+	if (len < sizeof(h))
+		goto bad1;
+
+	if (h.ac_errno) {
+		errno = h.ac_errno;
+		goto bad1;
+	}
+
+	/* allocate buffer */
+	if ((*combufp = vmalloc(h.ac_len)) == NULL)
+		goto bad1;
+
+	/* read real message */
+	p = (*combufp)->v;
+	while (l < len) {
+		if ((len = recv(so, p, h.ac_len, 0)) < 0) {
+			perror("recv");
+			goto bad2;
+		}
+		l += len;
+		p += len;
+	}
+	
+	return 0;
+
+bad2:
+	vfree(*combufp);
+bad1:
+	*combufp = NULL;
+	return -1;
+}
+
+/*
+ * Dumb plog functions (used by sockmisc.c) 
+ */
+void
+_plog(int pri, const char *func, struct sockaddr *sa, const char *fmt, ...)
+{
+	va_list ap;
+
+	va_start(ap, fmt);
+	vprintf(fmt, ap);
+	va_end(ap);
+}
+
+void
+plogdump(pri, data, len) 
+	int pri;
+	void *data;
+	size_t len;
+{
+	return;
+}
+
+struct sockaddr *
+get_sockaddr(family, name, port)
+	int family;
+	char *name, *port;
+{
+	struct addrinfo hint, *ai;
+	int error;
+
+	memset(&hint, 0, sizeof(hint));
+	hint.ai_family = PF_UNSPEC;
+	hint.ai_family = family;
+	hint.ai_socktype = SOCK_STREAM;
+
+	error = getaddrinfo(name, port, &hint, &ai);
+	if (error != 0) {
+		printf("%s: %s/%s\n", gai_strerror(error), name, port);
+		return NULL;
+	}
+
+	return ai->ai_addr;
+}
diff --git a/src/racoon/localconf.c b/src/racoon/localconf.c
new file mode 100644
index 0000000..ede1d9b
--- /dev/null
+++ b/src/racoon/localconf.c
@@ -0,0 +1,371 @@
+/*	$NetBSD: localconf.c,v 1.4 2006/09/09 16:22:09 manu Exp $	*/
+
+/*	$KAME: localconf.c,v 1.33 2001/08/09 07:32:19 sakane Exp $	*/
+
+/*
+ * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include <sys/types.h>
+#include <sys/param.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <ctype.h>
+#include <err.h>
+
+#include "var.h"
+#include "misc.h"
+#include "vmbuf.h"
+#include "plog.h"
+#include "debug.h"
+
+#include "localconf.h"
+#include "algorithm.h"
+#include "admin.h"
+#include "privsep.h"
+#include "isakmp_var.h"
+#include "isakmp.h"
+#include "ipsec_doi.h"
+#include "grabmyaddr.h"
+#include "vendorid.h"
+#include "str2val.h"
+#include "safefile.h"
+#include "admin.h"
+#include "gcmalloc.h"
+
+struct localconf *lcconf;
+
+static void setdefault __P((void));
+
+void
+initlcconf()
+{
+	lcconf = racoon_calloc(1, sizeof(*lcconf));
+	if (lcconf == NULL)
+		errx(1, "failed to allocate local conf.");
+
+	setdefault();
+
+	lcconf->racoon_conf = LC_DEFAULT_CF;
+}
+
+void
+flushlcconf()
+{
+	int i;
+
+	setdefault();
+	clear_myaddr(&lcconf->myaddrs);
+	for (i = 0; i < LC_PATHTYPE_MAX; i++) {
+		if (lcconf->pathinfo[i]) {
+			racoon_free(lcconf->pathinfo[i]);
+			lcconf->pathinfo[i] = NULL;
+		}
+	}
+	for (i = 0; i < LC_IDENTTYPE_MAX; i++) {
+		if (lcconf->ident[i])
+			vfree(lcconf->ident[i]);
+		lcconf->ident[i] = NULL;
+	}
+}
+
+static void
+setdefault()
+{
+	lcconf->uid = 0;
+	lcconf->gid = 0;
+	lcconf->chroot = NULL;
+	lcconf->autograbaddr = 1;
+	lcconf->port_isakmp = PORT_ISAKMP;
+	lcconf->port_isakmp_natt = PORT_ISAKMP_NATT;
+	lcconf->default_af = AF_INET;
+	lcconf->pad_random = LC_DEFAULT_PAD_RANDOM;
+	lcconf->pad_randomlen = LC_DEFAULT_PAD_RANDOMLEN;
+	lcconf->pad_maxsize = LC_DEFAULT_PAD_MAXSIZE;
+	lcconf->pad_strict = LC_DEFAULT_PAD_STRICT;
+	lcconf->pad_excltail = LC_DEFAULT_PAD_EXCLTAIL;
+	lcconf->retry_counter = LC_DEFAULT_RETRY_COUNTER;
+	lcconf->retry_interval = LC_DEFAULT_RETRY_INTERVAL;
+	lcconf->count_persend = LC_DEFAULT_COUNT_PERSEND;
+	lcconf->secret_size = LC_DEFAULT_SECRETSIZE;
+	lcconf->retry_checkph1 = LC_DEFAULT_RETRY_CHECKPH1;
+	lcconf->wait_ph2complete = LC_DEFAULT_WAIT_PH2COMPLETE;
+	lcconf->strict_address = FALSE;
+	lcconf->complex_bundle = TRUE; /*XXX FALSE;*/
+	lcconf->gss_id_enc = LC_GSSENC_UTF16LE; /* Windows compatibility */
+	lcconf->natt_ka_interval = LC_DEFAULT_NATT_KA_INTERVAL;
+}
+
+/*
+ * get PSK by string.
+ */
+vchar_t *
+getpskbyname(id0)
+	vchar_t *id0;
+{
+	char *id;
+	vchar_t *key = NULL;
+
+	id = racoon_calloc(1, 1 + id0->l - sizeof(struct ipsecdoi_id_b));
+	if (id == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"failed to get psk buffer.\n");
+		goto end;
+	}
+	memcpy(id, id0->v + sizeof(struct ipsecdoi_id_b),
+		id0->l - sizeof(struct ipsecdoi_id_b));
+	id[id0->l - sizeof(struct ipsecdoi_id_b)] = '\0';
+
+	key = privsep_getpsk(id, id0->l - sizeof(struct ipsecdoi_id_b));
+
+end:
+	if (id)
+		racoon_free(id);
+	return key;
+}
+
+/*
+ * get PSK by address.
+ */
+vchar_t *
+getpskbyaddr(remote)
+	struct sockaddr *remote;
+{
+	vchar_t *key = NULL;
+	char addr[NI_MAXHOST], port[NI_MAXSERV];
+
+	GETNAMEINFO(remote, addr, port);
+
+	key = privsep_getpsk(addr, strlen(addr));
+
+	return key;
+}
+
+vchar_t *
+getpsk(str, len)
+	const char *str;
+	const int len;
+{
+	FILE *fp;
+	char buf[1024];	/* XXX how is variable length ? */
+	vchar_t *key = NULL;
+	char *p, *q;
+	size_t keylen;
+	char *k = NULL;
+
+	if (safefile(lcconf->pathinfo[LC_PATHTYPE_PSK], 1) == 0)
+		fp = fopen(lcconf->pathinfo[LC_PATHTYPE_PSK], "r");
+	else
+		fp = NULL;
+	if (fp == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"failed to open pre_share_key file %s\n",
+			lcconf->pathinfo[LC_PATHTYPE_PSK]);
+		return NULL;
+	}
+
+	while (fgets(buf, sizeof(buf), fp) != NULL) {
+		/* comment line */
+		if (buf[0] == '#')
+			continue;
+
+		/* search the end of 1st string. */
+		for (p = buf; *p != '\0' && !isspace((int)*p); p++)
+			;
+		if (*p == '\0')
+			continue;	/* no 2nd parameter */
+		*p = '\0';
+		/* search the 1st of 2nd string. */
+		while (isspace((int)*++p))
+			;
+		if (*p == '\0')
+			continue;	/* no 2nd parameter */
+		p--;
+		if (strncmp(buf, str, len) == 0 && buf[len] == '\0') {
+			p++;
+			keylen = 0;
+			for (q = p; *q != '\0' && *q != '\n'; q++)
+				keylen++;
+			*q = '\0';
+
+			/* fix key if hex string */
+			if (strncmp(p, "0x", 2) == 0) {
+				k = str2val(p + 2, 16, &keylen);
+				if (k == NULL) {
+					plog(LLV_ERROR, LOCATION, NULL,
+						"failed to get psk buffer.\n");
+					goto end;
+				}
+				p = k;
+			}
+
+			key = vmalloc(keylen);
+			if (key == NULL) {
+				plog(LLV_ERROR, LOCATION, NULL,
+					"failed to allocate key buffer.\n");
+				goto end;
+			}
+			memcpy(key->v, p, key->l);
+			if (k)
+				racoon_free(k);
+			goto end;
+		}
+	}
+
+end:
+	fclose(fp);
+	return key;
+}
+
+/*
+ * get a file name of a type specified.
+ */
+void
+getpathname(path, len, type, name)
+	char *path;
+	int len, type;
+	const char *name;
+{
+	snprintf(path, len, "%s%s%s", 
+		name[0] == '/' ? "" : lcconf->pathinfo[type],
+		name[0] == '/' ? "" : "/",
+		name);
+
+	plog(LLV_DEBUG, LOCATION, NULL, "filename: %s\n", path);
+}
+
+#if 0 /* DELETEIT */
+static int lc_doi2idtype[] = {
+	-1,
+	-1,
+	LC_IDENTTYPE_FQDN,
+	LC_IDENTTYPE_USERFQDN,
+	-1,
+	-1,
+	-1,
+	-1,
+	-1,
+	LC_IDENTTYPE_CERTNAME,
+	-1,
+	LC_IDENTTYPE_KEYID,
+};
+
+/*
+ * convert DOI value to idtype
+ * OUT	-1   : NG
+ *	other: converted.
+ */
+int
+doi2idtype(idtype)
+	int idtype;
+{
+	if (ARRAYLEN(lc_doi2idtype) > idtype)
+		return lc_doi2idtype[idtype];
+	return -1;
+}
+#endif
+
+static int lc_sittype2doi[] = {
+	IPSECDOI_SIT_IDENTITY_ONLY,
+	IPSECDOI_SIT_SECRECY,
+	IPSECDOI_SIT_INTEGRITY,
+};
+
+/*
+ * convert sittype to DOI value.
+ * OUT	-1   : NG
+ *	other: converted.
+ */
+int
+sittype2doi(sittype)
+	int sittype;
+{
+	if (ARRAYLEN(lc_sittype2doi) > sittype)
+		return lc_sittype2doi[sittype];
+	return -1;
+}
+
+static int lc_doitype2doi[] = {
+	IPSEC_DOI,
+};
+
+/*
+ * convert doitype to DOI value.
+ * OUT	-1   : NG
+ *	other: converted.
+ */
+int
+doitype2doi(doitype)
+	int doitype;
+{
+	if (ARRAYLEN(lc_doitype2doi) > doitype)
+		return lc_doitype2doi[doitype];
+	return -1;
+}
+
+
+
+static void
+saverestore_params(f)
+	int f;
+{
+	static u_int16_t s_port_isakmp;
+#ifdef ENABLE_ADMINPORT
+	static u_int16_t s_port_admin;
+#endif
+
+	/* 0: save, 1: restore */
+	if (f) {
+		lcconf->port_isakmp = s_port_isakmp;
+#ifdef ENABLE_ADMINPORT
+		lcconf->port_admin = s_port_admin;
+#endif
+	} else {
+		s_port_isakmp = lcconf->port_isakmp;
+#ifdef ENABLE_ADMINPORT
+		s_port_admin = lcconf->port_admin;
+#endif
+	}
+}
+
+void
+restore_params()
+{
+	saverestore_params(1);
+}
+
+void
+save_params()
+{
+	saverestore_params(0);
+}
diff --git a/src/racoon/localconf.h b/src/racoon/localconf.h
new file mode 100644
index 0000000..f7cf33a
--- /dev/null
+++ b/src/racoon/localconf.h
@@ -0,0 +1,137 @@
+/*	$NetBSD: localconf.h,v 1.4 2006/09/09 16:22:09 manu Exp $	*/
+
+/* Id: localconf.h,v 1.13 2005/11/06 18:13:18 monas Exp */
+
+/*
+ * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _LOCALCONF_H
+#define _LOCALCONF_H
+
+/* local configuration */
+
+#define LC_DEFAULT_CF	SYSCONFDIR "/racoon.conf"
+
+#define LC_PATHTYPE_INCLUDE	0
+#define LC_PATHTYPE_PSK		1
+#define LC_PATHTYPE_CERT	2
+#define LC_PATHTYPE_BACKUPSA	3
+#define LC_PATHTYPE_SCRIPT	4
+#define LC_PATHTYPE_PIDFILE	5
+#define LC_PATHTYPE_MAX		6
+
+#define LC_DEFAULT_PAD_MAXSIZE		20
+#define LC_DEFAULT_PAD_RANDOM		TRUE
+#define LC_DEFAULT_PAD_RANDOMLEN	FALSE
+#define LC_DEFAULT_PAD_STRICT		FALSE
+#define LC_DEFAULT_PAD_EXCLTAIL		TRUE
+#define LC_DEFAULT_RETRY_COUNTER	5
+#define LC_DEFAULT_RETRY_INTERVAL	10
+#define LC_DEFAULT_COUNT_PERSEND	1
+#define LC_DEFAULT_RETRY_CHECKPH1	30
+#define LC_DEFAULT_WAIT_PH2COMPLETE	30
+#define LC_DEFAULT_NATT_KA_INTERVAL	20
+
+#define LC_DEFAULT_SECRETSIZE	16	/* 128 bits */
+
+#define LC_IDENTTYPE_MAX	5	/* XXX */
+
+#define	LC_GSSENC_UTF16LE	0	/* GSS ID in UTF-16LE */
+#define	LC_GSSENC_LATIN1	1	/* GSS ID in ISO-Latin-1 */
+#define	LC_GSSENC_MAX		2
+
+struct localconf {
+	char *racoon_conf;		/* configuration filename */
+
+	uid_t uid;
+	gid_t gid;
+	char *chroot;			/* chroot path */
+	u_int16_t port_isakmp;		/* port for isakmp as default */
+	u_int16_t port_isakmp_natt;	/* port for NAT-T use */
+	u_int16_t port_admin;		/* port for admin */
+	int default_af;			/* default address family */
+
+	int sock_admin;
+	int sock_pfkey;
+	int rtsock;			/* routing socket */
+
+	int autograbaddr;
+	struct myaddrs *myaddrs;
+
+	char *pathinfo[LC_PATHTYPE_MAX];
+	vchar_t *ident[LC_IDENTTYPE_MAX]; /* base of Identifier payload. */
+
+	int pad_random;
+	int pad_randomlen;
+	int pad_maxsize;
+	int pad_strict;
+	int pad_excltail;
+
+	int retry_counter;		/* times to retry. */
+	int retry_interval;		/* interval each retry. */
+	int count_persend;		/* the number of packets each retry. */
+				/* above 3 values are copied into a handler. */
+
+	int retry_checkph1;
+	int wait_ph2complete;
+
+	int natt_ka_interval;		/* NAT-T keepalive interval. */
+
+	int secret_size;
+	int strict_address;		/* strictly check addresses. */
+
+	int complex_bundle;
+		/*
+		 * If we want to make a packet "IP2 AH ESP IP1 ULP",
+		 * the SPD in KAME expresses AH transport + ESP tunnel.
+		 * So racoon sent the proposal contained such the order.
+		 * But lots of implementation interprets AH tunnel + ESP
+		 * tunnel in this case.  racoon has changed the format,
+		 * usually uses this format.  If the option, 'complex_bundle'
+		 * is enable, racoon uses old format.
+		 */
+
+	int gss_id_enc;			/* GSS ID encoding to use */
+};
+
+extern struct localconf *lcconf;
+
+extern void initlcconf __P((void));
+extern void flushlcconf __P((void));
+extern vchar_t *getpskbyname __P((vchar_t *));
+extern vchar_t *getpskbyaddr __P((struct sockaddr *));
+extern void getpathname __P((char *, int, int, const char *));
+extern int sittype2doi __P((int));
+extern int doitype2doi __P((int));
+extern vchar_t *getpsk __P((const char *, const int)); 
+
+extern void restore_params __P((void));
+extern void save_params __P((void));
+
+#endif /* _LOCALCONF_H */
diff --git a/src/racoon/logger.c b/src/racoon/logger.c
new file mode 100644
index 0000000..06991cc
--- /dev/null
+++ b/src/racoon/logger.c
@@ -0,0 +1,262 @@
+/*	$NetBSD: logger.c,v 1.4 2006/09/09 16:22:09 manu Exp $	*/
+
+/*	$KAME: logger.c,v 1.9 2002/09/03 14:37:03 itojun Exp $	*/
+
+/*
+ * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include <sys/types.h>
+#include <sys/param.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#ifdef HAVE_STDARG_H
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
+#if TIME_WITH_SYS_TIME
+# include <sys/time.h>
+# include <time.h>
+#else
+# if HAVE_SYS_TIME_H
+#  include <sys/time.h>
+# else
+#  include <time.h>
+# endif
+#endif
+
+#include "logger.h"
+#include "var.h"
+#include "gcmalloc.h"
+
+struct log *
+log_open(siz, fname)
+	size_t siz;
+	char *fname;
+{
+	struct log *p;
+
+	p = (struct log *)racoon_malloc(sizeof(*p));
+	if (p == NULL)
+		return NULL;
+	memset(p, 0, sizeof(*p));
+
+	p->buf = (char **)racoon_malloc(sizeof(char *) * siz);
+	if (p->buf == NULL) {
+		racoon_free(p);
+		return NULL;
+	}
+	memset(p->buf, 0, sizeof(char *) * siz);
+
+	p->tbuf = (time_t *)racoon_malloc(sizeof(time_t *) * siz);
+	if (p->tbuf == NULL) {
+		racoon_free(p->buf);
+		racoon_free(p);
+		return NULL;
+	}
+	memset(p->tbuf, 0, sizeof(time_t *) * siz);
+
+	p->siz = siz;
+	if (fname)
+		p->fname = racoon_strdup(fname);
+
+	return p;
+}
+
+/*
+ * append string to ring buffer.
+ * string must be \n-terminated (since we add timestamps).
+ * even if not, we'll add \n to avoid formatting mistake (see log_close()).
+ */
+void
+log_add(p, str)
+	struct log *p;
+	char *str;
+{
+	/* syslog if p->fname == NULL? */
+	if (p->buf[p->head])
+		racoon_free(p->buf[p->head]);
+	p->buf[p->head] = racoon_strdup(str);
+	p->tbuf[p->head] = time(NULL);
+	p->head++;
+	p->head %= p->siz;
+}
+
+/*
+ * write out string to the log file, as is.
+ * \n-termination is up to the caller.  if you don't add \n, the file
+ * format may be broken.
+ */
+int
+log_print(p, str)
+	struct log *p;
+	char *str;
+{
+	FILE *fp;
+
+	if (p->fname == NULL)
+		return -1;	/*XXX syslog?*/
+	fp = fopen(p->fname, "a");
+	if (fp == NULL)
+		return -1;
+	fprintf(fp, "%s", str);
+	fclose(fp);
+
+	return 0;
+}
+
+int
+log_vprint(struct log *p, const char *fmt, ...)
+{
+	va_list ap;
+
+	FILE *fp;
+
+	if (p->fname == NULL)
+		return -1;	/*XXX syslog?*/
+	fp = fopen(p->fname, "a");
+	if (fp == NULL)
+		return -1;
+	va_start(ap, fmt);
+	vfprintf(fp, fmt, ap);
+	va_end(ap);
+
+	fclose(fp);
+
+	return 0;
+}
+
+int
+log_vaprint(struct log *p, const char *fmt, va_list ap)
+{
+	FILE *fp;
+
+	if (p->fname == NULL)
+		return -1;	/*XXX syslog?*/
+	fp = fopen(p->fname, "a");
+	if (fp == NULL)
+		return -1;
+	vfprintf(fp, fmt, ap);
+	fclose(fp);
+
+	return 0;
+}
+
+/*
+ * write out content of ring buffer, and reclaim the log structure
+ */
+int
+log_close(p)
+	struct log *p;
+{
+	FILE *fp;
+	int i, j;
+	char ts[256];
+	struct tm *tm;
+
+	if (p->fname == NULL)
+		goto nowrite;
+	fp = fopen(p->fname, "a");
+	if (fp == NULL)
+		goto nowrite;
+
+	for (i = 0; i < p->siz; i++) {
+		j = (p->head + i) % p->siz;
+		if (p->buf[j]) {
+			tm = localtime(&p->tbuf[j]);
+			strftime(ts, sizeof(ts), "%B %d %T", tm);
+			fprintf(fp, "%s: %s\n", ts, p->buf[j]);
+			if (*(p->buf[j] + strlen(p->buf[j]) - 1) != '\n')
+				fprintf(fp, "\n");
+		}
+	}
+	fclose(fp);
+
+nowrite:
+	log_free(p);
+	return 0;
+}
+
+void
+log_free(p)
+	struct log *p;
+{
+	int i;
+
+	for (i = 0; i < p->siz; i++)
+		racoon_free(p->buf[i]);
+	racoon_free(p->buf);
+	racoon_free(p->tbuf);
+	if (p->fname)
+		racoon_free(p->fname);
+	racoon_free(p);
+}
+
+#ifdef TEST
+struct log *l;
+
+void
+vatest(const char *fmt, ...)
+{
+	va_list ap;
+	va_start(ap, fmt);
+	log_vaprint(l, fmt, ap);
+	va_end(ap);
+}
+
+int
+main(argc, argv)
+	int argc;
+	char **argv;
+{
+	int i;
+
+	l = log_open(30, "/tmp/hoge");
+	if (l == NULL)
+		errx(1, "hoge");
+
+	for (i = 0; i < 50; i++) {
+		log_add(l, "foo");
+		log_add(l, "baa");
+		log_add(l, "baz");
+	}
+	log_print(l, "hoge\n");
+	log_vprint(l, "hoge %s\n", "this is test");
+	vatest("%s %s\n", "this is", "vprint test");
+	abort();
+	log_free(l);
+}
+
+#endif
+
diff --git a/src/racoon/logger.h b/src/racoon/logger.h
new file mode 100644
index 0000000..3fd3e94
--- /dev/null
+++ b/src/racoon/logger.h
@@ -0,0 +1,53 @@
+/*	$NetBSD: logger.h,v 1.4 2006/09/09 16:22:09 manu Exp $	*/
+
+/* Id: logger.h,v 1.3 2004/06/11 16:00:16 ludvigm Exp */
+
+/*
+ * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _LOGGER_H
+#define _LOGGER_H
+
+struct log {
+	int head;
+	int siz;
+	char **buf;
+	time_t *tbuf;
+	char *fname;
+};
+
+extern struct log *log_open __P((size_t, char *));
+extern void log_add __P((struct log *, char *));
+extern int log_print __P((struct log *, char *));
+extern int log_vprint __P((struct log *, const char *, ...));
+extern int log_vaprint __P((struct log *, const char *, va_list));
+extern int log_close __P((struct log *));
+extern void log_free __P((struct log *));
+
+#endif /* _LOGGER_H */
diff --git a/src/racoon/main.c b/src/racoon/main.c
new file mode 100644
index 0000000..aee7515
--- /dev/null
+++ b/src/racoon/main.c
@@ -0,0 +1,403 @@
+/*	$NetBSD: main.c,v 1.6.6.1 2007/06/07 20:34:18 manu Exp $	*/
+
+/* Id: main.c,v 1.25 2006/06/20 20:31:34 manubsd Exp */
+
+/*
+ * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+
+#include <netinet/in.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <limits.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <paths.h>
+#include <err.h>
+
+/*
+ * If we're using a debugging malloc library, this may define our
+ * wrapper stubs.
+ */
+#define	RACOON_MAIN_PROGRAM
+#include "gcmalloc.h"
+
+#include "var.h"
+#include "misc.h"
+#include "vmbuf.h"
+#include "plog.h"
+#include "debug.h"
+
+#include "cfparse_proto.h"
+#include "isakmp_var.h"
+#ifdef ENABLE_HYBRID
+#include <resolv.h>
+#include "isakmp.h"
+#include "isakmp_xauth.h"
+#include "isakmp_cfg.h"
+#endif
+#include "remoteconf.h"
+#include "localconf.h"
+#include "session.h"
+#include "oakley.h"
+#include "pfkey.h"
+#include "policy.h"
+#include "crypto_openssl.h"
+#include "backupsa.h"
+#include "vendorid.h"
+
+#include "package_version.h"
+#ifdef ANDROID_CHANGES
+#include <stdarg.h>
+void errx(int eval, const char *fmt, ...)
+{ 
+	va_list p;
+	va_start(p, fmt);
+	fprintf(stderr, fmt, p);
+	va_end(p);
+	exit(eval);
+}
+#endif
+
+int f_local = 0;	/* local test mode.  behave like a wall. */
+int vflag = 1;		/* for print-isakmp.c */
+static int loading_sa = 0;	/* install sa when racoon boots up. */
+static int dump_config = 0;	/* dump parsed config file. */
+
+#ifdef TOP_PACKAGE
+static char version[] = "@(#)" TOP_PACKAGE_STRING " (" TOP_PACKAGE_URL ")";
+#else /* TOP_PACKAGE */
+static char version[] = "@(#) racoon / IPsec-tools";
+#endif /* TOP_PACKAGE */
+
+int main __P((int, char **));
+static void usage __P((void));
+static void parse __P((int, char **));
+#if 0
+static void cleanup_pidfile __P((void));
+#endif
+
+void
+usage()
+{
+	printf("usage: racoon [-BdFv%s] %s[-f (file)] [-l (file)] [-p (port)]\n",
+#ifdef INET6
+		"46",
+#else
+		"",
+#endif
+#ifdef ENABLE_ADMINPORT
+		"[-a (port)] "
+#else
+		""
+#endif
+		);
+	printf("   -B: install SA to the kernel from the file "
+		"specified by the configuration file.\n");
+	printf("   -d: debug level, more -d will generate more debug message.\n");
+	printf("   -C: dump parsed config file.\n");
+	printf("   -L: include location in debug messages\n");
+	printf("   -F: run in foreground, do not become daemon.\n");
+	printf("   -v: be more verbose\n");
+#ifdef INET6
+	printf("   -4: IPv4 mode.\n");
+	printf("   -6: IPv6 mode.\n");
+#endif
+#ifdef ENABLE_ADMINPORT
+	printf("   -a: port number for admin port.\n");
+#endif
+	printf("   -f: pathname for configuration file.\n");
+	printf("   -l: pathname for log file.\n");
+	printf("   -p: port number for isakmp (default: %d).\n", PORT_ISAKMP);
+	printf("   -P: port number for NAT-T (default: %d).\n", PORT_ISAKMP_NATT);
+	exit(1);
+}
+
+int
+main(ac, av)
+	int ac;
+	char **av;
+{
+	int error;
+
+	if (geteuid() != 0) {
+		errx(1, "must be root to invoke this program.");
+		/* NOTREACHED*/
+	}
+
+	/*
+	 * Don't let anyone read files I write.  Although some files (such as
+	 * the PID file) can be other readable, we dare to use the global mask,
+	 * because racoon uses fopen(3), which can't specify the permission
+	 * at the creation time.
+	 */
+	umask(077);
+	if (umask(077) != 077) {
+		errx(1, "could not set umask");
+		/* NOTREACHED*/
+	}
+
+#ifdef DEBUG_RECORD_MALLOCATION
+	DRM_init();
+#endif
+
+#ifdef HAVE_SECCTX
+	init_avc();
+#endif
+	eay_init();
+	initlcconf();
+	initrmconf();
+	oakley_dhinit();
+	compute_vendorids();
+
+	parse(ac, av);
+
+	ploginit();
+
+	plog(LLV_INFO, LOCATION, NULL, "%s\n", version);
+	plog(LLV_INFO, LOCATION, NULL, "@(#)"
+	    "This product linked %s (http://www.openssl.org/)"
+	    "\n", eay_version());
+	plog(LLV_INFO, LOCATION, NULL, "Reading configuration from \"%s\"\n", 
+	    lcconf->racoon_conf);
+
+	if (pfkey_init() < 0) {
+		errx(1, "something error happened "
+			"while pfkey initializing.");
+		/* NOTREACHED*/
+	}
+
+#ifdef ENABLE_HYBRID
+	if (isakmp_cfg_init(ISAKMP_CFG_INIT_COLD))
+		errx(1, "could not initialize ISAKMP mode config structures");
+#endif
+
+#ifdef HAVE_LIBLDAP
+	if (xauth_ldap_init() != 0)
+		errx(1, "could not initialize libldap");
+#endif
+
+	/*
+	 * in order to prefer the parameters by command line,
+	 * saving some parameters before parsing configuration file.
+	 */
+	save_params();
+	error = cfparse();
+	if (error != 0)
+		errx(1, "failed to parse configuration file.");
+	restore_params();
+
+	if (dump_config)
+		dumprmconf ();
+
+#ifdef HAVE_LIBRADIUS
+	if (xauth_radius_init() != 0) {
+		errx(1, "could not initialize libradius");
+		/* NOTREACHED*/
+	}
+#endif
+
+	/*
+	 * install SAs from the specified file.  If the file is not specified
+	 * by the configuration file, racoon will exit.
+	 */
+	if (loading_sa && !f_local) {
+		if (backupsa_from_file() != 0)
+			errx(1, "something error happened "
+				"SA recovering.");
+	}
+
+	if (f_foreground)
+		close(0);
+	else {
+		if (daemon(0, 0) < 0) {
+			errx(1, "failed to be daemon. (%s)",
+				strerror(errno));
+		}
+#ifndef __linux__
+		/*
+		 * In case somebody has started inetd manually, we need to
+		 * clear the logname, so that old servers run as root do not
+		 * get the user's logname..
+		 */
+		if (setlogin("") < 0) {
+			plog(LLV_ERROR, LOCATION, NULL,
+				"cannot clear logname: %s\n", strerror(errno));
+			/* no big deal if it fails.. */
+		}
+#endif
+		if (!f_local) {
+#if 0
+			if (atexit(cleanup_pidfile) < 0) {
+				plog(LLV_ERROR, LOCATION, NULL,
+					"cannot register pidfile cleanup");
+			}
+#endif
+		}
+	}
+
+	session();
+
+	exit(0);
+}
+
+#if 0
+static void
+cleanup_pidfile()
+{
+	pid_t p = getpid();
+
+	/* if it's not child process, clean everything */
+	if (racoon_pid == p) {
+		const char *pid_file = _PATH_VARRUN "racoon.pid";
+
+		(void) unlink(pid_file);
+	}
+}
+#endif
+
+static void
+parse(ac, av)
+	int ac;
+	char **av;
+{
+	extern char *optarg;
+	extern int optind;
+	int c;
+#ifdef YYDEBUG
+	extern int yydebug;
+#endif
+
+	pname = strrchr(*av, '/');
+	if (pname)
+		pname++;
+	else
+		pname = *av;
+
+	while ((c = getopt(ac, av, "dLFp:P:a:f:l:vZBC"
+#ifdef YYDEBUG
+			"y"
+#endif
+#ifdef INET6
+			"46"
+#endif
+			)) != -1) {
+		switch (c) {
+		case 'd':
+			loglevel++;
+			break;
+		case 'L':
+			print_location = 1;
+			break;
+		case 'F':
+			printf("Foreground mode.\n");
+			f_foreground = 1;
+			break;
+		case 'p':
+			lcconf->port_isakmp = atoi(optarg);
+			break;
+		case 'P':
+			lcconf->port_isakmp_natt = atoi(optarg);
+			break;
+		case 'a':
+#ifdef ENABLE_ADMINPORT
+			lcconf->port_admin = atoi(optarg);
+			break;
+#else
+			fprintf(stderr, "%s: the option is disabled "
+			    "in the configuration\n", pname);
+			exit(1);
+#endif
+		case 'f':
+			lcconf->racoon_conf = optarg;
+			break;
+		case 'l':
+			plogset(optarg);
+			break;
+		case 'v':
+			vflag++;
+			break;
+		case 'Z':
+			/*
+			 * only local test.
+			 * To specify -Z option and to choice a appropriate
+			 * port number for ISAKMP, you can launch some racoons
+			 * on the local host for debug.
+			 * pk_sendadd() on initiator side is always failed
+			 * even if this flag is used.  Because there is same
+			 * spi in the SAD which is inserted by pk_sendgetspi()
+			 * on responder side.
+			 */
+			printf("Local test mode.\n");
+			f_local = 1;
+			break;
+#ifdef YYDEBUG
+		case 'y':
+			yydebug = 1;
+			break;
+#endif
+#ifdef INET6
+		case '4':
+			lcconf->default_af = AF_INET;
+			break;
+		case '6':
+			lcconf->default_af = AF_INET6;
+			break;
+#endif
+		case 'B':
+			loading_sa++;
+			break;
+		case 'C':
+			dump_config++;
+			break;
+		default:
+			usage();
+			/* NOTREACHED */
+		}
+	}
+	ac -= optind;
+	av += optind;
+
+	if (ac != 0) {
+		usage();
+		/* NOTREACHED */
+	}
+
+	return;
+}
diff --git a/src/racoon/misc.c b/src/racoon/misc.c
new file mode 100644
index 0000000..4daa0ed
--- /dev/null
+++ b/src/racoon/misc.c
@@ -0,0 +1,171 @@
+/*	$NetBSD: misc.c,v 1.4.6.1 2008/07/15 00:55:48 mgrooms Exp $	*/
+
+/*	$KAME: misc.c,v 1.23 2001/08/16 14:37:29 itojun Exp $	*/
+
+/*
+ * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <syslog.h>
+#include <ctype.h>
+
+#include "var.h"
+#include "misc.h"
+#include "debug.h"
+
+#if 0
+static int bindump __P((void *, size_t));
+
+static int
+bindump(buf0, len)
+        void *buf0;
+        size_t len;
+{
+	unsigned char *buf = (unsigned char *)buf0;
+	size_t i;
+
+	for (i = 0; i < len; i++) {
+		if ((buf[i] & 0x80) || !isprint(buf[i]))
+			printf("\\x%x", buf[i]);
+		else
+			printf("%c", buf[i]);
+	}
+	printf("\n");
+
+	return 0;
+}
+#endif
+
+int
+racoon_hexdump(buf0, len)
+	void *buf0;
+	size_t len;
+{
+	caddr_t buf = (caddr_t)buf0;
+	size_t i;
+
+	for (i = 0; i < len; i++) {
+		if (i != 0 && i % 32 == 0)
+			printf("\n");
+		if (i % 4 == 0)
+			printf(" ");
+		printf("%02x", (unsigned char)buf[i]);
+	}
+	printf("\n");
+
+	return 0;
+}
+
+char *
+bit2str(n, bl)
+	int n, bl;
+{
+#define MAXBITLEN 128
+	static char b[MAXBITLEN + 1];
+	int i;
+
+	if (bl > MAXBITLEN)
+		return "Failed to convert.";	/* NG */
+	memset(b, '0', bl);
+	b[bl] = '\0';
+
+	for (i = 0; i < bl; i++) {
+		if (n & (1 << i))
+			b[bl - 1 - i] = '1';
+	}
+
+	return b;
+}
+
+const char *
+debug_location(file, line, func)
+	const char *file;
+	int line;
+	const char *func;
+{
+	static char buf[1024];
+	const char *p;
+
+	/* truncate pathname */
+	p = strrchr(file, '/');
+	if (p)
+		p++;
+	else
+		p = file;
+
+	if (func)
+		snprintf(buf, sizeof(buf), "%s:%d:%s()", p, line, func);
+	else
+		snprintf(buf, sizeof(buf), "%s:%d", p, line);
+
+	return buf;
+}
+
+/*
+ * get file size.
+ * -1: error occured.
+ */
+int
+getfsize(path)
+	char *path;
+{
+        struct stat st;
+
+        if (stat(path, &st) != 0)
+                return -1;
+        else
+                return st.st_size;
+}
+
+/*
+ * calculate the difference between two times.
+ * t1: start
+ * t2: end
+ */
+double
+timedelta(t1, t2)
+	struct timeval *t1, *t2;
+{
+	if (t2->tv_usec >= t1->tv_usec)
+		return t2->tv_sec - t1->tv_sec +
+			(double)(t2->tv_usec - t1->tv_usec) / 1000000;
+
+	return t2->tv_sec - t1->tv_sec - 1 +
+		(double)(1000000 + t2->tv_usec - t1->tv_usec) / 1000000;
+}
diff --git a/src/racoon/misc.h b/src/racoon/misc.h
new file mode 100644
index 0000000..66e42b1
--- /dev/null
+++ b/src/racoon/misc.h
@@ -0,0 +1,77 @@
+/*	$NetBSD: misc.h,v 1.4.6.1 2008/07/15 00:55:48 mgrooms Exp $	*/
+
+/* Id: misc.h,v 1.9 2006/04/06 14:00:06 manubsd Exp */
+
+/*
+ * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _MISC_H
+#define _MISC_H
+
+#define BIT2STR(b) bit2str(b, sizeof(b)<<3)
+
+#ifdef HAVE_FUNC_MACRO
+#define LOCATION        debug_location(__FILE__, __LINE__, __func__)
+#else
+#define LOCATION        debug_location(__FILE__, __LINE__, NULL)
+#endif
+
+extern int racoon_hexdump __P((void *, size_t));
+extern char *bit2str __P((int, int));
+extern void *get_newbuf __P((void *, size_t));
+extern const char *debug_location __P((const char *, int, const char *));
+extern int getfsize __P((char *));
+struct timeval;
+extern double timedelta __P((struct timeval *, struct timeval *));
+char *strdup __P((const char *));
+
+#if defined(__APPLE__) && defined(__MACH__)
+#define RACOON_TAILQ_FOREACH_REVERSE(var, head, headname ,field)	\
+  TAILQ_FOREACH_REVERSE(var, head, field, headname)
+#else
+#define RACOON_TAILQ_FOREACH_REVERSE(var, head, headname ,field)	\
+    TAILQ_FOREACH_REVERSE(var, head, headname, field)
+#endif
+
+#ifndef HAVE_STRLCPY
+#define strlcpy(d,s,l) (strncpy(d,s,l), (d)[(l)-1] = '\0')
+#endif
+
+#ifndef HAVE_STRLCAT
+#define strlcat(d,s,l) strncat(d,s,(l)-strlen(d)-1)
+#endif
+
+#define STRDUP_FATAL(x) if (x == NULL) {			\
+	plog(LLV_ERROR, LOCATION, NULL, "strdup failed\n");	\
+	exit(1);						\
+}
+
+#include "libpfkey.h"
+
+#endif /* _MISC_H */
diff --git a/src/racoon/missing/crypto/rijndael/boxes-fst.dat b/src/racoon/missing/crypto/rijndael/boxes-fst.dat
new file mode 100644
index 0000000..28d15d3
--- /dev/null
+++ b/src/racoon/missing/crypto/rijndael/boxes-fst.dat
@@ -0,0 +1,957 @@
+/*	$KAME: boxes-fst.dat,v 1.1.1.1 2001/08/08 09:56:27 sakane Exp $	*/
+
+const word8 S[256] = {
+ 99, 124, 119, 123, 242, 107, 111, 197,  48,   1, 103,  43, 254, 215, 171, 118, 
+202, 130, 201, 125, 250,  89,  71, 240, 173, 212, 162, 175, 156, 164, 114, 192, 
+183, 253, 147,  38,  54,  63, 247, 204,  52, 165, 229, 241, 113, 216,  49,  21, 
+  4, 199,  35, 195,  24, 150,   5, 154,   7,  18, 128, 226, 235,  39, 178, 117, 
+  9, 131,  44,  26,  27, 110,  90, 160,  82,  59, 214, 179,  41, 227,  47, 132, 
+ 83, 209,   0, 237,  32, 252, 177,  91, 106, 203, 190,  57,  74,  76,  88, 207, 
+208, 239, 170, 251,  67,  77,  51, 133,  69, 249,   2, 127,  80,  60, 159, 168, 
+ 81, 163,  64, 143, 146, 157,  56, 245, 188, 182, 218,  33,  16, 255, 243, 210, 
+205,  12,  19, 236,  95, 151,  68,  23, 196, 167, 126,  61, 100,  93,  25, 115, 
+ 96, 129,  79, 220,  34,  42, 144, 136,  70, 238, 184,  20, 222,  94,  11, 219, 
+224,  50,  58,  10,  73,   6,  36,  92, 194, 211, 172,  98, 145, 149, 228, 121, 
+231, 200,  55, 109, 141, 213,  78, 169, 108,  86, 244, 234, 101, 122, 174,   8, 
+186, 120,  37,  46,  28, 166, 180, 198, 232, 221, 116,  31,  75, 189, 139, 138, 
+112,  62, 181, 102,  72,   3, 246,  14,  97,  53,  87, 185, 134, 193,  29, 158, 
+225, 248, 152,  17, 105, 217, 142, 148, 155,  30, 135, 233, 206,  85,  40, 223, 
+140, 161, 137,  13, 191, 230,  66, 104,  65, 153,  45,  15, 176,  84, 187,  22
+};
+
+#ifdef INTERMEDIATE_VALUE_KAT
+static const word8 Si[256] = {
+ 82,   9, 106, 213,  48,  54, 165,  56, 191,  64, 163, 158, 129, 243, 215, 251, 
+124, 227,  57, 130, 155,  47, 255, 135,  52, 142,  67,  68, 196, 222, 233, 203, 
+ 84, 123, 148,  50, 166, 194,  35,  61, 238,  76, 149,  11,  66, 250, 195,  78, 
+  8,  46, 161, 102,  40, 217,  36, 178, 118,  91, 162,  73, 109, 139, 209,  37, 
+114, 248, 246, 100, 134, 104, 152,  22, 212, 164,  92, 204,  93, 101, 182, 146, 
+108, 112,  72,  80, 253, 237, 185, 218,  94,  21,  70,  87, 167, 141, 157, 132, 
+144, 216, 171,   0, 140, 188, 211,  10, 247, 228,  88,   5, 184, 179,  69,   6, 
+208,  44,  30, 143, 202,  63,  15,   2, 193, 175, 189,   3,   1,  19, 138, 107, 
+ 58, 145,  17,  65,  79, 103, 220, 234, 151, 242, 207, 206, 240, 180, 230, 115, 
+150, 172, 116,  34, 231, 173,  53, 133, 226, 249,  55, 232,  28, 117, 223, 110, 
+ 71, 241,  26, 113,  29,  41, 197, 137, 111, 183,  98,  14, 170,  24, 190,  27, 
+252,  86,  62,  75, 198, 210, 121,  32, 154, 219, 192, 254, 120, 205,  90, 244, 
+ 31, 221, 168,  51, 136,   7, 199,  49, 177,  18,  16,  89,  39, 128, 236,  95, 
+ 96,  81, 127, 169,  25, 181,  74,  13,  45, 229, 122, 159, 147, 201, 156, 239, 
+160, 224,  59,  77, 174,  42, 245, 176, 200, 235, 187,  60, 131,  83, 153,  97, 
+ 23,  43,   4, 126, 186, 119, 214,  38, 225, 105,  20,  99,  85,  33,  12, 125
+};
+#endif /* INTERMEDIATE_VALUE_KAT */
+
+union xtab {
+	word32	xt32[256];
+	word8	xt8[256][4];
+};
+
+static const union xtab xT1 = {
+	.xt8 = {
+{0xc6,0x63,0x63,0xa5}, {0xf8,0x7c,0x7c,0x84}, {0xee,0x77,0x77,0x99}, {0xf6,0x7b,0x7b,0x8d},
+{0xff,0xf2,0xf2,0x0d}, {0xd6,0x6b,0x6b,0xbd}, {0xde,0x6f,0x6f,0xb1}, {0x91,0xc5,0xc5,0x54},
+{0x60,0x30,0x30,0x50}, {0x02,0x01,0x01,0x03}, {0xce,0x67,0x67,0xa9}, {0x56,0x2b,0x2b,0x7d},
+{0xe7,0xfe,0xfe,0x19}, {0xb5,0xd7,0xd7,0x62}, {0x4d,0xab,0xab,0xe6}, {0xec,0x76,0x76,0x9a},
+{0x8f,0xca,0xca,0x45}, {0x1f,0x82,0x82,0x9d}, {0x89,0xc9,0xc9,0x40}, {0xfa,0x7d,0x7d,0x87},
+{0xef,0xfa,0xfa,0x15}, {0xb2,0x59,0x59,0xeb}, {0x8e,0x47,0x47,0xc9}, {0xfb,0xf0,0xf0,0x0b},
+{0x41,0xad,0xad,0xec}, {0xb3,0xd4,0xd4,0x67}, {0x5f,0xa2,0xa2,0xfd}, {0x45,0xaf,0xaf,0xea},
+{0x23,0x9c,0x9c,0xbf}, {0x53,0xa4,0xa4,0xf7}, {0xe4,0x72,0x72,0x96}, {0x9b,0xc0,0xc0,0x5b},
+{0x75,0xb7,0xb7,0xc2}, {0xe1,0xfd,0xfd,0x1c}, {0x3d,0x93,0x93,0xae}, {0x4c,0x26,0x26,0x6a},
+{0x6c,0x36,0x36,0x5a}, {0x7e,0x3f,0x3f,0x41}, {0xf5,0xf7,0xf7,0x02}, {0x83,0xcc,0xcc,0x4f},
+{0x68,0x34,0x34,0x5c}, {0x51,0xa5,0xa5,0xf4}, {0xd1,0xe5,0xe5,0x34}, {0xf9,0xf1,0xf1,0x08},
+{0xe2,0x71,0x71,0x93}, {0xab,0xd8,0xd8,0x73}, {0x62,0x31,0x31,0x53}, {0x2a,0x15,0x15,0x3f},
+{0x08,0x04,0x04,0x0c}, {0x95,0xc7,0xc7,0x52}, {0x46,0x23,0x23,0x65}, {0x9d,0xc3,0xc3,0x5e},
+{0x30,0x18,0x18,0x28}, {0x37,0x96,0x96,0xa1}, {0x0a,0x05,0x05,0x0f}, {0x2f,0x9a,0x9a,0xb5},
+{0x0e,0x07,0x07,0x09}, {0x24,0x12,0x12,0x36}, {0x1b,0x80,0x80,0x9b}, {0xdf,0xe2,0xe2,0x3d},
+{0xcd,0xeb,0xeb,0x26}, {0x4e,0x27,0x27,0x69}, {0x7f,0xb2,0xb2,0xcd}, {0xea,0x75,0x75,0x9f},
+{0x12,0x09,0x09,0x1b}, {0x1d,0x83,0x83,0x9e}, {0x58,0x2c,0x2c,0x74}, {0x34,0x1a,0x1a,0x2e},
+{0x36,0x1b,0x1b,0x2d}, {0xdc,0x6e,0x6e,0xb2}, {0xb4,0x5a,0x5a,0xee}, {0x5b,0xa0,0xa0,0xfb},
+{0xa4,0x52,0x52,0xf6}, {0x76,0x3b,0x3b,0x4d}, {0xb7,0xd6,0xd6,0x61}, {0x7d,0xb3,0xb3,0xce},
+{0x52,0x29,0x29,0x7b}, {0xdd,0xe3,0xe3,0x3e}, {0x5e,0x2f,0x2f,0x71}, {0x13,0x84,0x84,0x97},
+{0xa6,0x53,0x53,0xf5}, {0xb9,0xd1,0xd1,0x68}, {0x00,0x00,0x00,0x00}, {0xc1,0xed,0xed,0x2c},
+{0x40,0x20,0x20,0x60}, {0xe3,0xfc,0xfc,0x1f}, {0x79,0xb1,0xb1,0xc8}, {0xb6,0x5b,0x5b,0xed},
+{0xd4,0x6a,0x6a,0xbe}, {0x8d,0xcb,0xcb,0x46}, {0x67,0xbe,0xbe,0xd9}, {0x72,0x39,0x39,0x4b},
+{0x94,0x4a,0x4a,0xde}, {0x98,0x4c,0x4c,0xd4}, {0xb0,0x58,0x58,0xe8}, {0x85,0xcf,0xcf,0x4a},
+{0xbb,0xd0,0xd0,0x6b}, {0xc5,0xef,0xef,0x2a}, {0x4f,0xaa,0xaa,0xe5}, {0xed,0xfb,0xfb,0x16},
+{0x86,0x43,0x43,0xc5}, {0x9a,0x4d,0x4d,0xd7}, {0x66,0x33,0x33,0x55}, {0x11,0x85,0x85,0x94},
+{0x8a,0x45,0x45,0xcf}, {0xe9,0xf9,0xf9,0x10}, {0x04,0x02,0x02,0x06}, {0xfe,0x7f,0x7f,0x81},
+{0xa0,0x50,0x50,0xf0}, {0x78,0x3c,0x3c,0x44}, {0x25,0x9f,0x9f,0xba}, {0x4b,0xa8,0xa8,0xe3},
+{0xa2,0x51,0x51,0xf3}, {0x5d,0xa3,0xa3,0xfe}, {0x80,0x40,0x40,0xc0}, {0x05,0x8f,0x8f,0x8a},
+{0x3f,0x92,0x92,0xad}, {0x21,0x9d,0x9d,0xbc}, {0x70,0x38,0x38,0x48}, {0xf1,0xf5,0xf5,0x04},
+{0x63,0xbc,0xbc,0xdf}, {0x77,0xb6,0xb6,0xc1}, {0xaf,0xda,0xda,0x75}, {0x42,0x21,0x21,0x63},
+{0x20,0x10,0x10,0x30}, {0xe5,0xff,0xff,0x1a}, {0xfd,0xf3,0xf3,0x0e}, {0xbf,0xd2,0xd2,0x6d},
+{0x81,0xcd,0xcd,0x4c}, {0x18,0x0c,0x0c,0x14}, {0x26,0x13,0x13,0x35}, {0xc3,0xec,0xec,0x2f},
+{0xbe,0x5f,0x5f,0xe1}, {0x35,0x97,0x97,0xa2}, {0x88,0x44,0x44,0xcc}, {0x2e,0x17,0x17,0x39},
+{0x93,0xc4,0xc4,0x57}, {0x55,0xa7,0xa7,0xf2}, {0xfc,0x7e,0x7e,0x82}, {0x7a,0x3d,0x3d,0x47},
+{0xc8,0x64,0x64,0xac}, {0xba,0x5d,0x5d,0xe7}, {0x32,0x19,0x19,0x2b}, {0xe6,0x73,0x73,0x95},
+{0xc0,0x60,0x60,0xa0}, {0x19,0x81,0x81,0x98}, {0x9e,0x4f,0x4f,0xd1}, {0xa3,0xdc,0xdc,0x7f},
+{0x44,0x22,0x22,0x66}, {0x54,0x2a,0x2a,0x7e}, {0x3b,0x90,0x90,0xab}, {0x0b,0x88,0x88,0x83},
+{0x8c,0x46,0x46,0xca}, {0xc7,0xee,0xee,0x29}, {0x6b,0xb8,0xb8,0xd3}, {0x28,0x14,0x14,0x3c},
+{0xa7,0xde,0xde,0x79}, {0xbc,0x5e,0x5e,0xe2}, {0x16,0x0b,0x0b,0x1d}, {0xad,0xdb,0xdb,0x76},
+{0xdb,0xe0,0xe0,0x3b}, {0x64,0x32,0x32,0x56}, {0x74,0x3a,0x3a,0x4e}, {0x14,0x0a,0x0a,0x1e},
+{0x92,0x49,0x49,0xdb}, {0x0c,0x06,0x06,0x0a}, {0x48,0x24,0x24,0x6c}, {0xb8,0x5c,0x5c,0xe4},
+{0x9f,0xc2,0xc2,0x5d}, {0xbd,0xd3,0xd3,0x6e}, {0x43,0xac,0xac,0xef}, {0xc4,0x62,0x62,0xa6},
+{0x39,0x91,0x91,0xa8}, {0x31,0x95,0x95,0xa4}, {0xd3,0xe4,0xe4,0x37}, {0xf2,0x79,0x79,0x8b},
+{0xd5,0xe7,0xe7,0x32}, {0x8b,0xc8,0xc8,0x43}, {0x6e,0x37,0x37,0x59}, {0xda,0x6d,0x6d,0xb7},
+{0x01,0x8d,0x8d,0x8c}, {0xb1,0xd5,0xd5,0x64}, {0x9c,0x4e,0x4e,0xd2}, {0x49,0xa9,0xa9,0xe0},
+{0xd8,0x6c,0x6c,0xb4}, {0xac,0x56,0x56,0xfa}, {0xf3,0xf4,0xf4,0x07}, {0xcf,0xea,0xea,0x25},
+{0xca,0x65,0x65,0xaf}, {0xf4,0x7a,0x7a,0x8e}, {0x47,0xae,0xae,0xe9}, {0x10,0x08,0x08,0x18},
+{0x6f,0xba,0xba,0xd5}, {0xf0,0x78,0x78,0x88}, {0x4a,0x25,0x25,0x6f}, {0x5c,0x2e,0x2e,0x72},
+{0x38,0x1c,0x1c,0x24}, {0x57,0xa6,0xa6,0xf1}, {0x73,0xb4,0xb4,0xc7}, {0x97,0xc6,0xc6,0x51},
+{0xcb,0xe8,0xe8,0x23}, {0xa1,0xdd,0xdd,0x7c}, {0xe8,0x74,0x74,0x9c}, {0x3e,0x1f,0x1f,0x21},
+{0x96,0x4b,0x4b,0xdd}, {0x61,0xbd,0xbd,0xdc}, {0x0d,0x8b,0x8b,0x86}, {0x0f,0x8a,0x8a,0x85},
+{0xe0,0x70,0x70,0x90}, {0x7c,0x3e,0x3e,0x42}, {0x71,0xb5,0xb5,0xc4}, {0xcc,0x66,0x66,0xaa},
+{0x90,0x48,0x48,0xd8}, {0x06,0x03,0x03,0x05}, {0xf7,0xf6,0xf6,0x01}, {0x1c,0x0e,0x0e,0x12},
+{0xc2,0x61,0x61,0xa3}, {0x6a,0x35,0x35,0x5f}, {0xae,0x57,0x57,0xf9}, {0x69,0xb9,0xb9,0xd0},
+{0x17,0x86,0x86,0x91}, {0x99,0xc1,0xc1,0x58}, {0x3a,0x1d,0x1d,0x27}, {0x27,0x9e,0x9e,0xb9},
+{0xd9,0xe1,0xe1,0x38}, {0xeb,0xf8,0xf8,0x13}, {0x2b,0x98,0x98,0xb3}, {0x22,0x11,0x11,0x33},
+{0xd2,0x69,0x69,0xbb}, {0xa9,0xd9,0xd9,0x70}, {0x07,0x8e,0x8e,0x89}, {0x33,0x94,0x94,0xa7},
+{0x2d,0x9b,0x9b,0xb6}, {0x3c,0x1e,0x1e,0x22}, {0x15,0x87,0x87,0x92}, {0xc9,0xe9,0xe9,0x20},
+{0x87,0xce,0xce,0x49}, {0xaa,0x55,0x55,0xff}, {0x50,0x28,0x28,0x78}, {0xa5,0xdf,0xdf,0x7a},
+{0x03,0x8c,0x8c,0x8f}, {0x59,0xa1,0xa1,0xf8}, {0x09,0x89,0x89,0x80}, {0x1a,0x0d,0x0d,0x17},
+{0x65,0xbf,0xbf,0xda}, {0xd7,0xe6,0xe6,0x31}, {0x84,0x42,0x42,0xc6}, {0xd0,0x68,0x68,0xb8},
+{0x82,0x41,0x41,0xc3}, {0x29,0x99,0x99,0xb0}, {0x5a,0x2d,0x2d,0x77}, {0x1e,0x0f,0x0f,0x11},
+{0x7b,0xb0,0xb0,0xcb}, {0xa8,0x54,0x54,0xfc}, {0x6d,0xbb,0xbb,0xd6}, {0x2c,0x16,0x16,0x3a}
+	}
+};
+#define	T1	xT1.xt8
+
+static const union xtab xT2 = {
+	.xt8 = {
+{0xa5,0xc6,0x63,0x63}, {0x84,0xf8,0x7c,0x7c}, {0x99,0xee,0x77,0x77}, {0x8d,0xf6,0x7b,0x7b},
+{0x0d,0xff,0xf2,0xf2}, {0xbd,0xd6,0x6b,0x6b}, {0xb1,0xde,0x6f,0x6f}, {0x54,0x91,0xc5,0xc5},
+{0x50,0x60,0x30,0x30}, {0x03,0x02,0x01,0x01}, {0xa9,0xce,0x67,0x67}, {0x7d,0x56,0x2b,0x2b},
+{0x19,0xe7,0xfe,0xfe}, {0x62,0xb5,0xd7,0xd7}, {0xe6,0x4d,0xab,0xab}, {0x9a,0xec,0x76,0x76},
+{0x45,0x8f,0xca,0xca}, {0x9d,0x1f,0x82,0x82}, {0x40,0x89,0xc9,0xc9}, {0x87,0xfa,0x7d,0x7d},
+{0x15,0xef,0xfa,0xfa}, {0xeb,0xb2,0x59,0x59}, {0xc9,0x8e,0x47,0x47}, {0x0b,0xfb,0xf0,0xf0},
+{0xec,0x41,0xad,0xad}, {0x67,0xb3,0xd4,0xd4}, {0xfd,0x5f,0xa2,0xa2}, {0xea,0x45,0xaf,0xaf},
+{0xbf,0x23,0x9c,0x9c}, {0xf7,0x53,0xa4,0xa4}, {0x96,0xe4,0x72,0x72}, {0x5b,0x9b,0xc0,0xc0},
+{0xc2,0x75,0xb7,0xb7}, {0x1c,0xe1,0xfd,0xfd}, {0xae,0x3d,0x93,0x93}, {0x6a,0x4c,0x26,0x26},
+{0x5a,0x6c,0x36,0x36}, {0x41,0x7e,0x3f,0x3f}, {0x02,0xf5,0xf7,0xf7}, {0x4f,0x83,0xcc,0xcc},
+{0x5c,0x68,0x34,0x34}, {0xf4,0x51,0xa5,0xa5}, {0x34,0xd1,0xe5,0xe5}, {0x08,0xf9,0xf1,0xf1},
+{0x93,0xe2,0x71,0x71}, {0x73,0xab,0xd8,0xd8}, {0x53,0x62,0x31,0x31}, {0x3f,0x2a,0x15,0x15},
+{0x0c,0x08,0x04,0x04}, {0x52,0x95,0xc7,0xc7}, {0x65,0x46,0x23,0x23}, {0x5e,0x9d,0xc3,0xc3},
+{0x28,0x30,0x18,0x18}, {0xa1,0x37,0x96,0x96}, {0x0f,0x0a,0x05,0x05}, {0xb5,0x2f,0x9a,0x9a},
+{0x09,0x0e,0x07,0x07}, {0x36,0x24,0x12,0x12}, {0x9b,0x1b,0x80,0x80}, {0x3d,0xdf,0xe2,0xe2},
+{0x26,0xcd,0xeb,0xeb}, {0x69,0x4e,0x27,0x27}, {0xcd,0x7f,0xb2,0xb2}, {0x9f,0xea,0x75,0x75},
+{0x1b,0x12,0x09,0x09}, {0x9e,0x1d,0x83,0x83}, {0x74,0x58,0x2c,0x2c}, {0x2e,0x34,0x1a,0x1a},
+{0x2d,0x36,0x1b,0x1b}, {0xb2,0xdc,0x6e,0x6e}, {0xee,0xb4,0x5a,0x5a}, {0xfb,0x5b,0xa0,0xa0},
+{0xf6,0xa4,0x52,0x52}, {0x4d,0x76,0x3b,0x3b}, {0x61,0xb7,0xd6,0xd6}, {0xce,0x7d,0xb3,0xb3},
+{0x7b,0x52,0x29,0x29}, {0x3e,0xdd,0xe3,0xe3}, {0x71,0x5e,0x2f,0x2f}, {0x97,0x13,0x84,0x84},
+{0xf5,0xa6,0x53,0x53}, {0x68,0xb9,0xd1,0xd1}, {0x00,0x00,0x00,0x00}, {0x2c,0xc1,0xed,0xed},
+{0x60,0x40,0x20,0x20}, {0x1f,0xe3,0xfc,0xfc}, {0xc8,0x79,0xb1,0xb1}, {0xed,0xb6,0x5b,0x5b},
+{0xbe,0xd4,0x6a,0x6a}, {0x46,0x8d,0xcb,0xcb}, {0xd9,0x67,0xbe,0xbe}, {0x4b,0x72,0x39,0x39},
+{0xde,0x94,0x4a,0x4a}, {0xd4,0x98,0x4c,0x4c}, {0xe8,0xb0,0x58,0x58}, {0x4a,0x85,0xcf,0xcf},
+{0x6b,0xbb,0xd0,0xd0}, {0x2a,0xc5,0xef,0xef}, {0xe5,0x4f,0xaa,0xaa}, {0x16,0xed,0xfb,0xfb},
+{0xc5,0x86,0x43,0x43}, {0xd7,0x9a,0x4d,0x4d}, {0x55,0x66,0x33,0x33}, {0x94,0x11,0x85,0x85},
+{0xcf,0x8a,0x45,0x45}, {0x10,0xe9,0xf9,0xf9}, {0x06,0x04,0x02,0x02}, {0x81,0xfe,0x7f,0x7f},
+{0xf0,0xa0,0x50,0x50}, {0x44,0x78,0x3c,0x3c}, {0xba,0x25,0x9f,0x9f}, {0xe3,0x4b,0xa8,0xa8},
+{0xf3,0xa2,0x51,0x51}, {0xfe,0x5d,0xa3,0xa3}, {0xc0,0x80,0x40,0x40}, {0x8a,0x05,0x8f,0x8f},
+{0xad,0x3f,0x92,0x92}, {0xbc,0x21,0x9d,0x9d}, {0x48,0x70,0x38,0x38}, {0x04,0xf1,0xf5,0xf5},
+{0xdf,0x63,0xbc,0xbc}, {0xc1,0x77,0xb6,0xb6}, {0x75,0xaf,0xda,0xda}, {0x63,0x42,0x21,0x21},
+{0x30,0x20,0x10,0x10}, {0x1a,0xe5,0xff,0xff}, {0x0e,0xfd,0xf3,0xf3}, {0x6d,0xbf,0xd2,0xd2},
+{0x4c,0x81,0xcd,0xcd}, {0x14,0x18,0x0c,0x0c}, {0x35,0x26,0x13,0x13}, {0x2f,0xc3,0xec,0xec},
+{0xe1,0xbe,0x5f,0x5f}, {0xa2,0x35,0x97,0x97}, {0xcc,0x88,0x44,0x44}, {0x39,0x2e,0x17,0x17},
+{0x57,0x93,0xc4,0xc4}, {0xf2,0x55,0xa7,0xa7}, {0x82,0xfc,0x7e,0x7e}, {0x47,0x7a,0x3d,0x3d},
+{0xac,0xc8,0x64,0x64}, {0xe7,0xba,0x5d,0x5d}, {0x2b,0x32,0x19,0x19}, {0x95,0xe6,0x73,0x73},
+{0xa0,0xc0,0x60,0x60}, {0x98,0x19,0x81,0x81}, {0xd1,0x9e,0x4f,0x4f}, {0x7f,0xa3,0xdc,0xdc},
+{0x66,0x44,0x22,0x22}, {0x7e,0x54,0x2a,0x2a}, {0xab,0x3b,0x90,0x90}, {0x83,0x0b,0x88,0x88},
+{0xca,0x8c,0x46,0x46}, {0x29,0xc7,0xee,0xee}, {0xd3,0x6b,0xb8,0xb8}, {0x3c,0x28,0x14,0x14},
+{0x79,0xa7,0xde,0xde}, {0xe2,0xbc,0x5e,0x5e}, {0x1d,0x16,0x0b,0x0b}, {0x76,0xad,0xdb,0xdb},
+{0x3b,0xdb,0xe0,0xe0}, {0x56,0x64,0x32,0x32}, {0x4e,0x74,0x3a,0x3a}, {0x1e,0x14,0x0a,0x0a},
+{0xdb,0x92,0x49,0x49}, {0x0a,0x0c,0x06,0x06}, {0x6c,0x48,0x24,0x24}, {0xe4,0xb8,0x5c,0x5c},
+{0x5d,0x9f,0xc2,0xc2}, {0x6e,0xbd,0xd3,0xd3}, {0xef,0x43,0xac,0xac}, {0xa6,0xc4,0x62,0x62},
+{0xa8,0x39,0x91,0x91}, {0xa4,0x31,0x95,0x95}, {0x37,0xd3,0xe4,0xe4}, {0x8b,0xf2,0x79,0x79},
+{0x32,0xd5,0xe7,0xe7}, {0x43,0x8b,0xc8,0xc8}, {0x59,0x6e,0x37,0x37}, {0xb7,0xda,0x6d,0x6d},
+{0x8c,0x01,0x8d,0x8d}, {0x64,0xb1,0xd5,0xd5}, {0xd2,0x9c,0x4e,0x4e}, {0xe0,0x49,0xa9,0xa9},
+{0xb4,0xd8,0x6c,0x6c}, {0xfa,0xac,0x56,0x56}, {0x07,0xf3,0xf4,0xf4}, {0x25,0xcf,0xea,0xea},
+{0xaf,0xca,0x65,0x65}, {0x8e,0xf4,0x7a,0x7a}, {0xe9,0x47,0xae,0xae}, {0x18,0x10,0x08,0x08},
+{0xd5,0x6f,0xba,0xba}, {0x88,0xf0,0x78,0x78}, {0x6f,0x4a,0x25,0x25}, {0x72,0x5c,0x2e,0x2e},
+{0x24,0x38,0x1c,0x1c}, {0xf1,0x57,0xa6,0xa6}, {0xc7,0x73,0xb4,0xb4}, {0x51,0x97,0xc6,0xc6},
+{0x23,0xcb,0xe8,0xe8}, {0x7c,0xa1,0xdd,0xdd}, {0x9c,0xe8,0x74,0x74}, {0x21,0x3e,0x1f,0x1f},
+{0xdd,0x96,0x4b,0x4b}, {0xdc,0x61,0xbd,0xbd}, {0x86,0x0d,0x8b,0x8b}, {0x85,0x0f,0x8a,0x8a},
+{0x90,0xe0,0x70,0x70}, {0x42,0x7c,0x3e,0x3e}, {0xc4,0x71,0xb5,0xb5}, {0xaa,0xcc,0x66,0x66},
+{0xd8,0x90,0x48,0x48}, {0x05,0x06,0x03,0x03}, {0x01,0xf7,0xf6,0xf6}, {0x12,0x1c,0x0e,0x0e},
+{0xa3,0xc2,0x61,0x61}, {0x5f,0x6a,0x35,0x35}, {0xf9,0xae,0x57,0x57}, {0xd0,0x69,0xb9,0xb9},
+{0x91,0x17,0x86,0x86}, {0x58,0x99,0xc1,0xc1}, {0x27,0x3a,0x1d,0x1d}, {0xb9,0x27,0x9e,0x9e},
+{0x38,0xd9,0xe1,0xe1}, {0x13,0xeb,0xf8,0xf8}, {0xb3,0x2b,0x98,0x98}, {0x33,0x22,0x11,0x11},
+{0xbb,0xd2,0x69,0x69}, {0x70,0xa9,0xd9,0xd9}, {0x89,0x07,0x8e,0x8e}, {0xa7,0x33,0x94,0x94},
+{0xb6,0x2d,0x9b,0x9b}, {0x22,0x3c,0x1e,0x1e}, {0x92,0x15,0x87,0x87}, {0x20,0xc9,0xe9,0xe9},
+{0x49,0x87,0xce,0xce}, {0xff,0xaa,0x55,0x55}, {0x78,0x50,0x28,0x28}, {0x7a,0xa5,0xdf,0xdf},
+{0x8f,0x03,0x8c,0x8c}, {0xf8,0x59,0xa1,0xa1}, {0x80,0x09,0x89,0x89}, {0x17,0x1a,0x0d,0x0d},
+{0xda,0x65,0xbf,0xbf}, {0x31,0xd7,0xe6,0xe6}, {0xc6,0x84,0x42,0x42}, {0xb8,0xd0,0x68,0x68},
+{0xc3,0x82,0x41,0x41}, {0xb0,0x29,0x99,0x99}, {0x77,0x5a,0x2d,0x2d}, {0x11,0x1e,0x0f,0x0f},
+{0xcb,0x7b,0xb0,0xb0}, {0xfc,0xa8,0x54,0x54}, {0xd6,0x6d,0xbb,0xbb}, {0x3a,0x2c,0x16,0x16}
+	}
+};
+#define	T2	xT2.xt8
+
+static const union xtab xT3 = {
+	.xt8 = {
+{0x63,0xa5,0xc6,0x63}, {0x7c,0x84,0xf8,0x7c}, {0x77,0x99,0xee,0x77}, {0x7b,0x8d,0xf6,0x7b},
+{0xf2,0x0d,0xff,0xf2}, {0x6b,0xbd,0xd6,0x6b}, {0x6f,0xb1,0xde,0x6f}, {0xc5,0x54,0x91,0xc5},
+{0x30,0x50,0x60,0x30}, {0x01,0x03,0x02,0x01}, {0x67,0xa9,0xce,0x67}, {0x2b,0x7d,0x56,0x2b},
+{0xfe,0x19,0xe7,0xfe}, {0xd7,0x62,0xb5,0xd7}, {0xab,0xe6,0x4d,0xab}, {0x76,0x9a,0xec,0x76},
+{0xca,0x45,0x8f,0xca}, {0x82,0x9d,0x1f,0x82}, {0xc9,0x40,0x89,0xc9}, {0x7d,0x87,0xfa,0x7d},
+{0xfa,0x15,0xef,0xfa}, {0x59,0xeb,0xb2,0x59}, {0x47,0xc9,0x8e,0x47}, {0xf0,0x0b,0xfb,0xf0},
+{0xad,0xec,0x41,0xad}, {0xd4,0x67,0xb3,0xd4}, {0xa2,0xfd,0x5f,0xa2}, {0xaf,0xea,0x45,0xaf},
+{0x9c,0xbf,0x23,0x9c}, {0xa4,0xf7,0x53,0xa4}, {0x72,0x96,0xe4,0x72}, {0xc0,0x5b,0x9b,0xc0},
+{0xb7,0xc2,0x75,0xb7}, {0xfd,0x1c,0xe1,0xfd}, {0x93,0xae,0x3d,0x93}, {0x26,0x6a,0x4c,0x26},
+{0x36,0x5a,0x6c,0x36}, {0x3f,0x41,0x7e,0x3f}, {0xf7,0x02,0xf5,0xf7}, {0xcc,0x4f,0x83,0xcc},
+{0x34,0x5c,0x68,0x34}, {0xa5,0xf4,0x51,0xa5}, {0xe5,0x34,0xd1,0xe5}, {0xf1,0x08,0xf9,0xf1},
+{0x71,0x93,0xe2,0x71}, {0xd8,0x73,0xab,0xd8}, {0x31,0x53,0x62,0x31}, {0x15,0x3f,0x2a,0x15},
+{0x04,0x0c,0x08,0x04}, {0xc7,0x52,0x95,0xc7}, {0x23,0x65,0x46,0x23}, {0xc3,0x5e,0x9d,0xc3},
+{0x18,0x28,0x30,0x18}, {0x96,0xa1,0x37,0x96}, {0x05,0x0f,0x0a,0x05}, {0x9a,0xb5,0x2f,0x9a},
+{0x07,0x09,0x0e,0x07}, {0x12,0x36,0x24,0x12}, {0x80,0x9b,0x1b,0x80}, {0xe2,0x3d,0xdf,0xe2},
+{0xeb,0x26,0xcd,0xeb}, {0x27,0x69,0x4e,0x27}, {0xb2,0xcd,0x7f,0xb2}, {0x75,0x9f,0xea,0x75},
+{0x09,0x1b,0x12,0x09}, {0x83,0x9e,0x1d,0x83}, {0x2c,0x74,0x58,0x2c}, {0x1a,0x2e,0x34,0x1a},
+{0x1b,0x2d,0x36,0x1b}, {0x6e,0xb2,0xdc,0x6e}, {0x5a,0xee,0xb4,0x5a}, {0xa0,0xfb,0x5b,0xa0},
+{0x52,0xf6,0xa4,0x52}, {0x3b,0x4d,0x76,0x3b}, {0xd6,0x61,0xb7,0xd6}, {0xb3,0xce,0x7d,0xb3},
+{0x29,0x7b,0x52,0x29}, {0xe3,0x3e,0xdd,0xe3}, {0x2f,0x71,0x5e,0x2f}, {0x84,0x97,0x13,0x84},
+{0x53,0xf5,0xa6,0x53}, {0xd1,0x68,0xb9,0xd1}, {0x00,0x00,0x00,0x00}, {0xed,0x2c,0xc1,0xed},
+{0x20,0x60,0x40,0x20}, {0xfc,0x1f,0xe3,0xfc}, {0xb1,0xc8,0x79,0xb1}, {0x5b,0xed,0xb6,0x5b},
+{0x6a,0xbe,0xd4,0x6a}, {0xcb,0x46,0x8d,0xcb}, {0xbe,0xd9,0x67,0xbe}, {0x39,0x4b,0x72,0x39},
+{0x4a,0xde,0x94,0x4a}, {0x4c,0xd4,0x98,0x4c}, {0x58,0xe8,0xb0,0x58}, {0xcf,0x4a,0x85,0xcf},
+{0xd0,0x6b,0xbb,0xd0}, {0xef,0x2a,0xc5,0xef}, {0xaa,0xe5,0x4f,0xaa}, {0xfb,0x16,0xed,0xfb},
+{0x43,0xc5,0x86,0x43}, {0x4d,0xd7,0x9a,0x4d}, {0x33,0x55,0x66,0x33}, {0x85,0x94,0x11,0x85},
+{0x45,0xcf,0x8a,0x45}, {0xf9,0x10,0xe9,0xf9}, {0x02,0x06,0x04,0x02}, {0x7f,0x81,0xfe,0x7f},
+{0x50,0xf0,0xa0,0x50}, {0x3c,0x44,0x78,0x3c}, {0x9f,0xba,0x25,0x9f}, {0xa8,0xe3,0x4b,0xa8},
+{0x51,0xf3,0xa2,0x51}, {0xa3,0xfe,0x5d,0xa3}, {0x40,0xc0,0x80,0x40}, {0x8f,0x8a,0x05,0x8f},
+{0x92,0xad,0x3f,0x92}, {0x9d,0xbc,0x21,0x9d}, {0x38,0x48,0x70,0x38}, {0xf5,0x04,0xf1,0xf5},
+{0xbc,0xdf,0x63,0xbc}, {0xb6,0xc1,0x77,0xb6}, {0xda,0x75,0xaf,0xda}, {0x21,0x63,0x42,0x21},
+{0x10,0x30,0x20,0x10}, {0xff,0x1a,0xe5,0xff}, {0xf3,0x0e,0xfd,0xf3}, {0xd2,0x6d,0xbf,0xd2},
+{0xcd,0x4c,0x81,0xcd}, {0x0c,0x14,0x18,0x0c}, {0x13,0x35,0x26,0x13}, {0xec,0x2f,0xc3,0xec},
+{0x5f,0xe1,0xbe,0x5f}, {0x97,0xa2,0x35,0x97}, {0x44,0xcc,0x88,0x44}, {0x17,0x39,0x2e,0x17},
+{0xc4,0x57,0x93,0xc4}, {0xa7,0xf2,0x55,0xa7}, {0x7e,0x82,0xfc,0x7e}, {0x3d,0x47,0x7a,0x3d},
+{0x64,0xac,0xc8,0x64}, {0x5d,0xe7,0xba,0x5d}, {0x19,0x2b,0x32,0x19}, {0x73,0x95,0xe6,0x73},
+{0x60,0xa0,0xc0,0x60}, {0x81,0x98,0x19,0x81}, {0x4f,0xd1,0x9e,0x4f}, {0xdc,0x7f,0xa3,0xdc},
+{0x22,0x66,0x44,0x22}, {0x2a,0x7e,0x54,0x2a}, {0x90,0xab,0x3b,0x90}, {0x88,0x83,0x0b,0x88},
+{0x46,0xca,0x8c,0x46}, {0xee,0x29,0xc7,0xee}, {0xb8,0xd3,0x6b,0xb8}, {0x14,0x3c,0x28,0x14},
+{0xde,0x79,0xa7,0xde}, {0x5e,0xe2,0xbc,0x5e}, {0x0b,0x1d,0x16,0x0b}, {0xdb,0x76,0xad,0xdb},
+{0xe0,0x3b,0xdb,0xe0}, {0x32,0x56,0x64,0x32}, {0x3a,0x4e,0x74,0x3a}, {0x0a,0x1e,0x14,0x0a},
+{0x49,0xdb,0x92,0x49}, {0x06,0x0a,0x0c,0x06}, {0x24,0x6c,0x48,0x24}, {0x5c,0xe4,0xb8,0x5c},
+{0xc2,0x5d,0x9f,0xc2}, {0xd3,0x6e,0xbd,0xd3}, {0xac,0xef,0x43,0xac}, {0x62,0xa6,0xc4,0x62},
+{0x91,0xa8,0x39,0x91}, {0x95,0xa4,0x31,0x95}, {0xe4,0x37,0xd3,0xe4}, {0x79,0x8b,0xf2,0x79},
+{0xe7,0x32,0xd5,0xe7}, {0xc8,0x43,0x8b,0xc8}, {0x37,0x59,0x6e,0x37}, {0x6d,0xb7,0xda,0x6d},
+{0x8d,0x8c,0x01,0x8d}, {0xd5,0x64,0xb1,0xd5}, {0x4e,0xd2,0x9c,0x4e}, {0xa9,0xe0,0x49,0xa9},
+{0x6c,0xb4,0xd8,0x6c}, {0x56,0xfa,0xac,0x56}, {0xf4,0x07,0xf3,0xf4}, {0xea,0x25,0xcf,0xea},
+{0x65,0xaf,0xca,0x65}, {0x7a,0x8e,0xf4,0x7a}, {0xae,0xe9,0x47,0xae}, {0x08,0x18,0x10,0x08},
+{0xba,0xd5,0x6f,0xba}, {0x78,0x88,0xf0,0x78}, {0x25,0x6f,0x4a,0x25}, {0x2e,0x72,0x5c,0x2e},
+{0x1c,0x24,0x38,0x1c}, {0xa6,0xf1,0x57,0xa6}, {0xb4,0xc7,0x73,0xb4}, {0xc6,0x51,0x97,0xc6},
+{0xe8,0x23,0xcb,0xe8}, {0xdd,0x7c,0xa1,0xdd}, {0x74,0x9c,0xe8,0x74}, {0x1f,0x21,0x3e,0x1f},
+{0x4b,0xdd,0x96,0x4b}, {0xbd,0xdc,0x61,0xbd}, {0x8b,0x86,0x0d,0x8b}, {0x8a,0x85,0x0f,0x8a},
+{0x70,0x90,0xe0,0x70}, {0x3e,0x42,0x7c,0x3e}, {0xb5,0xc4,0x71,0xb5}, {0x66,0xaa,0xcc,0x66},
+{0x48,0xd8,0x90,0x48}, {0x03,0x05,0x06,0x03}, {0xf6,0x01,0xf7,0xf6}, {0x0e,0x12,0x1c,0x0e},
+{0x61,0xa3,0xc2,0x61}, {0x35,0x5f,0x6a,0x35}, {0x57,0xf9,0xae,0x57}, {0xb9,0xd0,0x69,0xb9},
+{0x86,0x91,0x17,0x86}, {0xc1,0x58,0x99,0xc1}, {0x1d,0x27,0x3a,0x1d}, {0x9e,0xb9,0x27,0x9e},
+{0xe1,0x38,0xd9,0xe1}, {0xf8,0x13,0xeb,0xf8}, {0x98,0xb3,0x2b,0x98}, {0x11,0x33,0x22,0x11},
+{0x69,0xbb,0xd2,0x69}, {0xd9,0x70,0xa9,0xd9}, {0x8e,0x89,0x07,0x8e}, {0x94,0xa7,0x33,0x94},
+{0x9b,0xb6,0x2d,0x9b}, {0x1e,0x22,0x3c,0x1e}, {0x87,0x92,0x15,0x87}, {0xe9,0x20,0xc9,0xe9},
+{0xce,0x49,0x87,0xce}, {0x55,0xff,0xaa,0x55}, {0x28,0x78,0x50,0x28}, {0xdf,0x7a,0xa5,0xdf},
+{0x8c,0x8f,0x03,0x8c}, {0xa1,0xf8,0x59,0xa1}, {0x89,0x80,0x09,0x89}, {0x0d,0x17,0x1a,0x0d},
+{0xbf,0xda,0x65,0xbf}, {0xe6,0x31,0xd7,0xe6}, {0x42,0xc6,0x84,0x42}, {0x68,0xb8,0xd0,0x68},
+{0x41,0xc3,0x82,0x41}, {0x99,0xb0,0x29,0x99}, {0x2d,0x77,0x5a,0x2d}, {0x0f,0x11,0x1e,0x0f},
+{0xb0,0xcb,0x7b,0xb0}, {0x54,0xfc,0xa8,0x54}, {0xbb,0xd6,0x6d,0xbb}, {0x16,0x3a,0x2c,0x16}
+	}
+};
+#define	T3	xT3.xt8
+
+static const union xtab xT4 = {
+	.xt8 = {
+{0x63,0x63,0xa5,0xc6}, {0x7c,0x7c,0x84,0xf8}, {0x77,0x77,0x99,0xee}, {0x7b,0x7b,0x8d,0xf6},
+{0xf2,0xf2,0x0d,0xff}, {0x6b,0x6b,0xbd,0xd6}, {0x6f,0x6f,0xb1,0xde}, {0xc5,0xc5,0x54,0x91},
+{0x30,0x30,0x50,0x60}, {0x01,0x01,0x03,0x02}, {0x67,0x67,0xa9,0xce}, {0x2b,0x2b,0x7d,0x56},
+{0xfe,0xfe,0x19,0xe7}, {0xd7,0xd7,0x62,0xb5}, {0xab,0xab,0xe6,0x4d}, {0x76,0x76,0x9a,0xec},
+{0xca,0xca,0x45,0x8f}, {0x82,0x82,0x9d,0x1f}, {0xc9,0xc9,0x40,0x89}, {0x7d,0x7d,0x87,0xfa},
+{0xfa,0xfa,0x15,0xef}, {0x59,0x59,0xeb,0xb2}, {0x47,0x47,0xc9,0x8e}, {0xf0,0xf0,0x0b,0xfb},
+{0xad,0xad,0xec,0x41}, {0xd4,0xd4,0x67,0xb3}, {0xa2,0xa2,0xfd,0x5f}, {0xaf,0xaf,0xea,0x45},
+{0x9c,0x9c,0xbf,0x23}, {0xa4,0xa4,0xf7,0x53}, {0x72,0x72,0x96,0xe4}, {0xc0,0xc0,0x5b,0x9b},
+{0xb7,0xb7,0xc2,0x75}, {0xfd,0xfd,0x1c,0xe1}, {0x93,0x93,0xae,0x3d}, {0x26,0x26,0x6a,0x4c},
+{0x36,0x36,0x5a,0x6c}, {0x3f,0x3f,0x41,0x7e}, {0xf7,0xf7,0x02,0xf5}, {0xcc,0xcc,0x4f,0x83},
+{0x34,0x34,0x5c,0x68}, {0xa5,0xa5,0xf4,0x51}, {0xe5,0xe5,0x34,0xd1}, {0xf1,0xf1,0x08,0xf9},
+{0x71,0x71,0x93,0xe2}, {0xd8,0xd8,0x73,0xab}, {0x31,0x31,0x53,0x62}, {0x15,0x15,0x3f,0x2a},
+{0x04,0x04,0x0c,0x08}, {0xc7,0xc7,0x52,0x95}, {0x23,0x23,0x65,0x46}, {0xc3,0xc3,0x5e,0x9d},
+{0x18,0x18,0x28,0x30}, {0x96,0x96,0xa1,0x37}, {0x05,0x05,0x0f,0x0a}, {0x9a,0x9a,0xb5,0x2f},
+{0x07,0x07,0x09,0x0e}, {0x12,0x12,0x36,0x24}, {0x80,0x80,0x9b,0x1b}, {0xe2,0xe2,0x3d,0xdf},
+{0xeb,0xeb,0x26,0xcd}, {0x27,0x27,0x69,0x4e}, {0xb2,0xb2,0xcd,0x7f}, {0x75,0x75,0x9f,0xea},
+{0x09,0x09,0x1b,0x12}, {0x83,0x83,0x9e,0x1d}, {0x2c,0x2c,0x74,0x58}, {0x1a,0x1a,0x2e,0x34},
+{0x1b,0x1b,0x2d,0x36}, {0x6e,0x6e,0xb2,0xdc}, {0x5a,0x5a,0xee,0xb4}, {0xa0,0xa0,0xfb,0x5b},
+{0x52,0x52,0xf6,0xa4}, {0x3b,0x3b,0x4d,0x76}, {0xd6,0xd6,0x61,0xb7}, {0xb3,0xb3,0xce,0x7d},
+{0x29,0x29,0x7b,0x52}, {0xe3,0xe3,0x3e,0xdd}, {0x2f,0x2f,0x71,0x5e}, {0x84,0x84,0x97,0x13},
+{0x53,0x53,0xf5,0xa6}, {0xd1,0xd1,0x68,0xb9}, {0x00,0x00,0x00,0x00}, {0xed,0xed,0x2c,0xc1},
+{0x20,0x20,0x60,0x40}, {0xfc,0xfc,0x1f,0xe3}, {0xb1,0xb1,0xc8,0x79}, {0x5b,0x5b,0xed,0xb6},
+{0x6a,0x6a,0xbe,0xd4}, {0xcb,0xcb,0x46,0x8d}, {0xbe,0xbe,0xd9,0x67}, {0x39,0x39,0x4b,0x72},
+{0x4a,0x4a,0xde,0x94}, {0x4c,0x4c,0xd4,0x98}, {0x58,0x58,0xe8,0xb0}, {0xcf,0xcf,0x4a,0x85},
+{0xd0,0xd0,0x6b,0xbb}, {0xef,0xef,0x2a,0xc5}, {0xaa,0xaa,0xe5,0x4f}, {0xfb,0xfb,0x16,0xed},
+{0x43,0x43,0xc5,0x86}, {0x4d,0x4d,0xd7,0x9a}, {0x33,0x33,0x55,0x66}, {0x85,0x85,0x94,0x11},
+{0x45,0x45,0xcf,0x8a}, {0xf9,0xf9,0x10,0xe9}, {0x02,0x02,0x06,0x04}, {0x7f,0x7f,0x81,0xfe},
+{0x50,0x50,0xf0,0xa0}, {0x3c,0x3c,0x44,0x78}, {0x9f,0x9f,0xba,0x25}, {0xa8,0xa8,0xe3,0x4b},
+{0x51,0x51,0xf3,0xa2}, {0xa3,0xa3,0xfe,0x5d}, {0x40,0x40,0xc0,0x80}, {0x8f,0x8f,0x8a,0x05},
+{0x92,0x92,0xad,0x3f}, {0x9d,0x9d,0xbc,0x21}, {0x38,0x38,0x48,0x70}, {0xf5,0xf5,0x04,0xf1},
+{0xbc,0xbc,0xdf,0x63}, {0xb6,0xb6,0xc1,0x77}, {0xda,0xda,0x75,0xaf}, {0x21,0x21,0x63,0x42},
+{0x10,0x10,0x30,0x20}, {0xff,0xff,0x1a,0xe5}, {0xf3,0xf3,0x0e,0xfd}, {0xd2,0xd2,0x6d,0xbf},
+{0xcd,0xcd,0x4c,0x81}, {0x0c,0x0c,0x14,0x18}, {0x13,0x13,0x35,0x26}, {0xec,0xec,0x2f,0xc3},
+{0x5f,0x5f,0xe1,0xbe}, {0x97,0x97,0xa2,0x35}, {0x44,0x44,0xcc,0x88}, {0x17,0x17,0x39,0x2e},
+{0xc4,0xc4,0x57,0x93}, {0xa7,0xa7,0xf2,0x55}, {0x7e,0x7e,0x82,0xfc}, {0x3d,0x3d,0x47,0x7a},
+{0x64,0x64,0xac,0xc8}, {0x5d,0x5d,0xe7,0xba}, {0x19,0x19,0x2b,0x32}, {0x73,0x73,0x95,0xe6},
+{0x60,0x60,0xa0,0xc0}, {0x81,0x81,0x98,0x19}, {0x4f,0x4f,0xd1,0x9e}, {0xdc,0xdc,0x7f,0xa3},
+{0x22,0x22,0x66,0x44}, {0x2a,0x2a,0x7e,0x54}, {0x90,0x90,0xab,0x3b}, {0x88,0x88,0x83,0x0b},
+{0x46,0x46,0xca,0x8c}, {0xee,0xee,0x29,0xc7}, {0xb8,0xb8,0xd3,0x6b}, {0x14,0x14,0x3c,0x28},
+{0xde,0xde,0x79,0xa7}, {0x5e,0x5e,0xe2,0xbc}, {0x0b,0x0b,0x1d,0x16}, {0xdb,0xdb,0x76,0xad},
+{0xe0,0xe0,0x3b,0xdb}, {0x32,0x32,0x56,0x64}, {0x3a,0x3a,0x4e,0x74}, {0x0a,0x0a,0x1e,0x14},
+{0x49,0x49,0xdb,0x92}, {0x06,0x06,0x0a,0x0c}, {0x24,0x24,0x6c,0x48}, {0x5c,0x5c,0xe4,0xb8},
+{0xc2,0xc2,0x5d,0x9f}, {0xd3,0xd3,0x6e,0xbd}, {0xac,0xac,0xef,0x43}, {0x62,0x62,0xa6,0xc4},
+{0x91,0x91,0xa8,0x39}, {0x95,0x95,0xa4,0x31}, {0xe4,0xe4,0x37,0xd3}, {0x79,0x79,0x8b,0xf2},
+{0xe7,0xe7,0x32,0xd5}, {0xc8,0xc8,0x43,0x8b}, {0x37,0x37,0x59,0x6e}, {0x6d,0x6d,0xb7,0xda},
+{0x8d,0x8d,0x8c,0x01}, {0xd5,0xd5,0x64,0xb1}, {0x4e,0x4e,0xd2,0x9c}, {0xa9,0xa9,0xe0,0x49},
+{0x6c,0x6c,0xb4,0xd8}, {0x56,0x56,0xfa,0xac}, {0xf4,0xf4,0x07,0xf3}, {0xea,0xea,0x25,0xcf},
+{0x65,0x65,0xaf,0xca}, {0x7a,0x7a,0x8e,0xf4}, {0xae,0xae,0xe9,0x47}, {0x08,0x08,0x18,0x10},
+{0xba,0xba,0xd5,0x6f}, {0x78,0x78,0x88,0xf0}, {0x25,0x25,0x6f,0x4a}, {0x2e,0x2e,0x72,0x5c},
+{0x1c,0x1c,0x24,0x38}, {0xa6,0xa6,0xf1,0x57}, {0xb4,0xb4,0xc7,0x73}, {0xc6,0xc6,0x51,0x97},
+{0xe8,0xe8,0x23,0xcb}, {0xdd,0xdd,0x7c,0xa1}, {0x74,0x74,0x9c,0xe8}, {0x1f,0x1f,0x21,0x3e},
+{0x4b,0x4b,0xdd,0x96}, {0xbd,0xbd,0xdc,0x61}, {0x8b,0x8b,0x86,0x0d}, {0x8a,0x8a,0x85,0x0f},
+{0x70,0x70,0x90,0xe0}, {0x3e,0x3e,0x42,0x7c}, {0xb5,0xb5,0xc4,0x71}, {0x66,0x66,0xaa,0xcc},
+{0x48,0x48,0xd8,0x90}, {0x03,0x03,0x05,0x06}, {0xf6,0xf6,0x01,0xf7}, {0x0e,0x0e,0x12,0x1c},
+{0x61,0x61,0xa3,0xc2}, {0x35,0x35,0x5f,0x6a}, {0x57,0x57,0xf9,0xae}, {0xb9,0xb9,0xd0,0x69},
+{0x86,0x86,0x91,0x17}, {0xc1,0xc1,0x58,0x99}, {0x1d,0x1d,0x27,0x3a}, {0x9e,0x9e,0xb9,0x27},
+{0xe1,0xe1,0x38,0xd9}, {0xf8,0xf8,0x13,0xeb}, {0x98,0x98,0xb3,0x2b}, {0x11,0x11,0x33,0x22},
+{0x69,0x69,0xbb,0xd2}, {0xd9,0xd9,0x70,0xa9}, {0x8e,0x8e,0x89,0x07}, {0x94,0x94,0xa7,0x33},
+{0x9b,0x9b,0xb6,0x2d}, {0x1e,0x1e,0x22,0x3c}, {0x87,0x87,0x92,0x15}, {0xe9,0xe9,0x20,0xc9},
+{0xce,0xce,0x49,0x87}, {0x55,0x55,0xff,0xaa}, {0x28,0x28,0x78,0x50}, {0xdf,0xdf,0x7a,0xa5},
+{0x8c,0x8c,0x8f,0x03}, {0xa1,0xa1,0xf8,0x59}, {0x89,0x89,0x80,0x09}, {0x0d,0x0d,0x17,0x1a},
+{0xbf,0xbf,0xda,0x65}, {0xe6,0xe6,0x31,0xd7}, {0x42,0x42,0xc6,0x84}, {0x68,0x68,0xb8,0xd0},
+{0x41,0x41,0xc3,0x82}, {0x99,0x99,0xb0,0x29}, {0x2d,0x2d,0x77,0x5a}, {0x0f,0x0f,0x11,0x1e},
+{0xb0,0xb0,0xcb,0x7b}, {0x54,0x54,0xfc,0xa8}, {0xbb,0xbb,0xd6,0x6d}, {0x16,0x16,0x3a,0x2c}
+	}
+};
+#define	T4	xT4.xt8
+
+static const union xtab xT5 = {
+	.xt8 = {
+{0x51,0xf4,0xa7,0x50}, {0x7e,0x41,0x65,0x53}, {0x1a,0x17,0xa4,0xc3}, {0x3a,0x27,0x5e,0x96},
+{0x3b,0xab,0x6b,0xcb}, {0x1f,0x9d,0x45,0xf1}, {0xac,0xfa,0x58,0xab}, {0x4b,0xe3,0x03,0x93},
+{0x20,0x30,0xfa,0x55}, {0xad,0x76,0x6d,0xf6}, {0x88,0xcc,0x76,0x91}, {0xf5,0x02,0x4c,0x25},
+{0x4f,0xe5,0xd7,0xfc}, {0xc5,0x2a,0xcb,0xd7}, {0x26,0x35,0x44,0x80}, {0xb5,0x62,0xa3,0x8f},
+{0xde,0xb1,0x5a,0x49}, {0x25,0xba,0x1b,0x67}, {0x45,0xea,0x0e,0x98}, {0x5d,0xfe,0xc0,0xe1},
+{0xc3,0x2f,0x75,0x02}, {0x81,0x4c,0xf0,0x12}, {0x8d,0x46,0x97,0xa3}, {0x6b,0xd3,0xf9,0xc6},
+{0x03,0x8f,0x5f,0xe7}, {0x15,0x92,0x9c,0x95}, {0xbf,0x6d,0x7a,0xeb}, {0x95,0x52,0x59,0xda},
+{0xd4,0xbe,0x83,0x2d}, {0x58,0x74,0x21,0xd3}, {0x49,0xe0,0x69,0x29}, {0x8e,0xc9,0xc8,0x44},
+{0x75,0xc2,0x89,0x6a}, {0xf4,0x8e,0x79,0x78}, {0x99,0x58,0x3e,0x6b}, {0x27,0xb9,0x71,0xdd},
+{0xbe,0xe1,0x4f,0xb6}, {0xf0,0x88,0xad,0x17}, {0xc9,0x20,0xac,0x66}, {0x7d,0xce,0x3a,0xb4},
+{0x63,0xdf,0x4a,0x18}, {0xe5,0x1a,0x31,0x82}, {0x97,0x51,0x33,0x60}, {0x62,0x53,0x7f,0x45},
+{0xb1,0x64,0x77,0xe0}, {0xbb,0x6b,0xae,0x84}, {0xfe,0x81,0xa0,0x1c}, {0xf9,0x08,0x2b,0x94},
+{0x70,0x48,0x68,0x58}, {0x8f,0x45,0xfd,0x19}, {0x94,0xde,0x6c,0x87}, {0x52,0x7b,0xf8,0xb7},
+{0xab,0x73,0xd3,0x23}, {0x72,0x4b,0x02,0xe2}, {0xe3,0x1f,0x8f,0x57}, {0x66,0x55,0xab,0x2a},
+{0xb2,0xeb,0x28,0x07}, {0x2f,0xb5,0xc2,0x03}, {0x86,0xc5,0x7b,0x9a}, {0xd3,0x37,0x08,0xa5},
+{0x30,0x28,0x87,0xf2}, {0x23,0xbf,0xa5,0xb2}, {0x02,0x03,0x6a,0xba}, {0xed,0x16,0x82,0x5c},
+{0x8a,0xcf,0x1c,0x2b}, {0xa7,0x79,0xb4,0x92}, {0xf3,0x07,0xf2,0xf0}, {0x4e,0x69,0xe2,0xa1},
+{0x65,0xda,0xf4,0xcd}, {0x06,0x05,0xbe,0xd5}, {0xd1,0x34,0x62,0x1f}, {0xc4,0xa6,0xfe,0x8a},
+{0x34,0x2e,0x53,0x9d}, {0xa2,0xf3,0x55,0xa0}, {0x05,0x8a,0xe1,0x32}, {0xa4,0xf6,0xeb,0x75},
+{0x0b,0x83,0xec,0x39}, {0x40,0x60,0xef,0xaa}, {0x5e,0x71,0x9f,0x06}, {0xbd,0x6e,0x10,0x51},
+{0x3e,0x21,0x8a,0xf9}, {0x96,0xdd,0x06,0x3d}, {0xdd,0x3e,0x05,0xae}, {0x4d,0xe6,0xbd,0x46},
+{0x91,0x54,0x8d,0xb5}, {0x71,0xc4,0x5d,0x05}, {0x04,0x06,0xd4,0x6f}, {0x60,0x50,0x15,0xff},
+{0x19,0x98,0xfb,0x24}, {0xd6,0xbd,0xe9,0x97}, {0x89,0x40,0x43,0xcc}, {0x67,0xd9,0x9e,0x77},
+{0xb0,0xe8,0x42,0xbd}, {0x07,0x89,0x8b,0x88}, {0xe7,0x19,0x5b,0x38}, {0x79,0xc8,0xee,0xdb},
+{0xa1,0x7c,0x0a,0x47}, {0x7c,0x42,0x0f,0xe9}, {0xf8,0x84,0x1e,0xc9}, {0x00,0x00,0x00,0x00},
+{0x09,0x80,0x86,0x83}, {0x32,0x2b,0xed,0x48}, {0x1e,0x11,0x70,0xac}, {0x6c,0x5a,0x72,0x4e},
+{0xfd,0x0e,0xff,0xfb}, {0x0f,0x85,0x38,0x56}, {0x3d,0xae,0xd5,0x1e}, {0x36,0x2d,0x39,0x27},
+{0x0a,0x0f,0xd9,0x64}, {0x68,0x5c,0xa6,0x21}, {0x9b,0x5b,0x54,0xd1}, {0x24,0x36,0x2e,0x3a},
+{0x0c,0x0a,0x67,0xb1}, {0x93,0x57,0xe7,0x0f}, {0xb4,0xee,0x96,0xd2}, {0x1b,0x9b,0x91,0x9e},
+{0x80,0xc0,0xc5,0x4f}, {0x61,0xdc,0x20,0xa2}, {0x5a,0x77,0x4b,0x69}, {0x1c,0x12,0x1a,0x16},
+{0xe2,0x93,0xba,0x0a}, {0xc0,0xa0,0x2a,0xe5}, {0x3c,0x22,0xe0,0x43}, {0x12,0x1b,0x17,0x1d},
+{0x0e,0x09,0x0d,0x0b}, {0xf2,0x8b,0xc7,0xad}, {0x2d,0xb6,0xa8,0xb9}, {0x14,0x1e,0xa9,0xc8},
+{0x57,0xf1,0x19,0x85}, {0xaf,0x75,0x07,0x4c}, {0xee,0x99,0xdd,0xbb}, {0xa3,0x7f,0x60,0xfd},
+{0xf7,0x01,0x26,0x9f}, {0x5c,0x72,0xf5,0xbc}, {0x44,0x66,0x3b,0xc5}, {0x5b,0xfb,0x7e,0x34},
+{0x8b,0x43,0x29,0x76}, {0xcb,0x23,0xc6,0xdc}, {0xb6,0xed,0xfc,0x68}, {0xb8,0xe4,0xf1,0x63},
+{0xd7,0x31,0xdc,0xca}, {0x42,0x63,0x85,0x10}, {0x13,0x97,0x22,0x40}, {0x84,0xc6,0x11,0x20},
+{0x85,0x4a,0x24,0x7d}, {0xd2,0xbb,0x3d,0xf8}, {0xae,0xf9,0x32,0x11}, {0xc7,0x29,0xa1,0x6d},
+{0x1d,0x9e,0x2f,0x4b}, {0xdc,0xb2,0x30,0xf3}, {0x0d,0x86,0x52,0xec}, {0x77,0xc1,0xe3,0xd0},
+{0x2b,0xb3,0x16,0x6c}, {0xa9,0x70,0xb9,0x99}, {0x11,0x94,0x48,0xfa}, {0x47,0xe9,0x64,0x22},
+{0xa8,0xfc,0x8c,0xc4}, {0xa0,0xf0,0x3f,0x1a}, {0x56,0x7d,0x2c,0xd8}, {0x22,0x33,0x90,0xef},
+{0x87,0x49,0x4e,0xc7}, {0xd9,0x38,0xd1,0xc1}, {0x8c,0xca,0xa2,0xfe}, {0x98,0xd4,0x0b,0x36},
+{0xa6,0xf5,0x81,0xcf}, {0xa5,0x7a,0xde,0x28}, {0xda,0xb7,0x8e,0x26}, {0x3f,0xad,0xbf,0xa4},
+{0x2c,0x3a,0x9d,0xe4}, {0x50,0x78,0x92,0x0d}, {0x6a,0x5f,0xcc,0x9b}, {0x54,0x7e,0x46,0x62},
+{0xf6,0x8d,0x13,0xc2}, {0x90,0xd8,0xb8,0xe8}, {0x2e,0x39,0xf7,0x5e}, {0x82,0xc3,0xaf,0xf5},
+{0x9f,0x5d,0x80,0xbe}, {0x69,0xd0,0x93,0x7c}, {0x6f,0xd5,0x2d,0xa9}, {0xcf,0x25,0x12,0xb3},
+{0xc8,0xac,0x99,0x3b}, {0x10,0x18,0x7d,0xa7}, {0xe8,0x9c,0x63,0x6e}, {0xdb,0x3b,0xbb,0x7b},
+{0xcd,0x26,0x78,0x09}, {0x6e,0x59,0x18,0xf4}, {0xec,0x9a,0xb7,0x01}, {0x83,0x4f,0x9a,0xa8},
+{0xe6,0x95,0x6e,0x65}, {0xaa,0xff,0xe6,0x7e}, {0x21,0xbc,0xcf,0x08}, {0xef,0x15,0xe8,0xe6},
+{0xba,0xe7,0x9b,0xd9}, {0x4a,0x6f,0x36,0xce}, {0xea,0x9f,0x09,0xd4}, {0x29,0xb0,0x7c,0xd6},
+{0x31,0xa4,0xb2,0xaf}, {0x2a,0x3f,0x23,0x31}, {0xc6,0xa5,0x94,0x30}, {0x35,0xa2,0x66,0xc0},
+{0x74,0x4e,0xbc,0x37}, {0xfc,0x82,0xca,0xa6}, {0xe0,0x90,0xd0,0xb0}, {0x33,0xa7,0xd8,0x15},
+{0xf1,0x04,0x98,0x4a}, {0x41,0xec,0xda,0xf7}, {0x7f,0xcd,0x50,0x0e}, {0x17,0x91,0xf6,0x2f},
+{0x76,0x4d,0xd6,0x8d}, {0x43,0xef,0xb0,0x4d}, {0xcc,0xaa,0x4d,0x54}, {0xe4,0x96,0x04,0xdf},
+{0x9e,0xd1,0xb5,0xe3}, {0x4c,0x6a,0x88,0x1b}, {0xc1,0x2c,0x1f,0xb8}, {0x46,0x65,0x51,0x7f},
+{0x9d,0x5e,0xea,0x04}, {0x01,0x8c,0x35,0x5d}, {0xfa,0x87,0x74,0x73}, {0xfb,0x0b,0x41,0x2e},
+{0xb3,0x67,0x1d,0x5a}, {0x92,0xdb,0xd2,0x52}, {0xe9,0x10,0x56,0x33}, {0x6d,0xd6,0x47,0x13},
+{0x9a,0xd7,0x61,0x8c}, {0x37,0xa1,0x0c,0x7a}, {0x59,0xf8,0x14,0x8e}, {0xeb,0x13,0x3c,0x89},
+{0xce,0xa9,0x27,0xee}, {0xb7,0x61,0xc9,0x35}, {0xe1,0x1c,0xe5,0xed}, {0x7a,0x47,0xb1,0x3c},
+{0x9c,0xd2,0xdf,0x59}, {0x55,0xf2,0x73,0x3f}, {0x18,0x14,0xce,0x79}, {0x73,0xc7,0x37,0xbf},
+{0x53,0xf7,0xcd,0xea}, {0x5f,0xfd,0xaa,0x5b}, {0xdf,0x3d,0x6f,0x14}, {0x78,0x44,0xdb,0x86},
+{0xca,0xaf,0xf3,0x81}, {0xb9,0x68,0xc4,0x3e}, {0x38,0x24,0x34,0x2c}, {0xc2,0xa3,0x40,0x5f},
+{0x16,0x1d,0xc3,0x72}, {0xbc,0xe2,0x25,0x0c}, {0x28,0x3c,0x49,0x8b}, {0xff,0x0d,0x95,0x41},
+{0x39,0xa8,0x01,0x71}, {0x08,0x0c,0xb3,0xde}, {0xd8,0xb4,0xe4,0x9c}, {0x64,0x56,0xc1,0x90},
+{0x7b,0xcb,0x84,0x61}, {0xd5,0x32,0xb6,0x70}, {0x48,0x6c,0x5c,0x74}, {0xd0,0xb8,0x57,0x42}
+	}
+};
+#define	T5	xT5.xt8
+
+static const union xtab xT6 = {
+	.xt8 = {
+{0x50,0x51,0xf4,0xa7}, {0x53,0x7e,0x41,0x65}, {0xc3,0x1a,0x17,0xa4}, {0x96,0x3a,0x27,0x5e},
+{0xcb,0x3b,0xab,0x6b}, {0xf1,0x1f,0x9d,0x45}, {0xab,0xac,0xfa,0x58}, {0x93,0x4b,0xe3,0x03},
+{0x55,0x20,0x30,0xfa}, {0xf6,0xad,0x76,0x6d}, {0x91,0x88,0xcc,0x76}, {0x25,0xf5,0x02,0x4c},
+{0xfc,0x4f,0xe5,0xd7}, {0xd7,0xc5,0x2a,0xcb}, {0x80,0x26,0x35,0x44}, {0x8f,0xb5,0x62,0xa3},
+{0x49,0xde,0xb1,0x5a}, {0x67,0x25,0xba,0x1b}, {0x98,0x45,0xea,0x0e}, {0xe1,0x5d,0xfe,0xc0},
+{0x02,0xc3,0x2f,0x75}, {0x12,0x81,0x4c,0xf0}, {0xa3,0x8d,0x46,0x97}, {0xc6,0x6b,0xd3,0xf9},
+{0xe7,0x03,0x8f,0x5f}, {0x95,0x15,0x92,0x9c}, {0xeb,0xbf,0x6d,0x7a}, {0xda,0x95,0x52,0x59},
+{0x2d,0xd4,0xbe,0x83}, {0xd3,0x58,0x74,0x21}, {0x29,0x49,0xe0,0x69}, {0x44,0x8e,0xc9,0xc8},
+{0x6a,0x75,0xc2,0x89}, {0x78,0xf4,0x8e,0x79}, {0x6b,0x99,0x58,0x3e}, {0xdd,0x27,0xb9,0x71},
+{0xb6,0xbe,0xe1,0x4f}, {0x17,0xf0,0x88,0xad}, {0x66,0xc9,0x20,0xac}, {0xb4,0x7d,0xce,0x3a},
+{0x18,0x63,0xdf,0x4a}, {0x82,0xe5,0x1a,0x31}, {0x60,0x97,0x51,0x33}, {0x45,0x62,0x53,0x7f},
+{0xe0,0xb1,0x64,0x77}, {0x84,0xbb,0x6b,0xae}, {0x1c,0xfe,0x81,0xa0}, {0x94,0xf9,0x08,0x2b},
+{0x58,0x70,0x48,0x68}, {0x19,0x8f,0x45,0xfd}, {0x87,0x94,0xde,0x6c}, {0xb7,0x52,0x7b,0xf8},
+{0x23,0xab,0x73,0xd3}, {0xe2,0x72,0x4b,0x02}, {0x57,0xe3,0x1f,0x8f}, {0x2a,0x66,0x55,0xab},
+{0x07,0xb2,0xeb,0x28}, {0x03,0x2f,0xb5,0xc2}, {0x9a,0x86,0xc5,0x7b}, {0xa5,0xd3,0x37,0x08},
+{0xf2,0x30,0x28,0x87}, {0xb2,0x23,0xbf,0xa5}, {0xba,0x02,0x03,0x6a}, {0x5c,0xed,0x16,0x82},
+{0x2b,0x8a,0xcf,0x1c}, {0x92,0xa7,0x79,0xb4}, {0xf0,0xf3,0x07,0xf2}, {0xa1,0x4e,0x69,0xe2},
+{0xcd,0x65,0xda,0xf4}, {0xd5,0x06,0x05,0xbe}, {0x1f,0xd1,0x34,0x62}, {0x8a,0xc4,0xa6,0xfe},
+{0x9d,0x34,0x2e,0x53}, {0xa0,0xa2,0xf3,0x55}, {0x32,0x05,0x8a,0xe1}, {0x75,0xa4,0xf6,0xeb},
+{0x39,0x0b,0x83,0xec}, {0xaa,0x40,0x60,0xef}, {0x06,0x5e,0x71,0x9f}, {0x51,0xbd,0x6e,0x10},
+{0xf9,0x3e,0x21,0x8a}, {0x3d,0x96,0xdd,0x06}, {0xae,0xdd,0x3e,0x05}, {0x46,0x4d,0xe6,0xbd},
+{0xb5,0x91,0x54,0x8d}, {0x05,0x71,0xc4,0x5d}, {0x6f,0x04,0x06,0xd4}, {0xff,0x60,0x50,0x15},
+{0x24,0x19,0x98,0xfb}, {0x97,0xd6,0xbd,0xe9}, {0xcc,0x89,0x40,0x43}, {0x77,0x67,0xd9,0x9e},
+{0xbd,0xb0,0xe8,0x42}, {0x88,0x07,0x89,0x8b}, {0x38,0xe7,0x19,0x5b}, {0xdb,0x79,0xc8,0xee},
+{0x47,0xa1,0x7c,0x0a}, {0xe9,0x7c,0x42,0x0f}, {0xc9,0xf8,0x84,0x1e}, {0x00,0x00,0x00,0x00},
+{0x83,0x09,0x80,0x86}, {0x48,0x32,0x2b,0xed}, {0xac,0x1e,0x11,0x70}, {0x4e,0x6c,0x5a,0x72},
+{0xfb,0xfd,0x0e,0xff}, {0x56,0x0f,0x85,0x38}, {0x1e,0x3d,0xae,0xd5}, {0x27,0x36,0x2d,0x39},
+{0x64,0x0a,0x0f,0xd9}, {0x21,0x68,0x5c,0xa6}, {0xd1,0x9b,0x5b,0x54}, {0x3a,0x24,0x36,0x2e},
+{0xb1,0x0c,0x0a,0x67}, {0x0f,0x93,0x57,0xe7}, {0xd2,0xb4,0xee,0x96}, {0x9e,0x1b,0x9b,0x91},
+{0x4f,0x80,0xc0,0xc5}, {0xa2,0x61,0xdc,0x20}, {0x69,0x5a,0x77,0x4b}, {0x16,0x1c,0x12,0x1a},
+{0x0a,0xe2,0x93,0xba}, {0xe5,0xc0,0xa0,0x2a}, {0x43,0x3c,0x22,0xe0}, {0x1d,0x12,0x1b,0x17},
+{0x0b,0x0e,0x09,0x0d}, {0xad,0xf2,0x8b,0xc7}, {0xb9,0x2d,0xb6,0xa8}, {0xc8,0x14,0x1e,0xa9},
+{0x85,0x57,0xf1,0x19}, {0x4c,0xaf,0x75,0x07}, {0xbb,0xee,0x99,0xdd}, {0xfd,0xa3,0x7f,0x60},
+{0x9f,0xf7,0x01,0x26}, {0xbc,0x5c,0x72,0xf5}, {0xc5,0x44,0x66,0x3b}, {0x34,0x5b,0xfb,0x7e},
+{0x76,0x8b,0x43,0x29}, {0xdc,0xcb,0x23,0xc6}, {0x68,0xb6,0xed,0xfc}, {0x63,0xb8,0xe4,0xf1},
+{0xca,0xd7,0x31,0xdc}, {0x10,0x42,0x63,0x85}, {0x40,0x13,0x97,0x22}, {0x20,0x84,0xc6,0x11},
+{0x7d,0x85,0x4a,0x24}, {0xf8,0xd2,0xbb,0x3d}, {0x11,0xae,0xf9,0x32}, {0x6d,0xc7,0x29,0xa1},
+{0x4b,0x1d,0x9e,0x2f}, {0xf3,0xdc,0xb2,0x30}, {0xec,0x0d,0x86,0x52}, {0xd0,0x77,0xc1,0xe3},
+{0x6c,0x2b,0xb3,0x16}, {0x99,0xa9,0x70,0xb9}, {0xfa,0x11,0x94,0x48}, {0x22,0x47,0xe9,0x64},
+{0xc4,0xa8,0xfc,0x8c}, {0x1a,0xa0,0xf0,0x3f}, {0xd8,0x56,0x7d,0x2c}, {0xef,0x22,0x33,0x90},
+{0xc7,0x87,0x49,0x4e}, {0xc1,0xd9,0x38,0xd1}, {0xfe,0x8c,0xca,0xa2}, {0x36,0x98,0xd4,0x0b},
+{0xcf,0xa6,0xf5,0x81}, {0x28,0xa5,0x7a,0xde}, {0x26,0xda,0xb7,0x8e}, {0xa4,0x3f,0xad,0xbf},
+{0xe4,0x2c,0x3a,0x9d}, {0x0d,0x50,0x78,0x92}, {0x9b,0x6a,0x5f,0xcc}, {0x62,0x54,0x7e,0x46},
+{0xc2,0xf6,0x8d,0x13}, {0xe8,0x90,0xd8,0xb8}, {0x5e,0x2e,0x39,0xf7}, {0xf5,0x82,0xc3,0xaf},
+{0xbe,0x9f,0x5d,0x80}, {0x7c,0x69,0xd0,0x93}, {0xa9,0x6f,0xd5,0x2d}, {0xb3,0xcf,0x25,0x12},
+{0x3b,0xc8,0xac,0x99}, {0xa7,0x10,0x18,0x7d}, {0x6e,0xe8,0x9c,0x63}, {0x7b,0xdb,0x3b,0xbb},
+{0x09,0xcd,0x26,0x78}, {0xf4,0x6e,0x59,0x18}, {0x01,0xec,0x9a,0xb7}, {0xa8,0x83,0x4f,0x9a},
+{0x65,0xe6,0x95,0x6e}, {0x7e,0xaa,0xff,0xe6}, {0x08,0x21,0xbc,0xcf}, {0xe6,0xef,0x15,0xe8},
+{0xd9,0xba,0xe7,0x9b}, {0xce,0x4a,0x6f,0x36}, {0xd4,0xea,0x9f,0x09}, {0xd6,0x29,0xb0,0x7c},
+{0xaf,0x31,0xa4,0xb2}, {0x31,0x2a,0x3f,0x23}, {0x30,0xc6,0xa5,0x94}, {0xc0,0x35,0xa2,0x66},
+{0x37,0x74,0x4e,0xbc}, {0xa6,0xfc,0x82,0xca}, {0xb0,0xe0,0x90,0xd0}, {0x15,0x33,0xa7,0xd8},
+{0x4a,0xf1,0x04,0x98}, {0xf7,0x41,0xec,0xda}, {0x0e,0x7f,0xcd,0x50}, {0x2f,0x17,0x91,0xf6},
+{0x8d,0x76,0x4d,0xd6}, {0x4d,0x43,0xef,0xb0}, {0x54,0xcc,0xaa,0x4d}, {0xdf,0xe4,0x96,0x04},
+{0xe3,0x9e,0xd1,0xb5}, {0x1b,0x4c,0x6a,0x88}, {0xb8,0xc1,0x2c,0x1f}, {0x7f,0x46,0x65,0x51},
+{0x04,0x9d,0x5e,0xea}, {0x5d,0x01,0x8c,0x35}, {0x73,0xfa,0x87,0x74}, {0x2e,0xfb,0x0b,0x41},
+{0x5a,0xb3,0x67,0x1d}, {0x52,0x92,0xdb,0xd2}, {0x33,0xe9,0x10,0x56}, {0x13,0x6d,0xd6,0x47},
+{0x8c,0x9a,0xd7,0x61}, {0x7a,0x37,0xa1,0x0c}, {0x8e,0x59,0xf8,0x14}, {0x89,0xeb,0x13,0x3c},
+{0xee,0xce,0xa9,0x27}, {0x35,0xb7,0x61,0xc9}, {0xed,0xe1,0x1c,0xe5}, {0x3c,0x7a,0x47,0xb1},
+{0x59,0x9c,0xd2,0xdf}, {0x3f,0x55,0xf2,0x73}, {0x79,0x18,0x14,0xce}, {0xbf,0x73,0xc7,0x37},
+{0xea,0x53,0xf7,0xcd}, {0x5b,0x5f,0xfd,0xaa}, {0x14,0xdf,0x3d,0x6f}, {0x86,0x78,0x44,0xdb},
+{0x81,0xca,0xaf,0xf3}, {0x3e,0xb9,0x68,0xc4}, {0x2c,0x38,0x24,0x34}, {0x5f,0xc2,0xa3,0x40},
+{0x72,0x16,0x1d,0xc3}, {0x0c,0xbc,0xe2,0x25}, {0x8b,0x28,0x3c,0x49}, {0x41,0xff,0x0d,0x95},
+{0x71,0x39,0xa8,0x01}, {0xde,0x08,0x0c,0xb3}, {0x9c,0xd8,0xb4,0xe4}, {0x90,0x64,0x56,0xc1},
+{0x61,0x7b,0xcb,0x84}, {0x70,0xd5,0x32,0xb6}, {0x74,0x48,0x6c,0x5c}, {0x42,0xd0,0xb8,0x57}
+	}
+};
+#define	T6	xT6.xt8
+
+static const union xtab xT7 = {
+	.xt8 = {
+{0xa7,0x50,0x51,0xf4}, {0x65,0x53,0x7e,0x41}, {0xa4,0xc3,0x1a,0x17}, {0x5e,0x96,0x3a,0x27},
+{0x6b,0xcb,0x3b,0xab}, {0x45,0xf1,0x1f,0x9d}, {0x58,0xab,0xac,0xfa}, {0x03,0x93,0x4b,0xe3},
+{0xfa,0x55,0x20,0x30}, {0x6d,0xf6,0xad,0x76}, {0x76,0x91,0x88,0xcc}, {0x4c,0x25,0xf5,0x02},
+{0xd7,0xfc,0x4f,0xe5}, {0xcb,0xd7,0xc5,0x2a}, {0x44,0x80,0x26,0x35}, {0xa3,0x8f,0xb5,0x62},
+{0x5a,0x49,0xde,0xb1}, {0x1b,0x67,0x25,0xba}, {0x0e,0x98,0x45,0xea}, {0xc0,0xe1,0x5d,0xfe},
+{0x75,0x02,0xc3,0x2f}, {0xf0,0x12,0x81,0x4c}, {0x97,0xa3,0x8d,0x46}, {0xf9,0xc6,0x6b,0xd3},
+{0x5f,0xe7,0x03,0x8f}, {0x9c,0x95,0x15,0x92}, {0x7a,0xeb,0xbf,0x6d}, {0x59,0xda,0x95,0x52},
+{0x83,0x2d,0xd4,0xbe}, {0x21,0xd3,0x58,0x74}, {0x69,0x29,0x49,0xe0}, {0xc8,0x44,0x8e,0xc9},
+{0x89,0x6a,0x75,0xc2}, {0x79,0x78,0xf4,0x8e}, {0x3e,0x6b,0x99,0x58}, {0x71,0xdd,0x27,0xb9},
+{0x4f,0xb6,0xbe,0xe1}, {0xad,0x17,0xf0,0x88}, {0xac,0x66,0xc9,0x20}, {0x3a,0xb4,0x7d,0xce},
+{0x4a,0x18,0x63,0xdf}, {0x31,0x82,0xe5,0x1a}, {0x33,0x60,0x97,0x51}, {0x7f,0x45,0x62,0x53},
+{0x77,0xe0,0xb1,0x64}, {0xae,0x84,0xbb,0x6b}, {0xa0,0x1c,0xfe,0x81}, {0x2b,0x94,0xf9,0x08},
+{0x68,0x58,0x70,0x48}, {0xfd,0x19,0x8f,0x45}, {0x6c,0x87,0x94,0xde}, {0xf8,0xb7,0x52,0x7b},
+{0xd3,0x23,0xab,0x73}, {0x02,0xe2,0x72,0x4b}, {0x8f,0x57,0xe3,0x1f}, {0xab,0x2a,0x66,0x55},
+{0x28,0x07,0xb2,0xeb}, {0xc2,0x03,0x2f,0xb5}, {0x7b,0x9a,0x86,0xc5}, {0x08,0xa5,0xd3,0x37},
+{0x87,0xf2,0x30,0x28}, {0xa5,0xb2,0x23,0xbf}, {0x6a,0xba,0x02,0x03}, {0x82,0x5c,0xed,0x16},
+{0x1c,0x2b,0x8a,0xcf}, {0xb4,0x92,0xa7,0x79}, {0xf2,0xf0,0xf3,0x07}, {0xe2,0xa1,0x4e,0x69},
+{0xf4,0xcd,0x65,0xda}, {0xbe,0xd5,0x06,0x05}, {0x62,0x1f,0xd1,0x34}, {0xfe,0x8a,0xc4,0xa6},
+{0x53,0x9d,0x34,0x2e}, {0x55,0xa0,0xa2,0xf3}, {0xe1,0x32,0x05,0x8a}, {0xeb,0x75,0xa4,0xf6},
+{0xec,0x39,0x0b,0x83}, {0xef,0xaa,0x40,0x60}, {0x9f,0x06,0x5e,0x71}, {0x10,0x51,0xbd,0x6e},
+{0x8a,0xf9,0x3e,0x21}, {0x06,0x3d,0x96,0xdd}, {0x05,0xae,0xdd,0x3e}, {0xbd,0x46,0x4d,0xe6},
+{0x8d,0xb5,0x91,0x54}, {0x5d,0x05,0x71,0xc4}, {0xd4,0x6f,0x04,0x06}, {0x15,0xff,0x60,0x50},
+{0xfb,0x24,0x19,0x98}, {0xe9,0x97,0xd6,0xbd}, {0x43,0xcc,0x89,0x40}, {0x9e,0x77,0x67,0xd9},
+{0x42,0xbd,0xb0,0xe8}, {0x8b,0x88,0x07,0x89}, {0x5b,0x38,0xe7,0x19}, {0xee,0xdb,0x79,0xc8},
+{0x0a,0x47,0xa1,0x7c}, {0x0f,0xe9,0x7c,0x42}, {0x1e,0xc9,0xf8,0x84}, {0x00,0x00,0x00,0x00},
+{0x86,0x83,0x09,0x80}, {0xed,0x48,0x32,0x2b}, {0x70,0xac,0x1e,0x11}, {0x72,0x4e,0x6c,0x5a},
+{0xff,0xfb,0xfd,0x0e}, {0x38,0x56,0x0f,0x85}, {0xd5,0x1e,0x3d,0xae}, {0x39,0x27,0x36,0x2d},
+{0xd9,0x64,0x0a,0x0f}, {0xa6,0x21,0x68,0x5c}, {0x54,0xd1,0x9b,0x5b}, {0x2e,0x3a,0x24,0x36},
+{0x67,0xb1,0x0c,0x0a}, {0xe7,0x0f,0x93,0x57}, {0x96,0xd2,0xb4,0xee}, {0x91,0x9e,0x1b,0x9b},
+{0xc5,0x4f,0x80,0xc0}, {0x20,0xa2,0x61,0xdc}, {0x4b,0x69,0x5a,0x77}, {0x1a,0x16,0x1c,0x12},
+{0xba,0x0a,0xe2,0x93}, {0x2a,0xe5,0xc0,0xa0}, {0xe0,0x43,0x3c,0x22}, {0x17,0x1d,0x12,0x1b},
+{0x0d,0x0b,0x0e,0x09}, {0xc7,0xad,0xf2,0x8b}, {0xa8,0xb9,0x2d,0xb6}, {0xa9,0xc8,0x14,0x1e},
+{0x19,0x85,0x57,0xf1}, {0x07,0x4c,0xaf,0x75}, {0xdd,0xbb,0xee,0x99}, {0x60,0xfd,0xa3,0x7f},
+{0x26,0x9f,0xf7,0x01}, {0xf5,0xbc,0x5c,0x72}, {0x3b,0xc5,0x44,0x66}, {0x7e,0x34,0x5b,0xfb},
+{0x29,0x76,0x8b,0x43}, {0xc6,0xdc,0xcb,0x23}, {0xfc,0x68,0xb6,0xed}, {0xf1,0x63,0xb8,0xe4},
+{0xdc,0xca,0xd7,0x31}, {0x85,0x10,0x42,0x63}, {0x22,0x40,0x13,0x97}, {0x11,0x20,0x84,0xc6},
+{0x24,0x7d,0x85,0x4a}, {0x3d,0xf8,0xd2,0xbb}, {0x32,0x11,0xae,0xf9}, {0xa1,0x6d,0xc7,0x29},
+{0x2f,0x4b,0x1d,0x9e}, {0x30,0xf3,0xdc,0xb2}, {0x52,0xec,0x0d,0x86}, {0xe3,0xd0,0x77,0xc1},
+{0x16,0x6c,0x2b,0xb3}, {0xb9,0x99,0xa9,0x70}, {0x48,0xfa,0x11,0x94}, {0x64,0x22,0x47,0xe9},
+{0x8c,0xc4,0xa8,0xfc}, {0x3f,0x1a,0xa0,0xf0}, {0x2c,0xd8,0x56,0x7d}, {0x90,0xef,0x22,0x33},
+{0x4e,0xc7,0x87,0x49}, {0xd1,0xc1,0xd9,0x38}, {0xa2,0xfe,0x8c,0xca}, {0x0b,0x36,0x98,0xd4},
+{0x81,0xcf,0xa6,0xf5}, {0xde,0x28,0xa5,0x7a}, {0x8e,0x26,0xda,0xb7}, {0xbf,0xa4,0x3f,0xad},
+{0x9d,0xe4,0x2c,0x3a}, {0x92,0x0d,0x50,0x78}, {0xcc,0x9b,0x6a,0x5f}, {0x46,0x62,0x54,0x7e},
+{0x13,0xc2,0xf6,0x8d}, {0xb8,0xe8,0x90,0xd8}, {0xf7,0x5e,0x2e,0x39}, {0xaf,0xf5,0x82,0xc3},
+{0x80,0xbe,0x9f,0x5d}, {0x93,0x7c,0x69,0xd0}, {0x2d,0xa9,0x6f,0xd5}, {0x12,0xb3,0xcf,0x25},
+{0x99,0x3b,0xc8,0xac}, {0x7d,0xa7,0x10,0x18}, {0x63,0x6e,0xe8,0x9c}, {0xbb,0x7b,0xdb,0x3b},
+{0x78,0x09,0xcd,0x26}, {0x18,0xf4,0x6e,0x59}, {0xb7,0x01,0xec,0x9a}, {0x9a,0xa8,0x83,0x4f},
+{0x6e,0x65,0xe6,0x95}, {0xe6,0x7e,0xaa,0xff}, {0xcf,0x08,0x21,0xbc}, {0xe8,0xe6,0xef,0x15},
+{0x9b,0xd9,0xba,0xe7}, {0x36,0xce,0x4a,0x6f}, {0x09,0xd4,0xea,0x9f}, {0x7c,0xd6,0x29,0xb0},
+{0xb2,0xaf,0x31,0xa4}, {0x23,0x31,0x2a,0x3f}, {0x94,0x30,0xc6,0xa5}, {0x66,0xc0,0x35,0xa2},
+{0xbc,0x37,0x74,0x4e}, {0xca,0xa6,0xfc,0x82}, {0xd0,0xb0,0xe0,0x90}, {0xd8,0x15,0x33,0xa7},
+{0x98,0x4a,0xf1,0x04}, {0xda,0xf7,0x41,0xec}, {0x50,0x0e,0x7f,0xcd}, {0xf6,0x2f,0x17,0x91},
+{0xd6,0x8d,0x76,0x4d}, {0xb0,0x4d,0x43,0xef}, {0x4d,0x54,0xcc,0xaa}, {0x04,0xdf,0xe4,0x96},
+{0xb5,0xe3,0x9e,0xd1}, {0x88,0x1b,0x4c,0x6a}, {0x1f,0xb8,0xc1,0x2c}, {0x51,0x7f,0x46,0x65},
+{0xea,0x04,0x9d,0x5e}, {0x35,0x5d,0x01,0x8c}, {0x74,0x73,0xfa,0x87}, {0x41,0x2e,0xfb,0x0b},
+{0x1d,0x5a,0xb3,0x67}, {0xd2,0x52,0x92,0xdb}, {0x56,0x33,0xe9,0x10}, {0x47,0x13,0x6d,0xd6},
+{0x61,0x8c,0x9a,0xd7}, {0x0c,0x7a,0x37,0xa1}, {0x14,0x8e,0x59,0xf8}, {0x3c,0x89,0xeb,0x13},
+{0x27,0xee,0xce,0xa9}, {0xc9,0x35,0xb7,0x61}, {0xe5,0xed,0xe1,0x1c}, {0xb1,0x3c,0x7a,0x47},
+{0xdf,0x59,0x9c,0xd2}, {0x73,0x3f,0x55,0xf2}, {0xce,0x79,0x18,0x14}, {0x37,0xbf,0x73,0xc7},
+{0xcd,0xea,0x53,0xf7}, {0xaa,0x5b,0x5f,0xfd}, {0x6f,0x14,0xdf,0x3d}, {0xdb,0x86,0x78,0x44},
+{0xf3,0x81,0xca,0xaf}, {0xc4,0x3e,0xb9,0x68}, {0x34,0x2c,0x38,0x24}, {0x40,0x5f,0xc2,0xa3},
+{0xc3,0x72,0x16,0x1d}, {0x25,0x0c,0xbc,0xe2}, {0x49,0x8b,0x28,0x3c}, {0x95,0x41,0xff,0x0d},
+{0x01,0x71,0x39,0xa8}, {0xb3,0xde,0x08,0x0c}, {0xe4,0x9c,0xd8,0xb4}, {0xc1,0x90,0x64,0x56},
+{0x84,0x61,0x7b,0xcb}, {0xb6,0x70,0xd5,0x32}, {0x5c,0x74,0x48,0x6c}, {0x57,0x42,0xd0,0xb8}
+	}
+};
+#define	T7	xT7.xt8
+
+static const union xtab xT8 = {
+	.xt8 = {
+{0xf4,0xa7,0x50,0x51}, {0x41,0x65,0x53,0x7e}, {0x17,0xa4,0xc3,0x1a}, {0x27,0x5e,0x96,0x3a},
+{0xab,0x6b,0xcb,0x3b}, {0x9d,0x45,0xf1,0x1f}, {0xfa,0x58,0xab,0xac}, {0xe3,0x03,0x93,0x4b},
+{0x30,0xfa,0x55,0x20}, {0x76,0x6d,0xf6,0xad}, {0xcc,0x76,0x91,0x88}, {0x02,0x4c,0x25,0xf5},
+{0xe5,0xd7,0xfc,0x4f}, {0x2a,0xcb,0xd7,0xc5}, {0x35,0x44,0x80,0x26}, {0x62,0xa3,0x8f,0xb5},
+{0xb1,0x5a,0x49,0xde}, {0xba,0x1b,0x67,0x25}, {0xea,0x0e,0x98,0x45}, {0xfe,0xc0,0xe1,0x5d},
+{0x2f,0x75,0x02,0xc3}, {0x4c,0xf0,0x12,0x81}, {0x46,0x97,0xa3,0x8d}, {0xd3,0xf9,0xc6,0x6b},
+{0x8f,0x5f,0xe7,0x03}, {0x92,0x9c,0x95,0x15}, {0x6d,0x7a,0xeb,0xbf}, {0x52,0x59,0xda,0x95},
+{0xbe,0x83,0x2d,0xd4}, {0x74,0x21,0xd3,0x58}, {0xe0,0x69,0x29,0x49}, {0xc9,0xc8,0x44,0x8e},
+{0xc2,0x89,0x6a,0x75}, {0x8e,0x79,0x78,0xf4}, {0x58,0x3e,0x6b,0x99}, {0xb9,0x71,0xdd,0x27},
+{0xe1,0x4f,0xb6,0xbe}, {0x88,0xad,0x17,0xf0}, {0x20,0xac,0x66,0xc9}, {0xce,0x3a,0xb4,0x7d},
+{0xdf,0x4a,0x18,0x63}, {0x1a,0x31,0x82,0xe5}, {0x51,0x33,0x60,0x97}, {0x53,0x7f,0x45,0x62},
+{0x64,0x77,0xe0,0xb1}, {0x6b,0xae,0x84,0xbb}, {0x81,0xa0,0x1c,0xfe}, {0x08,0x2b,0x94,0xf9},
+{0x48,0x68,0x58,0x70}, {0x45,0xfd,0x19,0x8f}, {0xde,0x6c,0x87,0x94}, {0x7b,0xf8,0xb7,0x52},
+{0x73,0xd3,0x23,0xab}, {0x4b,0x02,0xe2,0x72}, {0x1f,0x8f,0x57,0xe3}, {0x55,0xab,0x2a,0x66},
+{0xeb,0x28,0x07,0xb2}, {0xb5,0xc2,0x03,0x2f}, {0xc5,0x7b,0x9a,0x86}, {0x37,0x08,0xa5,0xd3},
+{0x28,0x87,0xf2,0x30}, {0xbf,0xa5,0xb2,0x23}, {0x03,0x6a,0xba,0x02}, {0x16,0x82,0x5c,0xed},
+{0xcf,0x1c,0x2b,0x8a}, {0x79,0xb4,0x92,0xa7}, {0x07,0xf2,0xf0,0xf3}, {0x69,0xe2,0xa1,0x4e},
+{0xda,0xf4,0xcd,0x65}, {0x05,0xbe,0xd5,0x06}, {0x34,0x62,0x1f,0xd1}, {0xa6,0xfe,0x8a,0xc4},
+{0x2e,0x53,0x9d,0x34}, {0xf3,0x55,0xa0,0xa2}, {0x8a,0xe1,0x32,0x05}, {0xf6,0xeb,0x75,0xa4},
+{0x83,0xec,0x39,0x0b}, {0x60,0xef,0xaa,0x40}, {0x71,0x9f,0x06,0x5e}, {0x6e,0x10,0x51,0xbd},
+{0x21,0x8a,0xf9,0x3e}, {0xdd,0x06,0x3d,0x96}, {0x3e,0x05,0xae,0xdd}, {0xe6,0xbd,0x46,0x4d},
+{0x54,0x8d,0xb5,0x91}, {0xc4,0x5d,0x05,0x71}, {0x06,0xd4,0x6f,0x04}, {0x50,0x15,0xff,0x60},
+{0x98,0xfb,0x24,0x19}, {0xbd,0xe9,0x97,0xd6}, {0x40,0x43,0xcc,0x89}, {0xd9,0x9e,0x77,0x67},
+{0xe8,0x42,0xbd,0xb0}, {0x89,0x8b,0x88,0x07}, {0x19,0x5b,0x38,0xe7}, {0xc8,0xee,0xdb,0x79},
+{0x7c,0x0a,0x47,0xa1}, {0x42,0x0f,0xe9,0x7c}, {0x84,0x1e,0xc9,0xf8}, {0x00,0x00,0x00,0x00},
+{0x80,0x86,0x83,0x09}, {0x2b,0xed,0x48,0x32}, {0x11,0x70,0xac,0x1e}, {0x5a,0x72,0x4e,0x6c},
+{0x0e,0xff,0xfb,0xfd}, {0x85,0x38,0x56,0x0f}, {0xae,0xd5,0x1e,0x3d}, {0x2d,0x39,0x27,0x36},
+{0x0f,0xd9,0x64,0x0a}, {0x5c,0xa6,0x21,0x68}, {0x5b,0x54,0xd1,0x9b}, {0x36,0x2e,0x3a,0x24},
+{0x0a,0x67,0xb1,0x0c}, {0x57,0xe7,0x0f,0x93}, {0xee,0x96,0xd2,0xb4}, {0x9b,0x91,0x9e,0x1b},
+{0xc0,0xc5,0x4f,0x80}, {0xdc,0x20,0xa2,0x61}, {0x77,0x4b,0x69,0x5a}, {0x12,0x1a,0x16,0x1c},
+{0x93,0xba,0x0a,0xe2}, {0xa0,0x2a,0xe5,0xc0}, {0x22,0xe0,0x43,0x3c}, {0x1b,0x17,0x1d,0x12},
+{0x09,0x0d,0x0b,0x0e}, {0x8b,0xc7,0xad,0xf2}, {0xb6,0xa8,0xb9,0x2d}, {0x1e,0xa9,0xc8,0x14},
+{0xf1,0x19,0x85,0x57}, {0x75,0x07,0x4c,0xaf}, {0x99,0xdd,0xbb,0xee}, {0x7f,0x60,0xfd,0xa3},
+{0x01,0x26,0x9f,0xf7}, {0x72,0xf5,0xbc,0x5c}, {0x66,0x3b,0xc5,0x44}, {0xfb,0x7e,0x34,0x5b},
+{0x43,0x29,0x76,0x8b}, {0x23,0xc6,0xdc,0xcb}, {0xed,0xfc,0x68,0xb6}, {0xe4,0xf1,0x63,0xb8},
+{0x31,0xdc,0xca,0xd7}, {0x63,0x85,0x10,0x42}, {0x97,0x22,0x40,0x13}, {0xc6,0x11,0x20,0x84},
+{0x4a,0x24,0x7d,0x85}, {0xbb,0x3d,0xf8,0xd2}, {0xf9,0x32,0x11,0xae}, {0x29,0xa1,0x6d,0xc7},
+{0x9e,0x2f,0x4b,0x1d}, {0xb2,0x30,0xf3,0xdc}, {0x86,0x52,0xec,0x0d}, {0xc1,0xe3,0xd0,0x77},
+{0xb3,0x16,0x6c,0x2b}, {0x70,0xb9,0x99,0xa9}, {0x94,0x48,0xfa,0x11}, {0xe9,0x64,0x22,0x47},
+{0xfc,0x8c,0xc4,0xa8}, {0xf0,0x3f,0x1a,0xa0}, {0x7d,0x2c,0xd8,0x56}, {0x33,0x90,0xef,0x22},
+{0x49,0x4e,0xc7,0x87}, {0x38,0xd1,0xc1,0xd9}, {0xca,0xa2,0xfe,0x8c}, {0xd4,0x0b,0x36,0x98},
+{0xf5,0x81,0xcf,0xa6}, {0x7a,0xde,0x28,0xa5}, {0xb7,0x8e,0x26,0xda}, {0xad,0xbf,0xa4,0x3f},
+{0x3a,0x9d,0xe4,0x2c}, {0x78,0x92,0x0d,0x50}, {0x5f,0xcc,0x9b,0x6a}, {0x7e,0x46,0x62,0x54},
+{0x8d,0x13,0xc2,0xf6}, {0xd8,0xb8,0xe8,0x90}, {0x39,0xf7,0x5e,0x2e}, {0xc3,0xaf,0xf5,0x82},
+{0x5d,0x80,0xbe,0x9f}, {0xd0,0x93,0x7c,0x69}, {0xd5,0x2d,0xa9,0x6f}, {0x25,0x12,0xb3,0xcf},
+{0xac,0x99,0x3b,0xc8}, {0x18,0x7d,0xa7,0x10}, {0x9c,0x63,0x6e,0xe8}, {0x3b,0xbb,0x7b,0xdb},
+{0x26,0x78,0x09,0xcd}, {0x59,0x18,0xf4,0x6e}, {0x9a,0xb7,0x01,0xec}, {0x4f,0x9a,0xa8,0x83},
+{0x95,0x6e,0x65,0xe6}, {0xff,0xe6,0x7e,0xaa}, {0xbc,0xcf,0x08,0x21}, {0x15,0xe8,0xe6,0xef},
+{0xe7,0x9b,0xd9,0xba}, {0x6f,0x36,0xce,0x4a}, {0x9f,0x09,0xd4,0xea}, {0xb0,0x7c,0xd6,0x29},
+{0xa4,0xb2,0xaf,0x31}, {0x3f,0x23,0x31,0x2a}, {0xa5,0x94,0x30,0xc6}, {0xa2,0x66,0xc0,0x35},
+{0x4e,0xbc,0x37,0x74}, {0x82,0xca,0xa6,0xfc}, {0x90,0xd0,0xb0,0xe0}, {0xa7,0xd8,0x15,0x33},
+{0x04,0x98,0x4a,0xf1}, {0xec,0xda,0xf7,0x41}, {0xcd,0x50,0x0e,0x7f}, {0x91,0xf6,0x2f,0x17},
+{0x4d,0xd6,0x8d,0x76}, {0xef,0xb0,0x4d,0x43}, {0xaa,0x4d,0x54,0xcc}, {0x96,0x04,0xdf,0xe4},
+{0xd1,0xb5,0xe3,0x9e}, {0x6a,0x88,0x1b,0x4c}, {0x2c,0x1f,0xb8,0xc1}, {0x65,0x51,0x7f,0x46},
+{0x5e,0xea,0x04,0x9d}, {0x8c,0x35,0x5d,0x01}, {0x87,0x74,0x73,0xfa}, {0x0b,0x41,0x2e,0xfb},
+{0x67,0x1d,0x5a,0xb3}, {0xdb,0xd2,0x52,0x92}, {0x10,0x56,0x33,0xe9}, {0xd6,0x47,0x13,0x6d},
+{0xd7,0x61,0x8c,0x9a}, {0xa1,0x0c,0x7a,0x37}, {0xf8,0x14,0x8e,0x59}, {0x13,0x3c,0x89,0xeb},
+{0xa9,0x27,0xee,0xce}, {0x61,0xc9,0x35,0xb7}, {0x1c,0xe5,0xed,0xe1}, {0x47,0xb1,0x3c,0x7a},
+{0xd2,0xdf,0x59,0x9c}, {0xf2,0x73,0x3f,0x55}, {0x14,0xce,0x79,0x18}, {0xc7,0x37,0xbf,0x73},
+{0xf7,0xcd,0xea,0x53}, {0xfd,0xaa,0x5b,0x5f}, {0x3d,0x6f,0x14,0xdf}, {0x44,0xdb,0x86,0x78},
+{0xaf,0xf3,0x81,0xca}, {0x68,0xc4,0x3e,0xb9}, {0x24,0x34,0x2c,0x38}, {0xa3,0x40,0x5f,0xc2},
+{0x1d,0xc3,0x72,0x16}, {0xe2,0x25,0x0c,0xbc}, {0x3c,0x49,0x8b,0x28}, {0x0d,0x95,0x41,0xff},
+{0xa8,0x01,0x71,0x39}, {0x0c,0xb3,0xde,0x08}, {0xb4,0xe4,0x9c,0xd8}, {0x56,0xc1,0x90,0x64},
+{0xcb,0x84,0x61,0x7b}, {0x32,0xb6,0x70,0xd5}, {0x6c,0x5c,0x74,0x48}, {0xb8,0x57,0x42,0xd0}
+	}
+};
+#define	T8	xT8.xt8
+
+static const word8 S5[256] = {
+0x52,0x09,0x6a,0xd5,
+0x30,0x36,0xa5,0x38,
+0xbf,0x40,0xa3,0x9e,
+0x81,0xf3,0xd7,0xfb,
+0x7c,0xe3,0x39,0x82,
+0x9b,0x2f,0xff,0x87,
+0x34,0x8e,0x43,0x44,
+0xc4,0xde,0xe9,0xcb,
+0x54,0x7b,0x94,0x32,
+0xa6,0xc2,0x23,0x3d,
+0xee,0x4c,0x95,0x0b,
+0x42,0xfa,0xc3,0x4e,
+0x08,0x2e,0xa1,0x66,
+0x28,0xd9,0x24,0xb2,
+0x76,0x5b,0xa2,0x49,
+0x6d,0x8b,0xd1,0x25,
+0x72,0xf8,0xf6,0x64,
+0x86,0x68,0x98,0x16,
+0xd4,0xa4,0x5c,0xcc,
+0x5d,0x65,0xb6,0x92,
+0x6c,0x70,0x48,0x50,
+0xfd,0xed,0xb9,0xda,
+0x5e,0x15,0x46,0x57,
+0xa7,0x8d,0x9d,0x84,
+0x90,0xd8,0xab,0x00,
+0x8c,0xbc,0xd3,0x0a,
+0xf7,0xe4,0x58,0x05,
+0xb8,0xb3,0x45,0x06,
+0xd0,0x2c,0x1e,0x8f,
+0xca,0x3f,0x0f,0x02,
+0xc1,0xaf,0xbd,0x03,
+0x01,0x13,0x8a,0x6b,
+0x3a,0x91,0x11,0x41,
+0x4f,0x67,0xdc,0xea,
+0x97,0xf2,0xcf,0xce,
+0xf0,0xb4,0xe6,0x73,
+0x96,0xac,0x74,0x22,
+0xe7,0xad,0x35,0x85,
+0xe2,0xf9,0x37,0xe8,
+0x1c,0x75,0xdf,0x6e,
+0x47,0xf1,0x1a,0x71,
+0x1d,0x29,0xc5,0x89,
+0x6f,0xb7,0x62,0x0e,
+0xaa,0x18,0xbe,0x1b,
+0xfc,0x56,0x3e,0x4b,
+0xc6,0xd2,0x79,0x20,
+0x9a,0xdb,0xc0,0xfe,
+0x78,0xcd,0x5a,0xf4,
+0x1f,0xdd,0xa8,0x33,
+0x88,0x07,0xc7,0x31,
+0xb1,0x12,0x10,0x59,
+0x27,0x80,0xec,0x5f,
+0x60,0x51,0x7f,0xa9,
+0x19,0xb5,0x4a,0x0d,
+0x2d,0xe5,0x7a,0x9f,
+0x93,0xc9,0x9c,0xef,
+0xa0,0xe0,0x3b,0x4d,
+0xae,0x2a,0xf5,0xb0,
+0xc8,0xeb,0xbb,0x3c,
+0x83,0x53,0x99,0x61,
+0x17,0x2b,0x04,0x7e,
+0xba,0x77,0xd6,0x26,
+0xe1,0x69,0x14,0x63,
+0x55,0x21,0x0c,0x7d
+};
+
+static const union xtab xU1 = {
+	.xt8 = {
+{0x00,0x00,0x00,0x00}, {0x0e,0x09,0x0d,0x0b}, {0x1c,0x12,0x1a,0x16}, {0x12,0x1b,0x17,0x1d},
+{0x38,0x24,0x34,0x2c}, {0x36,0x2d,0x39,0x27}, {0x24,0x36,0x2e,0x3a}, {0x2a,0x3f,0x23,0x31},
+{0x70,0x48,0x68,0x58}, {0x7e,0x41,0x65,0x53}, {0x6c,0x5a,0x72,0x4e}, {0x62,0x53,0x7f,0x45},
+{0x48,0x6c,0x5c,0x74}, {0x46,0x65,0x51,0x7f}, {0x54,0x7e,0x46,0x62}, {0x5a,0x77,0x4b,0x69},
+{0xe0,0x90,0xd0,0xb0}, {0xee,0x99,0xdd,0xbb}, {0xfc,0x82,0xca,0xa6}, {0xf2,0x8b,0xc7,0xad},
+{0xd8,0xb4,0xe4,0x9c}, {0xd6,0xbd,0xe9,0x97}, {0xc4,0xa6,0xfe,0x8a}, {0xca,0xaf,0xf3,0x81},
+{0x90,0xd8,0xb8,0xe8}, {0x9e,0xd1,0xb5,0xe3}, {0x8c,0xca,0xa2,0xfe}, {0x82,0xc3,0xaf,0xf5},
+{0xa8,0xfc,0x8c,0xc4}, {0xa6,0xf5,0x81,0xcf}, {0xb4,0xee,0x96,0xd2}, {0xba,0xe7,0x9b,0xd9},
+{0xdb,0x3b,0xbb,0x7b}, {0xd5,0x32,0xb6,0x70}, {0xc7,0x29,0xa1,0x6d}, {0xc9,0x20,0xac,0x66},
+{0xe3,0x1f,0x8f,0x57}, {0xed,0x16,0x82,0x5c}, {0xff,0x0d,0x95,0x41}, {0xf1,0x04,0x98,0x4a},
+{0xab,0x73,0xd3,0x23}, {0xa5,0x7a,0xde,0x28}, {0xb7,0x61,0xc9,0x35}, {0xb9,0x68,0xc4,0x3e},
+{0x93,0x57,0xe7,0x0f}, {0x9d,0x5e,0xea,0x04}, {0x8f,0x45,0xfd,0x19}, {0x81,0x4c,0xf0,0x12},
+{0x3b,0xab,0x6b,0xcb}, {0x35,0xa2,0x66,0xc0}, {0x27,0xb9,0x71,0xdd}, {0x29,0xb0,0x7c,0xd6},
+{0x03,0x8f,0x5f,0xe7}, {0x0d,0x86,0x52,0xec}, {0x1f,0x9d,0x45,0xf1}, {0x11,0x94,0x48,0xfa},
+{0x4b,0xe3,0x03,0x93}, {0x45,0xea,0x0e,0x98}, {0x57,0xf1,0x19,0x85}, {0x59,0xf8,0x14,0x8e},
+{0x73,0xc7,0x37,0xbf}, {0x7d,0xce,0x3a,0xb4}, {0x6f,0xd5,0x2d,0xa9}, {0x61,0xdc,0x20,0xa2},
+{0xad,0x76,0x6d,0xf6}, {0xa3,0x7f,0x60,0xfd}, {0xb1,0x64,0x77,0xe0}, {0xbf,0x6d,0x7a,0xeb},
+{0x95,0x52,0x59,0xda}, {0x9b,0x5b,0x54,0xd1}, {0x89,0x40,0x43,0xcc}, {0x87,0x49,0x4e,0xc7},
+{0xdd,0x3e,0x05,0xae}, {0xd3,0x37,0x08,0xa5}, {0xc1,0x2c,0x1f,0xb8}, {0xcf,0x25,0x12,0xb3},
+{0xe5,0x1a,0x31,0x82}, {0xeb,0x13,0x3c,0x89}, {0xf9,0x08,0x2b,0x94}, {0xf7,0x01,0x26,0x9f},
+{0x4d,0xe6,0xbd,0x46}, {0x43,0xef,0xb0,0x4d}, {0x51,0xf4,0xa7,0x50}, {0x5f,0xfd,0xaa,0x5b},
+{0x75,0xc2,0x89,0x6a}, {0x7b,0xcb,0x84,0x61}, {0x69,0xd0,0x93,0x7c}, {0x67,0xd9,0x9e,0x77},
+{0x3d,0xae,0xd5,0x1e}, {0x33,0xa7,0xd8,0x15}, {0x21,0xbc,0xcf,0x08}, {0x2f,0xb5,0xc2,0x03},
+{0x05,0x8a,0xe1,0x32}, {0x0b,0x83,0xec,0x39}, {0x19,0x98,0xfb,0x24}, {0x17,0x91,0xf6,0x2f},
+{0x76,0x4d,0xd6,0x8d}, {0x78,0x44,0xdb,0x86}, {0x6a,0x5f,0xcc,0x9b}, {0x64,0x56,0xc1,0x90},
+{0x4e,0x69,0xe2,0xa1}, {0x40,0x60,0xef,0xaa}, {0x52,0x7b,0xf8,0xb7}, {0x5c,0x72,0xf5,0xbc},
+{0x06,0x05,0xbe,0xd5}, {0x08,0x0c,0xb3,0xde}, {0x1a,0x17,0xa4,0xc3}, {0x14,0x1e,0xa9,0xc8},
+{0x3e,0x21,0x8a,0xf9}, {0x30,0x28,0x87,0xf2}, {0x22,0x33,0x90,0xef}, {0x2c,0x3a,0x9d,0xe4},
+{0x96,0xdd,0x06,0x3d}, {0x98,0xd4,0x0b,0x36}, {0x8a,0xcf,0x1c,0x2b}, {0x84,0xc6,0x11,0x20},
+{0xae,0xf9,0x32,0x11}, {0xa0,0xf0,0x3f,0x1a}, {0xb2,0xeb,0x28,0x07}, {0xbc,0xe2,0x25,0x0c},
+{0xe6,0x95,0x6e,0x65}, {0xe8,0x9c,0x63,0x6e}, {0xfa,0x87,0x74,0x73}, {0xf4,0x8e,0x79,0x78},
+{0xde,0xb1,0x5a,0x49}, {0xd0,0xb8,0x57,0x42}, {0xc2,0xa3,0x40,0x5f}, {0xcc,0xaa,0x4d,0x54},
+{0x41,0xec,0xda,0xf7}, {0x4f,0xe5,0xd7,0xfc}, {0x5d,0xfe,0xc0,0xe1}, {0x53,0xf7,0xcd,0xea},
+{0x79,0xc8,0xee,0xdb}, {0x77,0xc1,0xe3,0xd0}, {0x65,0xda,0xf4,0xcd}, {0x6b,0xd3,0xf9,0xc6},
+{0x31,0xa4,0xb2,0xaf}, {0x3f,0xad,0xbf,0xa4}, {0x2d,0xb6,0xa8,0xb9}, {0x23,0xbf,0xa5,0xb2},
+{0x09,0x80,0x86,0x83}, {0x07,0x89,0x8b,0x88}, {0x15,0x92,0x9c,0x95}, {0x1b,0x9b,0x91,0x9e},
+{0xa1,0x7c,0x0a,0x47}, {0xaf,0x75,0x07,0x4c}, {0xbd,0x6e,0x10,0x51}, {0xb3,0x67,0x1d,0x5a},
+{0x99,0x58,0x3e,0x6b}, {0x97,0x51,0x33,0x60}, {0x85,0x4a,0x24,0x7d}, {0x8b,0x43,0x29,0x76},
+{0xd1,0x34,0x62,0x1f}, {0xdf,0x3d,0x6f,0x14}, {0xcd,0x26,0x78,0x09}, {0xc3,0x2f,0x75,0x02},
+{0xe9,0x10,0x56,0x33}, {0xe7,0x19,0x5b,0x38}, {0xf5,0x02,0x4c,0x25}, {0xfb,0x0b,0x41,0x2e},
+{0x9a,0xd7,0x61,0x8c}, {0x94,0xde,0x6c,0x87}, {0x86,0xc5,0x7b,0x9a}, {0x88,0xcc,0x76,0x91},
+{0xa2,0xf3,0x55,0xa0}, {0xac,0xfa,0x58,0xab}, {0xbe,0xe1,0x4f,0xb6}, {0xb0,0xe8,0x42,0xbd},
+{0xea,0x9f,0x09,0xd4}, {0xe4,0x96,0x04,0xdf}, {0xf6,0x8d,0x13,0xc2}, {0xf8,0x84,0x1e,0xc9},
+{0xd2,0xbb,0x3d,0xf8}, {0xdc,0xb2,0x30,0xf3}, {0xce,0xa9,0x27,0xee}, {0xc0,0xa0,0x2a,0xe5},
+{0x7a,0x47,0xb1,0x3c}, {0x74,0x4e,0xbc,0x37}, {0x66,0x55,0xab,0x2a}, {0x68,0x5c,0xa6,0x21},
+{0x42,0x63,0x85,0x10}, {0x4c,0x6a,0x88,0x1b}, {0x5e,0x71,0x9f,0x06}, {0x50,0x78,0x92,0x0d},
+{0x0a,0x0f,0xd9,0x64}, {0x04,0x06,0xd4,0x6f}, {0x16,0x1d,0xc3,0x72}, {0x18,0x14,0xce,0x79},
+{0x32,0x2b,0xed,0x48}, {0x3c,0x22,0xe0,0x43}, {0x2e,0x39,0xf7,0x5e}, {0x20,0x30,0xfa,0x55},
+{0xec,0x9a,0xb7,0x01}, {0xe2,0x93,0xba,0x0a}, {0xf0,0x88,0xad,0x17}, {0xfe,0x81,0xa0,0x1c},
+{0xd4,0xbe,0x83,0x2d}, {0xda,0xb7,0x8e,0x26}, {0xc8,0xac,0x99,0x3b}, {0xc6,0xa5,0x94,0x30},
+{0x9c,0xd2,0xdf,0x59}, {0x92,0xdb,0xd2,0x52}, {0x80,0xc0,0xc5,0x4f}, {0x8e,0xc9,0xc8,0x44},
+{0xa4,0xf6,0xeb,0x75}, {0xaa,0xff,0xe6,0x7e}, {0xb8,0xe4,0xf1,0x63}, {0xb6,0xed,0xfc,0x68},
+{0x0c,0x0a,0x67,0xb1}, {0x02,0x03,0x6a,0xba}, {0x10,0x18,0x7d,0xa7}, {0x1e,0x11,0x70,0xac},
+{0x34,0x2e,0x53,0x9d}, {0x3a,0x27,0x5e,0x96}, {0x28,0x3c,0x49,0x8b}, {0x26,0x35,0x44,0x80},
+{0x7c,0x42,0x0f,0xe9}, {0x72,0x4b,0x02,0xe2}, {0x60,0x50,0x15,0xff}, {0x6e,0x59,0x18,0xf4},
+{0x44,0x66,0x3b,0xc5}, {0x4a,0x6f,0x36,0xce}, {0x58,0x74,0x21,0xd3}, {0x56,0x7d,0x2c,0xd8},
+{0x37,0xa1,0x0c,0x7a}, {0x39,0xa8,0x01,0x71}, {0x2b,0xb3,0x16,0x6c}, {0x25,0xba,0x1b,0x67},
+{0x0f,0x85,0x38,0x56}, {0x01,0x8c,0x35,0x5d}, {0x13,0x97,0x22,0x40}, {0x1d,0x9e,0x2f,0x4b},
+{0x47,0xe9,0x64,0x22}, {0x49,0xe0,0x69,0x29}, {0x5b,0xfb,0x7e,0x34}, {0x55,0xf2,0x73,0x3f},
+{0x7f,0xcd,0x50,0x0e}, {0x71,0xc4,0x5d,0x05}, {0x63,0xdf,0x4a,0x18}, {0x6d,0xd6,0x47,0x13},
+{0xd7,0x31,0xdc,0xca}, {0xd9,0x38,0xd1,0xc1}, {0xcb,0x23,0xc6,0xdc}, {0xc5,0x2a,0xcb,0xd7},
+{0xef,0x15,0xe8,0xe6}, {0xe1,0x1c,0xe5,0xed}, {0xf3,0x07,0xf2,0xf0}, {0xfd,0x0e,0xff,0xfb},
+{0xa7,0x79,0xb4,0x92}, {0xa9,0x70,0xb9,0x99}, {0xbb,0x6b,0xae,0x84}, {0xb5,0x62,0xa3,0x8f},
+{0x9f,0x5d,0x80,0xbe}, {0x91,0x54,0x8d,0xb5}, {0x83,0x4f,0x9a,0xa8}, {0x8d,0x46,0x97,0xa3}
+	}
+};
+#define	U1	xU1.xt8
+
+static const union xtab xU2 = {
+	.xt8 = {
+{0x00,0x00,0x00,0x00}, {0x0b,0x0e,0x09,0x0d}, {0x16,0x1c,0x12,0x1a}, {0x1d,0x12,0x1b,0x17},
+{0x2c,0x38,0x24,0x34}, {0x27,0x36,0x2d,0x39}, {0x3a,0x24,0x36,0x2e}, {0x31,0x2a,0x3f,0x23},
+{0x58,0x70,0x48,0x68}, {0x53,0x7e,0x41,0x65}, {0x4e,0x6c,0x5a,0x72}, {0x45,0x62,0x53,0x7f},
+{0x74,0x48,0x6c,0x5c}, {0x7f,0x46,0x65,0x51}, {0x62,0x54,0x7e,0x46}, {0x69,0x5a,0x77,0x4b},
+{0xb0,0xe0,0x90,0xd0}, {0xbb,0xee,0x99,0xdd}, {0xa6,0xfc,0x82,0xca}, {0xad,0xf2,0x8b,0xc7},
+{0x9c,0xd8,0xb4,0xe4}, {0x97,0xd6,0xbd,0xe9}, {0x8a,0xc4,0xa6,0xfe}, {0x81,0xca,0xaf,0xf3},
+{0xe8,0x90,0xd8,0xb8}, {0xe3,0x9e,0xd1,0xb5}, {0xfe,0x8c,0xca,0xa2}, {0xf5,0x82,0xc3,0xaf},
+{0xc4,0xa8,0xfc,0x8c}, {0xcf,0xa6,0xf5,0x81}, {0xd2,0xb4,0xee,0x96}, {0xd9,0xba,0xe7,0x9b},
+{0x7b,0xdb,0x3b,0xbb}, {0x70,0xd5,0x32,0xb6}, {0x6d,0xc7,0x29,0xa1}, {0x66,0xc9,0x20,0xac},
+{0x57,0xe3,0x1f,0x8f}, {0x5c,0xed,0x16,0x82}, {0x41,0xff,0x0d,0x95}, {0x4a,0xf1,0x04,0x98},
+{0x23,0xab,0x73,0xd3}, {0x28,0xa5,0x7a,0xde}, {0x35,0xb7,0x61,0xc9}, {0x3e,0xb9,0x68,0xc4},
+{0x0f,0x93,0x57,0xe7}, {0x04,0x9d,0x5e,0xea}, {0x19,0x8f,0x45,0xfd}, {0x12,0x81,0x4c,0xf0},
+{0xcb,0x3b,0xab,0x6b}, {0xc0,0x35,0xa2,0x66}, {0xdd,0x27,0xb9,0x71}, {0xd6,0x29,0xb0,0x7c},
+{0xe7,0x03,0x8f,0x5f}, {0xec,0x0d,0x86,0x52}, {0xf1,0x1f,0x9d,0x45}, {0xfa,0x11,0x94,0x48},
+{0x93,0x4b,0xe3,0x03}, {0x98,0x45,0xea,0x0e}, {0x85,0x57,0xf1,0x19}, {0x8e,0x59,0xf8,0x14},
+{0xbf,0x73,0xc7,0x37}, {0xb4,0x7d,0xce,0x3a}, {0xa9,0x6f,0xd5,0x2d}, {0xa2,0x61,0xdc,0x20},
+{0xf6,0xad,0x76,0x6d}, {0xfd,0xa3,0x7f,0x60}, {0xe0,0xb1,0x64,0x77}, {0xeb,0xbf,0x6d,0x7a},
+{0xda,0x95,0x52,0x59}, {0xd1,0x9b,0x5b,0x54}, {0xcc,0x89,0x40,0x43}, {0xc7,0x87,0x49,0x4e},
+{0xae,0xdd,0x3e,0x05}, {0xa5,0xd3,0x37,0x08}, {0xb8,0xc1,0x2c,0x1f}, {0xb3,0xcf,0x25,0x12},
+{0x82,0xe5,0x1a,0x31}, {0x89,0xeb,0x13,0x3c}, {0x94,0xf9,0x08,0x2b}, {0x9f,0xf7,0x01,0x26},
+{0x46,0x4d,0xe6,0xbd}, {0x4d,0x43,0xef,0xb0}, {0x50,0x51,0xf4,0xa7}, {0x5b,0x5f,0xfd,0xaa},
+{0x6a,0x75,0xc2,0x89}, {0x61,0x7b,0xcb,0x84}, {0x7c,0x69,0xd0,0x93}, {0x77,0x67,0xd9,0x9e},
+{0x1e,0x3d,0xae,0xd5}, {0x15,0x33,0xa7,0xd8}, {0x08,0x21,0xbc,0xcf}, {0x03,0x2f,0xb5,0xc2},
+{0x32,0x05,0x8a,0xe1}, {0x39,0x0b,0x83,0xec}, {0x24,0x19,0x98,0xfb}, {0x2f,0x17,0x91,0xf6},
+{0x8d,0x76,0x4d,0xd6}, {0x86,0x78,0x44,0xdb}, {0x9b,0x6a,0x5f,0xcc}, {0x90,0x64,0x56,0xc1},
+{0xa1,0x4e,0x69,0xe2}, {0xaa,0x40,0x60,0xef}, {0xb7,0x52,0x7b,0xf8}, {0xbc,0x5c,0x72,0xf5},
+{0xd5,0x06,0x05,0xbe}, {0xde,0x08,0x0c,0xb3}, {0xc3,0x1a,0x17,0xa4}, {0xc8,0x14,0x1e,0xa9},
+{0xf9,0x3e,0x21,0x8a}, {0xf2,0x30,0x28,0x87}, {0xef,0x22,0x33,0x90}, {0xe4,0x2c,0x3a,0x9d},
+{0x3d,0x96,0xdd,0x06}, {0x36,0x98,0xd4,0x0b}, {0x2b,0x8a,0xcf,0x1c}, {0x20,0x84,0xc6,0x11},
+{0x11,0xae,0xf9,0x32}, {0x1a,0xa0,0xf0,0x3f}, {0x07,0xb2,0xeb,0x28}, {0x0c,0xbc,0xe2,0x25},
+{0x65,0xe6,0x95,0x6e}, {0x6e,0xe8,0x9c,0x63}, {0x73,0xfa,0x87,0x74}, {0x78,0xf4,0x8e,0x79},
+{0x49,0xde,0xb1,0x5a}, {0x42,0xd0,0xb8,0x57}, {0x5f,0xc2,0xa3,0x40}, {0x54,0xcc,0xaa,0x4d},
+{0xf7,0x41,0xec,0xda}, {0xfc,0x4f,0xe5,0xd7}, {0xe1,0x5d,0xfe,0xc0}, {0xea,0x53,0xf7,0xcd},
+{0xdb,0x79,0xc8,0xee}, {0xd0,0x77,0xc1,0xe3}, {0xcd,0x65,0xda,0xf4}, {0xc6,0x6b,0xd3,0xf9},
+{0xaf,0x31,0xa4,0xb2}, {0xa4,0x3f,0xad,0xbf}, {0xb9,0x2d,0xb6,0xa8}, {0xb2,0x23,0xbf,0xa5},
+{0x83,0x09,0x80,0x86}, {0x88,0x07,0x89,0x8b}, {0x95,0x15,0x92,0x9c}, {0x9e,0x1b,0x9b,0x91},
+{0x47,0xa1,0x7c,0x0a}, {0x4c,0xaf,0x75,0x07}, {0x51,0xbd,0x6e,0x10}, {0x5a,0xb3,0x67,0x1d},
+{0x6b,0x99,0x58,0x3e}, {0x60,0x97,0x51,0x33}, {0x7d,0x85,0x4a,0x24}, {0x76,0x8b,0x43,0x29},
+{0x1f,0xd1,0x34,0x62}, {0x14,0xdf,0x3d,0x6f}, {0x09,0xcd,0x26,0x78}, {0x02,0xc3,0x2f,0x75},
+{0x33,0xe9,0x10,0x56}, {0x38,0xe7,0x19,0x5b}, {0x25,0xf5,0x02,0x4c}, {0x2e,0xfb,0x0b,0x41},
+{0x8c,0x9a,0xd7,0x61}, {0x87,0x94,0xde,0x6c}, {0x9a,0x86,0xc5,0x7b}, {0x91,0x88,0xcc,0x76},
+{0xa0,0xa2,0xf3,0x55}, {0xab,0xac,0xfa,0x58}, {0xb6,0xbe,0xe1,0x4f}, {0xbd,0xb0,0xe8,0x42},
+{0xd4,0xea,0x9f,0x09}, {0xdf,0xe4,0x96,0x04}, {0xc2,0xf6,0x8d,0x13}, {0xc9,0xf8,0x84,0x1e},
+{0xf8,0xd2,0xbb,0x3d}, {0xf3,0xdc,0xb2,0x30}, {0xee,0xce,0xa9,0x27}, {0xe5,0xc0,0xa0,0x2a},
+{0x3c,0x7a,0x47,0xb1}, {0x37,0x74,0x4e,0xbc}, {0x2a,0x66,0x55,0xab}, {0x21,0x68,0x5c,0xa6},
+{0x10,0x42,0x63,0x85}, {0x1b,0x4c,0x6a,0x88}, {0x06,0x5e,0x71,0x9f}, {0x0d,0x50,0x78,0x92},
+{0x64,0x0a,0x0f,0xd9}, {0x6f,0x04,0x06,0xd4}, {0x72,0x16,0x1d,0xc3}, {0x79,0x18,0x14,0xce},
+{0x48,0x32,0x2b,0xed}, {0x43,0x3c,0x22,0xe0}, {0x5e,0x2e,0x39,0xf7}, {0x55,0x20,0x30,0xfa},
+{0x01,0xec,0x9a,0xb7}, {0x0a,0xe2,0x93,0xba}, {0x17,0xf0,0x88,0xad}, {0x1c,0xfe,0x81,0xa0},
+{0x2d,0xd4,0xbe,0x83}, {0x26,0xda,0xb7,0x8e}, {0x3b,0xc8,0xac,0x99}, {0x30,0xc6,0xa5,0x94},
+{0x59,0x9c,0xd2,0xdf}, {0x52,0x92,0xdb,0xd2}, {0x4f,0x80,0xc0,0xc5}, {0x44,0x8e,0xc9,0xc8},
+{0x75,0xa4,0xf6,0xeb}, {0x7e,0xaa,0xff,0xe6}, {0x63,0xb8,0xe4,0xf1}, {0x68,0xb6,0xed,0xfc},
+{0xb1,0x0c,0x0a,0x67}, {0xba,0x02,0x03,0x6a}, {0xa7,0x10,0x18,0x7d}, {0xac,0x1e,0x11,0x70},
+{0x9d,0x34,0x2e,0x53}, {0x96,0x3a,0x27,0x5e}, {0x8b,0x28,0x3c,0x49}, {0x80,0x26,0x35,0x44},
+{0xe9,0x7c,0x42,0x0f}, {0xe2,0x72,0x4b,0x02}, {0xff,0x60,0x50,0x15}, {0xf4,0x6e,0x59,0x18},
+{0xc5,0x44,0x66,0x3b}, {0xce,0x4a,0x6f,0x36}, {0xd3,0x58,0x74,0x21}, {0xd8,0x56,0x7d,0x2c},
+{0x7a,0x37,0xa1,0x0c}, {0x71,0x39,0xa8,0x01}, {0x6c,0x2b,0xb3,0x16}, {0x67,0x25,0xba,0x1b},
+{0x56,0x0f,0x85,0x38}, {0x5d,0x01,0x8c,0x35}, {0x40,0x13,0x97,0x22}, {0x4b,0x1d,0x9e,0x2f},
+{0x22,0x47,0xe9,0x64}, {0x29,0x49,0xe0,0x69}, {0x34,0x5b,0xfb,0x7e}, {0x3f,0x55,0xf2,0x73},
+{0x0e,0x7f,0xcd,0x50}, {0x05,0x71,0xc4,0x5d}, {0x18,0x63,0xdf,0x4a}, {0x13,0x6d,0xd6,0x47},
+{0xca,0xd7,0x31,0xdc}, {0xc1,0xd9,0x38,0xd1}, {0xdc,0xcb,0x23,0xc6}, {0xd7,0xc5,0x2a,0xcb},
+{0xe6,0xef,0x15,0xe8}, {0xed,0xe1,0x1c,0xe5}, {0xf0,0xf3,0x07,0xf2}, {0xfb,0xfd,0x0e,0xff},
+{0x92,0xa7,0x79,0xb4}, {0x99,0xa9,0x70,0xb9}, {0x84,0xbb,0x6b,0xae}, {0x8f,0xb5,0x62,0xa3},
+{0xbe,0x9f,0x5d,0x80}, {0xb5,0x91,0x54,0x8d}, {0xa8,0x83,0x4f,0x9a}, {0xa3,0x8d,0x46,0x97}
+	}
+};
+#define	U2	xU2.xt8
+
+static const union xtab xU3 = {
+	.xt8 = {
+{0x00,0x00,0x00,0x00}, {0x0d,0x0b,0x0e,0x09}, {0x1a,0x16,0x1c,0x12}, {0x17,0x1d,0x12,0x1b},
+{0x34,0x2c,0x38,0x24}, {0x39,0x27,0x36,0x2d}, {0x2e,0x3a,0x24,0x36}, {0x23,0x31,0x2a,0x3f},
+{0x68,0x58,0x70,0x48}, {0x65,0x53,0x7e,0x41}, {0x72,0x4e,0x6c,0x5a}, {0x7f,0x45,0x62,0x53},
+{0x5c,0x74,0x48,0x6c}, {0x51,0x7f,0x46,0x65}, {0x46,0x62,0x54,0x7e}, {0x4b,0x69,0x5a,0x77},
+{0xd0,0xb0,0xe0,0x90}, {0xdd,0xbb,0xee,0x99}, {0xca,0xa6,0xfc,0x82}, {0xc7,0xad,0xf2,0x8b},
+{0xe4,0x9c,0xd8,0xb4}, {0xe9,0x97,0xd6,0xbd}, {0xfe,0x8a,0xc4,0xa6}, {0xf3,0x81,0xca,0xaf},
+{0xb8,0xe8,0x90,0xd8}, {0xb5,0xe3,0x9e,0xd1}, {0xa2,0xfe,0x8c,0xca}, {0xaf,0xf5,0x82,0xc3},
+{0x8c,0xc4,0xa8,0xfc}, {0x81,0xcf,0xa6,0xf5}, {0x96,0xd2,0xb4,0xee}, {0x9b,0xd9,0xba,0xe7},
+{0xbb,0x7b,0xdb,0x3b}, {0xb6,0x70,0xd5,0x32}, {0xa1,0x6d,0xc7,0x29}, {0xac,0x66,0xc9,0x20},
+{0x8f,0x57,0xe3,0x1f}, {0x82,0x5c,0xed,0x16}, {0x95,0x41,0xff,0x0d}, {0x98,0x4a,0xf1,0x04},
+{0xd3,0x23,0xab,0x73}, {0xde,0x28,0xa5,0x7a}, {0xc9,0x35,0xb7,0x61}, {0xc4,0x3e,0xb9,0x68},
+{0xe7,0x0f,0x93,0x57}, {0xea,0x04,0x9d,0x5e}, {0xfd,0x19,0x8f,0x45}, {0xf0,0x12,0x81,0x4c},
+{0x6b,0xcb,0x3b,0xab}, {0x66,0xc0,0x35,0xa2}, {0x71,0xdd,0x27,0xb9}, {0x7c,0xd6,0x29,0xb0},
+{0x5f,0xe7,0x03,0x8f}, {0x52,0xec,0x0d,0x86}, {0x45,0xf1,0x1f,0x9d}, {0x48,0xfa,0x11,0x94},
+{0x03,0x93,0x4b,0xe3}, {0x0e,0x98,0x45,0xea}, {0x19,0x85,0x57,0xf1}, {0x14,0x8e,0x59,0xf8},
+{0x37,0xbf,0x73,0xc7}, {0x3a,0xb4,0x7d,0xce}, {0x2d,0xa9,0x6f,0xd5}, {0x20,0xa2,0x61,0xdc},
+{0x6d,0xf6,0xad,0x76}, {0x60,0xfd,0xa3,0x7f}, {0x77,0xe0,0xb1,0x64}, {0x7a,0xeb,0xbf,0x6d},
+{0x59,0xda,0x95,0x52}, {0x54,0xd1,0x9b,0x5b}, {0x43,0xcc,0x89,0x40}, {0x4e,0xc7,0x87,0x49},
+{0x05,0xae,0xdd,0x3e}, {0x08,0xa5,0xd3,0x37}, {0x1f,0xb8,0xc1,0x2c}, {0x12,0xb3,0xcf,0x25},
+{0x31,0x82,0xe5,0x1a}, {0x3c,0x89,0xeb,0x13}, {0x2b,0x94,0xf9,0x08}, {0x26,0x9f,0xf7,0x01},
+{0xbd,0x46,0x4d,0xe6}, {0xb0,0x4d,0x43,0xef}, {0xa7,0x50,0x51,0xf4}, {0xaa,0x5b,0x5f,0xfd},
+{0x89,0x6a,0x75,0xc2}, {0x84,0x61,0x7b,0xcb}, {0x93,0x7c,0x69,0xd0}, {0x9e,0x77,0x67,0xd9},
+{0xd5,0x1e,0x3d,0xae}, {0xd8,0x15,0x33,0xa7}, {0xcf,0x08,0x21,0xbc}, {0xc2,0x03,0x2f,0xb5},
+{0xe1,0x32,0x05,0x8a}, {0xec,0x39,0x0b,0x83}, {0xfb,0x24,0x19,0x98}, {0xf6,0x2f,0x17,0x91},
+{0xd6,0x8d,0x76,0x4d}, {0xdb,0x86,0x78,0x44}, {0xcc,0x9b,0x6a,0x5f}, {0xc1,0x90,0x64,0x56},
+{0xe2,0xa1,0x4e,0x69}, {0xef,0xaa,0x40,0x60}, {0xf8,0xb7,0x52,0x7b}, {0xf5,0xbc,0x5c,0x72},
+{0xbe,0xd5,0x06,0x05}, {0xb3,0xde,0x08,0x0c}, {0xa4,0xc3,0x1a,0x17}, {0xa9,0xc8,0x14,0x1e},
+{0x8a,0xf9,0x3e,0x21}, {0x87,0xf2,0x30,0x28}, {0x90,0xef,0x22,0x33}, {0x9d,0xe4,0x2c,0x3a},
+{0x06,0x3d,0x96,0xdd}, {0x0b,0x36,0x98,0xd4}, {0x1c,0x2b,0x8a,0xcf}, {0x11,0x20,0x84,0xc6},
+{0x32,0x11,0xae,0xf9}, {0x3f,0x1a,0xa0,0xf0}, {0x28,0x07,0xb2,0xeb}, {0x25,0x0c,0xbc,0xe2},
+{0x6e,0x65,0xe6,0x95}, {0x63,0x6e,0xe8,0x9c}, {0x74,0x73,0xfa,0x87}, {0x79,0x78,0xf4,0x8e},
+{0x5a,0x49,0xde,0xb1}, {0x57,0x42,0xd0,0xb8}, {0x40,0x5f,0xc2,0xa3}, {0x4d,0x54,0xcc,0xaa},
+{0xda,0xf7,0x41,0xec}, {0xd7,0xfc,0x4f,0xe5}, {0xc0,0xe1,0x5d,0xfe}, {0xcd,0xea,0x53,0xf7},
+{0xee,0xdb,0x79,0xc8}, {0xe3,0xd0,0x77,0xc1}, {0xf4,0xcd,0x65,0xda}, {0xf9,0xc6,0x6b,0xd3},
+{0xb2,0xaf,0x31,0xa4}, {0xbf,0xa4,0x3f,0xad}, {0xa8,0xb9,0x2d,0xb6}, {0xa5,0xb2,0x23,0xbf},
+{0x86,0x83,0x09,0x80}, {0x8b,0x88,0x07,0x89}, {0x9c,0x95,0x15,0x92}, {0x91,0x9e,0x1b,0x9b},
+{0x0a,0x47,0xa1,0x7c}, {0x07,0x4c,0xaf,0x75}, {0x10,0x51,0xbd,0x6e}, {0x1d,0x5a,0xb3,0x67},
+{0x3e,0x6b,0x99,0x58}, {0x33,0x60,0x97,0x51}, {0x24,0x7d,0x85,0x4a}, {0x29,0x76,0x8b,0x43},
+{0x62,0x1f,0xd1,0x34}, {0x6f,0x14,0xdf,0x3d}, {0x78,0x09,0xcd,0x26}, {0x75,0x02,0xc3,0x2f},
+{0x56,0x33,0xe9,0x10}, {0x5b,0x38,0xe7,0x19}, {0x4c,0x25,0xf5,0x02}, {0x41,0x2e,0xfb,0x0b},
+{0x61,0x8c,0x9a,0xd7}, {0x6c,0x87,0x94,0xde}, {0x7b,0x9a,0x86,0xc5}, {0x76,0x91,0x88,0xcc},
+{0x55,0xa0,0xa2,0xf3}, {0x58,0xab,0xac,0xfa}, {0x4f,0xb6,0xbe,0xe1}, {0x42,0xbd,0xb0,0xe8},
+{0x09,0xd4,0xea,0x9f}, {0x04,0xdf,0xe4,0x96}, {0x13,0xc2,0xf6,0x8d}, {0x1e,0xc9,0xf8,0x84},
+{0x3d,0xf8,0xd2,0xbb}, {0x30,0xf3,0xdc,0xb2}, {0x27,0xee,0xce,0xa9}, {0x2a,0xe5,0xc0,0xa0},
+{0xb1,0x3c,0x7a,0x47}, {0xbc,0x37,0x74,0x4e}, {0xab,0x2a,0x66,0x55}, {0xa6,0x21,0x68,0x5c},
+{0x85,0x10,0x42,0x63}, {0x88,0x1b,0x4c,0x6a}, {0x9f,0x06,0x5e,0x71}, {0x92,0x0d,0x50,0x78},
+{0xd9,0x64,0x0a,0x0f}, {0xd4,0x6f,0x04,0x06}, {0xc3,0x72,0x16,0x1d}, {0xce,0x79,0x18,0x14},
+{0xed,0x48,0x32,0x2b}, {0xe0,0x43,0x3c,0x22}, {0xf7,0x5e,0x2e,0x39}, {0xfa,0x55,0x20,0x30},
+{0xb7,0x01,0xec,0x9a}, {0xba,0x0a,0xe2,0x93}, {0xad,0x17,0xf0,0x88}, {0xa0,0x1c,0xfe,0x81},
+{0x83,0x2d,0xd4,0xbe}, {0x8e,0x26,0xda,0xb7}, {0x99,0x3b,0xc8,0xac}, {0x94,0x30,0xc6,0xa5},
+{0xdf,0x59,0x9c,0xd2}, {0xd2,0x52,0x92,0xdb}, {0xc5,0x4f,0x80,0xc0}, {0xc8,0x44,0x8e,0xc9},
+{0xeb,0x75,0xa4,0xf6}, {0xe6,0x7e,0xaa,0xff}, {0xf1,0x63,0xb8,0xe4}, {0xfc,0x68,0xb6,0xed},
+{0x67,0xb1,0x0c,0x0a}, {0x6a,0xba,0x02,0x03}, {0x7d,0xa7,0x10,0x18}, {0x70,0xac,0x1e,0x11},
+{0x53,0x9d,0x34,0x2e}, {0x5e,0x96,0x3a,0x27}, {0x49,0x8b,0x28,0x3c}, {0x44,0x80,0x26,0x35},
+{0x0f,0xe9,0x7c,0x42}, {0x02,0xe2,0x72,0x4b}, {0x15,0xff,0x60,0x50}, {0x18,0xf4,0x6e,0x59},
+{0x3b,0xc5,0x44,0x66}, {0x36,0xce,0x4a,0x6f}, {0x21,0xd3,0x58,0x74}, {0x2c,0xd8,0x56,0x7d},
+{0x0c,0x7a,0x37,0xa1}, {0x01,0x71,0x39,0xa8}, {0x16,0x6c,0x2b,0xb3}, {0x1b,0x67,0x25,0xba},
+{0x38,0x56,0x0f,0x85}, {0x35,0x5d,0x01,0x8c}, {0x22,0x40,0x13,0x97}, {0x2f,0x4b,0x1d,0x9e},
+{0x64,0x22,0x47,0xe9}, {0x69,0x29,0x49,0xe0}, {0x7e,0x34,0x5b,0xfb}, {0x73,0x3f,0x55,0xf2},
+{0x50,0x0e,0x7f,0xcd}, {0x5d,0x05,0x71,0xc4}, {0x4a,0x18,0x63,0xdf}, {0x47,0x13,0x6d,0xd6},
+{0xdc,0xca,0xd7,0x31}, {0xd1,0xc1,0xd9,0x38}, {0xc6,0xdc,0xcb,0x23}, {0xcb,0xd7,0xc5,0x2a},
+{0xe8,0xe6,0xef,0x15}, {0xe5,0xed,0xe1,0x1c}, {0xf2,0xf0,0xf3,0x07}, {0xff,0xfb,0xfd,0x0e},
+{0xb4,0x92,0xa7,0x79}, {0xb9,0x99,0xa9,0x70}, {0xae,0x84,0xbb,0x6b}, {0xa3,0x8f,0xb5,0x62},
+{0x80,0xbe,0x9f,0x5d}, {0x8d,0xb5,0x91,0x54}, {0x9a,0xa8,0x83,0x4f}, {0x97,0xa3,0x8d,0x46}
+	}
+};
+#define	U3	xU3.xt8
+
+static const union xtab xU4 = {
+	.xt8 = {
+{0x00,0x00,0x00,0x00}, {0x09,0x0d,0x0b,0x0e}, {0x12,0x1a,0x16,0x1c}, {0x1b,0x17,0x1d,0x12},
+{0x24,0x34,0x2c,0x38}, {0x2d,0x39,0x27,0x36}, {0x36,0x2e,0x3a,0x24}, {0x3f,0x23,0x31,0x2a},
+{0x48,0x68,0x58,0x70}, {0x41,0x65,0x53,0x7e}, {0x5a,0x72,0x4e,0x6c}, {0x53,0x7f,0x45,0x62},
+{0x6c,0x5c,0x74,0x48}, {0x65,0x51,0x7f,0x46}, {0x7e,0x46,0x62,0x54}, {0x77,0x4b,0x69,0x5a},
+{0x90,0xd0,0xb0,0xe0}, {0x99,0xdd,0xbb,0xee}, {0x82,0xca,0xa6,0xfc}, {0x8b,0xc7,0xad,0xf2},
+{0xb4,0xe4,0x9c,0xd8}, {0xbd,0xe9,0x97,0xd6}, {0xa6,0xfe,0x8a,0xc4}, {0xaf,0xf3,0x81,0xca},
+{0xd8,0xb8,0xe8,0x90}, {0xd1,0xb5,0xe3,0x9e}, {0xca,0xa2,0xfe,0x8c}, {0xc3,0xaf,0xf5,0x82},
+{0xfc,0x8c,0xc4,0xa8}, {0xf5,0x81,0xcf,0xa6}, {0xee,0x96,0xd2,0xb4}, {0xe7,0x9b,0xd9,0xba},
+{0x3b,0xbb,0x7b,0xdb}, {0x32,0xb6,0x70,0xd5}, {0x29,0xa1,0x6d,0xc7}, {0x20,0xac,0x66,0xc9},
+{0x1f,0x8f,0x57,0xe3}, {0x16,0x82,0x5c,0xed}, {0x0d,0x95,0x41,0xff}, {0x04,0x98,0x4a,0xf1},
+{0x73,0xd3,0x23,0xab}, {0x7a,0xde,0x28,0xa5}, {0x61,0xc9,0x35,0xb7}, {0x68,0xc4,0x3e,0xb9},
+{0x57,0xe7,0x0f,0x93}, {0x5e,0xea,0x04,0x9d}, {0x45,0xfd,0x19,0x8f}, {0x4c,0xf0,0x12,0x81},
+{0xab,0x6b,0xcb,0x3b}, {0xa2,0x66,0xc0,0x35}, {0xb9,0x71,0xdd,0x27}, {0xb0,0x7c,0xd6,0x29},
+{0x8f,0x5f,0xe7,0x03}, {0x86,0x52,0xec,0x0d}, {0x9d,0x45,0xf1,0x1f}, {0x94,0x48,0xfa,0x11},
+{0xe3,0x03,0x93,0x4b}, {0xea,0x0e,0x98,0x45}, {0xf1,0x19,0x85,0x57}, {0xf8,0x14,0x8e,0x59},
+{0xc7,0x37,0xbf,0x73}, {0xce,0x3a,0xb4,0x7d}, {0xd5,0x2d,0xa9,0x6f}, {0xdc,0x20,0xa2,0x61},
+{0x76,0x6d,0xf6,0xad}, {0x7f,0x60,0xfd,0xa3}, {0x64,0x77,0xe0,0xb1}, {0x6d,0x7a,0xeb,0xbf},
+{0x52,0x59,0xda,0x95}, {0x5b,0x54,0xd1,0x9b}, {0x40,0x43,0xcc,0x89}, {0x49,0x4e,0xc7,0x87},
+{0x3e,0x05,0xae,0xdd}, {0x37,0x08,0xa5,0xd3}, {0x2c,0x1f,0xb8,0xc1}, {0x25,0x12,0xb3,0xcf},
+{0x1a,0x31,0x82,0xe5}, {0x13,0x3c,0x89,0xeb}, {0x08,0x2b,0x94,0xf9}, {0x01,0x26,0x9f,0xf7},
+{0xe6,0xbd,0x46,0x4d}, {0xef,0xb0,0x4d,0x43}, {0xf4,0xa7,0x50,0x51}, {0xfd,0xaa,0x5b,0x5f},
+{0xc2,0x89,0x6a,0x75}, {0xcb,0x84,0x61,0x7b}, {0xd0,0x93,0x7c,0x69}, {0xd9,0x9e,0x77,0x67},
+{0xae,0xd5,0x1e,0x3d}, {0xa7,0xd8,0x15,0x33}, {0xbc,0xcf,0x08,0x21}, {0xb5,0xc2,0x03,0x2f},
+{0x8a,0xe1,0x32,0x05}, {0x83,0xec,0x39,0x0b}, {0x98,0xfb,0x24,0x19}, {0x91,0xf6,0x2f,0x17},
+{0x4d,0xd6,0x8d,0x76}, {0x44,0xdb,0x86,0x78}, {0x5f,0xcc,0x9b,0x6a}, {0x56,0xc1,0x90,0x64},
+{0x69,0xe2,0xa1,0x4e}, {0x60,0xef,0xaa,0x40}, {0x7b,0xf8,0xb7,0x52}, {0x72,0xf5,0xbc,0x5c},
+{0x05,0xbe,0xd5,0x06}, {0x0c,0xb3,0xde,0x08}, {0x17,0xa4,0xc3,0x1a}, {0x1e,0xa9,0xc8,0x14},
+{0x21,0x8a,0xf9,0x3e}, {0x28,0x87,0xf2,0x30}, {0x33,0x90,0xef,0x22}, {0x3a,0x9d,0xe4,0x2c},
+{0xdd,0x06,0x3d,0x96}, {0xd4,0x0b,0x36,0x98}, {0xcf,0x1c,0x2b,0x8a}, {0xc6,0x11,0x20,0x84},
+{0xf9,0x32,0x11,0xae}, {0xf0,0x3f,0x1a,0xa0}, {0xeb,0x28,0x07,0xb2}, {0xe2,0x25,0x0c,0xbc},
+{0x95,0x6e,0x65,0xe6}, {0x9c,0x63,0x6e,0xe8}, {0x87,0x74,0x73,0xfa}, {0x8e,0x79,0x78,0xf4},
+{0xb1,0x5a,0x49,0xde}, {0xb8,0x57,0x42,0xd0}, {0xa3,0x40,0x5f,0xc2}, {0xaa,0x4d,0x54,0xcc},
+{0xec,0xda,0xf7,0x41}, {0xe5,0xd7,0xfc,0x4f}, {0xfe,0xc0,0xe1,0x5d}, {0xf7,0xcd,0xea,0x53},
+{0xc8,0xee,0xdb,0x79}, {0xc1,0xe3,0xd0,0x77}, {0xda,0xf4,0xcd,0x65}, {0xd3,0xf9,0xc6,0x6b},
+{0xa4,0xb2,0xaf,0x31}, {0xad,0xbf,0xa4,0x3f}, {0xb6,0xa8,0xb9,0x2d}, {0xbf,0xa5,0xb2,0x23},
+{0x80,0x86,0x83,0x09}, {0x89,0x8b,0x88,0x07}, {0x92,0x9c,0x95,0x15}, {0x9b,0x91,0x9e,0x1b},
+{0x7c,0x0a,0x47,0xa1}, {0x75,0x07,0x4c,0xaf}, {0x6e,0x10,0x51,0xbd}, {0x67,0x1d,0x5a,0xb3},
+{0x58,0x3e,0x6b,0x99}, {0x51,0x33,0x60,0x97}, {0x4a,0x24,0x7d,0x85}, {0x43,0x29,0x76,0x8b},
+{0x34,0x62,0x1f,0xd1}, {0x3d,0x6f,0x14,0xdf}, {0x26,0x78,0x09,0xcd}, {0x2f,0x75,0x02,0xc3},
+{0x10,0x56,0x33,0xe9}, {0x19,0x5b,0x38,0xe7}, {0x02,0x4c,0x25,0xf5}, {0x0b,0x41,0x2e,0xfb},
+{0xd7,0x61,0x8c,0x9a}, {0xde,0x6c,0x87,0x94}, {0xc5,0x7b,0x9a,0x86}, {0xcc,0x76,0x91,0x88},
+{0xf3,0x55,0xa0,0xa2}, {0xfa,0x58,0xab,0xac}, {0xe1,0x4f,0xb6,0xbe}, {0xe8,0x42,0xbd,0xb0},
+{0x9f,0x09,0xd4,0xea}, {0x96,0x04,0xdf,0xe4}, {0x8d,0x13,0xc2,0xf6}, {0x84,0x1e,0xc9,0xf8},
+{0xbb,0x3d,0xf8,0xd2}, {0xb2,0x30,0xf3,0xdc}, {0xa9,0x27,0xee,0xce}, {0xa0,0x2a,0xe5,0xc0},
+{0x47,0xb1,0x3c,0x7a}, {0x4e,0xbc,0x37,0x74}, {0x55,0xab,0x2a,0x66}, {0x5c,0xa6,0x21,0x68},
+{0x63,0x85,0x10,0x42}, {0x6a,0x88,0x1b,0x4c}, {0x71,0x9f,0x06,0x5e}, {0x78,0x92,0x0d,0x50},
+{0x0f,0xd9,0x64,0x0a}, {0x06,0xd4,0x6f,0x04}, {0x1d,0xc3,0x72,0x16}, {0x14,0xce,0x79,0x18},
+{0x2b,0xed,0x48,0x32}, {0x22,0xe0,0x43,0x3c}, {0x39,0xf7,0x5e,0x2e}, {0x30,0xfa,0x55,0x20},
+{0x9a,0xb7,0x01,0xec}, {0x93,0xba,0x0a,0xe2}, {0x88,0xad,0x17,0xf0}, {0x81,0xa0,0x1c,0xfe},
+{0xbe,0x83,0x2d,0xd4}, {0xb7,0x8e,0x26,0xda}, {0xac,0x99,0x3b,0xc8}, {0xa5,0x94,0x30,0xc6},
+{0xd2,0xdf,0x59,0x9c}, {0xdb,0xd2,0x52,0x92}, {0xc0,0xc5,0x4f,0x80}, {0xc9,0xc8,0x44,0x8e},
+{0xf6,0xeb,0x75,0xa4}, {0xff,0xe6,0x7e,0xaa}, {0xe4,0xf1,0x63,0xb8}, {0xed,0xfc,0x68,0xb6},
+{0x0a,0x67,0xb1,0x0c}, {0x03,0x6a,0xba,0x02}, {0x18,0x7d,0xa7,0x10}, {0x11,0x70,0xac,0x1e},
+{0x2e,0x53,0x9d,0x34}, {0x27,0x5e,0x96,0x3a}, {0x3c,0x49,0x8b,0x28}, {0x35,0x44,0x80,0x26},
+{0x42,0x0f,0xe9,0x7c}, {0x4b,0x02,0xe2,0x72}, {0x50,0x15,0xff,0x60}, {0x59,0x18,0xf4,0x6e},
+{0x66,0x3b,0xc5,0x44}, {0x6f,0x36,0xce,0x4a}, {0x74,0x21,0xd3,0x58}, {0x7d,0x2c,0xd8,0x56},
+{0xa1,0x0c,0x7a,0x37}, {0xa8,0x01,0x71,0x39}, {0xb3,0x16,0x6c,0x2b}, {0xba,0x1b,0x67,0x25},
+{0x85,0x38,0x56,0x0f}, {0x8c,0x35,0x5d,0x01}, {0x97,0x22,0x40,0x13}, {0x9e,0x2f,0x4b,0x1d},
+{0xe9,0x64,0x22,0x47}, {0xe0,0x69,0x29,0x49}, {0xfb,0x7e,0x34,0x5b}, {0xf2,0x73,0x3f,0x55},
+{0xcd,0x50,0x0e,0x7f}, {0xc4,0x5d,0x05,0x71}, {0xdf,0x4a,0x18,0x63}, {0xd6,0x47,0x13,0x6d},
+{0x31,0xdc,0xca,0xd7}, {0x38,0xd1,0xc1,0xd9}, {0x23,0xc6,0xdc,0xcb}, {0x2a,0xcb,0xd7,0xc5},
+{0x15,0xe8,0xe6,0xef}, {0x1c,0xe5,0xed,0xe1}, {0x07,0xf2,0xf0,0xf3}, {0x0e,0xff,0xfb,0xfd},
+{0x79,0xb4,0x92,0xa7}, {0x70,0xb9,0x99,0xa9}, {0x6b,0xae,0x84,0xbb}, {0x62,0xa3,0x8f,0xb5},
+{0x5d,0x80,0xbe,0x9f}, {0x54,0x8d,0xb5,0x91}, {0x4f,0x9a,0xa8,0x83}, {0x46,0x97,0xa3,0x8d}
+	}
+};
+#define	U4	xU4.xt8
+
+static const word32 rcon[30] = { 
+  0x01,0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91
+};
diff --git a/src/racoon/missing/crypto/rijndael/rijndael-alg-fst.c b/src/racoon/missing/crypto/rijndael/rijndael-alg-fst.c
new file mode 100644
index 0000000..7e48d44
--- /dev/null
+++ b/src/racoon/missing/crypto/rijndael/rijndael-alg-fst.c
@@ -0,0 +1,496 @@
+/*	$NetBSD: rijndael-alg-fst.c,v 1.4 2006/09/09 16:22:36 manu Exp $	*/
+
+/*	$KAME: rijndael-alg-fst.c,v 1.1.1.1 2001/08/08 09:56:23 sakane Exp $	*/
+
+/*
+ * rijndael-alg-fst.c   v2.3   April '2000
+ *
+ * Optimised ANSI C code
+ *
+ * authors: v1.0: Antoon Bosselaers
+ *          v2.0: Vincent Rijmen
+ *          v2.3: Paulo Barreto
+ *
+ * This code is placed in the public domain.
+ */
+
+#include "config.h"
+
+#include <sys/cdefs.h>
+#include <sys/types.h>
+#ifdef _KERNEL
+#include <sys/systm.h>
+#else
+#include <string.h>
+#endif
+#include <crypto/rijndael/rijndael-alg-fst.h>
+#include <crypto/rijndael/rijndael_local.h>
+
+#include <crypto/rijndael/boxes-fst.dat>
+
+#include <err.h>
+#define bcopy(a, b, c) memcpy((b), (a), (c))
+#define bzero(a, b) memset((a), 0, (b))
+#define panic(a) err(1, (a))
+
+int rijndaelKeySched(word8 k[MAXKC][4], word8 W[MAXROUNDS+1][4][4], int ROUNDS) {
+	/* Calculate the necessary round keys
+	 * The number of calculations depends on keyBits and blockBits
+	 */ 
+	int j, r, t, rconpointer = 0;
+	union {
+		word8	x8[MAXKC][4];
+		word32	x32[MAXKC];
+	} xtk;
+#define	tk	xtk.x8
+	int KC = ROUNDS - 6;
+
+	for (j = KC-1; j >= 0; j--) {
+		*((word32*)tk[j]) = *((word32*)k[j]);
+	}
+	r = 0;
+	t = 0;
+	/* copy values into round key array */
+	for (j = 0; (j < KC) && (r < ROUNDS + 1); ) {
+		for (; (j < KC) && (t < 4); j++, t++) {
+			*((word32*)W[r][t]) = *((word32*)tk[j]);
+		}
+		if (t == 4) {
+			r++;
+			t = 0;
+		}
+	}
+		
+	while (r < ROUNDS + 1) { /* while not enough round key material calculated */
+		/* calculate new values */
+		tk[0][0] ^= S[tk[KC-1][1]];
+		tk[0][1] ^= S[tk[KC-1][2]];
+		tk[0][2] ^= S[tk[KC-1][3]];
+		tk[0][3] ^= S[tk[KC-1][0]];
+		tk[0][0] ^= rcon[rconpointer++];
+
+		if (KC != 8) {
+			for (j = 1; j < KC; j++) {
+				*((word32*)tk[j]) ^= *((word32*)tk[j-1]);
+			}
+		} else {
+			for (j = 1; j < KC/2; j++) {
+				*((word32*)tk[j]) ^= *((word32*)tk[j-1]);
+			}
+			tk[KC/2][0] ^= S[tk[KC/2 - 1][0]];
+			tk[KC/2][1] ^= S[tk[KC/2 - 1][1]];
+			tk[KC/2][2] ^= S[tk[KC/2 - 1][2]];
+			tk[KC/2][3] ^= S[tk[KC/2 - 1][3]];
+			for (j = KC/2 + 1; j < KC; j++) {
+				*((word32*)tk[j]) ^= *((word32*)tk[j-1]);
+			}
+		}
+		/* copy values into round key array */
+		for (j = 0; (j < KC) && (r < ROUNDS + 1); ) {
+			for (; (j < KC) && (t < 4); j++, t++) {
+				*((word32*)W[r][t]) = *((word32*)tk[j]);
+			}
+			if (t == 4) {
+				r++;
+				t = 0;
+			}
+		}
+	}		
+	return 0;
+#undef tk
+}
+
+int rijndaelKeyEncToDec(word8 W[MAXROUNDS+1][4][4], int ROUNDS) {
+	int r;
+	word8 *w;
+
+	for (r = 1; r < ROUNDS; r++) {
+		w = W[r][0];
+		*((word32*)w) =
+			  *((const word32*)U1[w[0]])
+			^ *((const word32*)U2[w[1]])
+			^ *((const word32*)U3[w[2]])
+			^ *((const word32*)U4[w[3]]);
+
+		w = W[r][1];
+		*((word32*)w) =
+			  *((const word32*)U1[w[0]])
+			^ *((const word32*)U2[w[1]])
+			^ *((const word32*)U3[w[2]])
+			^ *((const word32*)U4[w[3]]);
+
+		w = W[r][2];
+		*((word32*)w) =
+			  *((const word32*)U1[w[0]])
+			^ *((const word32*)U2[w[1]])
+			^ *((const word32*)U3[w[2]])
+			^ *((const word32*)U4[w[3]]);
+
+		w = W[r][3];
+		*((word32*)w) =
+			  *((const word32*)U1[w[0]])
+			^ *((const word32*)U2[w[1]])
+			^ *((const word32*)U3[w[2]])
+			^ *((const word32*)U4[w[3]]);
+	}
+	return 0;
+}	
+
+/**
+ * Encrypt a single block. 
+ */
+int rijndaelEncrypt(word8 in[16], word8 out[16], word8 rk[MAXROUNDS+1][4][4], int ROUNDS) {
+	int r;
+	union {
+		word8	x8[16];
+		word32	x32[4];
+	} xa, xb;
+#define	a	xa.x8
+#define	b	xb.x8
+	union {
+		word8	x8[4][4];
+		word32	x32[4];
+	} xtemp;
+#define	temp	xtemp.x8
+
+    memcpy(a, in, sizeof a);
+
+    *((word32*)temp[0]) = *((word32*)(a   )) ^ *((word32*)rk[0][0]);
+    *((word32*)temp[1]) = *((word32*)(a+ 4)) ^ *((word32*)rk[0][1]);
+    *((word32*)temp[2]) = *((word32*)(a+ 8)) ^ *((word32*)rk[0][2]);
+    *((word32*)temp[3]) = *((word32*)(a+12)) ^ *((word32*)rk[0][3]);
+    *((word32*)(b    )) = *((const word32*)T1[temp[0][0]])
+					^ *((const word32*)T2[temp[1][1]])
+					^ *((const word32*)T3[temp[2][2]]) 
+					^ *((const word32*)T4[temp[3][3]]);
+    *((word32*)(b + 4)) = *((const word32*)T1[temp[1][0]])
+					^ *((const word32*)T2[temp[2][1]])
+					^ *((const word32*)T3[temp[3][2]]) 
+					^ *((const word32*)T4[temp[0][3]]);
+    *((word32*)(b + 8)) = *((const word32*)T1[temp[2][0]])
+					^ *((const word32*)T2[temp[3][1]])
+					^ *((const word32*)T3[temp[0][2]]) 
+					^ *((const word32*)T4[temp[1][3]]);
+    *((word32*)(b +12)) = *((const word32*)T1[temp[3][0]])
+					^ *((const word32*)T2[temp[0][1]])
+					^ *((const word32*)T3[temp[1][2]]) 
+					^ *((const word32*)T4[temp[2][3]]);
+	for (r = 1; r < ROUNDS-1; r++) {
+		*((word32*)temp[0]) = *((word32*)(b   )) ^ *((word32*)rk[r][0]);
+		*((word32*)temp[1]) = *((word32*)(b+ 4)) ^ *((word32*)rk[r][1]);
+		*((word32*)temp[2]) = *((word32*)(b+ 8)) ^ *((word32*)rk[r][2]);
+		*((word32*)temp[3]) = *((word32*)(b+12)) ^ *((word32*)rk[r][3]);
+
+		*((word32*)(b    )) = *((const word32*)T1[temp[0][0]])
+					^ *((const word32*)T2[temp[1][1]])
+					^ *((const word32*)T3[temp[2][2]]) 
+					^ *((const word32*)T4[temp[3][3]]);
+		*((word32*)(b + 4)) = *((const word32*)T1[temp[1][0]])
+					^ *((const word32*)T2[temp[2][1]])
+					^ *((const word32*)T3[temp[3][2]]) 
+					^ *((const word32*)T4[temp[0][3]]);
+		*((word32*)(b + 8)) = *((const word32*)T1[temp[2][0]])
+					^ *((const word32*)T2[temp[3][1]])
+					^ *((const word32*)T3[temp[0][2]]) 
+					^ *((const word32*)T4[temp[1][3]]);
+		*((word32*)(b +12)) = *((const word32*)T1[temp[3][0]])
+					^ *((const word32*)T2[temp[0][1]])
+					^ *((const word32*)T3[temp[1][2]]) 
+					^ *((const word32*)T4[temp[2][3]]);
+	}
+	/* last round is special */   
+	*((word32*)temp[0]) = *((word32*)(b   )) ^ *((word32*)rk[ROUNDS-1][0]);
+	*((word32*)temp[1]) = *((word32*)(b+ 4)) ^ *((word32*)rk[ROUNDS-1][1]);
+	*((word32*)temp[2]) = *((word32*)(b+ 8)) ^ *((word32*)rk[ROUNDS-1][2]);
+	*((word32*)temp[3]) = *((word32*)(b+12)) ^ *((word32*)rk[ROUNDS-1][3]);
+	b[ 0] = T1[temp[0][0]][1];
+	b[ 1] = T1[temp[1][1]][1];
+	b[ 2] = T1[temp[2][2]][1];
+	b[ 3] = T1[temp[3][3]][1];
+	b[ 4] = T1[temp[1][0]][1];
+	b[ 5] = T1[temp[2][1]][1];
+	b[ 6] = T1[temp[3][2]][1];
+	b[ 7] = T1[temp[0][3]][1];
+	b[ 8] = T1[temp[2][0]][1];
+	b[ 9] = T1[temp[3][1]][1];
+	b[10] = T1[temp[0][2]][1];
+	b[11] = T1[temp[1][3]][1];
+	b[12] = T1[temp[3][0]][1];
+	b[13] = T1[temp[0][1]][1];
+	b[14] = T1[temp[1][2]][1];
+	b[15] = T1[temp[2][3]][1];
+	*((word32*)(b   )) ^= *((word32*)rk[ROUNDS][0]);
+	*((word32*)(b+ 4)) ^= *((word32*)rk[ROUNDS][1]);
+	*((word32*)(b+ 8)) ^= *((word32*)rk[ROUNDS][2]);
+	*((word32*)(b+12)) ^= *((word32*)rk[ROUNDS][3]);
+
+	memcpy(out, b, sizeof b /* XXX out */);
+
+	return 0;
+#undef a
+#undef b
+#undef temp
+}
+
+#ifdef INTERMEDIATE_VALUE_KAT
+/**
+ * Encrypt only a certain number of rounds.
+ * Only used in the Intermediate Value Known Answer Test.
+ */
+int rijndaelEncryptRound(word8 a[4][4], word8 rk[MAXROUNDS+1][4][4], int ROUNDS, int rounds) {
+	int r;
+	word8 temp[4][4];
+
+	/* make number of rounds sane */
+	if (rounds > ROUNDS) {
+		rounds = ROUNDS;
+	}
+
+	*((word32*)a[0]) = *((word32*)a[0]) ^ *((word32*)rk[0][0]);
+	*((word32*)a[1]) = *((word32*)a[1]) ^ *((word32*)rk[0][1]);
+	*((word32*)a[2]) = *((word32*)a[2]) ^ *((word32*)rk[0][2]);
+	*((word32*)a[3]) = *((word32*)a[3]) ^ *((word32*)rk[0][3]);
+
+	for (r = 1; (r <= rounds) && (r < ROUNDS); r++) {
+		*((word32*)temp[0]) = *((const word32*)T1[a[0][0]])
+					   ^ *((const word32*)T2[a[1][1]])
+					   ^ *((const word32*)T3[a[2][2]]) 
+					   ^ *((const word32*)T4[a[3][3]]);
+		*((word32*)temp[1]) = *((const word32*)T1[a[1][0]])
+					   ^ *((const word32*)T2[a[2][1]])
+					   ^ *((const word32*)T3[a[3][2]]) 
+					   ^ *((const word32*)T4[a[0][3]]);
+		*((word32*)temp[2]) = *((const word32*)T1[a[2][0]])
+					   ^ *((const word32*)T2[a[3][1]])
+					   ^ *((const word32*)T3[a[0][2]]) 
+					   ^ *((const word32*)T4[a[1][3]]);
+		*((word32*)temp[3]) = *((const word32*)T1[a[3][0]])
+					   ^ *((const word32*)T2[a[0][1]])
+					   ^ *((const word32*)T3[a[1][2]]) 
+					   ^ *((const word32*)T4[a[2][3]]);
+		*((word32*)a[0]) = *((word32*)temp[0]) ^ *((word32*)rk[r][0]);
+		*((word32*)a[1]) = *((word32*)temp[1]) ^ *((word32*)rk[r][1]);
+		*((word32*)a[2]) = *((word32*)temp[2]) ^ *((word32*)rk[r][2]);
+		*((word32*)a[3]) = *((word32*)temp[3]) ^ *((word32*)rk[r][3]);
+	}
+	if (rounds == ROUNDS) {
+	   	/* last round is special */   
+	   	temp[0][0] = T1[a[0][0]][1];
+	   	temp[0][1] = T1[a[1][1]][1];
+	   	temp[0][2] = T1[a[2][2]][1]; 
+	   	temp[0][3] = T1[a[3][3]][1];
+	   	temp[1][0] = T1[a[1][0]][1];
+	   	temp[1][1] = T1[a[2][1]][1];
+	   	temp[1][2] = T1[a[3][2]][1]; 
+	   	temp[1][3] = T1[a[0][3]][1];
+	   	temp[2][0] = T1[a[2][0]][1];
+	   	temp[2][1] = T1[a[3][1]][1];
+	   	temp[2][2] = T1[a[0][2]][1]; 
+	   	temp[2][3] = T1[a[1][3]][1];
+	   	temp[3][0] = T1[a[3][0]][1];
+	   	temp[3][1] = T1[a[0][1]][1];
+	   	temp[3][2] = T1[a[1][2]][1]; 
+	   	temp[3][3] = T1[a[2][3]][1];
+		*((word32*)a[0]) = *((word32*)temp[0]) ^ *((word32*)rk[ROUNDS][0]);
+		*((word32*)a[1]) = *((word32*)temp[1]) ^ *((word32*)rk[ROUNDS][1]);
+		*((word32*)a[2]) = *((word32*)temp[2]) ^ *((word32*)rk[ROUNDS][2]);
+		*((word32*)a[3]) = *((word32*)temp[3]) ^ *((word32*)rk[ROUNDS][3]);
+	}
+
+	return 0;
+}   
+#endif /* INTERMEDIATE_VALUE_KAT */
+
+/**
+ * Decrypt a single block.
+ */
+int rijndaelDecrypt(word8 in[16], word8 out[16], word8 rk[MAXROUNDS+1][4][4], int ROUNDS) {
+	int r;
+	union {
+		word8	x8[16];
+		word32	x32[4];
+	} xa, xb;
+#define	a	xa.x8
+#define	b	xb.x8
+	union {
+		word8	x8[4][4];
+		word32	x32[4];
+	} xtemp;
+#define	temp	xtemp.x8
+	
+    memcpy(a, in, sizeof a);
+
+    *((word32*)temp[0]) = *((word32*)(a   )) ^ *((word32*)rk[ROUNDS][0]);
+    *((word32*)temp[1]) = *((word32*)(a+ 4)) ^ *((word32*)rk[ROUNDS][1]);
+    *((word32*)temp[2]) = *((word32*)(a+ 8)) ^ *((word32*)rk[ROUNDS][2]);
+    *((word32*)temp[3]) = *((word32*)(a+12)) ^ *((word32*)rk[ROUNDS][3]);
+
+    *((word32*)(b   )) = *((const word32*)T5[temp[0][0]])
+           ^ *((const word32*)T6[temp[3][1]])
+           ^ *((const word32*)T7[temp[2][2]]) 
+           ^ *((const word32*)T8[temp[1][3]]);
+	*((word32*)(b+ 4)) = *((const word32*)T5[temp[1][0]])
+           ^ *((const word32*)T6[temp[0][1]])
+           ^ *((const word32*)T7[temp[3][2]]) 
+           ^ *((const word32*)T8[temp[2][3]]);
+	*((word32*)(b+ 8)) = *((const word32*)T5[temp[2][0]])
+           ^ *((const word32*)T6[temp[1][1]])
+           ^ *((const word32*)T7[temp[0][2]]) 
+           ^ *((const word32*)T8[temp[3][3]]);
+	*((word32*)(b+12)) = *((const word32*)T5[temp[3][0]])
+           ^ *((const word32*)T6[temp[2][1]])
+           ^ *((const word32*)T7[temp[1][2]]) 
+           ^ *((const word32*)T8[temp[0][3]]);
+	for (r = ROUNDS-1; r > 1; r--) {
+		*((word32*)temp[0]) = *((word32*)(b   )) ^ *((word32*)rk[r][0]);
+		*((word32*)temp[1]) = *((word32*)(b+ 4)) ^ *((word32*)rk[r][1]);
+		*((word32*)temp[2]) = *((word32*)(b+ 8)) ^ *((word32*)rk[r][2]);
+		*((word32*)temp[3]) = *((word32*)(b+12)) ^ *((word32*)rk[r][3]);
+		*((word32*)(b   )) = *((const word32*)T5[temp[0][0]])
+		   ^ *((const word32*)T6[temp[3][1]])
+		   ^ *((const word32*)T7[temp[2][2]]) 
+		   ^ *((const word32*)T8[temp[1][3]]);
+		*((word32*)(b+ 4)) = *((const word32*)T5[temp[1][0]])
+		   ^ *((const word32*)T6[temp[0][1]])
+		   ^ *((const word32*)T7[temp[3][2]]) 
+		   ^ *((const word32*)T8[temp[2][3]]);
+		*((word32*)(b+ 8)) = *((const word32*)T5[temp[2][0]])
+		   ^ *((const word32*)T6[temp[1][1]])
+		   ^ *((const word32*)T7[temp[0][2]]) 
+		   ^ *((const word32*)T8[temp[3][3]]);
+		*((word32*)(b+12)) = *((const word32*)T5[temp[3][0]])
+		   ^ *((const word32*)T6[temp[2][1]])
+		   ^ *((const word32*)T7[temp[1][2]]) 
+		   ^ *((const word32*)T8[temp[0][3]]);
+	}
+	/* last round is special */   
+	*((word32*)temp[0]) = *((word32*)(b   )) ^ *((word32*)rk[1][0]);
+	*((word32*)temp[1]) = *((word32*)(b+ 4)) ^ *((word32*)rk[1][1]);
+	*((word32*)temp[2]) = *((word32*)(b+ 8)) ^ *((word32*)rk[1][2]);
+	*((word32*)temp[3]) = *((word32*)(b+12)) ^ *((word32*)rk[1][3]);
+	b[ 0] = S5[temp[0][0]];
+	b[ 1] = S5[temp[3][1]];
+	b[ 2] = S5[temp[2][2]];
+	b[ 3] = S5[temp[1][3]];
+	b[ 4] = S5[temp[1][0]];
+	b[ 5] = S5[temp[0][1]];
+	b[ 6] = S5[temp[3][2]];
+	b[ 7] = S5[temp[2][3]];
+	b[ 8] = S5[temp[2][0]];
+	b[ 9] = S5[temp[1][1]];
+	b[10] = S5[temp[0][2]];
+	b[11] = S5[temp[3][3]];
+	b[12] = S5[temp[3][0]];
+	b[13] = S5[temp[2][1]];
+	b[14] = S5[temp[1][2]];
+	b[15] = S5[temp[0][3]];
+	*((word32*)(b   )) ^= *((word32*)rk[0][0]);
+	*((word32*)(b+ 4)) ^= *((word32*)rk[0][1]);
+	*((word32*)(b+ 8)) ^= *((word32*)rk[0][2]);
+	*((word32*)(b+12)) ^= *((word32*)rk[0][3]);
+
+	memcpy(out, b, sizeof b /* XXX out */);
+
+	return 0;
+#undef a
+#undef b
+#undef temp
+}
+
+
+#ifdef INTERMEDIATE_VALUE_KAT
+/**
+ * Decrypt only a certain number of rounds.
+ * Only used in the Intermediate Value Known Answer Test.
+ * Operations rearranged such that the intermediate values
+ * of decryption correspond with the intermediate values
+ * of encryption.
+ */
+int rijndaelDecryptRound(word8 a[4][4], word8 rk[MAXROUNDS+1][4][4], int ROUNDS, int rounds) {
+	int r, i;
+	word8 temp[4], shift;
+
+	/* make number of rounds sane */
+	if (rounds > ROUNDS) {
+		rounds = ROUNDS;
+	}
+    /* first round is special: */
+	*(word32 *)a[0] ^= *(word32 *)rk[ROUNDS][0];
+	*(word32 *)a[1] ^= *(word32 *)rk[ROUNDS][1];
+	*(word32 *)a[2] ^= *(word32 *)rk[ROUNDS][2];
+	*(word32 *)a[3] ^= *(word32 *)rk[ROUNDS][3];
+	for (i = 0; i < 4; i++) {
+		a[i][0] = Si[a[i][0]];
+		a[i][1] = Si[a[i][1]];
+		a[i][2] = Si[a[i][2]];
+		a[i][3] = Si[a[i][3]];
+	}
+	for (i = 1; i < 4; i++) {
+		shift = (4 - i) & 3;
+		temp[0] = a[(0 + shift) & 3][i];
+		temp[1] = a[(1 + shift) & 3][i];
+		temp[2] = a[(2 + shift) & 3][i];
+		temp[3] = a[(3 + shift) & 3][i];
+		a[0][i] = temp[0];
+		a[1][i] = temp[1];
+		a[2][i] = temp[2];
+		a[3][i] = temp[3];
+	}
+	/* ROUNDS-1 ordinary rounds */
+	for (r = ROUNDS-1; r > rounds; r--) {
+		*(word32 *)a[0] ^= *(word32 *)rk[r][0];
+		*(word32 *)a[1] ^= *(word32 *)rk[r][1];
+		*(word32 *)a[2] ^= *(word32 *)rk[r][2];
+		*(word32 *)a[3] ^= *(word32 *)rk[r][3];
+
+		*((word32*)a[0]) =
+			  *((const word32*)U1[a[0][0]])
+			^ *((const word32*)U2[a[0][1]])
+			^ *((const word32*)U3[a[0][2]])
+			^ *((const word32*)U4[a[0][3]]);
+
+		*((word32*)a[1]) =
+			  *((const word32*)U1[a[1][0]])
+			^ *((const word32*)U2[a[1][1]])
+			^ *((const word32*)U3[a[1][2]])
+			^ *((const word32*)U4[a[1][3]]);
+
+		*((word32*)a[2]) =
+			  *((const word32*)U1[a[2][0]])
+			^ *((const word32*)U2[a[2][1]])
+			^ *((const word32*)U3[a[2][2]])
+			^ *((const word32*)U4[a[2][3]]);
+
+		*((word32*)a[3]) =
+			  *((const word32*)U1[a[3][0]])
+			^ *((const word32*)U2[a[3][1]])
+			^ *((const word32*)U3[a[3][2]])
+			^ *((const word32*)U4[a[3][3]]);
+		for (i = 0; i < 4; i++) {
+			a[i][0] = Si[a[i][0]];
+			a[i][1] = Si[a[i][1]];
+			a[i][2] = Si[a[i][2]];
+			a[i][3] = Si[a[i][3]];
+		}
+		for (i = 1; i < 4; i++) {
+			shift = (4 - i) & 3;
+			temp[0] = a[(0 + shift) & 3][i];
+			temp[1] = a[(1 + shift) & 3][i];
+			temp[2] = a[(2 + shift) & 3][i];
+			temp[3] = a[(3 + shift) & 3][i];
+			a[0][i] = temp[0];
+			a[1][i] = temp[1];
+			a[2][i] = temp[2];
+			a[3][i] = temp[3];
+		}
+	}
+	if (rounds == 0) {
+		/* End with the extra key addition */	
+		*(word32 *)a[0] ^= *(word32 *)rk[0][0];
+		*(word32 *)a[1] ^= *(word32 *)rk[0][1];
+		*(word32 *)a[2] ^= *(word32 *)rk[0][2];
+		*(word32 *)a[3] ^= *(word32 *)rk[0][3];
+	}    
+	return 0;
+}
+#endif /* INTERMEDIATE_VALUE_KAT */
diff --git a/src/racoon/missing/crypto/rijndael/rijndael-alg-fst.h b/src/racoon/missing/crypto/rijndael/rijndael-alg-fst.h
new file mode 100644
index 0000000..4afeca1
--- /dev/null
+++ b/src/racoon/missing/crypto/rijndael/rijndael-alg-fst.h
@@ -0,0 +1,35 @@
+/*	$NetBSD: rijndael-alg-fst.h,v 1.4 2006/09/09 16:22:36 manu Exp $	*/
+
+/*	$KAME: rijndael-alg-fst.h,v 1.1.1.1 2001/08/08 09:56:23 sakane Exp $	*/
+
+/*
+ * rijndael-alg-fst.h   v2.3   April '2000
+ *
+ * Optimised ANSI C code
+ *
+ * #define INTERMEDIATE_VALUE_KAT to generate the Intermediate Value Known Answer Test.
+ */
+
+#ifndef __RIJNDAEL_ALG_FST_H
+#define __RIJNDAEL_ALG_FST_H
+
+#define RIJNDAEL_MAXKC			(256/32)
+#define RIJNDAEL_MAXROUNDS		14
+
+int rijndaelKeySched(u_int8_t k[RIJNDAEL_MAXKC][4], u_int8_t rk[RIJNDAEL_MAXROUNDS+1][4][4], int ROUNDS);
+
+int rijndaelKeyEncToDec(u_int8_t W[RIJNDAEL_MAXROUNDS+1][4][4], int ROUNDS);
+
+int rijndaelEncrypt(u_int8_t a[16], u_int8_t b[16], u_int8_t rk[RIJNDAEL_MAXROUNDS+1][4][4], int ROUNDS);
+
+#ifdef INTERMEDIATE_VALUE_KAT
+int rijndaelEncryptRound(u_int8_t a[4][4], u_int8_t rk[RIJNDAEL_MAXROUNDS+1][4][4], int ROUNDS, int rounds);
+#endif /* INTERMEDIATE_VALUE_KAT */
+
+int rijndaelDecrypt(u_int8_t a[16], u_int8_t b[16], u_int8_t rk[RIJNDAEL_MAXROUNDS+1][4][4], int ROUNDS);
+
+#ifdef INTERMEDIATE_VALUE_KAT
+int rijndaelDecryptRound(u_int8_t a[4][4], u_int8_t rk[RIJNDAEL_MAXROUNDS+1][4][4], int ROUNDS, int rounds);
+#endif /* INTERMEDIATE_VALUE_KAT */
+
+#endif /* __RIJNDAEL_ALG_FST_H */
diff --git a/src/racoon/missing/crypto/rijndael/rijndael-api-fst.c b/src/racoon/missing/crypto/rijndael/rijndael-api-fst.c
new file mode 100644
index 0000000..9b6f5fe
--- /dev/null
+++ b/src/racoon/missing/crypto/rijndael/rijndael-api-fst.c
@@ -0,0 +1,494 @@
+/*	$NetBSD: rijndael-api-fst.c,v 1.4 2006/09/09 16:22:36 manu Exp $	*/
+
+/*	$KAME: rijndael-api-fst.c,v 1.8 2002/11/18 23:32:54 itojun Exp $	*/
+
+/*
+ * rijndael-api-fst.c   v2.3   April '2000
+ *
+ * Optimised ANSI C code
+ *
+ * authors: v1.0: Antoon Bosselaers
+ *          v2.0: Vincent Rijmen
+ *          v2.1: Vincent Rijmen
+ *          v2.2: Vincent Rijmen
+ *          v2.3: Paulo Barreto
+ *          v2.4: Vincent Rijmen
+ *
+ * This code is placed in the public domain.
+ */
+
+#include "config.h"
+
+#include <sys/param.h>
+#include <sys/types.h>
+#ifdef _KERNEL
+#include <sys/time.h>
+#include <sys/systm.h>
+#else
+#include <string.h>
+#endif
+#include <crypto/rijndael/rijndael-alg-fst.h>
+#include <crypto/rijndael/rijndael-api-fst.h>
+#include <crypto/rijndael/rijndael_local.h>
+
+#include <err.h>
+#define bcopy(a, b, c) memcpy(b, a, c)
+#define bzero(a, b) memset(a, 0, b)
+#define panic(a) err(1, (a))
+
+int rijndael_makeKey(keyInstance *key, BYTE direction, int keyLen, char *keyMaterial) {
+	word8 k[MAXKC][4];
+	int i;
+	char *keyMat;
+	
+	if (key == NULL) {
+		return BAD_KEY_INSTANCE;
+	}
+
+	if ((direction == DIR_ENCRYPT) || (direction == DIR_DECRYPT)) {
+		key->direction = direction;
+	} else {
+		return BAD_KEY_DIR;
+	}
+
+	if ((keyLen == 128) || (keyLen == 192) || (keyLen == 256)) { 
+		key->keyLen = keyLen;
+	} else {
+		return BAD_KEY_MAT;
+	}
+
+	if (keyMaterial != NULL) {
+		bcopy(keyMaterial, key->keyMaterial, keyLen/8);
+	}
+
+	key->ROUNDS = keyLen/32 + 6;
+
+	/* initialize key schedule: */
+	keyMat = key->keyMaterial;
+	for (i = 0; i < key->keyLen/8; i++) {
+		k[i >> 2][i & 3] = (word8)keyMat[i]; 
+	}
+	rijndaelKeySched(k, key->keySched, key->ROUNDS);
+	if (direction == DIR_DECRYPT) {
+		rijndaelKeyEncToDec(key->keySched, key->ROUNDS);
+	}
+
+	return TRUE;
+}
+
+int rijndael_cipherInit(cipherInstance *cipher, BYTE mode, char *IV) {
+	if ((mode == MODE_ECB) || (mode == MODE_CBC) || (mode == MODE_CFB1)) {
+		cipher->mode = mode;
+	} else {
+		return BAD_CIPHER_MODE;
+	}
+	if (IV != NULL) {
+		bcopy(IV, cipher->IV, MAX_IV_SIZE);
+	} else {
+		bzero(cipher->IV, MAX_IV_SIZE);
+	}
+	return TRUE;
+}
+
+int rijndael_blockEncrypt(cipherInstance *cipher, keyInstance *key,
+		BYTE *input, int inputLen, BYTE *outBuffer) {
+	int i, k, numBlocks;
+	word8 block[16], iv[4][4];
+
+	if (cipher == NULL ||
+		key == NULL ||
+		key->direction == DIR_DECRYPT) {
+		return BAD_CIPHER_STATE;
+	}
+	if (input == NULL || inputLen <= 0) {
+		return 0; /* nothing to do */
+	}
+
+	numBlocks = inputLen/128;
+	
+	switch (cipher->mode) {
+	case MODE_ECB: 
+		for (i = numBlocks; i > 0; i--) {
+			rijndaelEncrypt(input, outBuffer, key->keySched, key->ROUNDS);
+			input += 16;
+			outBuffer += 16;
+		}
+		break;
+		
+	case MODE_CBC:
+#if 1 /*STRICT_ALIGN*/
+		bcopy(cipher->IV, block, 16);
+		bcopy(input, iv, 16);
+		((word32*)block)[0] ^= ((word32*)iv)[0];
+		((word32*)block)[1] ^= ((word32*)iv)[1];
+		((word32*)block)[2] ^= ((word32*)iv)[2];
+		((word32*)block)[3] ^= ((word32*)iv)[3];
+#else
+		((word32*)block)[0] = ((word32*)cipher->IV)[0] ^ ((word32*)input)[0];
+		((word32*)block)[1] = ((word32*)cipher->IV)[1] ^ ((word32*)input)[1];
+		((word32*)block)[2] = ((word32*)cipher->IV)[2] ^ ((word32*)input)[2];
+		((word32*)block)[3] = ((word32*)cipher->IV)[3] ^ ((word32*)input)[3];
+#endif
+		rijndaelEncrypt(block, outBuffer, key->keySched, key->ROUNDS);
+		input += 16;
+		for (i = numBlocks - 1; i > 0; i--) {
+#if 1 /*STRICT_ALIGN*/
+			bcopy(outBuffer, block, 16);
+			bcopy(input, iv, 16);
+			((word32*)block)[0] ^= ((word32*)iv)[0];
+			((word32*)block)[1] ^= ((word32*)iv)[1];
+			((word32*)block)[2] ^= ((word32*)iv)[2];
+			((word32*)block)[3] ^= ((word32*)iv)[3];
+#else
+			((word32*)block)[0] = ((word32*)outBuffer)[0] ^ ((word32*)input)[0];
+			((word32*)block)[1] = ((word32*)outBuffer)[1] ^ ((word32*)input)[1];
+			((word32*)block)[2] = ((word32*)outBuffer)[2] ^ ((word32*)input)[2];
+			((word32*)block)[3] = ((word32*)outBuffer)[3] ^ ((word32*)input)[3];
+#endif
+			outBuffer += 16;
+			rijndaelEncrypt(block, outBuffer, key->keySched, key->ROUNDS);
+			input += 16;
+		}
+		break;
+	
+	case MODE_CFB1:
+#if 1 /*STRICT_ALIGN*/
+		bcopy(cipher->IV, iv, 16); 
+#else  /* !STRICT_ALIGN */
+		*((word32*)iv[0]) = *((word32*)(cipher->IV   ));
+		*((word32*)iv[1]) = *((word32*)(cipher->IV+ 4));
+		*((word32*)iv[2]) = *((word32*)(cipher->IV+ 8));
+		*((word32*)iv[3]) = *((word32*)(cipher->IV+12));
+#endif /* ?STRICT_ALIGN */
+		for (i = numBlocks; i > 0; i--) {
+			for (k = 0; k < 128; k++) {
+				*((word32*) block    ) = *((word32*)iv[0]);
+				*((word32*)(block+ 4)) = *((word32*)iv[1]);
+				*((word32*)(block+ 8)) = *((word32*)iv[2]);
+				*((word32*)(block+12)) = *((word32*)iv[3]);
+				rijndaelEncrypt(block, block, key->keySched, key->ROUNDS);
+				outBuffer[k/8] ^= (block[0] & 0x80) >> (k & 7);
+				iv[0][0] = (iv[0][0] << 1) | (iv[0][1] >> 7);
+				iv[0][1] = (iv[0][1] << 1) | (iv[0][2] >> 7);
+				iv[0][2] = (iv[0][2] << 1) | (iv[0][3] >> 7);
+				iv[0][3] = (iv[0][3] << 1) | (iv[1][0] >> 7);
+				iv[1][0] = (iv[1][0] << 1) | (iv[1][1] >> 7);
+				iv[1][1] = (iv[1][1] << 1) | (iv[1][2] >> 7);
+				iv[1][2] = (iv[1][2] << 1) | (iv[1][3] >> 7);
+				iv[1][3] = (iv[1][3] << 1) | (iv[2][0] >> 7);
+				iv[2][0] = (iv[2][0] << 1) | (iv[2][1] >> 7);
+				iv[2][1] = (iv[2][1] << 1) | (iv[2][2] >> 7);
+				iv[2][2] = (iv[2][2] << 1) | (iv[2][3] >> 7);
+				iv[2][3] = (iv[2][3] << 1) | (iv[3][0] >> 7);
+				iv[3][0] = (iv[3][0] << 1) | (iv[3][1] >> 7);
+				iv[3][1] = (iv[3][1] << 1) | (iv[3][2] >> 7);
+				iv[3][2] = (iv[3][2] << 1) | (iv[3][3] >> 7);
+				iv[3][3] = (iv[3][3] << 1) | ((outBuffer[k/8] >> (7-(k&7))) & 1);
+			}
+		}
+		break;
+	
+	default:
+		return BAD_CIPHER_STATE;
+	}
+	
+	return 128*numBlocks;
+}
+
+/**
+ * Encrypt data partitioned in octets, using RFC 2040-like padding.
+ *
+ * @param   input           data to be encrypted (octet sequence)
+ * @param   inputOctets		input length in octets (not bits)
+ * @param   outBuffer       encrypted output data
+ *
+ * @return	length in octets (not bits) of the encrypted output buffer.
+ */
+int rijndael_padEncrypt(cipherInstance *cipher, keyInstance *key,
+		BYTE *input, int inputOctets, BYTE *outBuffer) {
+	int i, numBlocks, padLen;
+	word8 block[16], *iv, *cp;
+
+	if (cipher == NULL ||
+		key == NULL ||
+		key->direction == DIR_DECRYPT) {
+		return BAD_CIPHER_STATE;
+	}
+	if (input == NULL || inputOctets <= 0) {
+		return 0; /* nothing to do */
+	}
+
+	numBlocks = inputOctets/16;
+
+	switch (cipher->mode) {
+	case MODE_ECB: 
+		for (i = numBlocks; i > 0; i--) {
+			rijndaelEncrypt(input, outBuffer, key->keySched, key->ROUNDS);
+			input += 16;
+			outBuffer += 16;
+		}
+		padLen = 16 - (inputOctets - 16*numBlocks);
+		if (padLen <= 0 || padLen > 16)
+			panic("rijndael_padEncrypt(ECB)");
+		bcopy(input, block, 16 - padLen);
+		for (cp = block + 16 - padLen; cp < block + 16; cp++)
+			*cp = padLen;
+		rijndaelEncrypt(block, outBuffer, key->keySched, key->ROUNDS);
+		break;
+
+	case MODE_CBC:
+		iv = cipher->IV;
+		for (i = numBlocks; i > 0; i--) {
+			((word32*)block)[0] = ((word32*)input)[0] ^ ((word32*)iv)[0];
+			((word32*)block)[1] = ((word32*)input)[1] ^ ((word32*)iv)[1];
+			((word32*)block)[2] = ((word32*)input)[2] ^ ((word32*)iv)[2];
+			((word32*)block)[3] = ((word32*)input)[3] ^ ((word32*)iv)[3];
+			rijndaelEncrypt(block, outBuffer, key->keySched, key->ROUNDS);
+			iv = outBuffer;
+			input += 16;
+			outBuffer += 16;
+		}
+		padLen = 16 - (inputOctets - 16*numBlocks);
+		if (padLen <= 0 || padLen > 16)
+			panic("rijndael_padEncrypt(CBC)");
+		for (i = 0; i < 16 - padLen; i++) {
+			block[i] = input[i] ^ iv[i];
+		}
+		for (i = 16 - padLen; i < 16; i++) {
+			block[i] = (BYTE)padLen ^ iv[i];
+		}
+		rijndaelEncrypt(block, outBuffer, key->keySched, key->ROUNDS);
+		break;
+
+	default:
+		return BAD_CIPHER_STATE;
+	}
+
+	return 16*(numBlocks + 1);
+}
+
+int rijndael_blockDecrypt(cipherInstance *cipher, keyInstance *key,
+		BYTE *input, int inputLen, BYTE *outBuffer) {
+	int i, k, numBlocks;
+	word8 block[16], iv[4][4];
+
+	if (cipher == NULL ||
+		key == NULL ||
+		(cipher->mode != MODE_CFB1 && key->direction == DIR_ENCRYPT)) {
+		return BAD_CIPHER_STATE;
+	}
+	if (input == NULL || inputLen <= 0) {
+		return 0; /* nothing to do */
+	}
+
+	numBlocks = inputLen/128;
+
+	switch (cipher->mode) {
+	case MODE_ECB: 
+		for (i = numBlocks; i > 0; i--) { 
+			rijndaelDecrypt(input, outBuffer, key->keySched, key->ROUNDS);
+			input += 16;
+			outBuffer += 16;
+		}
+		break;
+		
+	case MODE_CBC:
+#if 1 /*STRICT_ALIGN */
+		bcopy(cipher->IV, iv, 16); 
+#else
+		*((word32*)iv[0]) = *((word32*)(cipher->IV   ));
+		*((word32*)iv[1]) = *((word32*)(cipher->IV+ 4));
+		*((word32*)iv[2]) = *((word32*)(cipher->IV+ 8));
+		*((word32*)iv[3]) = *((word32*)(cipher->IV+12));
+#endif
+		for (i = numBlocks; i > 0; i--) {
+			rijndaelDecrypt(input, block, key->keySched, key->ROUNDS);
+			((word32*)block)[0] ^= *((word32*)iv[0]);
+			((word32*)block)[1] ^= *((word32*)iv[1]);
+			((word32*)block)[2] ^= *((word32*)iv[2]);
+			((word32*)block)[3] ^= *((word32*)iv[3]);
+#if 1 /*STRICT_ALIGN*/
+			bcopy(input, iv, 16);
+			bcopy(block, outBuffer, 16);
+#else
+			*((word32*)iv[0]) = ((word32*)input)[0]; ((word32*)outBuffer)[0] = ((word32*)block)[0];
+			*((word32*)iv[1]) = ((word32*)input)[1]; ((word32*)outBuffer)[1] = ((word32*)block)[1];
+			*((word32*)iv[2]) = ((word32*)input)[2]; ((word32*)outBuffer)[2] = ((word32*)block)[2];
+			*((word32*)iv[3]) = ((word32*)input)[3]; ((word32*)outBuffer)[3] = ((word32*)block)[3];
+#endif
+			input += 16;
+			outBuffer += 16;
+		}
+		break;
+	
+	case MODE_CFB1:
+#if 1 /*STRICT_ALIGN */
+		bcopy(cipher->IV, iv, 16); 
+#else
+		*((word32*)iv[0]) = *((word32*)(cipher->IV));
+		*((word32*)iv[1]) = *((word32*)(cipher->IV+ 4));
+		*((word32*)iv[2]) = *((word32*)(cipher->IV+ 8));
+		*((word32*)iv[3]) = *((word32*)(cipher->IV+12));
+#endif
+		for (i = numBlocks; i > 0; i--) {
+			for (k = 0; k < 128; k++) {
+				*((word32*) block    ) = *((word32*)iv[0]);
+				*((word32*)(block+ 4)) = *((word32*)iv[1]);
+				*((word32*)(block+ 8)) = *((word32*)iv[2]);
+				*((word32*)(block+12)) = *((word32*)iv[3]);
+				rijndaelEncrypt(block, block, key->keySched, key->ROUNDS);
+				iv[0][0] = (iv[0][0] << 1) | (iv[0][1] >> 7);
+				iv[0][1] = (iv[0][1] << 1) | (iv[0][2] >> 7);
+				iv[0][2] = (iv[0][2] << 1) | (iv[0][3] >> 7);
+				iv[0][3] = (iv[0][3] << 1) | (iv[1][0] >> 7);
+				iv[1][0] = (iv[1][0] << 1) | (iv[1][1] >> 7);
+				iv[1][1] = (iv[1][1] << 1) | (iv[1][2] >> 7);
+				iv[1][2] = (iv[1][2] << 1) | (iv[1][3] >> 7);
+				iv[1][3] = (iv[1][3] << 1) | (iv[2][0] >> 7);
+				iv[2][0] = (iv[2][0] << 1) | (iv[2][1] >> 7);
+				iv[2][1] = (iv[2][1] << 1) | (iv[2][2] >> 7);
+				iv[2][2] = (iv[2][2] << 1) | (iv[2][3] >> 7);
+				iv[2][3] = (iv[2][3] << 1) | (iv[3][0] >> 7);
+				iv[3][0] = (iv[3][0] << 1) | (iv[3][1] >> 7);
+				iv[3][1] = (iv[3][1] << 1) | (iv[3][2] >> 7);
+				iv[3][2] = (iv[3][2] << 1) | (iv[3][3] >> 7);
+				iv[3][3] = (iv[3][3] << 1) | ((input[k/8] >> (7-(k&7))) & 1);
+				outBuffer[k/8] ^= (block[0] & 0x80) >> (k & 7);
+			}
+		}
+		break;
+
+	default:
+		return BAD_CIPHER_STATE;
+	}
+	
+	return 128*numBlocks;
+}
+
+int rijndael_padDecrypt(cipherInstance *cipher, keyInstance *key,
+		BYTE *input, int inputOctets, BYTE *outBuffer) {
+	int i, numBlocks, padLen;
+	word8 block[16];
+	word32 iv[4];
+
+	if (cipher == NULL ||
+		key == NULL ||
+		key->direction == DIR_ENCRYPT) {
+		return BAD_CIPHER_STATE;
+	}
+	if (input == NULL || inputOctets <= 0) {
+		return 0; /* nothing to do */
+	}
+	if (inputOctets % 16 != 0) {
+		return BAD_DATA;
+	}
+
+	numBlocks = inputOctets/16;
+
+	switch (cipher->mode) {
+	case MODE_ECB:
+		/* all blocks but last */
+		for (i = numBlocks - 1; i > 0; i--) { 
+			rijndaelDecrypt(input, outBuffer, key->keySched, key->ROUNDS);
+			input += 16;
+			outBuffer += 16;
+		}
+		/* last block */
+		rijndaelDecrypt(input, block, key->keySched, key->ROUNDS);
+		padLen = block[15];
+		if (padLen >= 16) {
+			return BAD_DATA;
+		}
+		for (i = 16 - padLen; i < 16; i++) {
+			if (block[i] != padLen) {
+				return BAD_DATA;
+			}
+		}
+		bcopy(block, outBuffer, 16 - padLen);
+		break;
+		
+	case MODE_CBC:
+		bcopy(cipher->IV, iv, 16);
+		/* all blocks but last */
+		for (i = numBlocks - 1; i > 0; i--) {
+			rijndaelDecrypt(input, block, key->keySched, key->ROUNDS);
+			((word32*)block)[0] ^= iv[0];
+			((word32*)block)[1] ^= iv[1];
+			((word32*)block)[2] ^= iv[2];
+			((word32*)block)[3] ^= iv[3];
+			bcopy(input, iv, 16);
+			bcopy(block, outBuffer, 16);
+			input += 16;
+			outBuffer += 16;
+		}
+		/* last block */
+		rijndaelDecrypt(input, block, key->keySched, key->ROUNDS);
+		((word32*)block)[0] ^= iv[0];
+		((word32*)block)[1] ^= iv[1];
+		((word32*)block)[2] ^= iv[2];
+		((word32*)block)[3] ^= iv[3];
+		padLen = block[15];
+		if (padLen <= 0 || padLen > 16) {
+			return BAD_DATA;
+		}
+		for (i = 16 - padLen; i < 16; i++) {
+			if (block[i] != padLen) {
+				return BAD_DATA;
+			}
+		}
+		bcopy(block, outBuffer, 16 - padLen);
+		break;
+	
+	default:
+		return BAD_CIPHER_STATE;
+	}
+	
+	return 16*numBlocks - padLen;
+}
+
+#ifdef INTERMEDIATE_VALUE_KAT
+/**
+ *	cipherUpdateRounds:
+ *
+ *	Encrypts/Decrypts exactly one full block a specified number of rounds.
+ *	Only used in the Intermediate Value Known Answer Test.	
+ *
+ *	Returns:
+ *		TRUE - on success
+ *		BAD_CIPHER_STATE - cipher in bad state (e.g., not initialized)
+ */
+int rijndael_cipherUpdateRounds(cipherInstance *cipher, keyInstance *key,
+		BYTE *input, int inputLen, BYTE *outBuffer, int rounds) {
+	int j;
+	word8 block[4][4];
+
+	if (cipher == NULL || key == NULL) {
+		return BAD_CIPHER_STATE;
+	}
+
+	for (j = 3; j >= 0; j--) {
+		/* parse input stream into rectangular array */
+  		*((word32*)block[j]) = *((word32*)(input+4*j));
+	}
+
+	switch (key->direction) {
+	case DIR_ENCRYPT:
+		rijndaelEncryptRound(block, key->keySched, key->ROUNDS, rounds);
+		break;
+		
+	case DIR_DECRYPT:
+		rijndaelDecryptRound(block, key->keySched, key->ROUNDS, rounds);
+		break;
+		
+	default:
+		return BAD_KEY_DIR;
+	} 
+
+	for (j = 3; j >= 0; j--) {
+		/* parse rectangular array into output ciphertext bytes */
+		*((word32*)(outBuffer+4*j)) = *((word32*)block[j]);
+	}
+	
+	return TRUE;
+}
+#endif /* INTERMEDIATE_VALUE_KAT */
diff --git a/src/racoon/missing/crypto/rijndael/rijndael-api-fst.h b/src/racoon/missing/crypto/rijndael/rijndael-api-fst.h
new file mode 100644
index 0000000..1d76a21
--- /dev/null
+++ b/src/racoon/missing/crypto/rijndael/rijndael-api-fst.h
@@ -0,0 +1,105 @@
+/*	$NetBSD: rijndael-api-fst.h,v 1.4 2006/09/09 16:22:36 manu Exp $	*/
+
+/*	$KAME: rijndael-api-fst.h,v 1.1.1.1 2001/08/08 09:56:27 sakane Exp $	*/
+
+/*
+ * rijndael-api-fst.h   v2.3   April '2000
+ *
+ * Optimised ANSI C code
+ *
+ * #define INTERMEDIATE_VALUE_KAT to generate the Intermediate Value Known Answer Test.
+ */
+
+#ifndef __RIJNDAEL_API_FST_H
+#define __RIJNDAEL_API_FST_H
+
+#include <crypto/rijndael/rijndael-alg-fst.h>
+
+/*  Defines:
+	Add any additional defines you need
+*/
+
+#define     DIR_ENCRYPT           0 /*  Are we encrpyting?  */
+#define     DIR_DECRYPT           1 /*  Are we decrpyting?  */
+#define     MODE_ECB              1 /*  Are we ciphering in ECB mode?   */
+#define     MODE_CBC              2 /*  Are we ciphering in CBC mode?   */
+#define     MODE_CFB1             3 /*  Are we ciphering in 1-bit CFB mode? */
+#define     TRUE                  1
+#define     FALSE                 0
+#define     BITSPERBLOCK        128 /* Default number of bits in a cipher block */
+
+/*  Error Codes - CHANGE POSSIBLE: inclusion of additional error codes  */
+#define     BAD_KEY_DIR          -1 /*  Key direction is invalid, e.g., unknown value */
+#define     BAD_KEY_MAT          -2 /*  Key material not of correct length */
+#define     BAD_KEY_INSTANCE     -3 /*  Key passed is not valid */
+#define     BAD_CIPHER_MODE      -4 /*  Params struct passed to cipherInit invalid */
+#define     BAD_CIPHER_STATE     -5 /*  Cipher in wrong state (e.g., not initialized) */
+#define     BAD_BLOCK_LENGTH     -6
+#define     BAD_CIPHER_INSTANCE  -7
+#define     BAD_DATA             -8 /*  Data contents are invalid, e.g., invalid padding */
+#define     BAD_OTHER            -9 /*  Unknown error */
+
+/*  CHANGE POSSIBLE:  inclusion of algorithm specific defines  */
+#define     MAX_KEY_SIZE         64 /* # of ASCII char's needed to represent a key */
+#define     MAX_IV_SIZE          16 /* # bytes needed to represent an IV  */
+
+/*  Typedefs:
+
+	Typedef'ed data storage elements.  Add any algorithm specific 
+parameters at the bottom of the structs as appropriate.
+*/
+
+/*  The structure for key information */
+typedef struct {
+    u_int8_t  direction;            /* Key used for encrypting or decrypting? */
+    int   keyLen;                   /* Length of the key  */
+    char  keyMaterial[MAX_KEY_SIZE+1];  /* Raw key data in ASCII, e.g., user input or KAT values */
+        /*  The following parameters are algorithm dependent, replace or add as necessary  */
+	int   ROUNDS;                   /* key-length-dependent number of rounds */
+    int   blockLen;                 /* block length */
+    union {
+    	u_int8_t xkS8[RIJNDAEL_MAXROUNDS+1][4][4];	/* key schedule		*/
+    	u_int32_t xkS32[RIJNDAEL_MAXROUNDS+1][4];	/* key schedule		*/
+    } xKeySched;
+#define	keySched	xKeySched.xkS8
+} keyInstance;
+
+/*  The structure for cipher information */
+typedef struct {                    /* changed order of the components */
+    u_int8_t mode;                  /* MODE_ECB, MODE_CBC, or MODE_CFB1 */
+    u_int8_t IV[MAX_IV_SIZE];       /* A possible Initialization Vector for ciphering */
+        /*  Add any algorithm specific parameters needed here  */
+    int   blockLen;                 /* Sample: Handles non-128 bit block sizes (if available) */
+} cipherInstance;
+
+/*  Function prototypes  */
+/*  CHANGED: nothing
+	TODO: implement the following extensions to setup 192-bit and 256-bit block lengths:
+        makeKeyEx():    parameter blockLen added
+                        -- this parameter is absolutely necessary if you want to
+                        setup the round keys in a variable block length setting 
+	    cipherInitEx(): parameter blockLen added (for obvious reasons)		
+ */
+
+int rijndael_makeKey(keyInstance *key, u_int8_t direction, int keyLen, char *keyMaterial);
+
+int rijndael_cipherInit(cipherInstance *cipher, u_int8_t mode, char *IV);
+
+int rijndael_blockEncrypt(cipherInstance *cipher, keyInstance *key,
+        u_int8_t *input, int inputLen, u_int8_t *outBuffer);
+
+int rijndael_padEncrypt(cipherInstance *cipher, keyInstance *key,
+		u_int8_t *input, int inputOctets, u_int8_t *outBuffer);
+
+int rijndael_blockDecrypt(cipherInstance *cipher, keyInstance *key,
+        u_int8_t *input, int inputLen, u_int8_t *outBuffer);
+
+int rijndael_padDecrypt(cipherInstance *cipher, keyInstance *key,
+		u_int8_t *input, int inputOctets, u_int8_t *outBuffer);
+
+#ifdef INTERMEDIATE_VALUE_KAT
+int rijndael_cipherUpdateRounds(cipherInstance *cipher, keyInstance *key,
+        u_int8_t *input, int inputLen, u_int8_t *outBuffer, int Rounds);
+#endif /* INTERMEDIATE_VALUE_KAT */
+
+#endif /*  __RIJNDAEL_API_FST_H */
diff --git a/src/racoon/missing/crypto/rijndael/rijndael.h b/src/racoon/missing/crypto/rijndael/rijndael.h
new file mode 100644
index 0000000..59c3077
--- /dev/null
+++ b/src/racoon/missing/crypto/rijndael/rijndael.h
@@ -0,0 +1,5 @@
+/*	$NetBSD: rijndael.h,v 1.4 2006/09/09 16:22:36 manu Exp $	*/
+
+/*	$KAME: rijndael.h,v 1.1.1.1 2001/08/08 09:56:27 sakane Exp $	*/
+
+#include <crypto/rijndael/rijndael-api-fst.h>
diff --git a/src/racoon/missing/crypto/rijndael/rijndael_local.h b/src/racoon/missing/crypto/rijndael/rijndael_local.h
new file mode 100644
index 0000000..e446378
--- /dev/null
+++ b/src/racoon/missing/crypto/rijndael/rijndael_local.h
@@ -0,0 +1,12 @@
+/*	$NetBSD: rijndael_local.h,v 1.4 2006/09/09 16:22:36 manu Exp $	*/
+
+/*	$KAME: rijndael_local.h,v 1.1.1.1 2001/08/08 09:56:27 sakane Exp $	*/
+
+/* the file should not be used from outside */
+typedef u_int8_t		BYTE;
+typedef u_int8_t		word8;	
+typedef u_int16_t		word16;	
+typedef u_int32_t		word32;
+
+#define MAXKC		RIJNDAEL_MAXKC
+#define MAXROUNDS	RIJNDAEL_MAXROUNDS
diff --git a/src/racoon/missing/crypto/sha2/sha2.c b/src/racoon/missing/crypto/sha2/sha2.c
new file mode 100644
index 0000000..cfde829
--- /dev/null
+++ b/src/racoon/missing/crypto/sha2/sha2.c
@@ -0,0 +1,1201 @@
+/*	$NetBSD: sha2.c,v 1.4 2006/09/09 16:22:36 manu Exp $	*/
+
+/* Id: sha2.c,v 1.6 2004/09/21 14:35:25 ludvigm Exp */
+
+/*
+ * sha2.c
+ *
+ * Version 1.0.0beta1
+ *
+ * Written by Aaron D. Gifford <me@aarongifford.com>
+ *
+ * Copyright 2000 Aaron D. Gifford.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holder nor the names of contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) AND CONTRIBUTOR(S) ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR(S) OR CONTRIBUTOR(S) BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#include "config.h"
+
+#include <sys/types.h>
+#include <sys/time.h>
+#ifndef __linux__
+#include <machine/endian.h>
+#endif
+#include <crypto/sha2/sha2.h>
+#include <openssl/evp.h>
+
+/* get openssl/ssleay version number */
+#include <openssl/opensslv.h>
+
+#include <err.h>
+#include <string.h>
+#define bcopy(a, b, c) memcpy((b), (a), (c))
+#define bzero(a, b) memset((a), 0, (b))
+#define panic(a) err(1, (a))
+
+#if OPENSSL_VERSION_NUMBER >= 0x00907000L
+#define HAVE_EVP_097
+#endif
+
+/*
+ * ASSERT NOTE:
+ * Some sanity checking code is included using assert().  On my FreeBSD
+ * system, this additional code can be removed by compiling with NDEBUG
+ * defined.  Check your own systems manpage on assert() to see how to
+ * compile WITHOUT the sanity checking code on your system.
+ *
+ * UNROLLED TRANSFORM LOOP NOTE:
+ * You can define SHA2_UNROLL_TRANSFORM to use the unrolled transform
+ * loop version for the hash transform rounds (defined using macros
+ * later in this file).  Either define on the command line, for example:
+ *
+ *   cc -DSHA2_UNROLL_TRANSFORM -o sha2 sha2.c sha2prog.c
+ *
+ * or define below:
+ *
+ *   #define SHA2_UNROLL_TRANSFORM
+ *
+ */
+
+#define assert(x)
+
+
+/*** SHA-256/384/512 Machine Architecture Definitions *****************/
+/*
+ * BYTE_ORDER NOTE:
+ *
+ * Please make sure that your system defines BYTE_ORDER.  If your
+ * architecture is little-endian, make sure it also defines
+ * LITTLE_ENDIAN and that the two (BYTE_ORDER and LITTLE_ENDIAN) are
+ * equivilent.
+ *
+ * If your system does not define the above, then you can do so by
+ * hand like this:
+ *
+ *   #define LITTLE_ENDIAN 1234
+ *   #define BIG_ENDIAN    4321
+ *
+ * And for little-endian machines, add:
+ *
+ *   #define BYTE_ORDER LITTLE_ENDIAN 
+ *
+ * Or for big-endian machines:
+ *
+ *   #define BYTE_ORDER BIG_ENDIAN
+ *
+ * The FreeBSD machine this was written on defines BYTE_ORDER
+ * appropriately by including <sys/types.h> (which in turn includes
+ * <machine/endian.h> where the appropriate definitions are actually
+ * made).
+ */
+#if !defined(BYTE_ORDER) || (BYTE_ORDER != LITTLE_ENDIAN && BYTE_ORDER != BIG_ENDIAN)
+#error Define BYTE_ORDER to be equal to either LITTLE_ENDIAN or BIG_ENDIAN
+#endif
+
+/*
+ * Define the followingsha2_* types to types of the correct length on
+ * the native archtecture.   Most BSD systems and Linux define u_intXX_t
+ * types.  Machines with very recent ANSI C headers, can use the
+ * uintXX_t definintions from inttypes.h by defining SHA2_USE_INTTYPES_H
+ * during compile or in the sha.h header file.
+ *
+ * Machines that support neither u_intXX_t nor inttypes.h's uintXX_t
+ * will need to define these three typedefs below (and the appropriate
+ * ones in sha.h too) by hand according to their system architecture.
+ *
+ * Thank you, Jun-ichiro itojun Hagino, for suggesting using u_intXX_t
+ * types and pointing out recent ANSI C support for uintXX_t in inttypes.h.
+ */
+#if 0 /*def SHA2_USE_INTTYPES_H*/
+
+typedef uint8_t  sha2_byte;	/* Exactly 1 byte */
+typedef uint32_t sha2_word32;	/* Exactly 4 bytes */
+typedef uint64_t sha2_word64;	/* Exactly 8 bytes */
+
+#else /* SHA2_USE_INTTYPES_H */
+
+typedef u_int8_t  sha2_byte;	/* Exactly 1 byte */
+typedef u_int32_t sha2_word32;	/* Exactly 4 bytes */
+typedef u_int64_t sha2_word64;	/* Exactly 8 bytes */
+
+#endif /* SHA2_USE_INTTYPES_H */
+
+
+/*** SHA-256/384/512 Various Length Definitions ***********************/
+/* NOTE: Most of these are in sha2.h */
+#define SHA256_SHORT_BLOCK_LENGTH	(SHA256_BLOCK_LENGTH - 8)
+#define SHA384_SHORT_BLOCK_LENGTH	(SHA384_BLOCK_LENGTH - 16)
+#define SHA512_SHORT_BLOCK_LENGTH	(SHA512_BLOCK_LENGTH - 16)
+
+
+/*** ENDIAN REVERSAL MACROS *******************************************/
+#if BYTE_ORDER == LITTLE_ENDIAN
+#define REVERSE32(w,x)	{ \
+	sha2_word32 tmp = (w); \
+	tmp = (tmp >> 16) | (tmp << 16); \
+	(x) = ((tmp & 0xff00ff00UL) >> 8) | ((tmp & 0x00ff00ffUL) << 8); \
+}
+#define REVERSE64(w,x)	{ \
+	sha2_word64 tmp = (w); \
+	tmp = (tmp >> 32) | (tmp << 32); \
+	tmp = ((tmp & 0xff00ff00ff00ff00ULL) >> 8) | \
+	      ((tmp & 0x00ff00ff00ff00ffULL) << 8); \
+	(x) = ((tmp & 0xffff0000ffff0000ULL) >> 16) | \
+	      ((tmp & 0x0000ffff0000ffffULL) << 16); \
+}
+#endif /* BYTE_ORDER == LITTLE_ENDIAN */
+
+/*
+ * Macro for incrementally adding the unsigned 64-bit integer n to the
+ * unsigned 128-bit integer (represented using a two-element array of
+ * 64-bit words):
+ */
+#define ADDINC128(w,n)	{ \
+	(w)[0] += (sha2_word64)(n); \
+	if ((w)[0] < (n)) { \
+		(w)[1]++; \
+	} \
+}
+
+/*** THE SIX LOGICAL FUNCTIONS ****************************************/
+/*
+ * Bit shifting and rotation (used by the six SHA-XYZ logical functions:
+ *
+ *   NOTE:  The naming of R and S appears backwards here (R is a SHIFT and
+ *   S is a ROTATION) because the SHA-256/384/512 description document
+ *   (see http://csrc.nist.gov/cryptval/shs/sha256-384-512.pdf) uses this
+ *   same "backwards" definition.
+ */
+/* Shift-right (used in SHA-256, SHA-384, and SHA-512): */
+#define R(b,x) 		((x) >> (b))
+/* 32-bit Rotate-right (used in SHA-256): */
+#define S32(b,x)	(((x) >> (b)) | ((x) << (32 - (b))))
+/* 64-bit Rotate-right (used in SHA-384 and SHA-512): */
+#define S64(b,x)	(((x) >> (b)) | ((x) << (64 - (b))))
+
+/* Two of six logical functions used in SHA-256, SHA-384, and SHA-512: */
+#define Ch(x,y,z)	(((x) & (y)) ^ ((~(x)) & (z)))
+#define Maj(x,y,z)	(((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z)))
+
+/* Four of six logical functions used in SHA-256: */
+#define Sigma0_256(x)	(S32(2,  (x)) ^ S32(13, (x)) ^ S32(22, (x)))
+#define Sigma1_256(x)	(S32(6,  (x)) ^ S32(11, (x)) ^ S32(25, (x)))
+#define sigma0_256(x)	(S32(7,  (x)) ^ S32(18, (x)) ^ R(3 ,   (x)))
+#define sigma1_256(x)	(S32(17, (x)) ^ S32(19, (x)) ^ R(10,   (x)))
+
+/* Four of six logical functions used in SHA-384 and SHA-512: */
+#define Sigma0_512(x)	(S64(28, (x)) ^ S64(34, (x)) ^ S64(39, (x)))
+#define Sigma1_512(x)	(S64(14, (x)) ^ S64(18, (x)) ^ S64(41, (x)))
+#define sigma0_512(x)	(S64( 1, (x)) ^ S64( 8, (x)) ^ R( 7,   (x)))
+#define sigma1_512(x)	(S64(19, (x)) ^ S64(61, (x)) ^ R( 6,   (x)))
+
+/*** INTERNAL FUNCTION PROTOTYPES *************************************/
+/* NOTE: These should not be accessed directly from outside this
+ * library -- they are intended for private internal visibility/use
+ * only.
+ */
+void SHA512_Last(SHA512_CTX*);
+void SHA256_Transform(SHA256_CTX*, const sha2_word32*);
+void SHA512_Transform(SHA512_CTX*, const sha2_word64*);
+
+
+/*** SHA-XYZ INITIAL HASH VALUES AND CONSTANTS ************************/
+/* Hash constant words K for SHA-256: */
+const static sha2_word32 K256[64] = {
+	0x428a2f98UL, 0x71374491UL, 0xb5c0fbcfUL, 0xe9b5dba5UL,
+	0x3956c25bUL, 0x59f111f1UL, 0x923f82a4UL, 0xab1c5ed5UL,
+	0xd807aa98UL, 0x12835b01UL, 0x243185beUL, 0x550c7dc3UL,
+	0x72be5d74UL, 0x80deb1feUL, 0x9bdc06a7UL, 0xc19bf174UL,
+	0xe49b69c1UL, 0xefbe4786UL, 0x0fc19dc6UL, 0x240ca1ccUL,
+	0x2de92c6fUL, 0x4a7484aaUL, 0x5cb0a9dcUL, 0x76f988daUL,
+	0x983e5152UL, 0xa831c66dUL, 0xb00327c8UL, 0xbf597fc7UL,
+	0xc6e00bf3UL, 0xd5a79147UL, 0x06ca6351UL, 0x14292967UL,
+	0x27b70a85UL, 0x2e1b2138UL, 0x4d2c6dfcUL, 0x53380d13UL,
+	0x650a7354UL, 0x766a0abbUL, 0x81c2c92eUL, 0x92722c85UL,
+	0xa2bfe8a1UL, 0xa81a664bUL, 0xc24b8b70UL, 0xc76c51a3UL,
+	0xd192e819UL, 0xd6990624UL, 0xf40e3585UL, 0x106aa070UL,
+	0x19a4c116UL, 0x1e376c08UL, 0x2748774cUL, 0x34b0bcb5UL,
+	0x391c0cb3UL, 0x4ed8aa4aUL, 0x5b9cca4fUL, 0x682e6ff3UL,
+	0x748f82eeUL, 0x78a5636fUL, 0x84c87814UL, 0x8cc70208UL,
+	0x90befffaUL, 0xa4506cebUL, 0xbef9a3f7UL, 0xc67178f2UL
+};
+
+/* Initial hash value H for SHA-256: */
+const static sha2_word32 sha256_initial_hash_value[8] = {
+	0x6a09e667UL,
+	0xbb67ae85UL,
+	0x3c6ef372UL,
+	0xa54ff53aUL,
+	0x510e527fUL,
+	0x9b05688cUL,
+	0x1f83d9abUL,
+	0x5be0cd19UL
+};
+
+/* Hash constant words K for SHA-384 and SHA-512: */
+const static sha2_word64 K512[80] = {
+	0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL,
+	0xb5c0fbcfec4d3b2fULL, 0xe9b5dba58189dbbcULL,
+	0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL,
+	0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL,
+	0xd807aa98a3030242ULL, 0x12835b0145706fbeULL,
+	0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL,
+	0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL,
+	0x9bdc06a725c71235ULL, 0xc19bf174cf692694ULL,
+	0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL,
+	0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL,
+	0x2de92c6f592b0275ULL, 0x4a7484aa6ea6e483ULL,
+	0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL,
+	0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL,
+	0xb00327c898fb213fULL, 0xbf597fc7beef0ee4ULL,
+	0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL,
+	0x06ca6351e003826fULL, 0x142929670a0e6e70ULL,
+	0x27b70a8546d22ffcULL, 0x2e1b21385c26c926ULL,
+	0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL,
+	0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL,
+	0x81c2c92e47edaee6ULL, 0x92722c851482353bULL,
+	0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL,
+	0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL,
+	0xd192e819d6ef5218ULL, 0xd69906245565a910ULL,
+	0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL,
+	0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL,
+	0x2748774cdf8eeb99ULL, 0x34b0bcb5e19b48a8ULL,
+	0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL,
+	0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL,
+	0x748f82ee5defb2fcULL, 0x78a5636f43172f60ULL,
+	0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL,
+	0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL,
+	0xbef9a3f7b2c67915ULL, 0xc67178f2e372532bULL,
+	0xca273eceea26619cULL, 0xd186b8c721c0c207ULL,
+	0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL,
+	0x06f067aa72176fbaULL, 0x0a637dc5a2c898a6ULL,
+	0x113f9804bef90daeULL, 0x1b710b35131c471bULL,
+	0x28db77f523047d84ULL, 0x32caab7b40c72493ULL,
+	0x3c9ebe0a15c9bebcULL, 0x431d67c49c100d4cULL,
+	0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL,
+	0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL
+};
+
+/* Initial hash value H for SHA-384 */
+const static sha2_word64 sha384_initial_hash_value[8] = {
+	0xcbbb9d5dc1059ed8ULL,
+	0x629a292a367cd507ULL,
+	0x9159015a3070dd17ULL,
+	0x152fecd8f70e5939ULL,
+	0x67332667ffc00b31ULL,
+	0x8eb44a8768581511ULL,
+	0xdb0c2e0d64f98fa7ULL,
+	0x47b5481dbefa4fa4ULL
+};
+
+/* Initial hash value H for SHA-512 */
+const static sha2_word64 sha512_initial_hash_value[8] = {
+	0x6a09e667f3bcc908ULL,
+	0xbb67ae8584caa73bULL,
+	0x3c6ef372fe94f82bULL,
+	0xa54ff53a5f1d36f1ULL,
+	0x510e527fade682d1ULL,
+	0x9b05688c2b3e6c1fULL,
+	0x1f83d9abfb41bd6bULL,
+	0x5be0cd19137e2179ULL
+};
+
+/*
+ * Constant used by SHA256/384/512_End() functions for converting the
+ * digest to a readable hexadecimal character string:
+ */
+static const char *sha2_hex_digits = "0123456789abcdef";
+
+
+/*** SHA-256: *********************************************************/
+void SHA256_Init(SHA256_CTX* context) {
+	if (context == (SHA256_CTX*)0) {
+		return;
+	}
+	bcopy(sha256_initial_hash_value, context->state, SHA256_DIGEST_LENGTH);
+	bzero(context->buffer, SHA256_BLOCK_LENGTH);
+	context->bitcount = 0;
+}
+
+#ifdef SHA2_UNROLL_TRANSFORM
+
+/* Unrolled SHA-256 round macros: */
+
+#if BYTE_ORDER == LITTLE_ENDIAN
+
+#define ROUND256_0_TO_15(a,b,c,d,e,f,g,h)	\
+	REVERSE32(*data++, W256[j]); \
+	T1 = (h) + Sigma1_256(e) + Ch((e), (f), (g)) + \
+             K256[j] + W256[j]; \
+	(d) += T1; \
+	(h) = T1 + Sigma0_256(a) + Maj((a), (b), (c)); \
+	j++
+
+
+#else /* BYTE_ORDER == LITTLE_ENDIAN */
+
+#define ROUND256_0_TO_15(a,b,c,d,e,f,g,h)	\
+	T1 = (h) + Sigma1_256(e) + Ch((e), (f), (g)) + \
+	     K256[j] + (W256[j] = *data++); \
+	(d) += T1; \
+	(h) = T1 + Sigma0_256(a) + Maj((a), (b), (c)); \
+	j++
+
+#endif /* BYTE_ORDER == LITTLE_ENDIAN */
+
+#define ROUND256(a,b,c,d,e,f,g,h)	\
+	s0 = W256[(j+1)&0x0f]; \
+	s0 = sigma0_256(s0); \
+	s1 = W256[(j+14)&0x0f]; \
+	s1 = sigma1_256(s1); \
+	T1 = (h) + Sigma1_256(e) + Ch((e), (f), (g)) + K256[j] + \
+	     (W256[j&0x0f] += s1 + W256[(j+9)&0x0f] + s0); \
+	(d) += T1; \
+	(h) = T1 + Sigma0_256(a) + Maj((a), (b), (c)); \
+	j++
+
+void SHA256_Transform(SHA256_CTX* context, const sha2_word32* data) {
+	sha2_word32	a, b, c, d, e, f, g, h, s0, s1;
+	sha2_word32	T1, *W256;
+	int		j;
+
+	W256 = (sha2_word32*)context->buffer;
+
+	/* Initialize registers with the prev. intermediate value */
+	a = context->state[0];
+	b = context->state[1];
+	c = context->state[2];
+	d = context->state[3];
+	e = context->state[4];
+	f = context->state[5];
+	g = context->state[6];
+	h = context->state[7];
+
+	j = 0;
+	do {
+		/* Rounds 0 to 15 (unrolled): */
+		ROUND256_0_TO_15(a,b,c,d,e,f,g,h);
+		ROUND256_0_TO_15(h,a,b,c,d,e,f,g);
+		ROUND256_0_TO_15(g,h,a,b,c,d,e,f);
+		ROUND256_0_TO_15(f,g,h,a,b,c,d,e);
+		ROUND256_0_TO_15(e,f,g,h,a,b,c,d);
+		ROUND256_0_TO_15(d,e,f,g,h,a,b,c);
+		ROUND256_0_TO_15(c,d,e,f,g,h,a,b);
+		ROUND256_0_TO_15(b,c,d,e,f,g,h,a);
+	} while (j < 16);
+
+	/* Now for the remaining rounds to 64: */
+	do {
+		ROUND256(a,b,c,d,e,f,g,h);
+		ROUND256(h,a,b,c,d,e,f,g);
+		ROUND256(g,h,a,b,c,d,e,f);
+		ROUND256(f,g,h,a,b,c,d,e);
+		ROUND256(e,f,g,h,a,b,c,d);
+		ROUND256(d,e,f,g,h,a,b,c);
+		ROUND256(c,d,e,f,g,h,a,b);
+		ROUND256(b,c,d,e,f,g,h,a);
+	} while (j < 64);
+
+	/* Compute the current intermediate hash value */
+	context->state[0] += a;
+	context->state[1] += b;
+	context->state[2] += c;
+	context->state[3] += d;
+	context->state[4] += e;
+	context->state[5] += f;
+	context->state[6] += g;
+	context->state[7] += h;
+
+	/* Clean up */
+	a = b = c = d = e = f = g = h = T1 = 0;
+}
+
+#else /* SHA2_UNROLL_TRANSFORM */
+
+void SHA256_Transform(SHA256_CTX* context, const sha2_word32* data) {
+	sha2_word32	a, b, c, d, e, f, g, h, s0, s1;
+	sha2_word32	T1, T2, *W256;
+	int		j;
+
+	W256 = (sha2_word32*)context->buffer;
+
+	/* Initialize registers with the prev. intermediate value */
+	a = context->state[0];
+	b = context->state[1];
+	c = context->state[2];
+	d = context->state[3];
+	e = context->state[4];
+	f = context->state[5];
+	g = context->state[6];
+	h = context->state[7];
+
+	j = 0;
+	do {
+#if BYTE_ORDER == LITTLE_ENDIAN
+		/* Copy data while converting to host byte order */
+		REVERSE32(*data++,W256[j]);
+		/* Apply the SHA-256 compression function to update a..h */
+		T1 = h + Sigma1_256(e) + Ch(e, f, g) + K256[j] + W256[j];
+#else /* BYTE_ORDER == LITTLE_ENDIAN */
+		/* Apply the SHA-256 compression function to update a..h with copy */
+		T1 = h + Sigma1_256(e) + Ch(e, f, g) + K256[j] + (W256[j] = *data++);
+#endif /* BYTE_ORDER == LITTLE_ENDIAN */
+		T2 = Sigma0_256(a) + Maj(a, b, c);
+		h = g;
+		g = f;
+		f = e;
+		e = d + T1;
+		d = c;
+		c = b;
+		b = a;
+		a = T1 + T2;
+
+		j++;
+	} while (j < 16);
+
+	do {
+		/* Part of the message block expansion: */
+		s0 = W256[(j+1)&0x0f];
+		s0 = sigma0_256(s0);
+		s1 = W256[(j+14)&0x0f];	
+		s1 = sigma1_256(s1);
+
+		/* Apply the SHA-256 compression function to update a..h */
+		T1 = h + Sigma1_256(e) + Ch(e, f, g) + K256[j] + 
+		     (W256[j&0x0f] += s1 + W256[(j+9)&0x0f] + s0);
+		T2 = Sigma0_256(a) + Maj(a, b, c);
+		h = g;
+		g = f;
+		f = e;
+		e = d + T1;
+		d = c;
+		c = b;
+		b = a;
+		a = T1 + T2;
+
+		j++;
+	} while (j < 64);
+
+	/* Compute the current intermediate hash value */
+	context->state[0] += a;
+	context->state[1] += b;
+	context->state[2] += c;
+	context->state[3] += d;
+	context->state[4] += e;
+	context->state[5] += f;
+	context->state[6] += g;
+	context->state[7] += h;
+
+	/* Clean up */
+	a = b = c = d = e = f = g = h = T1 = T2 = 0;
+}
+
+#endif /* SHA2_UNROLL_TRANSFORM */
+
+void SHA256_Update(SHA256_CTX* context, const sha2_byte *data, size_t len) {
+	unsigned int	freespace, usedspace;
+
+	if (len == 0) {
+		/* Calling with no data is valid - we do nothing */
+		return;
+	}
+
+	/* Sanity check: */
+	assert(context != (SHA256_CTX*)0 && data != (sha2_byte*)0);
+
+	usedspace = (context->bitcount >> 3) % SHA256_BLOCK_LENGTH;
+	if (usedspace > 0) {
+		/* Calculate how much free space is available in the buffer */
+		freespace = SHA256_BLOCK_LENGTH - usedspace;
+
+		if (len >= freespace) {
+			/* Fill the buffer completely and process it */
+			bcopy(data, &context->buffer[usedspace], freespace);
+			context->bitcount += freespace << 3;
+			len -= freespace;
+			data += freespace;
+			SHA256_Transform(context, (sha2_word32*)context->buffer);
+		} else {
+			/* The buffer is not yet full */
+			bcopy(data, &context->buffer[usedspace], len);
+			context->bitcount += len << 3;
+			/* Clean up: */
+			usedspace = freespace = 0;
+			return;
+		}
+	}
+	while (len >= SHA256_BLOCK_LENGTH) {
+		/* Process as many complete blocks as we can */
+		SHA256_Transform(context, (const sha2_word32*)data);
+		context->bitcount += SHA256_BLOCK_LENGTH << 3;
+		len -= SHA256_BLOCK_LENGTH;
+		data += SHA256_BLOCK_LENGTH;
+	}
+	if (len > 0) {
+		/* There's left-overs, so save 'em */
+		bcopy(data, context->buffer, len);
+		context->bitcount += len << 3;
+	}
+	/* Clean up: */
+	usedspace = freespace = 0;
+}
+
+void SHA256_Final(sha2_byte digest[], SHA256_CTX* context) {
+	sha2_word32	*d = (sha2_word32*)digest;
+	unsigned int	usedspace;
+
+	/* Sanity check: */
+	assert(context != (SHA256_CTX*)0);
+
+	/* If no digest buffer is passed, we don't bother doing this: */
+	if (digest != (sha2_byte*)0) {
+		usedspace = (context->bitcount >> 3) % SHA256_BLOCK_LENGTH;
+#if BYTE_ORDER == LITTLE_ENDIAN
+		/* Convert FROM host byte order */
+		REVERSE64(context->bitcount,context->bitcount);
+#endif
+		if (usedspace > 0) {
+			/* Begin padding with a 1 bit: */
+			context->buffer[usedspace++] = 0x80;
+
+			if (usedspace <= SHA256_SHORT_BLOCK_LENGTH) {
+				/* Set-up for the last transform: */
+				bzero(&context->buffer[usedspace], SHA256_SHORT_BLOCK_LENGTH - usedspace);
+			} else {
+				if (usedspace < SHA256_BLOCK_LENGTH) {
+					bzero(&context->buffer[usedspace], SHA256_BLOCK_LENGTH - usedspace);
+				}
+				/* Do second-to-last transform: */
+				SHA256_Transform(context, (sha2_word32*)context->buffer);
+
+				/* And set-up for the last transform: */
+				bzero(context->buffer, SHA256_SHORT_BLOCK_LENGTH);
+			}
+		} else {
+			/* Set-up for the last transform: */
+			bzero(context->buffer, SHA256_SHORT_BLOCK_LENGTH);
+
+			/* Begin padding with a 1 bit: */
+			*context->buffer = 0x80;
+		}
+		/* Set the bit count: */
+		*(sha2_word64*)&context->buffer[SHA256_SHORT_BLOCK_LENGTH] = context->bitcount;
+
+		/* Final transform: */
+		SHA256_Transform(context, (sha2_word32*)context->buffer);
+
+#if BYTE_ORDER == LITTLE_ENDIAN
+		{
+			/* Convert TO host byte order */
+			int	j;
+			for (j = 0; j < 8; j++) {
+				REVERSE32(context->state[j],context->state[j]);
+				*d++ = context->state[j];
+			}
+		}
+#else
+		bcopy(context->state, d, SHA256_DIGEST_LENGTH);
+#endif
+	}
+
+	/* Clean up state data: */
+	bzero(context, sizeof(*context));
+	usedspace = 0;
+}
+
+char *SHA256_End(SHA256_CTX* context, char buffer[]) {
+	sha2_byte	digest[SHA256_DIGEST_LENGTH], *d = digest;
+	int		i;
+
+	/* Sanity check: */
+	assert(context != (SHA256_CTX*)0);
+
+	if (buffer != (char*)0) {
+		SHA256_Final(digest, context);
+
+		for (i = 0; i < SHA256_DIGEST_LENGTH; i++) {
+			*buffer++ = sha2_hex_digits[(*d & 0xf0) >> 4];
+			*buffer++ = sha2_hex_digits[*d & 0x0f];
+			d++;
+		}
+		*buffer = (char)0;
+	} else {
+		bzero(context, sizeof(*context));
+	}
+	bzero(digest, SHA256_DIGEST_LENGTH);
+	return buffer;
+}
+
+char* SHA256_Data(const sha2_byte* data, size_t len, char digest[SHA256_DIGEST_STRING_LENGTH]) {
+	SHA256_CTX	context;
+
+	SHA256_Init(&context);
+	SHA256_Update(&context, data, len);
+	return SHA256_End(&context, digest);
+}
+
+
+/*** SHA-512: *********************************************************/
+void SHA512_Init(SHA512_CTX* context) {
+	if (context == (SHA512_CTX*)0) {
+		return;
+	}
+	bcopy(sha512_initial_hash_value, context->state, SHA512_DIGEST_LENGTH);
+	bzero(context->buffer, SHA512_BLOCK_LENGTH);
+	context->bitcount[0] = context->bitcount[1] =  0;
+}
+
+#ifdef SHA2_UNROLL_TRANSFORM
+
+/* Unrolled SHA-512 round macros: */
+#if BYTE_ORDER == LITTLE_ENDIAN
+
+#define ROUND512_0_TO_15(a,b,c,d,e,f,g,h)	\
+	REVERSE64(*data++, W512[j]); \
+	T1 = (h) + Sigma1_512(e) + Ch((e), (f), (g)) + \
+             K512[j] + W512[j]; \
+	(d) += T1, \
+	(h) = T1 + Sigma0_512(a) + Maj((a), (b), (c)), \
+	j++
+
+
+#else /* BYTE_ORDER == LITTLE_ENDIAN */
+
+#define ROUND512_0_TO_15(a,b,c,d,e,f,g,h)	\
+	T1 = (h) + Sigma1_512(e) + Ch((e), (f), (g)) + \
+             K512[j] + (W512[j] = *data++); \
+	(d) += T1; \
+	(h) = T1 + Sigma0_512(a) + Maj((a), (b), (c)); \
+	j++
+
+#endif /* BYTE_ORDER == LITTLE_ENDIAN */
+
+#define ROUND512(a,b,c,d,e,f,g,h)	\
+	s0 = W512[(j+1)&0x0f]; \
+	s0 = sigma0_512(s0); \
+	s1 = W512[(j+14)&0x0f]; \
+	s1 = sigma1_512(s1); \
+	T1 = (h) + Sigma1_512(e) + Ch((e), (f), (g)) + K512[j] + \
+             (W512[j&0x0f] += s1 + W512[(j+9)&0x0f] + s0); \
+	(d) += T1; \
+	(h) = T1 + Sigma0_512(a) + Maj((a), (b), (c)); \
+	j++
+
+void SHA512_Transform(SHA512_CTX* context, const sha2_word64* data) {
+	sha2_word64	a, b, c, d, e, f, g, h, s0, s1;
+	sha2_word64	T1, *W512 = (sha2_word64*)context->buffer;
+	int		j;
+
+	/* Initialize registers with the prev. intermediate value */
+	a = context->state[0];
+	b = context->state[1];
+	c = context->state[2];
+	d = context->state[3];
+	e = context->state[4];
+	f = context->state[5];
+	g = context->state[6];
+	h = context->state[7];
+
+	j = 0;
+	do {
+		ROUND512_0_TO_15(a,b,c,d,e,f,g,h);
+		ROUND512_0_TO_15(h,a,b,c,d,e,f,g);
+		ROUND512_0_TO_15(g,h,a,b,c,d,e,f);
+		ROUND512_0_TO_15(f,g,h,a,b,c,d,e);
+		ROUND512_0_TO_15(e,f,g,h,a,b,c,d);
+		ROUND512_0_TO_15(d,e,f,g,h,a,b,c);
+		ROUND512_0_TO_15(c,d,e,f,g,h,a,b);
+		ROUND512_0_TO_15(b,c,d,e,f,g,h,a);
+	} while (j < 16);
+
+	/* Now for the remaining rounds up to 79: */
+	do {
+		ROUND512(a,b,c,d,e,f,g,h);
+		ROUND512(h,a,b,c,d,e,f,g);
+		ROUND512(g,h,a,b,c,d,e,f);
+		ROUND512(f,g,h,a,b,c,d,e);
+		ROUND512(e,f,g,h,a,b,c,d);
+		ROUND512(d,e,f,g,h,a,b,c);
+		ROUND512(c,d,e,f,g,h,a,b);
+		ROUND512(b,c,d,e,f,g,h,a);
+	} while (j < 80);
+
+	/* Compute the current intermediate hash value */
+	context->state[0] += a;
+	context->state[1] += b;
+	context->state[2] += c;
+	context->state[3] += d;
+	context->state[4] += e;
+	context->state[5] += f;
+	context->state[6] += g;
+	context->state[7] += h;
+
+	/* Clean up */
+	a = b = c = d = e = f = g = h = T1 = 0;
+}
+
+#else /* SHA2_UNROLL_TRANSFORM */
+
+void SHA512_Transform(SHA512_CTX* context, const sha2_word64* data) {
+	sha2_word64	a, b, c, d, e, f, g, h, s0, s1;
+	sha2_word64	T1, T2, *W512 = (sha2_word64*)context->buffer;
+	int		j;
+
+	/* Initialize registers with the prev. intermediate value */
+	a = context->state[0];
+	b = context->state[1];
+	c = context->state[2];
+	d = context->state[3];
+	e = context->state[4];
+	f = context->state[5];
+	g = context->state[6];
+	h = context->state[7];
+
+	j = 0;
+	do {
+#if BYTE_ORDER == LITTLE_ENDIAN
+		/* Convert TO host byte order */
+		REVERSE64(*data++, W512[j]);
+		/* Apply the SHA-512 compression function to update a..h */
+		T1 = h + Sigma1_512(e) + Ch(e, f, g) + K512[j] + W512[j];
+#else /* BYTE_ORDER == LITTLE_ENDIAN */
+		/* Apply the SHA-512 compression function to update a..h with copy */
+		T1 = h + Sigma1_512(e) + Ch(e, f, g) + K512[j] + (W512[j] = *data++);
+#endif /* BYTE_ORDER == LITTLE_ENDIAN */
+		T2 = Sigma0_512(a) + Maj(a, b, c);
+		h = g;
+		g = f;
+		f = e;
+		e = d + T1;
+		d = c;
+		c = b;
+		b = a;
+		a = T1 + T2;
+
+		j++;
+	} while (j < 16);
+
+	do {
+		/* Part of the message block expansion: */
+		s0 = W512[(j+1)&0x0f];
+		s0 = sigma0_512(s0);
+		s1 = W512[(j+14)&0x0f];
+		s1 =  sigma1_512(s1);
+
+		/* Apply the SHA-512 compression function to update a..h */
+		T1 = h + Sigma1_512(e) + Ch(e, f, g) + K512[j] +
+		     (W512[j&0x0f] += s1 + W512[(j+9)&0x0f] + s0);
+		T2 = Sigma0_512(a) + Maj(a, b, c);
+		h = g;
+		g = f;
+		f = e;
+		e = d + T1;
+		d = c;
+		c = b;
+		b = a;
+		a = T1 + T2;
+
+		j++;
+	} while (j < 80);
+
+	/* Compute the current intermediate hash value */
+	context->state[0] += a;
+	context->state[1] += b;
+	context->state[2] += c;
+	context->state[3] += d;
+	context->state[4] += e;
+	context->state[5] += f;
+	context->state[6] += g;
+	context->state[7] += h;
+
+	/* Clean up */
+	a = b = c = d = e = f = g = h = T1 = T2 = 0;
+}
+
+#endif /* SHA2_UNROLL_TRANSFORM */
+
+void SHA512_Update(SHA512_CTX* context, const sha2_byte *data, size_t len) {
+	unsigned int	freespace, usedspace;
+
+	if (len == 0) {
+		/* Calling with no data is valid - we do nothing */
+		return;
+	}
+
+	/* Sanity check: */
+	assert(context != (SHA512_CTX*)0 && data != (sha2_byte*)0);
+
+	usedspace = (context->bitcount[0] >> 3) % SHA512_BLOCK_LENGTH;
+	if (usedspace > 0) {
+		/* Calculate how much free space is available in the buffer */
+		freespace = SHA512_BLOCK_LENGTH - usedspace;
+
+		if (len >= freespace) {
+			/* Fill the buffer completely and process it */
+			bcopy(data, &context->buffer[usedspace], freespace);
+			ADDINC128(context->bitcount, freespace << 3);
+			len -= freespace;
+			data += freespace;
+			SHA512_Transform(context, (sha2_word64*)context->buffer);
+		} else {
+			/* The buffer is not yet full */
+			bcopy(data, &context->buffer[usedspace], len);
+			ADDINC128(context->bitcount, len << 3);
+			/* Clean up: */
+			usedspace = freespace = 0;
+			return;
+		}
+	}
+	while (len >= SHA512_BLOCK_LENGTH) {
+		/* Process as many complete blocks as we can */
+		SHA512_Transform(context, (const sha2_word64*)data);
+		ADDINC128(context->bitcount, SHA512_BLOCK_LENGTH << 3);
+		len -= SHA512_BLOCK_LENGTH;
+		data += SHA512_BLOCK_LENGTH;
+	}
+	if (len > 0) {
+		/* There's left-overs, so save 'em */
+		bcopy(data, context->buffer, len);
+		ADDINC128(context->bitcount, len << 3);
+	}
+	/* Clean up: */
+	usedspace = freespace = 0;
+}
+
+void SHA512_Last(SHA512_CTX* context) {
+	unsigned int	usedspace;
+
+	usedspace = (context->bitcount[0] >> 3) % SHA512_BLOCK_LENGTH;
+#if BYTE_ORDER == LITTLE_ENDIAN
+	/* Convert FROM host byte order */
+	REVERSE64(context->bitcount[0],context->bitcount[0]);
+	REVERSE64(context->bitcount[1],context->bitcount[1]);
+#endif
+	if (usedspace > 0) {
+		/* Begin padding with a 1 bit: */
+		context->buffer[usedspace++] = 0x80;
+
+		if (usedspace <= SHA512_SHORT_BLOCK_LENGTH) {
+			/* Set-up for the last transform: */
+			bzero(&context->buffer[usedspace], SHA512_SHORT_BLOCK_LENGTH - usedspace);
+		} else {
+			if (usedspace < SHA512_BLOCK_LENGTH) {
+				bzero(&context->buffer[usedspace], SHA512_BLOCK_LENGTH - usedspace);
+			}
+			/* Do second-to-last transform: */
+			SHA512_Transform(context, (sha2_word64*)context->buffer);
+
+			/* And set-up for the last transform: */
+			bzero(context->buffer, SHA512_BLOCK_LENGTH - 2);
+		}
+	} else {
+		/* Prepare for final transform: */
+		bzero(context->buffer, SHA512_SHORT_BLOCK_LENGTH);
+
+		/* Begin padding with a 1 bit: */
+		*context->buffer = 0x80;
+	}
+	/* Store the length of input data (in bits): */
+	*(sha2_word64*)&context->buffer[SHA512_SHORT_BLOCK_LENGTH] = context->bitcount[1];
+	*(sha2_word64*)&context->buffer[SHA512_SHORT_BLOCK_LENGTH+8] = context->bitcount[0];
+
+	/* Final transform: */
+	SHA512_Transform(context, (sha2_word64*)context->buffer);
+}
+
+void SHA512_Final(sha2_byte digest[], SHA512_CTX* context) {
+	sha2_word64	*d = (sha2_word64*)digest;
+
+	/* Sanity check: */
+	assert(context != (SHA512_CTX*)0);
+
+	/* If no digest buffer is passed, we don't bother doing this: */
+	if (digest != (sha2_byte*)0) {
+		SHA512_Last(context);
+
+		/* Save the hash data for output: */
+#if BYTE_ORDER == LITTLE_ENDIAN
+		{
+			/* Convert TO host byte order */
+			int	j;
+			for (j = 0; j < 8; j++) {
+				REVERSE64(context->state[j],context->state[j]);
+				*d++ = context->state[j];
+			}
+		}
+#else
+		bcopy(context->state, d, SHA512_DIGEST_LENGTH);
+#endif
+	}
+
+	/* Zero out state data */
+	bzero(context, sizeof(*context));
+}
+
+char *SHA512_End(SHA512_CTX* context, char buffer[]) {
+	sha2_byte	digest[SHA512_DIGEST_LENGTH], *d = digest;
+	int		i;
+
+	/* Sanity check: */
+	assert(context != (SHA512_CTX*)0);
+
+	if (buffer != (char*)0) {
+		SHA512_Final(digest, context);
+
+		for (i = 0; i < SHA512_DIGEST_LENGTH; i++) {
+			*buffer++ = sha2_hex_digits[(*d & 0xf0) >> 4];
+			*buffer++ = sha2_hex_digits[*d & 0x0f];
+			d++;
+		}
+		*buffer = (char)0;
+	} else {
+		bzero(context, sizeof(*context));
+	}
+	bzero(digest, SHA512_DIGEST_LENGTH);
+	return buffer;
+}
+
+char* SHA512_Data(const sha2_byte* data, size_t len, char digest[SHA512_DIGEST_STRING_LENGTH]) {
+	SHA512_CTX	context;
+
+	SHA512_Init(&context);
+	SHA512_Update(&context, data, len);
+	return SHA512_End(&context, digest);
+}
+
+
+/*** SHA-384: *********************************************************/
+void SHA384_Init(SHA384_CTX* context) {
+	if (context == (SHA384_CTX*)0) {
+		return;
+	}
+	bcopy(sha384_initial_hash_value, context->state, SHA512_DIGEST_LENGTH);
+	bzero(context->buffer, SHA384_BLOCK_LENGTH);
+	context->bitcount[0] = context->bitcount[1] = 0;
+}
+
+void SHA384_Update(SHA384_CTX* context, const sha2_byte* data, size_t len) {
+	SHA512_Update((SHA512_CTX*)context, data, len);
+}
+
+void SHA384_Final(sha2_byte digest[], SHA384_CTX* context) {
+	sha2_word64	*d = (sha2_word64*)digest;
+
+	/* Sanity check: */
+	assert(context != (SHA384_CTX*)0);
+
+	/* If no digest buffer is passed, we don't bother doing this: */
+	if (digest != (sha2_byte*)0) {
+		SHA512_Last((SHA512_CTX*)context);
+
+		/* Save the hash data for output: */
+#if BYTE_ORDER == LITTLE_ENDIAN
+		{
+			/* Convert TO host byte order */
+			int	j;
+			for (j = 0; j < 6; j++) {
+				REVERSE64(context->state[j],context->state[j]);
+				*d++ = context->state[j];
+			}
+		}
+#else
+		bcopy(context->state, d, SHA384_DIGEST_LENGTH);
+#endif
+	}
+
+	/* Zero out state data */
+	bzero(context, sizeof(*context));
+}
+
+char *SHA384_End(SHA384_CTX* context, char buffer[]) {
+	sha2_byte	digest[SHA384_DIGEST_LENGTH], *d = digest;
+	int		i;
+
+	/* Sanity check: */
+	assert(context != (SHA384_CTX*)0);
+
+	if (buffer != (char*)0) {
+		SHA384_Final(digest, context);
+
+		for (i = 0; i < SHA384_DIGEST_LENGTH; i++) {
+			*buffer++ = sha2_hex_digits[(*d & 0xf0) >> 4];
+			*buffer++ = sha2_hex_digits[*d & 0x0f];
+			d++;
+		}
+		*buffer = (char)0;
+	} else {
+		bzero(context, sizeof(*context));
+	}
+	bzero(digest, SHA384_DIGEST_LENGTH);
+	return buffer;
+}
+
+char* SHA384_Data(const sha2_byte* data, size_t len, char digest[SHA384_DIGEST_STRING_LENGTH]) {
+	SHA384_CTX	context;
+
+	SHA384_Init(&context);
+	SHA384_Update(&context, data, len);
+	return SHA384_End(&context, digest);
+}
+
+/*glue*/
+#ifdef HAVE_EVP_097
+
+/* SHA256 */
+#define data(ctx) ((SHA256_CTX *)(ctx)->md_data)
+static int sha256_init(EVP_MD_CTX *ctx)
+{
+  SHA256_Init(data(ctx));
+  return 1;
+}
+static int sha256_update(EVP_MD_CTX *ctx, const void *data, unsigned long count)
+{
+  SHA256_Update(data(ctx), data, count);
+  return 1;
+}
+static int sha256_final(EVP_MD_CTX *ctx, unsigned char *md)
+{
+  SHA256_Final(md, data(ctx));
+  return 1;
+}
+#undef data
+
+/* SHA384 */
+#define data(ctx) ((SHA384_CTX *)(ctx)->md_data)
+static int sha384_init(EVP_MD_CTX *ctx)
+{
+  SHA384_Init(data(ctx));
+  return 1;
+}
+static int sha384_update(EVP_MD_CTX *ctx, const void *data, unsigned long count)
+{
+  SHA384_Update(data(ctx), data, count);
+  return 1;
+}
+static int sha384_final(EVP_MD_CTX *ctx, unsigned char *md)
+{
+  SHA384_Final(md, data(ctx));
+  return 1;
+}
+#undef data
+
+/* SHA512 */
+#define data(ctx) ((SHA512_CTX *)(ctx)->md_data)
+static int sha512_init(EVP_MD_CTX *ctx)
+{
+  SHA512_Init(data(ctx));
+  return 1;
+}
+static int sha512_update(EVP_MD_CTX *ctx, const void *data, unsigned long count)
+{
+  SHA512_Update(data(ctx), data, count);
+  return 1;
+}
+static int sha512_final(EVP_MD_CTX *ctx, unsigned char *md)
+{
+  SHA512_Final(md, data(ctx));
+  return 1;
+}
+#undef data
+#endif
+
+static struct env_md_st sha2_256_md = {
+	0, /*NID_sha1*/
+	0, /*NID_sha1WithRSAEncryption*/
+	SHA256_DIGEST_LENGTH,
+#ifdef HAVE_EVP_097
+	0,			/* flags */
+	sha256_init,
+	sha256_update,
+	sha256_final,
+	NULL,			/* copy */
+	NULL,			/* cleanup */
+#else
+	SHA256_Init,
+	SHA256_Update,
+	SHA256_Final,
+#endif
+	NULL, NULL, {0, 0, 0, 0},
+	SHA256_BLOCK_LENGTH,
+	sizeof(struct env_md_st *) + sizeof(SHA256_CTX),
+};
+
+struct env_md_st *EVP_sha2_256(void)
+{
+	return(&sha2_256_md);
+}
+
+static struct env_md_st sha2_384_md = {
+	0, /*NID_sha1*/
+	0, /*NID_sha1WithRSAEncryption*/
+	SHA384_DIGEST_LENGTH,
+#ifdef HAVE_EVP_097
+	0,			/* flags */
+	sha384_init,
+	sha384_update,
+	sha384_final,
+	NULL,			/* copy */
+	NULL,			/* cleanup */
+#else
+	SHA384_Init,
+	SHA384_Update,
+	SHA384_Final,
+#endif
+	NULL, NULL, {0, 0, 0, 0},
+	SHA384_BLOCK_LENGTH,
+	sizeof(struct env_md_st *) + sizeof(SHA384_CTX),
+};
+
+struct env_md_st *EVP_sha2_384(void)
+{
+	return(&sha2_384_md);
+}
+
+static struct env_md_st sha2_512_md = {
+	0, /*NID_sha1*/
+	0, /*NID_sha1WithRSAEncryption*/
+	SHA512_DIGEST_LENGTH,
+#ifdef HAVE_EVP_097
+	0,			/* flags */
+	sha512_init,
+	sha512_update,
+	sha512_final,
+	NULL,			/* copy */
+	NULL,			/* cleanup */
+#else
+	SHA512_Init,
+	SHA512_Update,
+	SHA512_Final,
+#endif
+	NULL, NULL, {0, 0, 0, 0}, /*EVP_PKEY_RSA_method*/
+	SHA512_BLOCK_LENGTH,
+	sizeof(struct env_md_st *) + sizeof(SHA512_CTX),
+};
+
+struct env_md_st *EVP_sha2_512(void)
+{
+	return(&sha2_512_md);
+}
diff --git a/src/racoon/missing/crypto/sha2/sha2.h b/src/racoon/missing/crypto/sha2/sha2.h
new file mode 100644
index 0000000..42bcc2a
--- /dev/null
+++ b/src/racoon/missing/crypto/sha2/sha2.h
@@ -0,0 +1,161 @@
+/*	$NetBSD: sha2.h,v 1.4 2006/09/09 16:22:36 manu Exp $	*/
+
+/*	$KAME: sha2.h,v 1.2 2001/08/08 22:09:27 sakane Exp $	*/
+
+/*
+ * sha2.h
+ *
+ * Version 1.0.0beta1
+ *
+ * Written by Aaron D. Gifford <me@aarongifford.com>
+ *
+ * Copyright 2000 Aaron D. Gifford.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holder nor the names of contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) AND CONTRIBUTOR(S) ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR(S) OR CONTRIBUTOR(S) BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#ifndef __SHA2_H__
+#define __SHA2_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/*** SHA-256/384/512 Various Length Definitions ***********************/
+#define SHA256_BLOCK_LENGTH		64
+#define SHA256_DIGEST_LENGTH		32
+#define SHA256_DIGEST_STRING_LENGTH	(SHA256_DIGEST_LENGTH * 2 + 1)
+#define SHA384_BLOCK_LENGTH		128
+#define SHA384_DIGEST_LENGTH		48
+#define SHA384_DIGEST_STRING_LENGTH	(SHA384_DIGEST_LENGTH * 2 + 1)
+#define SHA512_BLOCK_LENGTH		128
+#define SHA512_DIGEST_LENGTH		64
+#define SHA512_DIGEST_STRING_LENGTH	(SHA512_DIGEST_LENGTH * 2 + 1)
+
+
+/*** SHA-256/384/512 Context Structures *******************************/
+/* NOTE: If your architecture does not define either u_intXX_t types or
+ * uintXX_t (from inttypes.h), you may need to define things by hand
+ * for your system:
+ */
+#if 0
+typedef unsigned char u_int8_t;		/* 1-byte  (8-bits)  */
+typedef unsigned int u_int32_t;		/* 4-bytes (32-bits) */
+typedef unsigned long long u_int64_t;	/* 8-bytes (64-bits) */
+#endif
+
+#ifndef HAVE_SHA2_IN_SHA_H
+/*
+ * Most BSD systems already define u_intXX_t types, as does Linux.
+ * Some systems, however, like Compaq's Tru64 Unix instead can use
+ * uintXX_t types defined by very recent ANSI C standards and included
+ * in the file:
+ *
+ *   #include <inttypes.h>
+ *
+ * If you choose to use <inttypes.h> then please define: 
+ *
+ *   #define SHA2_USE_INTTYPES_H
+ *
+ * Or on the command line during compile:
+ *
+ *   cc -DSHA2_USE_INTTYPES_H ...
+ */
+#if 0 /*def SHA2_USE_INTTYPES_H*/
+
+typedef struct _SHA256_CTX {
+	uint32_t	state[8];
+	uint64_t	bitcount;
+	uint8_t	buffer[SHA256_BLOCK_LENGTH];
+} SHA256_CTX;
+typedef struct _SHA512_CTX {
+	uint64_t	state[8];
+	uint64_t	bitcount[2];
+	uint8_t	buffer[SHA512_BLOCK_LENGTH];
+} SHA512_CTX;
+
+#else /* SHA2_USE_INTTYPES_H */
+
+typedef struct _SHA256_CTX {
+	u_int32_t	state[8];
+	u_int64_t	bitcount;
+	u_int8_t	buffer[SHA256_BLOCK_LENGTH];
+} SHA256_CTX;
+typedef struct _SHA512_CTX {
+	u_int64_t	state[8];
+	u_int64_t	bitcount[2];
+	u_int8_t	buffer[SHA512_BLOCK_LENGTH];
+} SHA512_CTX;
+
+#endif /* SHA2_USE_INTTYPES_H */
+#endif /* HAVE_SHA2_IN_SHA_H */
+
+typedef SHA512_CTX SHA384_CTX;
+
+
+/*** SHA-256/384/512 Function Prototypes ******************************/
+
+#ifndef HAVE_SHA2_IN_SHA_H
+void SHA256_Init __P((SHA256_CTX *));
+void SHA256_Update __P((SHA256_CTX*, const u_int8_t*, size_t));
+void SHA256_Final __P((u_int8_t[SHA256_DIGEST_LENGTH], SHA256_CTX*));
+#endif /* HAVE_SHA2_IN_SHA_H */
+char* SHA256_End __P((SHA256_CTX*, char[SHA256_DIGEST_STRING_LENGTH]));
+char* SHA256_Data __P((const u_int8_t*, size_t, char[SHA256_DIGEST_STRING_LENGTH]));
+
+#ifndef HAVE_SHA2_IN_SHA_H
+void SHA384_Init __P((SHA384_CTX*));
+void SHA384_Update __P((SHA384_CTX*, const u_int8_t*, size_t));
+void SHA384_Final __P((u_int8_t[SHA384_DIGEST_LENGTH], SHA384_CTX*));
+#endif /* HAVE_SHA2_IN_SHA_H */
+char* SHA384_End __P((SHA384_CTX*, char[SHA384_DIGEST_STRING_LENGTH]));
+char* SHA384_Data __P((const u_int8_t*, size_t, char[SHA384_DIGEST_STRING_LENGTH]));
+
+#ifndef HAVE_SHA2_IN_SHA_H
+void SHA512_Init __P((SHA512_CTX*));
+void SHA512_Update __P((SHA512_CTX*, const u_int8_t*, size_t));
+void SHA512_Final __P((u_int8_t[SHA512_DIGEST_LENGTH], SHA512_CTX*));
+#endif /* HAVE_SHA2_IN_SHA_H */
+char* SHA512_End __P((SHA512_CTX*, char[SHA512_DIGEST_STRING_LENGTH]));
+char* SHA512_Data __P((const u_int8_t*, size_t, char[SHA512_DIGEST_STRING_LENGTH]));
+
+struct env_md_st *EVP_sha2_256 __P((void));
+struct env_md_st *EVP_sha2_384 __P((void));
+struct env_md_st *EVP_sha2_512 __P((void));
+
+#ifdef HAVE_SHA2_IN_SHA_H
+#define EVP_sha2_256 EVP_sha256
+#define EVP_sha2_384 EVP_sha384
+#define EVP_sha2_512 EVP_sha512
+#endif
+
+#ifdef	__cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __SHA2_H__ */
+
diff --git a/src/racoon/nattraversal.c b/src/racoon/nattraversal.c
new file mode 100644
index 0000000..b6e08a1
--- /dev/null
+++ b/src/racoon/nattraversal.c
@@ -0,0 +1,521 @@
+/*	$NetBSD: nattraversal.c,v 1.6 2006/09/09 16:22:09 manu Exp $	*/
+
+/*
+ * Copyright (C) 2004 SuSE Linux AG, Nuernberg, Germany.
+ * Contributed by: Michal Ludvig <mludvig@suse.cz>, SUSE Labs
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include <sys/types.h>
+#include <sys/param.h>
+
+#ifdef __linux__
+#include <linux/udp.h>
+#endif
+#if defined(__NetBSD__) || defined (__FreeBSD__)
+#include <netinet/udp.h>
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <ctype.h>
+
+#include "var.h"
+#include "misc.h"
+#include "vmbuf.h"
+#include "plog.h"
+#include "debug.h"
+
+#include "localconf.h"
+#include "remoteconf.h"
+#include "sockmisc.h"
+#include "isakmp_var.h"
+#include "isakmp.h"
+#include "oakley.h"
+#include "ipsec_doi.h"
+#include "vendorid.h"
+#include "handler.h"
+#include "crypto_openssl.h"
+#include "schedule.h"
+#include "nattraversal.h"
+#include "grabmyaddr.h"
+
+struct natt_ka_addrs {
+  struct sockaddr	*src;
+  struct sockaddr	*dst;
+  unsigned		in_use;
+
+  TAILQ_ENTRY(natt_ka_addrs) chain;
+};
+
+static TAILQ_HEAD(_natt_ka_addrs, natt_ka_addrs) ka_tree;
+
+/*
+ * check if the given vid is NAT-T.
+ */
+int
+natt_vendorid (int vid)
+{
+  return (
+#ifdef ENABLE_NATT_00
+	  vid == VENDORID_NATT_00 ||
+#endif
+#ifdef ENABLE_NATT_01
+	  vid == VENDORID_NATT_01 ||
+#endif
+#ifdef ENABLE_NATT_02
+	  vid == VENDORID_NATT_02 ||
+	  vid == VENDORID_NATT_02_N ||
+#endif
+#ifdef ENABLE_NATT_03
+	  vid == VENDORID_NATT_03 ||
+#endif
+#ifdef ENABLE_NATT_04
+	  vid == VENDORID_NATT_04 ||
+#endif
+#ifdef ENABLE_NATT_05
+	  vid == VENDORID_NATT_05 ||
+#endif
+#ifdef ENABLE_NATT_06
+	  vid == VENDORID_NATT_06 ||
+#endif
+#ifdef ENABLE_NATT_07
+	  vid == VENDORID_NATT_07 ||
+#endif
+#ifdef ENABLE_NATT_08
+	  vid == VENDORID_NATT_08 ||
+#endif
+	  /* Always enable NATT RFC if ENABLE_NATT
+	   */
+	  vid == VENDORID_NATT_RFC);
+}
+
+vchar_t *
+natt_hash_addr (struct ph1handle *iph1, struct sockaddr *addr)
+{
+  vchar_t *natd;
+  vchar_t *buf;
+  char *ptr;
+  void *addr_ptr, *addr_port;
+  size_t buf_size, addr_size;
+
+  plog (LLV_INFO, LOCATION, addr, "Hashing %s with algo #%d %s\n",
+	saddr2str(addr), iph1->approval->hashtype, 
+	(iph1->rmconf->nat_traversal == NATT_FORCE)?"(NAT-T forced)":"");
+  
+  if (addr->sa_family == AF_INET) {
+    addr_size = sizeof (struct in_addr);	/* IPv4 address */
+    addr_ptr = &((struct sockaddr_in *)addr)->sin_addr;
+    addr_port = &((struct sockaddr_in *)addr)->sin_port;
+  }
+  else if (addr->sa_family == AF_INET6) {
+    addr_size = sizeof (struct in6_addr);	/* IPv6 address */
+    addr_ptr = &((struct sockaddr_in6 *)addr)->sin6_addr;
+    addr_port = &((struct sockaddr_in6 *)addr)->sin6_port;
+  }
+  else {
+    plog (LLV_ERROR, LOCATION, addr, "Unsupported address family #0x%x\n", addr->sa_family);
+    return NULL;
+  }
+
+  buf_size = 2 * sizeof (cookie_t);	/* CKY-I + CKY+R */
+  buf_size += addr_size + 2;	/* Address + Port */
+  
+  if ((buf = vmalloc (buf_size)) == NULL)
+    return NULL;
+
+  ptr = buf->v;
+  
+  /* Copy-in CKY-I */
+  memcpy (ptr, iph1->index.i_ck, sizeof (cookie_t));
+  ptr += sizeof (cookie_t);
+  
+  /* Copy-in CKY-I */
+  memcpy (ptr, iph1->index.r_ck, sizeof (cookie_t));
+  ptr += sizeof (cookie_t);
+  
+  /* Copy-in Address (or zeroes if NATT_FORCE) */
+  if (iph1->rmconf->nat_traversal == NATT_FORCE)
+    memset (ptr, 0, addr_size);
+  else
+    memcpy (ptr, addr_ptr, addr_size);
+  ptr += addr_size;
+
+  /* Copy-in Port number */
+  memcpy (ptr, addr_port, 2);
+
+  natd = oakley_hash (buf, iph1);
+  vfree(buf);
+
+  return natd;
+}
+
+int 
+natt_compare_addr_hash (struct ph1handle *iph1, vchar_t *natd_received,
+			int natd_seq)
+{
+  vchar_t *natd_computed;
+  u_int32_t flag;
+  int verified = 0;
+
+  if (iph1->rmconf->nat_traversal == NATT_FORCE)
+    return verified;
+
+  if (natd_seq == 0) {
+    natd_computed = natt_hash_addr (iph1, iph1->local);
+    flag = NAT_DETECTED_ME;
+  }
+  else {
+    natd_computed = natt_hash_addr (iph1, iph1->remote);
+    flag = NAT_DETECTED_PEER;
+  }
+
+  if (natd_computed == NULL) {
+	plog(LLV_ERROR, LOCATION, NULL, "natd_computed allocation failed\n");
+	return verified; /* XXX should abort */
+  }
+
+  if (natd_received->l == natd_computed->l &&
+      memcmp (natd_received->v, natd_computed->v, natd_received->l) == 0) {
+    iph1->natt_flags &= ~flag;
+    verified = 1;
+  }
+
+  vfree (natd_computed);
+
+  return verified;
+}
+
+int
+natt_udp_encap (int encmode)
+{
+  return (encmode == IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_RFC || 
+	  encmode == IPSECDOI_ATTR_ENC_MODE_UDPTRNS_RFC ||
+	  encmode == IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_DRAFT ||
+	  encmode == IPSECDOI_ATTR_ENC_MODE_UDPTRNS_DRAFT);
+}
+
+int
+natt_fill_options (struct ph1natt_options *opts, int version)
+{
+  if (! opts)
+    return -1;
+
+  opts->version = version;
+
+  switch (version) {
+    case VENDORID_NATT_00:
+    case VENDORID_NATT_01:
+      opts->float_port = 0; /* No port floating for those drafts */
+      opts->payload_nat_d = ISAKMP_NPTYPE_NATD_DRAFT;
+      opts->payload_nat_oa = ISAKMP_NPTYPE_NATOA_DRAFT;
+      opts->mode_udp_tunnel = IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_DRAFT;
+      opts->mode_udp_transport = IPSECDOI_ATTR_ENC_MODE_UDPTRNS_DRAFT;
+      opts->encaps_type = UDP_ENCAP_ESPINUDP_NON_IKE;
+		break;
+
+    case VENDORID_NATT_02:
+    case VENDORID_NATT_02_N:
+    case VENDORID_NATT_03:
+      opts->float_port = lcconf->port_isakmp_natt;
+      opts->payload_nat_d = ISAKMP_NPTYPE_NATD_DRAFT;
+      opts->payload_nat_oa = ISAKMP_NPTYPE_NATOA_DRAFT;
+      opts->mode_udp_tunnel = IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_DRAFT;
+      opts->mode_udp_transport = IPSECDOI_ATTR_ENC_MODE_UDPTRNS_DRAFT;
+      opts->encaps_type = UDP_ENCAP_ESPINUDP;
+      break;
+    case VENDORID_NATT_04:
+    case VENDORID_NATT_05:
+    case VENDORID_NATT_06:
+    case VENDORID_NATT_07:
+    case VENDORID_NATT_08:
+      opts->float_port = lcconf->port_isakmp_natt;
+      opts->payload_nat_d = ISAKMP_NPTYPE_NATD_BADDRAFT;
+      opts->payload_nat_oa = ISAKMP_NPTYPE_NATOA_BADDRAFT;
+      opts->mode_udp_tunnel = IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_RFC;
+      opts->mode_udp_transport = IPSECDOI_ATTR_ENC_MODE_UDPTRNS_RFC;
+      opts->encaps_type = UDP_ENCAP_ESPINUDP;
+      break;
+    case VENDORID_NATT_RFC:
+      opts->float_port = lcconf->port_isakmp_natt;
+      opts->payload_nat_d = ISAKMP_NPTYPE_NATD_RFC;
+      opts->payload_nat_oa = ISAKMP_NPTYPE_NATOA_RFC;
+      opts->mode_udp_tunnel = IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_RFC;
+      opts->mode_udp_transport = IPSECDOI_ATTR_ENC_MODE_UDPTRNS_RFC;
+      opts->encaps_type = UDP_ENCAP_ESPINUDP;
+	  break;
+    default:
+      plog(LLV_ERROR, LOCATION, NULL, 
+	   "unsupported NAT-T version: %s\n",
+	   vid_string_by_id(version));
+      return -1;
+  }
+ 
+  opts->mode_udp_diff = opts->mode_udp_tunnel - IPSECDOI_ATTR_ENC_MODE_TUNNEL;
+
+  return 0;
+}
+
+void
+natt_float_ports (struct ph1handle *iph1)
+{
+	if (! (iph1->natt_flags && NAT_DETECTED) )
+		return;
+	if (! iph1->natt_options->float_port){
+		/* Drafts 00 / 01, just schedule keepalive */
+		natt_keepalive_add_ph1 (iph1);
+		return;
+	}
+	
+	set_port (iph1->local, iph1->natt_options->float_port);
+	set_port (iph1->remote, iph1->natt_options->float_port);
+	iph1->natt_flags |= NAT_PORTS_CHANGED | NAT_ADD_NON_ESP_MARKER;
+	
+	natt_keepalive_add_ph1 (iph1);
+}
+
+void
+natt_handle_vendorid (struct ph1handle *iph1, int vid_numeric)
+{
+  if (! iph1->natt_options)
+    iph1->natt_options = racoon_calloc (1, sizeof (*iph1->natt_options));
+
+  if (! iph1->natt_options) {
+    plog (LLV_ERROR, LOCATION, NULL,
+	  "Allocating memory for natt_options failed!\n");
+    return;
+  }
+  
+  if (iph1->natt_options->version < vid_numeric)
+    if (natt_fill_options (iph1->natt_options, vid_numeric) == 0)
+      iph1->natt_flags |= NAT_ANNOUNCED;
+}
+
+/* NAT keepalive functions */
+static void
+natt_keepalive_send (void *param)
+{
+  struct natt_ka_addrs	*ka, *next = NULL;
+  char keepalive_packet[] = { 0xff };
+  size_t len;
+  int s;
+
+  for (ka = TAILQ_FIRST(&ka_tree); ka; ka = next) {
+    next = TAILQ_NEXT(ka, chain);
+    
+    s = getsockmyaddr(ka->src);
+    if (s == -1) {
+      TAILQ_REMOVE (&ka_tree, ka, chain);
+      racoon_free (ka);
+      continue;
+    }
+    plog (LLV_DEBUG, LOCATION, NULL, "KA: %s\n", 
+	  saddr2str_fromto("%s->%s", ka->src, ka->dst));
+    len = sendfromto(s, keepalive_packet, sizeof (keepalive_packet),
+		     ka->src, ka->dst, 1);
+    if (len == -1)
+      plog(LLV_ERROR, LOCATION, NULL, "KA: sendfromto failed: %s\n",
+	   strerror (errno));
+  }
+  
+  sched_new (lcconf->natt_ka_interval, natt_keepalive_send, NULL);
+}
+
+void
+natt_keepalive_init (void)
+{
+  TAILQ_INIT(&ka_tree);
+
+  /* To disable sending KAs set natt_ka_interval=0 */
+  if (lcconf->natt_ka_interval > 0)
+    sched_new (lcconf->natt_ka_interval, natt_keepalive_send, NULL);
+}
+
+int
+natt_keepalive_add (struct sockaddr *src, struct sockaddr *dst)
+{
+  struct natt_ka_addrs *ka = NULL, *new_addr;
+  
+  TAILQ_FOREACH (ka, &ka_tree, chain) {
+    if (cmpsaddrstrict(ka->src, src) == 0 && 
+	cmpsaddrstrict(ka->dst, dst) == 0) {
+      ka->in_use++;
+      plog (LLV_INFO, LOCATION, NULL, "KA found: %s (in_use=%u)\n",
+	    saddr2str_fromto("%s->%s", src, dst), ka->in_use);
+      return 0;
+    }
+  }
+
+  plog (LLV_INFO, LOCATION, NULL, "KA list add: %s\n", saddr2str_fromto("%s->%s", src, dst));
+
+  new_addr = (struct natt_ka_addrs *)racoon_malloc(sizeof(*new_addr));
+  if (! new_addr) {
+    plog (LLV_ERROR, LOCATION, NULL, "Can't allocate new KA list item\n");
+    return -1;
+  }
+
+  if ((new_addr->src = dupsaddr(src)) == NULL) {
+	racoon_free(new_addr);
+    	plog (LLV_ERROR, LOCATION, NULL, "Can't allocate new KA list item\n");
+	return -1;
+  }
+  if ((new_addr->dst = dupsaddr(dst)) == NULL) {
+	racoon_free(new_addr);
+    	plog (LLV_ERROR, LOCATION, NULL, "Can't allocate new KA list item\n");
+	return -1;
+  }
+  new_addr->in_use = 1;
+  TAILQ_INSERT_TAIL(&ka_tree, new_addr, chain);
+
+  return 0;
+}
+
+int
+natt_keepalive_add_ph1 (struct ph1handle *iph1)
+{
+  int ret = 0;
+  
+  /* Should only the NATed host send keepalives?
+     If yes, add '(iph1->natt_flags & NAT_DETECTED_ME)'
+     to the following condition. */
+  if (iph1->natt_flags & NAT_DETECTED &&
+      ! (iph1->natt_flags & NAT_KA_QUEUED)) {
+    ret = natt_keepalive_add (iph1->local, iph1->remote);
+    if (ret == 0)
+      iph1->natt_flags |= NAT_KA_QUEUED;
+  }
+
+  return ret;
+}
+
+void
+natt_keepalive_remove (struct sockaddr *src, struct sockaddr *dst)
+{
+  struct natt_ka_addrs *ka, *next = NULL;
+
+  plog (LLV_INFO, LOCATION, NULL, "KA remove: %s\n", saddr2str_fromto("%s->%s", src, dst));
+
+  for (ka = TAILQ_FIRST(&ka_tree); ka; ka = next) {
+    next = TAILQ_NEXT(ka, chain);
+ 
+    plog (LLV_DEBUG, LOCATION, NULL, "KA tree dump: %s (in_use=%u)\n",
+	  saddr2str_fromto("%s->%s", src, dst), ka->in_use);
+
+    if (cmpsaddrstrict(ka->src, src) == 0 && 
+	cmpsaddrstrict(ka->dst, dst) == 0 &&
+	-- ka->in_use <= 0) {
+
+      plog (LLV_DEBUG, LOCATION, NULL, "KA removing this one...\n");
+
+      TAILQ_REMOVE (&ka_tree, ka, chain);
+      racoon_free (ka);
+      /* Should we break here? Every pair of addresses should 
+         be inserted only once, but who knows :-) Lets traverse 
+	 the whole list... */
+    }
+  }
+}
+
+static struct remoteconf *
+natt_enabled_in_rmconf_stub (struct remoteconf *rmconf, void *data)
+{
+  return (rmconf->nat_traversal ? rmconf : NULL);
+}
+
+int
+natt_enabled_in_rmconf ()
+{
+  return foreachrmconf (natt_enabled_in_rmconf_stub, NULL) != NULL;
+}
+
+
+struct payload_list *
+isakmp_plist_append_natt_vids (struct payload_list *plist, vchar_t *vid_natt[MAX_NATT_VID_COUNT]){
+	int i, vid_natt_i = 0;
+
+	if(vid_natt == NULL)
+		return NULL;
+
+	for (i = 0; i < MAX_NATT_VID_COUNT; i++)
+		vid_natt[i]=NULL;
+	
+	/* Puts the olders VIDs last, as some implementations may choose the first
+	 * NATT VID given
+	 */
+
+	/* Always set RFC VID
+	 */
+	if ((vid_natt[vid_natt_i] = set_vendorid(VENDORID_NATT_RFC)) != NULL)
+		vid_natt_i++;
+#ifdef ENABLE_NATT_08
+	if ((vid_natt[vid_natt_i] = set_vendorid(VENDORID_NATT_08)) != NULL)
+		vid_natt_i++;
+#endif
+#ifdef ENABLE_NATT_07
+	if ((vid_natt[vid_natt_i] = set_vendorid(VENDORID_NATT_07)) != NULL)
+		vid_natt_i++;
+#endif
+#ifdef ENABLE_NATT_06
+	if ((vid_natt[vid_natt_i] = set_vendorid(VENDORID_NATT_06)) != NULL)
+		vid_natt_i++;
+#endif
+#ifdef ENABLE_NATT_05
+	if ((vid_natt[vid_natt_i] = set_vendorid(VENDORID_NATT_05)) != NULL)
+		vid_natt_i++;
+#endif
+#ifdef ENABLE_NATT_04
+	if ((vid_natt[vid_natt_i] = set_vendorid(VENDORID_NATT_04)) != NULL)
+		vid_natt_i++;
+#endif
+#ifdef ENABLE_NATT_03
+	if ((vid_natt[vid_natt_i] = set_vendorid(VENDORID_NATT_03)) != NULL)
+		vid_natt_i++;
+#endif
+#ifdef ENABLE_NATT_02
+	if ((vid_natt[vid_natt_i] = set_vendorid(VENDORID_NATT_02)) != NULL)
+		vid_natt_i++;
+	if ((vid_natt[vid_natt_i] = set_vendorid(VENDORID_NATT_02_N)) != NULL)
+		vid_natt_i++;
+#endif
+#ifdef ENABLE_NATT_01
+	if ((vid_natt[vid_natt_i] = set_vendorid(VENDORID_NATT_01)) != NULL)
+		vid_natt_i++;
+#endif
+#ifdef ENABLE_NATT_00
+	if ((vid_natt[vid_natt_i] = set_vendorid(VENDORID_NATT_00)) != NULL)
+		vid_natt_i++;
+#endif
+	/* set VID payload for NAT-T */
+	for (i = 0; i < vid_natt_i; i++)
+		plist = isakmp_plist_append(plist, vid_natt[i], ISAKMP_NPTYPE_VID);
+	
+	return plist;
+}
diff --git a/src/racoon/nattraversal.h b/src/racoon/nattraversal.h
new file mode 100644
index 0000000..cec5815
--- /dev/null
+++ b/src/racoon/nattraversal.h
@@ -0,0 +1,99 @@
+/*	$NetBSD: nattraversal.h,v 1.6 2006/09/09 16:22:09 manu Exp $	*/
+
+/*
+ * Copyright (C) 2004 SuSE Linux AG, Nuernberg, Germany.
+ * Contributed by: Michal Ludvig <mludvig@suse.cz>, SUSE Labs
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _NATTRAVERSAL_H
+#define _NATTRAVERSAL_H
+
+#include "vendorid.h"
+
+#define	NAT_ANNOUNCED		(1L<<0)
+#define	NAT_DETECTED_ME		(1L<<1)
+#define	NAT_DETECTED_PEER	(1L<<2)
+#define	NAT_PORTS_CHANGED	(1L<<3)
+#define	NAT_KA_QUEUED		(1L<<4)
+#define	NAT_ADD_NON_ESP_MARKER	(1L<<5)
+
+#define	NATT_AVAILABLE(ph1)	((iph1)->natt_flags & NAT_ANNOUNCED)
+
+#define	NAT_DETECTED	(NAT_DETECTED_ME | NAT_DETECTED_PEER)
+
+#define	NON_ESP_MARKER_LEN	sizeof(u_int32_t)
+#define	NON_ESP_MARKER_USE(iph1)	((iph1)->natt_flags & NAT_ADD_NON_ESP_MARKER)
+
+/* These are the values from parsing "remote {}" 
+   block of the config file. */
+#define NATT_OFF	FLASE	/* = 0 */
+#define NATT_ON		TRUE	/* = 1 */
+#define NATT_FORCE	2
+
+struct ph1natt_options {
+  int		version;
+  u_int16_t	float_port;
+  u_int16_t	mode_udp_tunnel;
+  u_int16_t	mode_udp_transport;
+  u_int16_t	encaps_type; /* ESPINUDP / ESPINUDP_NON_IKE */
+  u_int16_t	mode_udp_diff;
+  u_int16_t	payload_nat_d;
+  u_int16_t	payload_nat_oa;
+};
+
+struct ph2natt {
+  u_int8_t	type;
+  u_int16_t	sport;
+  u_int16_t	dport;
+  struct sockaddr	*oa;
+  u_int16_t	frag;
+};
+
+int natt_vendorid (int vid);
+vchar_t *natt_hash_addr (struct ph1handle *iph1, struct sockaddr *addr);
+int natt_compare_addr_hash (struct ph1handle *iph1, vchar_t *natd_received, int natd_seq);
+int natt_udp_encap (int encmode);
+int natt_fill_options (struct ph1natt_options *opts, int version);
+void natt_float_ports (struct ph1handle *iph1);
+void natt_handle_vendorid (struct ph1handle *iph1, int vid_numeric);
+
+
+struct payload_list *
+isakmp_plist_append_natt_vids (struct payload_list *plist, vchar_t *vid_natt[MAX_NATT_VID_COUNT]);
+
+
+/* NAT keepalive functions */
+void natt_keepalive_init (void);
+int natt_keepalive_add (struct sockaddr *src, struct sockaddr *dst);
+int natt_keepalive_add_ph1 (struct ph1handle *iph1);
+void natt_keepalive_remove (struct sockaddr *src, struct sockaddr *dst);
+
+/* Walk through all rmconfigs and tell if NAT-T is enabled in at least one. */
+int natt_enabled_in_rmconf (void);
+
+#endif /* _NATTRAVERSAL_H */
diff --git a/src/racoon/netdb_dnssec.h b/src/racoon/netdb_dnssec.h
new file mode 100644
index 0000000..a11209d
--- /dev/null
+++ b/src/racoon/netdb_dnssec.h
@@ -0,0 +1,74 @@
+/*	$NetBSD: netdb_dnssec.h,v 1.4 2006/09/09 16:22:09 manu Exp $	*/
+
+/* Id: netdb_dnssec.h,v 1.3 2004/06/11 16:00:17 ludvigm Exp */
+
+/*
+ * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _NETDB_DNSSEC_H
+#define _NETDB_DNSSEC_H
+
+#ifndef T_CERT
+#define T_CERT	37		/* defined by RFC2538 section 2 */
+#endif
+
+/* RFC2538 section 2.1 */
+#define DNSSEC_TYPE_PKIX	1
+#define DNSSEC_TYPE_SPKI	2
+#define DNSSEC_TYPE_PGP		3
+#define DNSSEC_TYPE_URI		4
+#define DNSSEC_TYPE_OID		5
+
+/* RFC2535 section 3.2 */
+#define DNSSEC_ALG_RSAMD5	1
+#define DNSSEC_ALG_DH		2
+#define DNSSEC_ALG_DSA		3
+#define DNSSEC_ALG_ECC		4
+#define DNSSEC_ALG_PRIVATEDNS	5
+#define DNSSEC_ALG_PRIVATEOID	6
+
+/*
+ * Structures returned by network data base library.  All addresses are
+ * supplied in host order, and returned in network order (suitable for
+ * use in system calls).
+ */
+struct certinfo {
+	int ci_type;			/* certificate type */
+	int ci_keytag;			/* keytag */
+	int ci_algorithm;		/* algorithm */
+	int ci_flags;			/* currently, 1:valid or 0:uncertain */
+	size_t ci_certlen;		/* length of certificate */
+	char *ci_cert;			/* certificate */
+	struct certinfo *ci_next;	/* next structure */
+};
+
+extern void freecertinfo __P((struct certinfo *));
+extern int getcertsbyname __P((char *, struct certinfo **));
+
+#endif /* _NETDB_DNSSEC_H */
diff --git a/src/racoon/oakley.c b/src/racoon/oakley.c
new file mode 100644
index 0000000..85b6586
--- /dev/null
+++ b/src/racoon/oakley.c
@@ -0,0 +1,3315 @@
+/*	$NetBSD: oakley.c,v 1.9.6.3 2008/03/06 17:00:25 vanhu Exp $	*/
+
+/* Id: oakley.c,v 1.32 2006/05/26 12:19:46 manubsd Exp */
+
+/*
+ * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/socket.h>	/* XXX for subjectaltname */
+#include <netinet/in.h>	/* XXX for subjectaltname */
+
+#include <openssl/pkcs7.h>
+#include <openssl/x509.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+
+#if TIME_WITH_SYS_TIME
+# include <sys/time.h>
+# include <time.h>
+#else
+# if HAVE_SYS_TIME_H
+#  include <sys/time.h>
+# else
+#  include <time.h>
+# endif
+#endif
+#ifdef ENABLE_HYBRID
+#include <resolv.h>
+#endif
+
+#include "var.h"
+#include "misc.h"
+#include "vmbuf.h"
+#include "str2val.h"
+#include "plog.h"
+#include "debug.h"
+
+#include "isakmp_var.h"
+#include "isakmp.h"
+#ifdef ENABLE_HYBRID
+#include "isakmp_xauth.h"
+#include "isakmp_cfg.h" 
+#endif                
+#include "oakley.h"
+#include "admin.h"
+#include "privsep.h"
+#include "localconf.h"
+#include "remoteconf.h"
+#include "policy.h"
+#include "handler.h"
+#include "ipsec_doi.h"
+#include "algorithm.h"
+#include "dhgroup.h"
+#include "sainfo.h"
+#include "proposal.h"
+#include "crypto_openssl.h"
+#include "dnssec.h"
+#include "sockmisc.h"
+#include "strnames.h"
+#include "gcmalloc.h"
+#include "rsalist.h"
+
+#ifdef HAVE_GSSAPI
+#include "gssapi.h"
+#endif
+
+#define OUTBOUND_SA	0
+#define INBOUND_SA	1
+
+#define INITDHVAL(a, s, d, t)                                                  \
+do {                                                                           \
+	vchar_t buf;                                                           \
+	buf.v = str2val((s), 16, &buf.l);                                      \
+	memset(&a, 0, sizeof(struct dhgroup));                                 \
+	a.type = (t);                                                          \
+	a.prime = vdup(&buf);                                                  \
+	a.gen1 = 2;                                                            \
+	a.gen2 = 0;                                                            \
+	racoon_free(buf.v);                                                    \
+} while(0);
+
+struct dhgroup dh_modp768;
+struct dhgroup dh_modp1024;
+struct dhgroup dh_modp1536;
+struct dhgroup dh_modp2048;
+struct dhgroup dh_modp3072;
+struct dhgroup dh_modp4096;
+struct dhgroup dh_modp6144;
+struct dhgroup dh_modp8192;
+
+
+static int oakley_check_dh_pub __P((vchar_t *, vchar_t **));
+static int oakley_compute_keymat_x __P((struct ph2handle *, int, int));
+static int get_cert_fromlocal __P((struct ph1handle *, int));
+static int get_plainrsa_fromlocal __P((struct ph1handle *, int));
+static int oakley_check_certid __P((struct ph1handle *iph1));
+static int check_typeofcertname __P((int, int));
+static cert_t *save_certbuf __P((struct isakmp_gen *));
+static cert_t *save_certx509 __P((X509 *));
+static int oakley_padlen __P((int, int));
+
+int
+oakley_get_defaultlifetime()
+{
+	return OAKLEY_ATTR_SA_LD_SEC_DEFAULT;
+}
+
+int
+oakley_dhinit()
+{
+	/* set DH MODP */
+	INITDHVAL(dh_modp768, OAKLEY_PRIME_MODP768,
+		OAKLEY_ATTR_GRP_DESC_MODP768, OAKLEY_ATTR_GRP_TYPE_MODP);
+	INITDHVAL(dh_modp1024, OAKLEY_PRIME_MODP1024,
+		OAKLEY_ATTR_GRP_DESC_MODP1024, OAKLEY_ATTR_GRP_TYPE_MODP);
+	INITDHVAL(dh_modp1536, OAKLEY_PRIME_MODP1536,
+		OAKLEY_ATTR_GRP_DESC_MODP1536, OAKLEY_ATTR_GRP_TYPE_MODP);
+	INITDHVAL(dh_modp2048, OAKLEY_PRIME_MODP2048,
+		OAKLEY_ATTR_GRP_DESC_MODP2048, OAKLEY_ATTR_GRP_TYPE_MODP);
+	INITDHVAL(dh_modp3072, OAKLEY_PRIME_MODP3072,
+		OAKLEY_ATTR_GRP_DESC_MODP3072, OAKLEY_ATTR_GRP_TYPE_MODP);
+	INITDHVAL(dh_modp4096, OAKLEY_PRIME_MODP4096,
+		OAKLEY_ATTR_GRP_DESC_MODP4096, OAKLEY_ATTR_GRP_TYPE_MODP);
+	INITDHVAL(dh_modp6144, OAKLEY_PRIME_MODP6144,
+		OAKLEY_ATTR_GRP_DESC_MODP6144, OAKLEY_ATTR_GRP_TYPE_MODP);
+	INITDHVAL(dh_modp8192, OAKLEY_PRIME_MODP8192,
+		OAKLEY_ATTR_GRP_DESC_MODP8192, OAKLEY_ATTR_GRP_TYPE_MODP);
+
+	return 0;
+}
+
+void
+oakley_dhgrp_free(dhgrp)
+	struct dhgroup *dhgrp;
+{
+	if (dhgrp->prime)
+		vfree(dhgrp->prime);
+	if (dhgrp->curve_a)
+		vfree(dhgrp->curve_a);
+	if (dhgrp->curve_b)
+		vfree(dhgrp->curve_b);
+	if (dhgrp->order)
+		vfree(dhgrp->order);
+	racoon_free(dhgrp);
+}
+
+/*
+ * RFC2409 5
+ * The length of the Diffie-Hellman public value MUST be equal to the
+ * length of the prime modulus over which the exponentiation was
+ * performed, prepending zero bits to the value if necessary.
+ */
+static int
+oakley_check_dh_pub(prime, pub0)
+	vchar_t *prime, **pub0;
+{
+	vchar_t *tmp;
+	vchar_t *pub = *pub0;
+
+	if (prime->l == pub->l)
+		return 0;
+
+	if (prime->l < pub->l) {
+		/* what should i do ? */
+		plog(LLV_ERROR, LOCATION, NULL,
+			"invalid public information was generated.\n");
+		return -1;
+	}
+
+	/* prime->l > pub->l */
+	tmp = vmalloc(prime->l);
+	if (tmp == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"failed to get DH buffer.\n");
+		return -1;
+	}
+	memcpy(tmp->v + prime->l - pub->l, pub->v, pub->l);
+
+	vfree(*pub0);
+	*pub0 = tmp;
+
+	return 0;
+}
+
+/*
+ * compute sharing secret of DH
+ * IN:	*dh, *pub, *priv, *pub_p
+ * OUT: **gxy
+ */
+int
+oakley_dh_compute(dh, pub, priv, pub_p, gxy)
+	const struct dhgroup *dh;
+	vchar_t *pub, *priv, *pub_p, **gxy;
+{
+#ifdef ENABLE_STATS
+	struct timeval start, end;
+#endif
+	if ((*gxy = vmalloc(dh->prime->l)) == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"failed to get DH buffer.\n");
+		return -1;
+	}
+
+#ifdef ENABLE_STATS
+	gettimeofday(&start, NULL);
+#endif
+	switch (dh->type) {
+	case OAKLEY_ATTR_GRP_TYPE_MODP:
+		if (eay_dh_compute(dh->prime, dh->gen1, pub, priv, pub_p, gxy) < 0) {
+			plog(LLV_ERROR, LOCATION, NULL,
+				"failed to compute dh value.\n");
+			return -1;
+		}
+		break;
+	case OAKLEY_ATTR_GRP_TYPE_ECP:
+	case OAKLEY_ATTR_GRP_TYPE_EC2N:
+		plog(LLV_ERROR, LOCATION, NULL,
+			"dh type %d isn't supported.\n", dh->type);
+		return -1;
+	default:
+		plog(LLV_ERROR, LOCATION, NULL,
+			"invalid dh type %d.\n", dh->type);
+		return -1;
+	}
+
+#ifdef ENABLE_STATS
+	gettimeofday(&end, NULL);
+	syslog(LOG_NOTICE, "%s(%s%zu): %8.6f", __func__,
+		s_attr_isakmp_group(dh->type), dh->prime->l << 3,
+		timedelta(&start, &end));
+#endif
+
+	plog(LLV_DEBUG, LOCATION, NULL, "compute DH's shared.\n");
+	plogdump(LLV_DEBUG, (*gxy)->v, (*gxy)->l);
+
+	return 0;
+}
+
+/*
+ * generate values of DH
+ * IN:	*dh
+ * OUT: **pub, **priv
+ */
+int
+oakley_dh_generate(dh, pub, priv)
+	const struct dhgroup *dh;
+	vchar_t **pub, **priv;
+{
+#ifdef ENABLE_STATS
+	struct timeval start, end;
+	gettimeofday(&start, NULL);
+#endif
+	switch (dh->type) {
+	case OAKLEY_ATTR_GRP_TYPE_MODP:
+		if (eay_dh_generate(dh->prime, dh->gen1, dh->gen2, pub, priv) < 0) {
+			plog(LLV_ERROR, LOCATION, NULL,
+				"failed to compute dh value.\n");
+			return -1;
+		}
+		break;
+
+	case OAKLEY_ATTR_GRP_TYPE_ECP:
+	case OAKLEY_ATTR_GRP_TYPE_EC2N:
+		plog(LLV_ERROR, LOCATION, NULL,
+			"dh type %d isn't supported.\n", dh->type);
+		return -1;
+	default:
+		plog(LLV_ERROR, LOCATION, NULL,
+			"invalid dh type %d.\n", dh->type);
+		return -1;
+	}
+
+#ifdef ENABLE_STATS
+	gettimeofday(&end, NULL);
+	syslog(LOG_NOTICE, "%s(%s%zu): %8.6f", __func__,
+		s_attr_isakmp_group(dh->type), dh->prime->l << 3,
+		timedelta(&start, &end));
+#endif
+
+	if (oakley_check_dh_pub(dh->prime, pub) != 0)
+		return -1;
+
+	plog(LLV_DEBUG, LOCATION, NULL, "compute DH's private.\n");
+	plogdump(LLV_DEBUG, (*priv)->v, (*priv)->l);
+	plog(LLV_DEBUG, LOCATION, NULL, "compute DH's public.\n");
+	plogdump(LLV_DEBUG, (*pub)->v, (*pub)->l);
+
+	return 0;
+}
+
+/*
+ * copy pre-defined dhgroup values.
+ */
+int
+oakley_setdhgroup(group, dhgrp)
+	int group;
+	struct dhgroup **dhgrp;
+{
+	struct dhgroup *g;
+
+	*dhgrp = NULL;	/* just make sure, initialize */
+
+	g = alg_oakley_dhdef_group(group);
+	if (g == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"invalid DH parameter grp=%d.\n", group);
+		return -1;
+	}
+
+	if (!g->type || !g->prime || !g->gen1) {
+		/* unsuported */
+		plog(LLV_ERROR, LOCATION, NULL,
+			"unsupported DH parameters grp=%d.\n", group);
+		return -1;
+	}
+
+	*dhgrp = racoon_calloc(1, sizeof(struct dhgroup));
+	if (*dhgrp == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"failed to get DH buffer.\n");
+		return 0;
+	}
+
+	/* set defined dh vlaues */
+	memcpy(*dhgrp, g, sizeof(*g));
+	(*dhgrp)->prime = vdup(g->prime);
+
+	return 0;
+}
+
+/*
+ * PRF
+ *
+ * NOTE: we do not support prf with different input/output bitwidth,
+ * so we do not implement RFC2409 Appendix B (DOORAK-MAC example) in
+ * oakley_compute_keymat().  If you add support for such prf function,
+ * modify oakley_compute_keymat() accordingly.
+ */
+vchar_t *
+oakley_prf(key, buf, iph1)
+	vchar_t *key, *buf;
+	struct ph1handle *iph1;
+{
+	vchar_t *res = NULL;
+	int type;
+
+	if (iph1->approval == NULL) {
+		/*
+		 * it's before negotiating hash algorithm.
+		 * We use md5 as default.
+		 */
+		type = OAKLEY_ATTR_HASH_ALG_MD5;
+	} else
+		type = iph1->approval->hashtype;
+
+	res = alg_oakley_hmacdef_one(type, key, buf);
+	if (res == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"invalid hmac algorithm %d.\n", type);
+		return NULL;
+	}
+
+	return res;
+}
+
+/*
+ * hash
+ */
+vchar_t *
+oakley_hash(buf, iph1)
+	vchar_t *buf;
+	struct ph1handle *iph1;
+{
+	vchar_t *res = NULL;
+	int type;
+
+	if (iph1->approval == NULL) {
+		/*
+		 * it's before negotiating hash algorithm.
+		 * We use md5 as default.
+		 */
+		type = OAKLEY_ATTR_HASH_ALG_MD5;
+	} else
+		type = iph1->approval->hashtype;
+
+	res = alg_oakley_hashdef_one(type, buf);
+	if (res == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"invalid hash algoriym %d.\n", type);
+		return NULL;
+	}
+
+	return res;
+}
+
+/*
+ * compute KEYMAT
+ *   see seciton 5.5 Phase 2 - Quick Mode in isakmp-oakley-05.
+ */
+int
+oakley_compute_keymat(iph2, side)
+	struct ph2handle *iph2;
+	int side;
+{
+	int error = -1;
+
+	/* compute sharing secret of DH when PFS */
+	if (iph2->approval->pfs_group && iph2->dhpub_p) {
+		if (oakley_dh_compute(iph2->pfsgrp, iph2->dhpub,
+				iph2->dhpriv, iph2->dhpub_p, &iph2->dhgxy) < 0)
+			goto end;
+	}
+
+	/* compute keymat */
+	if (oakley_compute_keymat_x(iph2, side, INBOUND_SA) < 0
+	 || oakley_compute_keymat_x(iph2, side, OUTBOUND_SA) < 0)
+		goto end;
+
+	plog(LLV_DEBUG, LOCATION, NULL, "KEYMAT computed.\n");
+
+	error = 0;
+
+end:
+	return error;
+}
+
+/*
+ * compute KEYMAT.
+ * KEYMAT = prf(SKEYID_d, protocol | SPI | Ni_b | Nr_b).
+ * If PFS is desired and KE payloads were exchanged,
+ *   KEYMAT = prf(SKEYID_d, g(qm)^xy | protocol | SPI | Ni_b | Nr_b)
+ *
+ * NOTE: we do not support prf with different input/output bitwidth,
+ * so we do not implement RFC2409 Appendix B (DOORAK-MAC example).
+ */
+static int
+oakley_compute_keymat_x(iph2, side, sa_dir)
+	struct ph2handle *iph2;
+	int side;
+	int sa_dir;
+{
+	vchar_t *buf = NULL, *res = NULL, *bp;
+	char *p;
+	int len;
+	int error = -1;
+	int pfs = 0;
+	int dupkeymat;	/* generate K[1-dupkeymat] */
+	struct saproto *pr;
+	struct satrns *tr;
+	int encklen, authklen, l;
+
+	pfs = ((iph2->approval->pfs_group && iph2->dhgxy) ? 1 : 0);
+	
+	len = pfs ? iph2->dhgxy->l : 0;
+	len += (1
+		+ sizeof(u_int32_t)	/* XXX SPI size */
+		+ iph2->nonce->l
+		+ iph2->nonce_p->l);
+	buf = vmalloc(len);
+	if (buf == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"failed to get keymat buffer.\n");
+		goto end;
+	}
+
+	for (pr = iph2->approval->head; pr != NULL; pr = pr->next) {
+		p = buf->v;
+
+		/* if PFS */
+		if (pfs) {
+			memcpy(p, iph2->dhgxy->v, iph2->dhgxy->l);
+			p += iph2->dhgxy->l;
+		}
+
+		p[0] = pr->proto_id;
+		p += 1;
+
+		memcpy(p, (sa_dir == INBOUND_SA ? &pr->spi : &pr->spi_p),
+			sizeof(pr->spi));
+		p += sizeof(pr->spi);
+
+		bp = (side == INITIATOR ? iph2->nonce : iph2->nonce_p);
+		memcpy(p, bp->v, bp->l);
+		p += bp->l;
+
+		bp = (side == INITIATOR ? iph2->nonce_p : iph2->nonce);
+		memcpy(p, bp->v, bp->l);
+		p += bp->l;
+
+		/* compute IV */
+		plog(LLV_DEBUG, LOCATION, NULL, "KEYMAT compute with\n");
+		plogdump(LLV_DEBUG, buf->v, buf->l);
+
+		/* res = K1 */
+		res = oakley_prf(iph2->ph1->skeyid_d, buf, iph2->ph1);
+		if (res == NULL)
+			goto end;
+
+		/* compute key length needed */
+		encklen = authklen = 0;
+		switch (pr->proto_id) {
+		case IPSECDOI_PROTO_IPSEC_ESP:
+			for (tr = pr->head; tr; tr = tr->next) {
+				l = alg_ipsec_encdef_keylen(tr->trns_id,
+				    tr->encklen);
+				if (l > encklen)
+					encklen = l;
+
+				l = alg_ipsec_hmacdef_hashlen(tr->authtype);
+				if (l > authklen)
+					authklen = l;
+			}
+			break;
+		case IPSECDOI_PROTO_IPSEC_AH:
+			for (tr = pr->head; tr; tr = tr->next) {
+				l = alg_ipsec_hmacdef_hashlen(tr->trns_id);
+				if (l > authklen)
+					authklen = l;
+			}
+			break;
+		default:
+			break;
+		}
+		plog(LLV_DEBUG, LOCATION, NULL, "encklen=%d authklen=%d\n",
+			encklen, authklen);
+
+		dupkeymat = (encklen + authklen) / 8 / res->l;
+		dupkeymat += 2;	/* safety mergin */
+		if (dupkeymat < 3)
+			dupkeymat = 3;
+		plog(LLV_DEBUG, LOCATION, NULL,
+			"generating %zu bits of key (dupkeymat=%d)\n",
+			dupkeymat * 8 * res->l, dupkeymat);
+		if (0 < --dupkeymat) {
+			vchar_t *prev = res;	/* K(n-1) */
+			vchar_t *seed = NULL;	/* seed for Kn */
+			size_t l;
+
+			/*
+			 * generating long key (isakmp-oakley-08 5.5)
+			 *   KEYMAT = K1 | K2 | K3 | ...
+			 * where
+			 *   src = [ g(qm)^xy | ] protocol | SPI | Ni_b | Nr_b
+			 *   K1 = prf(SKEYID_d, src)
+			 *   K2 = prf(SKEYID_d, K1 | src)
+			 *   K3 = prf(SKEYID_d, K2 | src)
+			 *   Kn = prf(SKEYID_d, K(n-1) | src)
+			 */
+			plog(LLV_DEBUG, LOCATION, NULL,
+				"generating K1...K%d for KEYMAT.\n",
+				dupkeymat + 1);
+
+			seed = vmalloc(prev->l + buf->l);
+			if (seed == NULL) {
+				plog(LLV_ERROR, LOCATION, NULL,
+					"failed to get keymat buffer.\n");
+				if (prev && prev != res)
+					vfree(prev);
+				goto end;
+			}
+
+			while (dupkeymat--) {
+				vchar_t *this = NULL;	/* Kn */
+				int update_prev;
+
+				memcpy(seed->v, prev->v, prev->l);
+				memcpy(seed->v + prev->l, buf->v, buf->l);
+				this = oakley_prf(iph2->ph1->skeyid_d, seed,
+							iph2->ph1);
+				if (!this) {
+					plog(LLV_ERROR, LOCATION, NULL,
+						"oakley_prf memory overflow\n");
+					if (prev && prev != res)
+						vfree(prev);
+					vfree(this);
+					vfree(seed);
+					goto end;
+				}
+
+				update_prev = (prev && prev == res) ? 1 : 0;
+
+				l = res->l;
+				res = vrealloc(res, l + this->l);
+
+				if (update_prev)
+					prev = res;
+
+				if (res == NULL) {
+					plog(LLV_ERROR, LOCATION, NULL,
+						"failed to get keymat buffer.\n");
+					if (prev && prev != res)
+						vfree(prev);
+					vfree(this);
+					vfree(seed);
+					goto end;
+				}
+				memcpy(res->v + l, this->v, this->l);
+
+				if (prev && prev != res)
+					vfree(prev);
+				prev = this;
+				this = NULL;
+			}
+
+			if (prev && prev != res)
+				vfree(prev);
+			vfree(seed);
+		}
+
+		plogdump(LLV_DEBUG, res->v, res->l);
+
+		if (sa_dir == INBOUND_SA)
+			pr->keymat = res;
+		else
+			pr->keymat_p = res;
+		res = NULL;
+	}
+
+	error = 0;
+
+end:
+	if (error) {
+		for (pr = iph2->approval->head; pr != NULL; pr = pr->next) {
+			if (pr->keymat) {
+				vfree(pr->keymat);
+				pr->keymat = NULL;
+			}
+			if (pr->keymat_p) {
+				vfree(pr->keymat_p);
+				pr->keymat_p = NULL;
+			}
+		}
+	}
+
+	if (buf != NULL)
+		vfree(buf);
+	if (res)
+		vfree(res);
+
+	return error;
+}
+
+#if notyet
+/*
+ * NOTE: Must terminate by NULL.
+ */
+vchar_t *
+oakley_compute_hashx(struct ph1handle *iph1, ...)
+{
+	vchar_t *buf, *res;
+	vchar_t *s;
+	caddr_t p;
+	int len;
+
+	va_list ap;
+
+	/* get buffer length */
+	va_start(ap, iph1);
+	len = 0;
+        while ((s = va_arg(ap, vchar_t *)) != NULL) {
+		len += s->l
+        }
+	va_end(ap);
+
+	buf = vmalloc(len);
+	if (buf == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"failed to get hash buffer\n");
+		return NULL;
+	}
+
+	/* set buffer */
+	va_start(ap, iph1);
+	p = buf->v;
+        while ((s = va_arg(ap, char *)) != NULL) {
+		memcpy(p, s->v, s->l);
+		p += s->l;
+	}
+	va_end(ap);
+
+	plog(LLV_DEBUG, LOCATION, NULL, "HASH with: \n");
+	plogdump(LLV_DEBUG, buf->v, buf->l);
+
+	/* compute HASH */
+	res = oakley_prf(iph1->skeyid_a, buf, iph1);
+	vfree(buf);
+	if (res == NULL)
+		return NULL;
+
+	plog(LLV_DEBUG, LOCATION, NULL, "HASH computed:\n");
+	plogdump(LLV_DEBUG, res->v, res->l);
+
+	return res;
+}
+#endif
+
+/*
+ * compute HASH(3) prf(SKEYID_a, 0 | M-ID | Ni_b | Nr_b)
+ *   see seciton 5.5 Phase 2 - Quick Mode in isakmp-oakley-05.
+ */
+vchar_t *
+oakley_compute_hash3(iph1, msgid, body)
+	struct ph1handle *iph1;
+	u_int32_t msgid;
+	vchar_t *body;
+{
+	vchar_t *buf = 0, *res = 0;
+	int len;
+	int error = -1;
+
+	/* create buffer */
+	len = 1 + sizeof(u_int32_t) + body->l;
+	buf = vmalloc(len);
+	if (buf == NULL) {
+		plog(LLV_DEBUG, LOCATION, NULL,
+			"failed to get hash buffer\n");
+		goto end;
+	}
+
+	buf->v[0] = 0;
+
+	memcpy(buf->v + 1, (char *)&msgid, sizeof(msgid));
+
+	memcpy(buf->v + 1 + sizeof(u_int32_t), body->v, body->l);
+
+	plog(LLV_DEBUG, LOCATION, NULL, "HASH with: \n");
+	plogdump(LLV_DEBUG, buf->v, buf->l);
+
+	/* compute HASH */
+	res = oakley_prf(iph1->skeyid_a, buf, iph1);
+	if (res == NULL)
+		goto end;
+
+	error = 0;
+
+	plog(LLV_DEBUG, LOCATION, NULL, "HASH computed:\n");
+	plogdump(LLV_DEBUG, res->v, res->l);
+
+end:
+	if (buf != NULL)
+		vfree(buf);
+	return res;
+}
+
+/*
+ * compute HASH type of prf(SKEYID_a, M-ID | buffer)
+ *	e.g.
+ *	for quick mode HASH(1):
+ *		prf(SKEYID_a, M-ID | SA | Ni [ | KE ] [ | IDci | IDcr ])
+ *	for quick mode HASH(2):
+ *		prf(SKEYID_a, M-ID | Ni_b | SA | Nr [ | KE ] [ | IDci | IDcr ])
+ *	for Informational exchange:
+ *		prf(SKEYID_a, M-ID | N/D)
+ */
+vchar_t *
+oakley_compute_hash1(iph1, msgid, body)
+	struct ph1handle *iph1;
+	u_int32_t msgid;
+	vchar_t *body;
+{
+	vchar_t *buf = NULL, *res = NULL;
+	char *p;
+	int len;
+	int error = -1;
+
+	/* create buffer */
+	len = sizeof(u_int32_t) + body->l;
+	buf = vmalloc(len);
+	if (buf == NULL) {
+		plog(LLV_DEBUG, LOCATION, NULL,
+			"failed to get hash buffer\n");
+		goto end;
+	}
+
+	p = buf->v;
+
+	memcpy(buf->v, (char *)&msgid, sizeof(msgid));
+	p += sizeof(u_int32_t);
+
+	memcpy(p, body->v, body->l);
+
+	plog(LLV_DEBUG, LOCATION, NULL, "HASH with:\n");
+	plogdump(LLV_DEBUG, buf->v, buf->l);
+
+	/* compute HASH */
+	res = oakley_prf(iph1->skeyid_a, buf, iph1);
+	if (res == NULL)
+		goto end;
+
+	error = 0;
+
+	plog(LLV_DEBUG, LOCATION, NULL, "HASH computed:\n");
+	plogdump(LLV_DEBUG, res->v, res->l);
+
+end:
+	if (buf != NULL)
+		vfree(buf);
+	return res;
+}
+
+/*
+ * compute phase1 HASH
+ * main/aggressive
+ *   I-digest = prf(SKEYID, g^i | g^r | CKY-I | CKY-R | SAi_b | ID_i1_b)
+ *   R-digest = prf(SKEYID, g^r | g^i | CKY-R | CKY-I | SAi_b | ID_r1_b)
+ * for gssapi, also include all GSS tokens, and call gss_wrap on the result
+ */
+vchar_t *
+oakley_ph1hash_common(iph1, sw)
+	struct ph1handle *iph1;
+	int sw;
+{
+	vchar_t *buf = NULL, *res = NULL, *bp;
+	char *p, *bp2;
+	int len, bl;
+	int error = -1;
+#ifdef HAVE_GSSAPI
+	vchar_t *gsstokens = NULL;
+#endif
+
+	/* create buffer */
+	len = iph1->dhpub->l
+		+ iph1->dhpub_p->l
+		+ sizeof(cookie_t) * 2
+		+ iph1->sa->l
+		+ (sw == GENERATE ? iph1->id->l : iph1->id_p->l);
+
+#ifdef HAVE_GSSAPI
+	if (AUTHMETHOD(iph1) == OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB) {
+		if (iph1->gi_i != NULL && iph1->gi_r != NULL) {
+			bp = (sw == GENERATE ? iph1->gi_i : iph1->gi_r);
+			len += bp->l;
+		}
+		if (sw == GENERATE)
+			gssapi_get_itokens(iph1, &gsstokens);
+		else
+			gssapi_get_rtokens(iph1, &gsstokens);
+		if (gsstokens == NULL)
+			return NULL;
+		len += gsstokens->l;
+	}
+#endif
+
+	buf = vmalloc(len);
+	if (buf == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"failed to get hash buffer\n");
+		goto end;
+	}
+
+	p = buf->v;
+
+	bp = (sw == GENERATE ? iph1->dhpub : iph1->dhpub_p);
+	memcpy(p, bp->v, bp->l);
+	p += bp->l;
+
+	bp = (sw == GENERATE ? iph1->dhpub_p : iph1->dhpub);
+	memcpy(p, bp->v, bp->l);
+	p += bp->l;
+
+	if (iph1->side == INITIATOR)
+		bp2 = (sw == GENERATE ?
+		      (char *)&iph1->index.i_ck : (char *)&iph1->index.r_ck);
+	else
+		bp2 = (sw == GENERATE ?
+		      (char *)&iph1->index.r_ck : (char *)&iph1->index.i_ck);
+	bl = sizeof(cookie_t);
+	memcpy(p, bp2, bl);
+	p += bl;
+
+	if (iph1->side == INITIATOR)
+		bp2 = (sw == GENERATE ?
+		      (char *)&iph1->index.r_ck : (char *)&iph1->index.i_ck);
+	else
+		bp2 = (sw == GENERATE ?
+		      (char *)&iph1->index.i_ck : (char *)&iph1->index.r_ck);
+	bl = sizeof(cookie_t);
+	memcpy(p, bp2, bl);
+	p += bl;
+
+	bp = iph1->sa;
+	memcpy(p, bp->v, bp->l);
+	p += bp->l;
+
+	bp = (sw == GENERATE ? iph1->id : iph1->id_p);
+	memcpy(p, bp->v, bp->l);
+	p += bp->l;
+
+#ifdef HAVE_GSSAPI
+	if (AUTHMETHOD(iph1) == OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB) {
+		if (iph1->gi_i != NULL && iph1->gi_r != NULL) {
+			bp = (sw == GENERATE ? iph1->gi_i : iph1->gi_r);
+			memcpy(p, bp->v, bp->l);
+			p += bp->l;
+		}
+		memcpy(p, gsstokens->v, gsstokens->l);
+		p += gsstokens->l;
+	}
+#endif
+
+	plog(LLV_DEBUG, LOCATION, NULL, "HASH with:\n");
+	plogdump(LLV_DEBUG, buf->v, buf->l);
+
+	/* compute HASH */
+	res = oakley_prf(iph1->skeyid, buf, iph1);
+	if (res == NULL)
+		goto end;
+
+	error = 0;
+
+	plog(LLV_DEBUG, LOCATION, NULL, "HASH (%s) computed:\n",
+		iph1->side == INITIATOR ? "init" : "resp");
+	plogdump(LLV_DEBUG, res->v, res->l);
+
+end:
+	if (buf != NULL)
+		vfree(buf);
+#ifdef HAVE_GSSAPI
+	if (gsstokens != NULL)
+		vfree(gsstokens);
+#endif
+	return res;
+}
+
+/*
+ * compute HASH_I on base mode.
+ * base:psk,rsa
+ *   HASH_I = prf(SKEYID, g^xi | CKY-I | CKY-R | SAi_b | IDii_b)
+ * base:sig
+ *   HASH_I = prf(hash(Ni_b | Nr_b), g^xi | CKY-I | CKY-R | SAi_b | IDii_b)
+ */
+vchar_t *
+oakley_ph1hash_base_i(iph1, sw)
+	struct ph1handle *iph1;
+	int sw;
+{
+	vchar_t *buf = NULL, *res = NULL, *bp;
+	vchar_t *hashkey = NULL;
+	vchar_t *hash = NULL;	/* for signature mode */
+	char *p;
+	int len;
+	int error = -1;
+
+	/* sanity check */
+	if (iph1->etype != ISAKMP_ETYPE_BASE) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"invalid etype for this hash function\n");
+		return NULL;
+	}
+
+	switch (AUTHMETHOD(iph1)) {
+	case OAKLEY_ATTR_AUTH_METHOD_PSKEY:
+	case OAKLEY_ATTR_AUTH_METHOD_RSAENC:
+	case OAKLEY_ATTR_AUTH_METHOD_RSAREV:
+#ifdef ENABLE_HYBRID
+	case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAENC_I:
+	case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAENC_R:
+	case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAREV_I:
+	case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAREV_R:
+	case FICTIVE_AUTH_METHOD_XAUTH_PSKEY_I:
+	case OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_R:
+#endif
+		if (iph1->skeyid == NULL) {
+			plog(LLV_ERROR, LOCATION, NULL, "no SKEYID found.\n");
+			return NULL;
+		}
+		hashkey = iph1->skeyid;
+		break;
+
+	case OAKLEY_ATTR_AUTH_METHOD_DSSSIG:
+	case OAKLEY_ATTR_AUTH_METHOD_RSASIG:
+#ifdef HAVE_GSSAPI
+	case OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB:
+#endif
+#ifdef ENABLE_HYBRID
+	case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_I:
+	case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_R:
+	case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_I:
+	case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_R:
+	case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_I:
+	case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_R:
+	case OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_I:
+	case OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_R:
+#endif
+		/* make hash for seed */
+		len = iph1->nonce->l + iph1->nonce_p->l;
+		buf = vmalloc(len);
+		if (buf == NULL) {
+			plog(LLV_ERROR, LOCATION, NULL,
+				"failed to get hash buffer\n");
+			goto end;
+		}
+		p = buf->v;
+
+		bp = (sw == GENERATE ? iph1->nonce_p : iph1->nonce);
+		memcpy(p, bp->v, bp->l);
+		p += bp->l;
+
+		bp = (sw == GENERATE ? iph1->nonce : iph1->nonce_p);
+		memcpy(p, bp->v, bp->l);
+		p += bp->l;
+
+		hash = oakley_hash(buf, iph1);
+		if (hash == NULL)
+			goto end;
+		vfree(buf);
+		buf = NULL;
+
+		hashkey = hash;
+		break;
+
+	default:
+		plog(LLV_ERROR, LOCATION, NULL,
+			"not supported authentication method %d\n",
+			iph1->approval->authmethod);
+		return NULL;
+
+	}
+
+	len = (sw == GENERATE ? iph1->dhpub->l : iph1->dhpub_p->l)
+		+ sizeof(cookie_t) * 2
+		+ iph1->sa->l
+		+ (sw == GENERATE ? iph1->id->l : iph1->id_p->l);
+	buf = vmalloc(len);
+	if (buf == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"failed to get hash buffer\n");
+		goto end;
+	}
+	p = buf->v;
+
+	bp = (sw == GENERATE ? iph1->dhpub : iph1->dhpub_p);
+	memcpy(p, bp->v, bp->l);
+	p += bp->l;
+
+	memcpy(p, &iph1->index.i_ck, sizeof(cookie_t));
+	p += sizeof(cookie_t);
+	memcpy(p, &iph1->index.r_ck, sizeof(cookie_t));
+	p += sizeof(cookie_t);
+
+	memcpy(p, iph1->sa->v, iph1->sa->l);
+	p += iph1->sa->l;
+
+	bp = (sw == GENERATE ? iph1->id : iph1->id_p);
+	memcpy(p, bp->v, bp->l);
+	p += bp->l;
+
+	plog(LLV_DEBUG, LOCATION, NULL, "HASH_I with:\n");
+	plogdump(LLV_DEBUG, buf->v, buf->l);
+
+	/* compute HASH */
+	res = oakley_prf(hashkey, buf, iph1);
+	if (res == NULL)
+		goto end;
+
+	error = 0;
+
+	plog(LLV_DEBUG, LOCATION, NULL, "HASH_I computed:\n");
+	plogdump(LLV_DEBUG, res->v, res->l);
+
+end:
+	if (hash != NULL)
+		vfree(hash);
+	if (buf != NULL)
+		vfree(buf);
+	return res;
+}
+
+/*
+ * compute HASH_R on base mode for signature method.
+ * base:
+ * HASH_R = prf(hash(Ni_b | Nr_b), g^xi | g^xr | CKY-I | CKY-R | SAi_b | IDii_b)
+ */
+vchar_t *
+oakley_ph1hash_base_r(iph1, sw)
+	struct ph1handle *iph1;
+	int sw;
+{
+	vchar_t *buf = NULL, *res = NULL, *bp;
+	vchar_t *hash = NULL;
+	char *p;
+	int len;
+	int error = -1;
+
+	/* sanity check */
+	if (iph1->etype != ISAKMP_ETYPE_BASE) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"invalid etype for this hash function\n");
+		return NULL;
+	}
+
+	switch(AUTHMETHOD(iph1)) {
+	case OAKLEY_ATTR_AUTH_METHOD_DSSSIG:
+	case OAKLEY_ATTR_AUTH_METHOD_RSASIG:
+#ifdef ENABLE_HYBRID
+	case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_I:
+	case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_R:
+	case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_I:
+	case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_R:
+	case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_I:
+	case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_R:
+	case OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_I:
+	case OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_R:
+	case FICTIVE_AUTH_METHOD_XAUTH_PSKEY_I:
+#endif
+		break;
+	default:
+		plog(LLV_ERROR, LOCATION, NULL,
+			"not supported authentication method %d\n",
+			iph1->approval->authmethod);
+		return NULL;
+		break;
+	}
+
+	/* make hash for seed */
+	len = iph1->nonce->l + iph1->nonce_p->l;
+	buf = vmalloc(len);
+	if (buf == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"failed to get hash buffer\n");
+		goto end;
+	}
+	p = buf->v;
+
+	bp = (sw == GENERATE ? iph1->nonce_p : iph1->nonce);
+	memcpy(p, bp->v, bp->l);
+	p += bp->l;
+
+	bp = (sw == GENERATE ? iph1->nonce : iph1->nonce_p);
+	memcpy(p, bp->v, bp->l);
+	p += bp->l;
+
+	hash = oakley_hash(buf, iph1);
+	if (hash == NULL)
+		goto end;
+	vfree(buf);
+	buf = NULL;
+
+	/* make really hash */
+	len = (sw == GENERATE ? iph1->dhpub_p->l : iph1->dhpub->l)
+		+ (sw == GENERATE ? iph1->dhpub->l : iph1->dhpub_p->l)
+		+ sizeof(cookie_t) * 2
+		+ iph1->sa->l
+		+ (sw == GENERATE ? iph1->id_p->l : iph1->id->l);
+	buf = vmalloc(len);
+	if (buf == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"failed to get hash buffer\n");
+		goto end;
+	}
+	p = buf->v;
+
+
+	bp = (sw == GENERATE ? iph1->dhpub_p : iph1->dhpub);
+	memcpy(p, bp->v, bp->l);
+	p += bp->l;
+
+	bp = (sw == GENERATE ? iph1->dhpub : iph1->dhpub_p);
+	memcpy(p, bp->v, bp->l);
+	p += bp->l;
+
+	memcpy(p, &iph1->index.i_ck, sizeof(cookie_t));
+	p += sizeof(cookie_t);
+	memcpy(p, &iph1->index.r_ck, sizeof(cookie_t));
+	p += sizeof(cookie_t);
+
+	memcpy(p, iph1->sa->v, iph1->sa->l);
+	p += iph1->sa->l;
+
+	bp = (sw == GENERATE ? iph1->id_p : iph1->id);
+	memcpy(p, bp->v, bp->l);
+	p += bp->l;
+
+	plog(LLV_DEBUG, LOCATION, NULL, "HASH_R with:\n");
+	plogdump(LLV_DEBUG, buf->v, buf->l);
+
+	/* compute HASH */
+	res = oakley_prf(hash, buf, iph1);
+	if (res == NULL)
+		goto end;
+
+	error = 0;
+
+	plog(LLV_DEBUG, LOCATION, NULL, "HASH_R computed:\n");
+	plogdump(LLV_DEBUG, res->v, res->l);
+
+end:
+	if (buf != NULL)
+		vfree(buf);
+	if (hash)
+		vfree(hash);
+	return res;
+}
+
+/*
+ * compute each authentication method in phase 1.
+ * OUT:
+ *	0:	OK
+ *	-1:	error
+ *	other:	error to be reply with notification.
+ *	        the value is notification type.
+ */
+int
+oakley_validate_auth(iph1)
+	struct ph1handle *iph1;
+{
+	vchar_t *my_hash = NULL;
+	int result;
+#ifdef HAVE_GSSAPI
+	vchar_t *gsshash = NULL;
+#endif
+#ifdef ENABLE_STATS
+	struct timeval start, end;
+#endif
+
+#ifdef ENABLE_STATS
+	gettimeofday(&start, NULL);
+#endif
+
+	switch (AUTHMETHOD(iph1)) {
+	case OAKLEY_ATTR_AUTH_METHOD_PSKEY:
+#ifdef ENABLE_HYBRID
+	case FICTIVE_AUTH_METHOD_XAUTH_PSKEY_I:
+	case OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_R:
+#endif
+		/* validate HASH */
+	    {
+		char *r_hash;
+
+		if (iph1->id_p == NULL || iph1->pl_hash == NULL) {
+			plog(LLV_ERROR, LOCATION, iph1->remote,
+				"few isakmp message received.\n");
+			return ISAKMP_NTYPE_PAYLOAD_MALFORMED;
+		}
+#ifdef ENABLE_HYBRID
+		if (AUTHMETHOD(iph1) == FICTIVE_AUTH_METHOD_XAUTH_PSKEY_I &&
+		    ((iph1->mode_cfg->flags & ISAKMP_CFG_VENDORID_XAUTH) == 0))
+		{
+			plog(LLV_ERROR, LOCATION, NULL, "No SIG was passed, "
+			    "hybrid auth is enabled, "
+			    "but peer is no Xauth compliant\n");
+			return ISAKMP_NTYPE_SITUATION_NOT_SUPPORTED;
+			break;
+		}
+#endif
+		r_hash = (caddr_t)(iph1->pl_hash + 1);
+
+		plog(LLV_DEBUG, LOCATION, NULL, "HASH received:\n");
+		plogdump(LLV_DEBUG, r_hash,
+			ntohs(iph1->pl_hash->h.len) - sizeof(*iph1->pl_hash));
+
+		switch (iph1->etype) {
+		case ISAKMP_ETYPE_IDENT:
+		case ISAKMP_ETYPE_AGG:
+			my_hash = oakley_ph1hash_common(iph1, VALIDATE);
+			break;
+		case ISAKMP_ETYPE_BASE:
+			if (iph1->side == INITIATOR)
+				my_hash = oakley_ph1hash_common(iph1, VALIDATE);
+			else
+				my_hash = oakley_ph1hash_base_i(iph1, VALIDATE);
+			break;
+		default:
+			plog(LLV_ERROR, LOCATION, NULL,
+				"invalid etype %d\n", iph1->etype);
+			return ISAKMP_NTYPE_INVALID_EXCHANGE_TYPE;
+		}
+		if (my_hash == NULL)
+			return ISAKMP_INTERNAL_ERROR;
+
+		result = memcmp(my_hash->v, r_hash, my_hash->l);
+		vfree(my_hash);
+
+		if (result) {
+			plog(LLV_ERROR, LOCATION, NULL, "HASH mismatched\n");
+			return ISAKMP_NTYPE_INVALID_HASH_INFORMATION;
+		}
+
+		plog(LLV_DEBUG, LOCATION, NULL, "HASH for PSK validated.\n");
+	    }
+		break;
+	case OAKLEY_ATTR_AUTH_METHOD_DSSSIG:
+	case OAKLEY_ATTR_AUTH_METHOD_RSASIG:
+#ifdef ENABLE_HYBRID
+	case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_I:
+	case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_I:
+	case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_I:
+	case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_R:
+	case OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_I:
+	case OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_R:
+#endif
+	    {
+		int error = 0;
+		int certtype = 0;
+
+		/* validation */
+		if (iph1->id_p == NULL) {
+			plog(LLV_ERROR, LOCATION, iph1->remote,
+				"no ID payload was passed.\n");
+			return ISAKMP_NTYPE_PAYLOAD_MALFORMED;
+		}
+		if (iph1->sig_p == NULL) {
+			plog(LLV_ERROR, LOCATION, iph1->remote,
+				"no SIG payload was passed.\n");
+			return ISAKMP_NTYPE_PAYLOAD_MALFORMED;
+		}
+
+		plog(LLV_DEBUG, LOCATION, NULL, "SIGN passed:\n");
+		plogdump(LLV_DEBUG, iph1->sig_p->v, iph1->sig_p->l);
+
+		/* get peer's cert */
+		switch (iph1->rmconf->getcert_method) {
+		case ISAKMP_GETCERT_PAYLOAD:
+			if (iph1->cert_p == NULL) {
+				plog(LLV_ERROR, LOCATION, NULL,
+					"no peer's CERT payload found.\n");
+				return ISAKMP_INTERNAL_ERROR;
+			}
+			break;
+		case ISAKMP_GETCERT_LOCALFILE:
+			switch (iph1->rmconf->certtype) {
+				case ISAKMP_CERT_X509SIGN:
+					if (iph1->rmconf->peerscertfile == NULL) {
+						plog(LLV_ERROR, LOCATION, NULL,
+							"no peer's CERT file found.\n");
+						return ISAKMP_INTERNAL_ERROR;
+					}
+
+					/* don't use cached cert */
+					if (iph1->cert_p != NULL) {
+						oakley_delcert(iph1->cert_p);
+						iph1->cert_p = NULL;
+					}
+
+					error = get_cert_fromlocal(iph1, 0);
+					break;
+
+				case ISAKMP_CERT_PLAINRSA:
+					error = get_plainrsa_fromlocal(iph1, 0);
+					break;
+			}
+			if (error)
+				return ISAKMP_INTERNAL_ERROR;
+			break;
+		case ISAKMP_GETCERT_DNS:
+			if (iph1->rmconf->peerscertfile != NULL) {
+				plog(LLV_ERROR, LOCATION, NULL,
+					"why peer's CERT file is defined "
+					"though getcert method is dns ?\n");
+				return ISAKMP_INTERNAL_ERROR;
+			}
+
+			/* don't use cached cert */
+			if (iph1->cert_p != NULL) {
+				oakley_delcert(iph1->cert_p);
+				iph1->cert_p = NULL;
+			}
+
+			iph1->cert_p = dnssec_getcert(iph1->id_p);
+			if (iph1->cert_p == NULL) {
+				plog(LLV_ERROR, LOCATION, NULL,
+					"no CERT RR found.\n");
+				return ISAKMP_INTERNAL_ERROR;
+			}
+			break;
+		default:
+			plog(LLV_ERROR, LOCATION, NULL,
+				"invalid getcert_mothod: %d\n",
+				iph1->rmconf->getcert_method);
+			return ISAKMP_INTERNAL_ERROR;
+		}
+
+		/* compare ID payload and certificate name */
+		if (iph1->rmconf->verify_cert &&
+		    (error = oakley_check_certid(iph1)) != 0)
+			return error;
+
+		/* verify certificate */
+		if (iph1->rmconf->verify_cert
+		 && iph1->rmconf->getcert_method == ISAKMP_GETCERT_PAYLOAD) {
+			certtype = iph1->rmconf->certtype;
+#ifdef ENABLE_HYBRID
+			switch (AUTHMETHOD(iph1)) {
+			case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_I:
+			case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_I:
+				certtype = iph1->cert_p->type;
+				break;
+			default:
+				break;
+			}
+#endif
+			switch (certtype) {
+			case ISAKMP_CERT_X509SIGN: {
+				char path[MAXPATHLEN];
+				char *ca;
+
+				if (iph1->rmconf->cacertfile != NULL) {
+					getpathname(path, sizeof(path), 
+					    LC_PATHTYPE_CERT, 
+					    iph1->rmconf->cacertfile);
+					ca = path;
+				} else {
+					ca = NULL;
+				}
+
+				error = eay_check_x509cert(&iph1->cert_p->cert,
+					lcconf->pathinfo[LC_PATHTYPE_CERT], 
+					ca, 0);
+				break;
+			}
+			
+			default:
+				plog(LLV_ERROR, LOCATION, NULL,
+					"no supported certtype %d\n", certtype);
+				return ISAKMP_INTERNAL_ERROR;
+			}
+			if (error != 0) {
+				plog(LLV_ERROR, LOCATION, NULL,
+					"the peer's certificate is not verified.\n");
+				return ISAKMP_NTYPE_INVALID_CERT_AUTHORITY;
+			}
+		}
+	
+		/* Generate a warning if verify_cert == 0
+		 */
+		if (iph1->rmconf->verify_cert){
+			plog(LLV_DEBUG, LOCATION, NULL, "CERT validated\n");
+		}else{
+			plog(LLV_WARNING, LOCATION, NULL,
+				"CERT validation disabled by configuration\n");
+		}
+
+		/* compute hash */
+		switch (iph1->etype) {
+		case ISAKMP_ETYPE_IDENT:
+		case ISAKMP_ETYPE_AGG:
+			my_hash = oakley_ph1hash_common(iph1, VALIDATE);
+			break;
+		case ISAKMP_ETYPE_BASE:
+			if (iph1->side == INITIATOR)
+				my_hash = oakley_ph1hash_base_r(iph1, VALIDATE);
+			else
+				my_hash = oakley_ph1hash_base_i(iph1, VALIDATE);
+			break;
+		default:
+			plog(LLV_ERROR, LOCATION, NULL,
+				"invalid etype %d\n", iph1->etype);
+			return ISAKMP_NTYPE_INVALID_EXCHANGE_TYPE;
+		}
+		if (my_hash == NULL)
+			return ISAKMP_INTERNAL_ERROR;
+
+
+		certtype = iph1->rmconf->certtype;
+#ifdef ENABLE_HYBRID
+		switch (AUTHMETHOD(iph1)) {
+		case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_I:
+		case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_I:
+			certtype = iph1->cert_p->type;
+			break;
+		default:
+			break;
+		}
+#endif
+		/* check signature */
+		switch (certtype) {
+		case ISAKMP_CERT_X509SIGN:
+		case ISAKMP_CERT_DNS:
+			error = eay_check_x509sign(my_hash,
+					iph1->sig_p,
+					&iph1->cert_p->cert);
+			break;
+		case ISAKMP_CERT_PLAINRSA:
+			iph1->rsa_p = rsa_try_check_rsasign(my_hash,
+					iph1->sig_p, iph1->rsa_candidates);
+			error = iph1->rsa_p ? 0 : -1;
+
+			break;
+		default:
+			plog(LLV_ERROR, LOCATION, NULL,
+				"no supported certtype %d\n",
+				certtype);
+			vfree(my_hash);
+			return ISAKMP_INTERNAL_ERROR;
+		}
+
+		vfree(my_hash);
+		if (error != 0) {
+			plog(LLV_ERROR, LOCATION, NULL,
+				"Invalid SIG.\n");
+			return ISAKMP_NTYPE_INVALID_SIGNATURE;
+		}
+		plog(LLV_DEBUG, LOCATION, NULL, "SIG authenticated\n");
+	    }
+		break;
+#ifdef ENABLE_HYBRID
+	case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_R:
+	case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_R:
+	    {
+		if ((iph1->mode_cfg->flags & ISAKMP_CFG_VENDORID_XAUTH) == 0) {
+			plog(LLV_ERROR, LOCATION, NULL, "No SIG was passed, "
+			    "hybrid auth is enabled, "
+			    "but peer is no Xauth compliant\n");
+			return ISAKMP_NTYPE_SITUATION_NOT_SUPPORTED;
+			break;
+		}
+		plog(LLV_INFO, LOCATION, NULL, "No SIG was passed, "
+		    "but hybrid auth is enabled\n");
+
+		return 0;
+		break;
+	    }
+#endif
+#ifdef HAVE_GSSAPI
+	case OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB:
+		/* check if we're not into XAUTH_PSKEY_I instead */
+#ifdef ENABLE_HYBRID
+		if (iph1->rmconf->xauth)
+			break;
+#endif
+		switch (iph1->etype) {
+		case ISAKMP_ETYPE_IDENT:
+		case ISAKMP_ETYPE_AGG:
+			my_hash = oakley_ph1hash_common(iph1, VALIDATE);
+			break;
+		default:
+			plog(LLV_ERROR, LOCATION, NULL,
+				"invalid etype %d\n", iph1->etype);
+			return ISAKMP_NTYPE_INVALID_EXCHANGE_TYPE;
+		}
+
+		if (my_hash == NULL) {
+			if (gssapi_more_tokens(iph1))
+				return ISAKMP_NTYPE_INVALID_EXCHANGE_TYPE;
+			else
+				return ISAKMP_NTYPE_INVALID_HASH_INFORMATION;
+		}
+
+		gsshash = gssapi_unwraphash(iph1);
+		if (gsshash == NULL) {
+			vfree(my_hash);
+			return ISAKMP_NTYPE_INVALID_HASH_INFORMATION;
+		}
+
+		result = memcmp(my_hash->v, gsshash->v, my_hash->l);
+		vfree(my_hash);
+		vfree(gsshash);
+
+		if (result) {
+			plog(LLV_ERROR, LOCATION, NULL, "HASH mismatched\n");
+			return ISAKMP_NTYPE_INVALID_HASH_INFORMATION;
+		}
+		plog(LLV_DEBUG, LOCATION, NULL, "hash compared OK\n");
+		break;
+#endif
+	case OAKLEY_ATTR_AUTH_METHOD_RSAENC:
+	case OAKLEY_ATTR_AUTH_METHOD_RSAREV:
+#ifdef ENABLE_HYBRID
+	case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAENC_I:
+	case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAENC_R:
+	case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAREV_I:
+	case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAREV_R:
+#endif
+		if (iph1->id_p == NULL || iph1->pl_hash == NULL) {
+			plog(LLV_ERROR, LOCATION, iph1->remote,
+				"few isakmp message received.\n");
+			return ISAKMP_NTYPE_PAYLOAD_MALFORMED;
+		}
+		plog(LLV_ERROR, LOCATION, iph1->remote,
+			"not supported authmethod type %s\n",
+			s_oakley_attr_method(iph1->approval->authmethod));
+		return ISAKMP_INTERNAL_ERROR;
+	default:
+		plog(LLV_ERROR, LOCATION, iph1->remote,
+			"invalid authmethod %d why ?\n",
+			iph1->approval->authmethod);
+		return ISAKMP_INTERNAL_ERROR;
+	}
+#ifdef ENABLE_STATS
+	gettimeofday(&end, NULL);
+	syslog(LOG_NOTICE, "%s(%s): %8.6f", __func__,
+		s_oakley_attr_method(iph1->approval->authmethod),
+		timedelta(&start, &end));
+#endif
+
+	return 0;
+}
+
+/* get my certificate
+ * NOTE: include certificate type.
+ */
+int
+oakley_getmycert(iph1)
+	struct ph1handle *iph1;
+{
+	switch (iph1->rmconf->certtype) {
+		case ISAKMP_CERT_X509SIGN:
+			if (iph1->cert)
+				return 0;
+			return get_cert_fromlocal(iph1, 1);
+
+		case ISAKMP_CERT_PLAINRSA:
+			if (iph1->rsa)
+				return 0;
+			return get_plainrsa_fromlocal(iph1, 1);
+
+		default:
+			plog(LLV_ERROR, LOCATION, NULL,
+			     "Unknown certtype #%d\n",
+			     iph1->rmconf->certtype);
+			return -1;
+	}
+
+}
+
+/*
+ * get a CERT from local file.
+ * IN:
+ *	my != 0 my cert.
+ *	my == 0 peer's cert.
+ */
+static int
+get_cert_fromlocal(iph1, my)
+	struct ph1handle *iph1;
+	int my;
+{
+	char path[MAXPATHLEN];
+	vchar_t *cert = NULL;
+	cert_t **certpl;
+	char *certfile;
+	int error = -1;
+
+	if (my) {
+		certfile = iph1->rmconf->mycertfile;
+		certpl = &iph1->cert;
+	} else {
+		certfile = iph1->rmconf->peerscertfile;
+		certpl = &iph1->cert_p;
+	}
+	if (!certfile) {
+		plog(LLV_ERROR, LOCATION, NULL, "no CERT defined.\n");
+		return 0;
+	}
+
+	switch (iph1->rmconf->certtype) {
+	case ISAKMP_CERT_X509SIGN:
+	case ISAKMP_CERT_DNS:
+		/* make public file name */
+		getpathname(path, sizeof(path), LC_PATHTYPE_CERT, certfile);
+		cert = eay_get_x509cert(path);
+		if (cert) {
+			char *p = NULL;
+			p = eay_get_x509text(cert);
+			plog(LLV_DEBUG, LOCATION, NULL, "%s", p ? p : "\n");
+			racoon_free(p);
+		};
+		break;
+
+	default:
+		plog(LLV_ERROR, LOCATION, NULL,
+			"not supported certtype %d\n",
+			iph1->rmconf->certtype);
+		goto end;
+	}
+
+	if (!cert) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"failed to get %s CERT.\n",
+			my ? "my" : "peers");
+		goto end;
+	}
+
+	*certpl = oakley_newcert();
+	if (!*certpl) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"failed to get cert buffer.\n");
+		goto end;
+	}
+	(*certpl)->pl = vmalloc(cert->l + 1);
+	if ((*certpl)->pl == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"failed to get cert buffer\n");
+		oakley_delcert(*certpl);
+		*certpl = NULL;
+		goto end;
+	}
+	memcpy((*certpl)->pl->v + 1, cert->v, cert->l);
+	(*certpl)->pl->v[0] = iph1->rmconf->certtype;
+	(*certpl)->type = iph1->rmconf->certtype;
+	(*certpl)->cert.v = (*certpl)->pl->v + 1;
+	(*certpl)->cert.l = (*certpl)->pl->l - 1;
+
+	plog(LLV_DEBUG, LOCATION, NULL, "created CERT payload:\n");
+	plogdump(LLV_DEBUG, (*certpl)->pl->v, (*certpl)->pl->l);
+
+	error = 0;
+
+end:
+	if (cert != NULL)
+		vfree(cert);
+
+	return error;
+}
+
+static int
+get_plainrsa_fromlocal(iph1, my)
+	struct ph1handle *iph1;
+	int my;
+{
+	char path[MAXPATHLEN];
+	vchar_t *cert = NULL;
+	char *certfile;
+	int error = -1;
+
+	iph1->rsa_candidates = rsa_lookup_keys(iph1, my);
+	if (!iph1->rsa_candidates || 
+	    rsa_list_count(iph1->rsa_candidates) == 0) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"%s RSA key not found for %s\n",
+			my ? "Private" : "Public",
+			saddr2str_fromto("%s <-> %s", 
+			iph1->local, iph1->remote));
+		goto end;
+	}
+
+	if (my && rsa_list_count(iph1->rsa_candidates) > 1) {
+		plog(LLV_WARNING, LOCATION, NULL,
+			"More than one (=%lu) private "
+			"PlainRSA key found for %s\n",
+			rsa_list_count(iph1->rsa_candidates),
+			saddr2str_fromto("%s <-> %s", 
+			iph1->local, iph1->remote));
+		plog(LLV_WARNING, LOCATION, NULL,
+			"This may have unpredictable results, "
+			"i.e. wrong key could be used!\n");
+		plog(LLV_WARNING, LOCATION, NULL,
+			"Consider using only one single private "
+			"key for all peers...\n");
+	}
+	if (my) {
+		iph1->rsa = ((struct rsa_key *)
+		    genlist_next(iph1->rsa_candidates, NULL))->rsa;
+
+		genlist_free(iph1->rsa_candidates, NULL);
+		iph1->rsa_candidates = NULL;
+
+		if (iph1->rsa == NULL)
+			goto end;
+	}
+
+	error = 0;
+
+end:
+	return error;
+}
+
+/* get signature */
+int
+oakley_getsign(iph1)
+	struct ph1handle *iph1;
+{
+	char path[MAXPATHLEN];
+	vchar_t *privkey = NULL;
+	int error = -1;
+
+	switch (iph1->rmconf->certtype) {
+	case ISAKMP_CERT_X509SIGN:
+	case ISAKMP_CERT_DNS:
+		if (iph1->rmconf->myprivfile == NULL) {
+			plog(LLV_ERROR, LOCATION, NULL, "no cert defined.\n");
+			goto end;
+		}
+
+		/* make private file name */
+		getpathname(path, sizeof(path),
+			LC_PATHTYPE_CERT,
+			iph1->rmconf->myprivfile);
+		privkey = privsep_eay_get_pkcs1privkey(path);
+		if (privkey == NULL) {
+			plog(LLV_ERROR, LOCATION, NULL,
+				"failed to get private key.\n");
+			goto end;
+		}
+		plog(LLV_DEBUG2, LOCATION, NULL, "private key:\n");
+		plogdump(LLV_DEBUG2, privkey->v, privkey->l);
+
+		iph1->sig = eay_get_x509sign(iph1->hash, privkey);
+		break;
+	case ISAKMP_CERT_PLAINRSA:
+		iph1->sig = eay_get_rsasign(iph1->hash, iph1->rsa);
+		break;
+	default:
+		plog(LLV_ERROR, LOCATION, NULL,
+		     "Unknown certtype #%d\n",
+		     iph1->rmconf->certtype);
+		goto end;
+	}
+
+	if (iph1->sig == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL, "failed to sign.\n");
+		goto end;
+	}
+
+	plog(LLV_DEBUG, LOCATION, NULL, "SIGN computed:\n");
+	plogdump(LLV_DEBUG, iph1->sig->v, iph1->sig->l);
+
+	error = 0;
+
+end:
+	if (privkey != NULL)
+		vfree(privkey);
+
+	return error;
+}
+
+/*
+ * compare certificate name and ID value.
+ */
+static int
+oakley_check_certid(iph1)
+	struct ph1handle *iph1;
+{
+	struct ipsecdoi_id_b *id_b;
+	vchar_t *name = NULL;
+	char *altname = NULL;
+	int idlen, type;
+	int error;
+
+	if (iph1->id_p == NULL || iph1->cert_p == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL, "no ID nor CERT found.\n");
+		return ISAKMP_NTYPE_INVALID_ID_INFORMATION;
+	}
+
+	id_b = (struct ipsecdoi_id_b *)iph1->id_p->v;
+	idlen = iph1->id_p->l - sizeof(*id_b);
+
+	switch (id_b->type) {
+	case IPSECDOI_ID_DER_ASN1_DN:
+		name = eay_get_x509asn1subjectname(&iph1->cert_p->cert);
+		if (!name) {
+			plog(LLV_ERROR, LOCATION, NULL,
+				"failed to get subjectName\n");
+			return ISAKMP_NTYPE_INVALID_CERTIFICATE;
+		}
+		if (idlen != name->l) {
+			plog(LLV_ERROR, LOCATION, NULL,
+				"Invalid ID length in phase 1.\n");
+			vfree(name);
+			return ISAKMP_NTYPE_INVALID_ID_INFORMATION;
+		}
+		error = memcmp(id_b + 1, name->v, idlen);
+		vfree(name);
+		if (error != 0) {
+			plog(LLV_ERROR, LOCATION, NULL,
+				"ID mismatched with ASN1 SubjectName.\n");
+			plogdump(LLV_DEBUG, id_b + 1, idlen);
+			plogdump(LLV_DEBUG, name->v, idlen);
+			return ISAKMP_NTYPE_INVALID_ID_INFORMATION;
+		}
+		return 0;
+	case IPSECDOI_ID_IPV4_ADDR:
+	case IPSECDOI_ID_IPV6_ADDR:
+	{
+		/*
+		 * converting to binary from string because openssl return
+		 * a string even if object is a binary.
+		 * XXX fix it !  access by ASN.1 directly without.
+		 */
+		struct addrinfo hints, *res;
+		caddr_t a = NULL;
+		int pos;
+
+		for (pos = 1; ; pos++) {
+			if (eay_get_x509subjectaltname(&iph1->cert_p->cert,
+					&altname, &type, pos) !=0) {
+				plog(LLV_ERROR, LOCATION, NULL,
+					"failed to get subjectAltName\n");
+				return ISAKMP_NTYPE_INVALID_CERTIFICATE;
+			}
+
+			/* it's the end condition of the loop. */
+			if (!altname) {
+				plog(LLV_ERROR, LOCATION, NULL,
+					"no proper subjectAltName.\n");
+				return ISAKMP_NTYPE_INVALID_CERTIFICATE;
+			}
+
+			if (check_typeofcertname(id_b->type, type) == 0)
+				break;
+
+			/* next name */
+			racoon_free(altname);
+			altname = NULL;
+		}
+		memset(&hints, 0, sizeof(hints));
+		hints.ai_family = PF_UNSPEC;
+		hints.ai_socktype = SOCK_RAW;
+		hints.ai_flags = AI_NUMERICHOST;
+		error = getaddrinfo(altname, NULL, &hints, &res);
+		if (error != 0) {
+			plog(LLV_ERROR, LOCATION, NULL,
+				"no proper subjectAltName.\n");
+			racoon_free(altname);
+			return ISAKMP_NTYPE_INVALID_CERTIFICATE;
+		}
+		switch (res->ai_family) {
+		case AF_INET:
+			a = (caddr_t)&((struct sockaddr_in *)res->ai_addr)->sin_addr.s_addr;
+			break;
+#ifdef INET6
+		case AF_INET6:
+			a = (caddr_t)&((struct sockaddr_in6 *)res->ai_addr)->sin6_addr.s6_addr;
+			break;
+#endif
+		default:
+			plog(LLV_ERROR, LOCATION, NULL,
+				"family not supported: %d.\n", res->ai_family);
+			racoon_free(altname);
+			freeaddrinfo(res);
+			return ISAKMP_NTYPE_INVALID_CERTIFICATE;
+		}
+		error = memcmp(id_b + 1, a, idlen);
+		freeaddrinfo(res);
+		vfree(name);
+		if (error != 0) {
+			plog(LLV_ERROR, LOCATION, NULL,
+				"ID mismatched with subjectAltName.\n");
+			plogdump(LLV_DEBUG, id_b + 1, idlen);
+			plogdump(LLV_DEBUG, a, idlen);
+			return ISAKMP_NTYPE_INVALID_ID_INFORMATION;
+		}
+		return 0;
+	}
+	case IPSECDOI_ID_FQDN:
+	case IPSECDOI_ID_USER_FQDN:
+	{
+		int pos;
+
+		for (pos = 1; ; pos++) {
+			if (eay_get_x509subjectaltname(&iph1->cert_p->cert,
+					&altname, &type, pos) != 0){
+				plog(LLV_ERROR, LOCATION, NULL,
+					"failed to get subjectAltName\n");
+				return ISAKMP_NTYPE_INVALID_CERTIFICATE;
+			}
+
+			/* it's the end condition of the loop. */
+			if (!altname) {
+				plog(LLV_ERROR, LOCATION, NULL,
+					"no proper subjectAltName.\n");
+				return ISAKMP_NTYPE_INVALID_CERTIFICATE;
+			}
+
+			if (check_typeofcertname(id_b->type, type) == 0)
+				break;
+
+			/* next name */
+			racoon_free(altname);
+			altname = NULL;
+		}
+		if (idlen != strlen(altname)) {
+			plog(LLV_ERROR, LOCATION, NULL,
+				"Invalid ID length in phase 1.\n");
+			racoon_free(altname);
+			return ISAKMP_NTYPE_INVALID_ID_INFORMATION;
+		}
+		if (check_typeofcertname(id_b->type, type) != 0) {
+			plog(LLV_ERROR, LOCATION, NULL,
+				"ID type mismatched. ID: %s CERT: %s.\n",
+				s_ipsecdoi_ident(id_b->type),
+				s_ipsecdoi_ident(type));
+			racoon_free(altname);
+			return ISAKMP_NTYPE_INVALID_ID_INFORMATION;
+		}
+		error = memcmp(id_b + 1, altname, idlen);
+		if (error) {
+			plog(LLV_ERROR, LOCATION, NULL, "ID mismatched.\n");
+			plogdump(LLV_DEBUG, id_b + 1, idlen);
+			plogdump(LLV_DEBUG, altname, idlen);
+			racoon_free(altname);
+			return ISAKMP_NTYPE_INVALID_ID_INFORMATION;
+		}
+		racoon_free(altname);
+		return 0;
+	}
+	default:
+		plog(LLV_ERROR, LOCATION, NULL,
+			"Inpropper ID type passed: %s.\n",
+			s_ipsecdoi_ident(id_b->type));
+		return ISAKMP_NTYPE_INVALID_ID_INFORMATION;
+	}
+	/*NOTREACHED*/
+}
+
+static int
+check_typeofcertname(doi, genid)
+	int doi, genid;
+{
+	switch (doi) {
+	case IPSECDOI_ID_IPV4_ADDR:
+	case IPSECDOI_ID_IPV4_ADDR_SUBNET:
+	case IPSECDOI_ID_IPV6_ADDR:
+	case IPSECDOI_ID_IPV6_ADDR_SUBNET:
+	case IPSECDOI_ID_IPV4_ADDR_RANGE:
+	case IPSECDOI_ID_IPV6_ADDR_RANGE:
+		if (genid != GENT_IPADD)
+			return -1;
+		return 0;
+	case IPSECDOI_ID_FQDN:
+		if (genid != GENT_DNS)
+			return -1;
+		return 0;
+	case IPSECDOI_ID_USER_FQDN:
+		if (genid != GENT_EMAIL)
+			return -1;
+		return 0;
+	case IPSECDOI_ID_DER_ASN1_DN: /* should not be passed to this function*/
+	case IPSECDOI_ID_DER_ASN1_GN:
+	case IPSECDOI_ID_KEY_ID:
+	default:
+		return -1;
+	}
+	/*NOTREACHED*/
+}
+
+/*
+ * save certificate including certificate type.
+ */
+int
+oakley_savecert(iph1, gen)
+	struct ph1handle *iph1;
+	struct isakmp_gen *gen;
+{
+	cert_t **c;
+	u_int8_t type;
+	STACK_OF(X509) *certs=NULL;
+	PKCS7 *p7;
+
+	type = *(u_int8_t *)(gen + 1) & 0xff;
+
+	switch (type) {
+	case ISAKMP_CERT_DNS:
+		plog(LLV_WARNING, LOCATION, NULL,
+			"CERT payload is unnecessary in DNSSEC. "
+			"ignore this CERT payload.\n");
+		return 0;
+	case ISAKMP_CERT_PKCS7:
+	case ISAKMP_CERT_PGP:
+	case ISAKMP_CERT_X509SIGN:
+	case ISAKMP_CERT_KERBEROS:
+	case ISAKMP_CERT_SPKI:
+		c = &iph1->cert_p;
+		break;
+	case ISAKMP_CERT_CRL:
+		c = &iph1->crl_p;
+		break;
+	case ISAKMP_CERT_X509KE:
+	case ISAKMP_CERT_X509ATTR:
+	case ISAKMP_CERT_ARL:
+		plog(LLV_ERROR, LOCATION, NULL,
+			"No supported such CERT type %d\n", type);
+		return -1;
+	default:
+		plog(LLV_ERROR, LOCATION, NULL,
+			"Invalid CERT type %d\n", type);
+		return -1;
+	}
+
+	/* XXX choice the 1th cert, ignore after the cert. */ 
+	/* XXX should be processed. */
+	if (*c) {
+		plog(LLV_WARNING, LOCATION, NULL,
+			"ignore 2nd CERT payload.\n");
+		return 0;
+	}
+
+	if (type == ISAKMP_CERT_PKCS7) {
+		u_char *bp;
+		int i;
+
+		/* Skip the header */
+		bp = (u_char *)(gen + 1);
+		/* And the first byte is the certificate type, 
+		 * we know that already
+		 */
+		bp++;
+		p7 = d2i_PKCS7(NULL, (void *)&bp, 
+		    ntohs(gen->len) - sizeof(*gen) - 1);
+
+		if (!p7) {
+			plog(LLV_ERROR, LOCATION, NULL,
+			     "Failed to parse PKCS#7 CERT.\n");
+			return -1;
+		}
+
+		/* Copied this from the openssl pkcs7 application;
+		 * there"s little by way of documentation for any of
+		 * it. I can only presume it"s correct.
+		 */
+		
+		i = OBJ_obj2nid(p7->type);
+		switch (i) {
+		case NID_pkcs7_signed:
+			certs=p7->d.sign->cert;
+			break;
+		case NID_pkcs7_signedAndEnveloped:
+			certs=p7->d.signed_and_enveloped->cert;
+			break;
+		default:
+			 break;
+		}
+
+		if (!certs) {
+			plog(LLV_ERROR, LOCATION, NULL,
+			     "CERT PKCS#7 bundle contains no certs.\n");
+			PKCS7_free(p7);
+			return -1;
+		}
+
+		for (i = 0; i < sk_X509_num(certs); i++) {
+			int len;
+			u_char *bp;
+			X509 *cert = sk_X509_value(certs,i);
+
+			plog(LLV_DEBUG, LOCATION, NULL, 
+			     "Trying PKCS#7 cert %d.\n", i);
+
+			/* We'll just try each cert in turn */
+			*c = save_certx509(cert);
+
+			if (!*c) {
+				plog(LLV_ERROR, LOCATION, NULL,
+				     "Failed to get CERT buffer.\n");
+				continue;
+			}
+
+			/* Ignore cert if it doesn't match identity
+			 * XXX If verify cert is disabled, we still just take
+			 * the first certificate....
+			 */
+			if(iph1->rmconf->verify_cert &&
+			   oakley_check_certid(iph1)) {
+				plog(LLV_DEBUG, LOCATION, NULL,
+				     "Discarding CERT: does not match ID.\n");
+				oakley_delcert((*c));
+				*c = NULL;
+				continue;
+			}
+
+			{
+				char *p = eay_get_x509text(&(*c)->cert);
+				plog(LLV_DEBUG, LOCATION, NULL, "CERT saved:\n");
+				plogdump(LLV_DEBUG, (*c)->cert.v, (*c)->cert.l);
+				plog(LLV_DEBUG, LOCATION, NULL, "%s", 
+				     p ? p : "\n");
+				racoon_free(p);
+			}
+			break;
+		}
+		PKCS7_free(p7);
+
+	} else {
+		*c = save_certbuf(gen);
+		if (!*c) {
+			plog(LLV_ERROR, LOCATION, NULL,
+			     "Failed to get CERT buffer.\n");
+			return -1;
+		}
+
+		switch ((*c)->type) {
+		case ISAKMP_CERT_DNS:
+			plog(LLV_WARNING, LOCATION, NULL,
+			     "CERT payload is unnecessary in DNSSEC. "
+			     "ignore it.\n");
+			return 0;
+		case ISAKMP_CERT_PGP:
+		case ISAKMP_CERT_X509SIGN:
+		case ISAKMP_CERT_KERBEROS:
+		case ISAKMP_CERT_SPKI:
+			/* Ignore cert if it doesn't match identity
+			 * XXX If verify cert is disabled, we still just take
+			 * the first certificate....
+			 */
+			if(iph1->rmconf->verify_cert &&
+			   oakley_check_certid(iph1)){
+				plog(LLV_DEBUG, LOCATION, NULL,
+				     "Discarding CERT: does not match ID.\n");
+				oakley_delcert((*c));
+				*c = NULL;
+				return 0;
+			}
+
+			{
+				char *p = eay_get_x509text(&(*c)->cert);
+				plog(LLV_DEBUG, LOCATION, NULL, "CERT saved:\n");
+				plogdump(LLV_DEBUG, (*c)->cert.v, (*c)->cert.l);
+				plog(LLV_DEBUG, LOCATION, NULL, "%s", p ? p : "\n");
+				racoon_free(p);
+			}
+			break;
+		case ISAKMP_CERT_CRL:
+			plog(LLV_DEBUG, LOCATION, NULL, "CRL saved:\n");
+			plogdump(LLV_DEBUG, (*c)->cert.v, (*c)->cert.l);
+			break;
+		case ISAKMP_CERT_X509KE:
+		case ISAKMP_CERT_X509ATTR:
+		case ISAKMP_CERT_ARL:
+		default:
+			/* XXX */
+			oakley_delcert((*c));
+			*c = NULL;
+			return 0;
+		}
+	}
+	
+	return 0;
+}
+
+/*
+ * save certificate including certificate type.
+ */
+int
+oakley_savecr(iph1, gen)
+	struct ph1handle *iph1;
+	struct isakmp_gen *gen;
+{
+	cert_t **c;
+	u_int8_t type;
+
+	type = *(u_int8_t *)(gen + 1) & 0xff;
+
+	switch (type) {
+	case ISAKMP_CERT_DNS:
+		plog(LLV_WARNING, LOCATION, NULL,
+			"CERT payload is unnecessary in DNSSEC\n");
+		/*FALLTHRU*/
+	case ISAKMP_CERT_PKCS7:
+	case ISAKMP_CERT_PGP:
+	case ISAKMP_CERT_X509SIGN:
+	case ISAKMP_CERT_KERBEROS:
+	case ISAKMP_CERT_SPKI:
+		c = &iph1->cr_p;
+		break;
+	case ISAKMP_CERT_X509KE:
+	case ISAKMP_CERT_X509ATTR:
+	case ISAKMP_CERT_ARL:
+		plog(LLV_ERROR, LOCATION, NULL,
+			"No supported such CR type %d\n", type);
+		return -1;
+	case ISAKMP_CERT_CRL:
+	default:
+		plog(LLV_ERROR, LOCATION, NULL,
+			"Invalid CR type %d\n", type);
+		return -1;
+	}
+
+	*c = save_certbuf(gen);
+	if (!*c) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"Failed to get CR buffer.\n");
+		return -1;
+	}
+
+	plog(LLV_DEBUG, LOCATION, NULL, "CR saved:\n");
+	plogdump(LLV_DEBUG, (*c)->cert.v, (*c)->cert.l);
+
+	return 0;
+}
+
+static cert_t *
+save_certbuf(gen)
+	struct isakmp_gen *gen;
+{
+	cert_t *new;
+
+	if(ntohs(gen->len) <= sizeof(*gen)){
+		plog(LLV_ERROR, LOCATION, NULL,
+			 "Len is too small !!.\n");
+		return NULL;
+	}
+
+	new = oakley_newcert();
+	if (!new) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"Failed to get CERT buffer.\n");
+		return NULL;
+	}
+
+	new->pl = vmalloc(ntohs(gen->len) - sizeof(*gen));
+	if (new->pl == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"Failed to copy CERT from packet.\n");
+		oakley_delcert(new);
+		new = NULL;
+		return NULL;
+	}
+	memcpy(new->pl->v, gen + 1, new->pl->l);
+	new->type = new->pl->v[0] & 0xff;
+	new->cert.v = new->pl->v + 1;
+	new->cert.l = new->pl->l - 1;
+
+	return new;
+}
+
+static cert_t *
+save_certx509(cert)
+	X509 *cert;
+{
+	cert_t *new;
+        int len;
+        u_char *bp;
+
+	new = oakley_newcert();
+	if (!new) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"Failed to get CERT buffer.\n");
+		return NULL;
+	}
+
+        len = i2d_X509(cert, NULL);
+	new->pl = vmalloc(len);
+	if (new->pl == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"Failed to copy CERT from packet.\n");
+		oakley_delcert(new);
+		new = NULL;
+		return NULL;
+	}
+        bp = (u_char *) new->pl->v;
+        len = i2d_X509(cert, &bp);
+	new->type = ISAKMP_CERT_X509SIGN;
+	new->cert.v = new->pl->v;
+	new->cert.l = new->pl->l;
+
+	return new;
+}
+
+/*
+ * get my CR.
+ * NOTE: No Certificate Authority field is included to CR payload at the
+ * moment. Becuase any certificate authority are accepted without any check.
+ * The section 3.10 in RFC2408 says that this field SHOULD not be included,
+ * if there is no specific certificate authority requested.
+ */
+vchar_t *
+oakley_getcr(iph1)
+	struct ph1handle *iph1;
+{
+	vchar_t *buf;
+
+	buf = vmalloc(1);
+	if (buf == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"failed to get cr buffer\n");
+		return NULL;
+	}
+	if(iph1->rmconf->certtype == ISAKMP_CERT_NONE) {
+		buf->v[0] = iph1->rmconf->cacerttype;
+		plog(LLV_DEBUG, LOCATION, NULL, "create my CR: NONE, using %s instead\n",
+		s_isakmp_certtype(iph1->rmconf->cacerttype));
+	} else {
+		buf->v[0] = iph1->rmconf->certtype;
+		plog(LLV_DEBUG, LOCATION, NULL, "create my CR: %s\n",
+		s_isakmp_certtype(iph1->rmconf->certtype));
+	}
+	if (buf->l > 1)
+		plogdump(LLV_DEBUG, buf->v, buf->l);
+
+	return buf;
+}
+
+/*
+ * check peer's CR.
+ */
+int
+oakley_checkcr(iph1)
+	struct ph1handle *iph1;
+{
+	if (iph1->cr_p == NULL)
+		return 0;
+
+	plog(LLV_DEBUG, LOCATION, iph1->remote,
+		"peer transmitted CR: %s\n",
+		s_isakmp_certtype(iph1->cr_p->type));
+
+	if (iph1->cr_p->type != iph1->rmconf->certtype) {
+		plog(LLV_ERROR, LOCATION, iph1->remote,
+			"such a cert type isn't supported: %d\n",
+			(char)iph1->cr_p->type);
+		return -1;
+	}
+
+	return 0;
+}
+
+/*
+ * check to need CR payload.
+ */
+int
+oakley_needcr(type)
+	int type;
+{
+	switch (type) {
+	case OAKLEY_ATTR_AUTH_METHOD_DSSSIG:
+	case OAKLEY_ATTR_AUTH_METHOD_RSASIG:
+#ifdef ENABLE_HYBRID
+	case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_I:
+	case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_I:
+	case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_I:
+	case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_R:
+	case OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_I:
+	case OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_R:
+#endif
+		return 1;
+	default:
+		return 0;
+	}
+	/*NOTREACHED*/
+}
+
+/*
+ * compute SKEYID
+ * see seciton 5. Exchanges in RFC 2409
+ * psk: SKEYID = prf(pre-shared-key, Ni_b | Nr_b)
+ * sig: SKEYID = prf(Ni_b | Nr_b, g^ir)
+ * enc: SKEYID = prf(H(Ni_b | Nr_b), CKY-I | CKY-R)
+ */
+int
+oakley_skeyid(iph1)
+	struct ph1handle *iph1;
+{
+	vchar_t *buf = NULL, *bp;
+	char *p;
+	int len;
+	int error = -1;
+	
+	/* SKEYID */
+	switch (AUTHMETHOD(iph1)) {
+	case OAKLEY_ATTR_AUTH_METHOD_PSKEY:
+#ifdef ENABLE_HYBRID
+	case FICTIVE_AUTH_METHOD_XAUTH_PSKEY_I:
+	case OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_R:
+#endif
+		if (iph1->etype != ISAKMP_ETYPE_IDENT) {
+			iph1->authstr = getpskbyname(iph1->id_p);
+			if (iph1->authstr == NULL) {
+				if (iph1->rmconf->verify_identifier) {
+					plog(LLV_ERROR, LOCATION, iph1->remote,
+						"couldn't find the pskey.\n");
+					goto end;
+				}
+				plog(LLV_NOTIFY, LOCATION, iph1->remote,
+					"couldn't find the proper pskey, "
+					"try to get one by the peer's address.\n");
+			}
+		}
+		if (iph1->authstr == NULL) {
+			/*
+			 * If the exchange type is the main mode or if it's
+			 * failed to get the psk by ID, racoon try to get
+			 * the psk by remote IP address.
+			 * It may be nonsense.
+			 */
+			iph1->authstr = getpskbyaddr(iph1->remote);
+			if (iph1->authstr == NULL) {
+				plog(LLV_ERROR, LOCATION, iph1->remote,
+					"couldn't find the pskey for %s.\n",
+					saddrwop2str(iph1->remote));
+				goto end;
+			}
+		}
+		plog(LLV_DEBUG, LOCATION, NULL, "the psk found.\n");
+		/* should be secret PSK */
+		plog(LLV_DEBUG2, LOCATION, NULL, "psk: ");
+		plogdump(LLV_DEBUG2, iph1->authstr->v, iph1->authstr->l);
+
+		len = iph1->nonce->l + iph1->nonce_p->l;
+		buf = vmalloc(len);
+		if (buf == NULL) {
+			plog(LLV_ERROR, LOCATION, NULL,
+				"failed to get skeyid buffer\n");
+			goto end;
+		}
+		p = buf->v;
+
+		bp = (iph1->side == INITIATOR ? iph1->nonce : iph1->nonce_p);
+		plog(LLV_DEBUG, LOCATION, NULL, "nonce 1: ");
+		plogdump(LLV_DEBUG, bp->v, bp->l);
+		memcpy(p, bp->v, bp->l);
+		p += bp->l;
+
+		bp = (iph1->side == INITIATOR ? iph1->nonce_p : iph1->nonce);
+		plog(LLV_DEBUG, LOCATION, NULL, "nonce 2: ");
+		plogdump(LLV_DEBUG, bp->v, bp->l);
+		memcpy(p, bp->v, bp->l);
+		p += bp->l;
+
+		iph1->skeyid = oakley_prf(iph1->authstr, buf, iph1);
+		if (iph1->skeyid == NULL)
+			goto end;
+		break;
+
+	case OAKLEY_ATTR_AUTH_METHOD_DSSSIG:
+	case OAKLEY_ATTR_AUTH_METHOD_RSASIG:
+#ifdef ENABLE_HYBRID
+	case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_I:
+	case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_I:
+	case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_R:
+	case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_R:
+	case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_I:
+	case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_R:
+	case OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_I:
+	case OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_R:
+#endif
+#ifdef HAVE_GSSAPI
+	case OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB:
+#endif
+		len = iph1->nonce->l + iph1->nonce_p->l;
+		buf = vmalloc(len);
+		if (buf == NULL) {
+			plog(LLV_ERROR, LOCATION, NULL,
+				"failed to get nonce buffer\n");
+			goto end;
+		}
+		p = buf->v;
+
+		bp = (iph1->side == INITIATOR ? iph1->nonce : iph1->nonce_p);
+		plog(LLV_DEBUG, LOCATION, NULL, "nonce1: ");
+		plogdump(LLV_DEBUG, bp->v, bp->l);
+		memcpy(p, bp->v, bp->l);
+		p += bp->l;
+
+		bp = (iph1->side == INITIATOR ? iph1->nonce_p : iph1->nonce);
+		plog(LLV_DEBUG, LOCATION, NULL, "nonce2: ");
+		plogdump(LLV_DEBUG, bp->v, bp->l);
+		memcpy(p, bp->v, bp->l);
+		p += bp->l;
+
+		iph1->skeyid = oakley_prf(buf, iph1->dhgxy, iph1);
+		if (iph1->skeyid == NULL)
+			goto end;
+		break;
+	case OAKLEY_ATTR_AUTH_METHOD_RSAENC:
+	case OAKLEY_ATTR_AUTH_METHOD_RSAREV:
+#ifdef ENABLE_HYBRID
+	case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAENC_I:
+	case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAENC_R:
+	case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAREV_I:
+	case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAREV_R:
+#endif
+		plog(LLV_WARNING, LOCATION, NULL,
+			"not supported authentication method %s\n",
+			s_oakley_attr_method(iph1->approval->authmethod));
+		goto end;
+	default:
+		plog(LLV_ERROR, LOCATION, NULL,
+			"invalid authentication method %d\n",
+			iph1->approval->authmethod);
+		goto end;
+	}
+
+	plog(LLV_DEBUG, LOCATION, NULL, "SKEYID computed:\n");
+	plogdump(LLV_DEBUG, iph1->skeyid->v, iph1->skeyid->l);
+
+	error = 0;
+
+end:
+	if (buf != NULL)
+		vfree(buf);
+	return error;
+}
+
+/*
+ * compute SKEYID_[dae]
+ * see seciton 5. Exchanges in RFC 2409
+ * SKEYID_d = prf(SKEYID, g^ir | CKY-I | CKY-R | 0)
+ * SKEYID_a = prf(SKEYID, SKEYID_d | g^ir | CKY-I | CKY-R | 1)
+ * SKEYID_e = prf(SKEYID, SKEYID_a | g^ir | CKY-I | CKY-R | 2)
+ */
+int
+oakley_skeyid_dae(iph1)
+	struct ph1handle *iph1;
+{
+	vchar_t *buf = NULL;
+	char *p;
+	int len;
+	int error = -1;
+
+	if (iph1->skeyid == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL, "no SKEYID found.\n");
+		goto end;
+	}
+
+	/* SKEYID D */
+	/* SKEYID_d = prf(SKEYID, g^xy | CKY-I | CKY-R | 0) */
+	len = iph1->dhgxy->l + sizeof(cookie_t) * 2 + 1;
+	buf = vmalloc(len);
+	if (buf == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"failed to get skeyid buffer\n");
+		goto end;
+	}
+	p = buf->v;
+
+	memcpy(p, iph1->dhgxy->v, iph1->dhgxy->l);
+	p += iph1->dhgxy->l;
+	memcpy(p, (caddr_t)&iph1->index.i_ck, sizeof(cookie_t));
+	p += sizeof(cookie_t);
+	memcpy(p, (caddr_t)&iph1->index.r_ck, sizeof(cookie_t));
+	p += sizeof(cookie_t);
+	*p = 0;
+	iph1->skeyid_d = oakley_prf(iph1->skeyid, buf, iph1);
+	if (iph1->skeyid_d == NULL)
+		goto end;
+
+	vfree(buf);
+	buf = NULL;
+
+	plog(LLV_DEBUG, LOCATION, NULL, "SKEYID_d computed:\n");
+	plogdump(LLV_DEBUG, iph1->skeyid_d->v, iph1->skeyid_d->l);
+
+	/* SKEYID A */
+	/* SKEYID_a = prf(SKEYID, SKEYID_d | g^xy | CKY-I | CKY-R | 1) */
+	len = iph1->skeyid_d->l + iph1->dhgxy->l + sizeof(cookie_t) * 2 + 1;
+	buf = vmalloc(len);
+	if (buf == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"failed to get skeyid buffer\n");
+		goto end;
+	}
+	p = buf->v;
+	memcpy(p, iph1->skeyid_d->v, iph1->skeyid_d->l);
+	p += iph1->skeyid_d->l;
+	memcpy(p, iph1->dhgxy->v, iph1->dhgxy->l);
+	p += iph1->dhgxy->l;
+	memcpy(p, (caddr_t)&iph1->index.i_ck, sizeof(cookie_t));
+	p += sizeof(cookie_t);
+	memcpy(p, (caddr_t)&iph1->index.r_ck, sizeof(cookie_t));
+	p += sizeof(cookie_t);
+	*p = 1;
+	iph1->skeyid_a = oakley_prf(iph1->skeyid, buf, iph1);
+	if (iph1->skeyid_a == NULL)
+		goto end;
+
+	vfree(buf);
+	buf = NULL;
+
+	plog(LLV_DEBUG, LOCATION, NULL, "SKEYID_a computed:\n");
+	plogdump(LLV_DEBUG, iph1->skeyid_a->v, iph1->skeyid_a->l);
+
+	/* SKEYID E */
+	/* SKEYID_e = prf(SKEYID, SKEYID_a | g^xy | CKY-I | CKY-R | 2) */
+	len = iph1->skeyid_a->l + iph1->dhgxy->l + sizeof(cookie_t) * 2 + 1;
+	buf = vmalloc(len);
+	if (buf == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"failed to get skeyid buffer\n");
+		goto end;
+	}
+	p = buf->v;
+	memcpy(p, iph1->skeyid_a->v, iph1->skeyid_a->l);
+	p += iph1->skeyid_a->l;
+	memcpy(p, iph1->dhgxy->v, iph1->dhgxy->l);
+	p += iph1->dhgxy->l;
+	memcpy(p, (caddr_t)&iph1->index.i_ck, sizeof(cookie_t));
+	p += sizeof(cookie_t);
+	memcpy(p, (caddr_t)&iph1->index.r_ck, sizeof(cookie_t));
+	p += sizeof(cookie_t);
+	*p = 2;
+	iph1->skeyid_e = oakley_prf(iph1->skeyid, buf, iph1);
+	if (iph1->skeyid_e == NULL)
+		goto end;
+
+	vfree(buf);
+	buf = NULL;
+
+	plog(LLV_DEBUG, LOCATION, NULL, "SKEYID_e computed:\n");
+	plogdump(LLV_DEBUG, iph1->skeyid_e->v, iph1->skeyid_e->l);
+
+	error = 0;
+
+end:
+	if (buf != NULL)
+		vfree(buf);
+	return error;
+}
+
+/*
+ * compute final encryption key.
+ * see Appendix B.
+ */
+int
+oakley_compute_enckey(iph1)
+	struct ph1handle *iph1;
+{
+	u_int keylen, prflen;
+	int error = -1;
+
+	/* RFC2409 p39 */
+	keylen = alg_oakley_encdef_keylen(iph1->approval->enctype,
+					iph1->approval->encklen);
+	if (keylen == -1) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"invalid encryption algoritym %d, "
+			"or invalid key length %d.\n",
+			iph1->approval->enctype,
+			iph1->approval->encklen);
+		goto end;
+	}
+	iph1->key = vmalloc(keylen >> 3);
+	if (iph1->key == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"failed to get key buffer\n");
+		goto end;
+	}
+
+	/* set prf length */
+	prflen = alg_oakley_hashdef_hashlen(iph1->approval->hashtype);
+	if (prflen == -1) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"invalid hash type %d.\n", iph1->approval->hashtype);
+		goto end;
+	}
+
+	/* see isakmp-oakley-08 5.3. */
+	if (iph1->key->l <= iph1->skeyid_e->l) {
+		/*
+		 * if length(Ka) <= length(SKEYID_e)
+		 *	Ka = first length(K) bit of SKEYID_e
+		 */
+		memcpy(iph1->key->v, iph1->skeyid_e->v, iph1->key->l);
+	} else {
+		vchar_t *buf = NULL, *res = NULL;
+		u_char *p, *ep;
+		int cplen;
+		int subkey;
+
+		/*
+		 * otherwise,
+		 *	Ka = K1 | K2 | K3
+		 * where
+		 *	K1 = prf(SKEYID_e, 0)
+		 *	K2 = prf(SKEYID_e, K1)
+		 *	K3 = prf(SKEYID_e, K2)
+		 */
+		plog(LLV_DEBUG, LOCATION, NULL,
+			"len(SKEYID_e) < len(Ka) (%zu < %zu), "
+			"generating long key (Ka = K1 | K2 | ...)\n",
+			iph1->skeyid_e->l, iph1->key->l);
+
+		if ((buf = vmalloc(prflen >> 3)) == 0) {
+			plog(LLV_ERROR, LOCATION, NULL,
+				"failed to get key buffer\n");
+			goto end;
+		}
+		p = (u_char *)iph1->key->v;
+		ep = p + iph1->key->l;
+
+		subkey = 1;
+		while (p < ep) {
+			if (p == (u_char *)iph1->key->v) {
+				/* just for computing K1 */
+				buf->v[0] = 0;
+				buf->l = 1;
+			}
+			res = oakley_prf(iph1->skeyid_e, buf, iph1);
+			if (res == NULL) {
+				vfree(buf);
+				goto end;
+			}
+			plog(LLV_DEBUG, LOCATION, NULL,
+				"compute intermediate encryption key K%d\n",
+				subkey);
+			plogdump(LLV_DEBUG, buf->v, buf->l);
+			plogdump(LLV_DEBUG, res->v, res->l);
+
+			cplen = (res->l < ep - p) ? res->l : ep - p;
+			memcpy(p, res->v, cplen);
+			p += cplen;
+
+			buf->l = prflen >> 3;	/* to cancel K1 speciality */
+			if (res->l != buf->l) {
+				plog(LLV_ERROR, LOCATION, NULL,
+					"internal error: res->l=%zu buf->l=%zu\n",
+					res->l, buf->l);
+				vfree(res);
+				vfree(buf);
+				goto end;
+			}
+			memcpy(buf->v, res->v, res->l);
+			vfree(res);
+			subkey++;
+		}
+
+		vfree(buf);
+	}
+
+	/*
+	 * don't check any weak key or not.
+	 * draft-ietf-ipsec-ike-01.txt Appendix B.
+	 * draft-ietf-ipsec-ciph-aes-cbc-00.txt Section 2.3.
+	 */
+#if 0
+	/* weakkey check */
+	if (iph1->approval->enctype > ARRAYLEN(oakley_encdef)
+	 || oakley_encdef[iph1->approval->enctype].weakkey == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"encryption algoritym %d isn't supported.\n",
+			iph1->approval->enctype);
+		goto end;
+	}
+	if ((oakley_encdef[iph1->approval->enctype].weakkey)(iph1->key)) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"weakkey was generated.\n");
+		goto end;
+	}
+#endif
+
+	plog(LLV_DEBUG, LOCATION, NULL, "final encryption key computed:\n");
+	plogdump(LLV_DEBUG, iph1->key->v, iph1->key->l);
+
+	error = 0;
+
+end:
+	return error;
+}
+
+/* allocated new buffer for CERT */
+cert_t *
+oakley_newcert()
+{
+	cert_t *new;
+
+	new = racoon_calloc(1, sizeof(*new));
+	if (new == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"failed to get cert's buffer\n");
+		return NULL;
+	}
+
+	new->pl = NULL;
+
+	return new;
+}
+
+/* delete buffer for CERT */
+void
+oakley_delcert(cert)
+	cert_t *cert;
+{
+	if (!cert)
+		return;
+	if (cert->pl)
+		VPTRINIT(cert->pl);
+	racoon_free(cert);
+}
+
+/*
+ * compute IV and set to ph1handle
+ *	IV = hash(g^xi | g^xr)
+ * see 4.1 Phase 1 state in draft-ietf-ipsec-ike.
+ */
+int
+oakley_newiv(iph1)
+	struct ph1handle *iph1;
+{
+	struct isakmp_ivm *newivm = NULL;
+	vchar_t *buf = NULL, *bp;
+	char *p;
+	int len;
+
+	/* create buffer */
+	len = iph1->dhpub->l + iph1->dhpub_p->l;
+	buf = vmalloc(len);
+	if (buf == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"failed to get iv buffer\n");
+		return -1;
+	}
+
+	p = buf->v;
+
+	bp = (iph1->side == INITIATOR ? iph1->dhpub : iph1->dhpub_p);
+	memcpy(p, bp->v, bp->l);
+	p += bp->l;
+
+	bp = (iph1->side == INITIATOR ? iph1->dhpub_p : iph1->dhpub);
+	memcpy(p, bp->v, bp->l);
+	p += bp->l;
+
+	/* allocate IVm */
+	newivm = racoon_calloc(1, sizeof(struct isakmp_ivm));
+	if (newivm == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"failed to get iv buffer\n");
+		vfree(buf);
+		return -1;
+	}
+
+	/* compute IV */
+	newivm->iv = oakley_hash(buf, iph1);
+	if (newivm->iv == NULL) {
+		vfree(buf);
+		oakley_delivm(newivm);
+		return -1;
+	}
+
+	/* adjust length of iv */
+	newivm->iv->l = alg_oakley_encdef_blocklen(iph1->approval->enctype);
+	if (newivm->iv->l == -1) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"invalid encryption algoriym %d.\n",
+			iph1->approval->enctype);
+		vfree(buf);
+		oakley_delivm(newivm);
+		return -1;
+	}
+
+	/* create buffer to save iv */
+	if ((newivm->ive = vdup(newivm->iv)) == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"vdup (%s)\n", strerror(errno));
+		vfree(buf);
+		oakley_delivm(newivm);
+		return -1;
+	}
+
+	vfree(buf);
+
+	plog(LLV_DEBUG, LOCATION, NULL, "IV computed:\n");
+	plogdump(LLV_DEBUG, newivm->iv->v, newivm->iv->l);
+
+	iph1->ivm = newivm;
+
+	return 0;
+}
+
+/*
+ * compute IV for the payload after phase 1.
+ * It's not limited for phase 2.
+ * if pahse 1 was encrypted.
+ *	IV = hash(last CBC block of Phase 1 | M-ID)
+ * if phase 1 was not encrypted.
+ *	IV = hash(phase 1 IV | M-ID)
+ * see 4.2 Phase 2 state in draft-ietf-ipsec-ike.
+ */
+struct isakmp_ivm *
+oakley_newiv2(iph1, msgid)
+	struct ph1handle *iph1;
+	u_int32_t msgid;
+{
+	struct isakmp_ivm *newivm = NULL;
+	vchar_t *buf = NULL;
+	char *p;
+	int len;
+	int error = -1;
+
+	/* create buffer */
+	len = iph1->ivm->iv->l + sizeof(msgid_t);
+	buf = vmalloc(len);
+	if (buf == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"failed to get iv buffer\n");
+		goto end;
+	}
+
+	p = buf->v;
+
+	memcpy(p, iph1->ivm->iv->v, iph1->ivm->iv->l);
+	p += iph1->ivm->iv->l;
+
+	memcpy(p, &msgid, sizeof(msgid));
+
+	plog(LLV_DEBUG, LOCATION, NULL, "compute IV for phase2\n");
+	plog(LLV_DEBUG, LOCATION, NULL, "phase1 last IV:\n");
+	plogdump(LLV_DEBUG, buf->v, buf->l);
+
+	/* allocate IVm */
+	newivm = racoon_calloc(1, sizeof(struct isakmp_ivm));
+	if (newivm == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"failed to get iv buffer\n");
+		goto end;
+	}
+
+	/* compute IV */
+	if ((newivm->iv = oakley_hash(buf, iph1)) == NULL)
+		goto end;
+
+	/* adjust length of iv */
+	newivm->iv->l = alg_oakley_encdef_blocklen(iph1->approval->enctype);
+	if (newivm->iv->l == -1) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"invalid encryption algoriym %d.\n",
+			iph1->approval->enctype);
+		goto end;
+	}
+
+	/* create buffer to save new iv */
+	if ((newivm->ive = vdup(newivm->iv)) == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL, "vdup (%s)\n", strerror(errno));
+		goto end;
+	}
+
+	error = 0;
+
+	plog(LLV_DEBUG, LOCATION, NULL, "phase2 IV computed:\n");
+	plogdump(LLV_DEBUG, newivm->iv->v, newivm->iv->l);
+
+end:
+	if (error && newivm != NULL){
+		oakley_delivm(newivm);
+		newivm=NULL;
+	}
+	if (buf != NULL)
+		vfree(buf);
+	return newivm;
+}
+
+void
+oakley_delivm(ivm)
+	struct isakmp_ivm *ivm;
+{
+	if (ivm == NULL)
+		return;
+
+	if (ivm->iv != NULL)
+		vfree(ivm->iv);
+	if (ivm->ive != NULL)
+		vfree(ivm->ive);
+	racoon_free(ivm);
+	plog(LLV_DEBUG, LOCATION, NULL, "IV freed\n");
+
+	return;
+}
+
+/*
+ * decrypt packet.
+ *   save new iv and old iv.
+ */
+vchar_t *
+oakley_do_decrypt(iph1, msg, ivdp, ivep)
+	struct ph1handle *iph1;
+	vchar_t *msg, *ivdp, *ivep;
+{
+	vchar_t *buf = NULL, *new = NULL;
+	char *pl;
+	int len;
+	u_int8_t padlen;
+	int blen;
+	int error = -1;
+
+	plog(LLV_DEBUG, LOCATION, NULL, "begin decryption.\n");
+
+	blen = alg_oakley_encdef_blocklen(iph1->approval->enctype);
+	if (blen == -1) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"invalid encryption algoriym %d.\n",
+			iph1->approval->enctype);
+		goto end;
+	}
+
+	/* save IV for next, but not sync. */
+	memset(ivep->v, 0, ivep->l);
+	memcpy(ivep->v, (caddr_t)&msg->v[msg->l - blen], blen);
+
+	plog(LLV_DEBUG, LOCATION, NULL,
+		"IV was saved for next processing:\n");
+	plogdump(LLV_DEBUG, ivep->v, ivep->l);
+
+	pl = msg->v + sizeof(struct isakmp);
+
+	len = msg->l - sizeof(struct isakmp);
+
+	/* create buffer */
+	buf = vmalloc(len);
+	if (buf == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"failed to get buffer to decrypt.\n");
+		goto end;
+	}
+	memcpy(buf->v, pl, len);
+
+	/* do decrypt */
+	new = alg_oakley_encdef_decrypt(iph1->approval->enctype,
+					buf, iph1->key, ivdp);
+	if (new == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"decryption %d failed.\n", iph1->approval->enctype);
+		goto end;
+	}
+	plog(LLV_DEBUG, LOCATION, NULL, "with key:\n");
+	plogdump(LLV_DEBUG, iph1->key->v, iph1->key->l);
+
+	vfree(buf);
+	buf = NULL;
+
+	plog(LLV_DEBUG, LOCATION, NULL, "decrypted payload by IV:\n");
+	plogdump(LLV_DEBUG, ivdp->v, ivdp->l);
+
+	plog(LLV_DEBUG, LOCATION, NULL,
+		"decrypted payload, but not trimed.\n");
+	plogdump(LLV_DEBUG, new->v, new->l);
+
+	/* get padding length */
+	if (lcconf->pad_excltail)
+		padlen = new->v[new->l - 1] + 1;
+	else
+		padlen = new->v[new->l - 1];
+	plog(LLV_DEBUG, LOCATION, NULL, "padding len=%u\n", padlen);
+
+	/* trim padding */
+	if (lcconf->pad_strict) {
+		if (padlen > new->l) {
+			plog(LLV_ERROR, LOCATION, NULL,
+				"invalied padding len=%u, buflen=%zu.\n",
+				padlen, new->l);
+			plogdump(LLV_ERROR, new->v, new->l);
+			goto end;
+		}
+		new->l -= padlen;
+		plog(LLV_DEBUG, LOCATION, NULL, "trimmed padding\n");
+	} else {
+		plog(LLV_DEBUG, LOCATION, NULL, "skip to trim padding.\n");
+	}
+
+	/* create new buffer */
+	len = sizeof(struct isakmp) + new->l;
+	buf = vmalloc(len);
+	if (buf == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"failed to get buffer to decrypt.\n");
+		goto end;
+	}
+	memcpy(buf->v, msg->v, sizeof(struct isakmp));
+	memcpy(buf->v + sizeof(struct isakmp), new->v, new->l);
+	((struct isakmp *)buf->v)->len = htonl(buf->l);
+
+	plog(LLV_DEBUG, LOCATION, NULL, "decrypted.\n");
+	plogdump(LLV_DEBUG, buf->v, buf->l);
+
+#ifdef HAVE_PRINT_ISAKMP_C
+	isakmp_printpacket(buf, iph1->remote, iph1->local, 1);
+#endif
+
+	error = 0;
+
+end:
+	if (error && buf != NULL) {
+		vfree(buf);
+		buf = NULL;
+	}
+	if (new != NULL)
+		vfree(new);
+
+	return buf;
+}
+
+/*
+ * encrypt packet.
+ */
+vchar_t *
+oakley_do_encrypt(iph1, msg, ivep, ivp)
+	struct ph1handle *iph1;
+	vchar_t *msg, *ivep, *ivp;
+{
+	vchar_t *buf = 0, *new = 0;
+	char *pl;
+	int len;
+	u_int padlen;
+	int blen;
+	int error = -1;
+
+	plog(LLV_DEBUG, LOCATION, NULL, "begin encryption.\n");
+
+	/* set cbc block length */
+	blen = alg_oakley_encdef_blocklen(iph1->approval->enctype);
+	if (blen == -1) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"invalid encryption algoriym %d.\n",
+			iph1->approval->enctype);
+		goto end;
+	}
+
+	pl = msg->v + sizeof(struct isakmp);
+	len = msg->l - sizeof(struct isakmp);
+
+	/* add padding */
+	padlen = oakley_padlen(len, blen);
+	plog(LLV_DEBUG, LOCATION, NULL, "pad length = %u\n", padlen);
+
+	/* create buffer */
+	buf = vmalloc(len + padlen);
+	if (buf == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"failed to get buffer to encrypt.\n");
+		goto end;
+	}
+        if (padlen) {
+                int i;
+		char *p = &buf->v[len];
+		if (lcconf->pad_random) {
+			for (i = 0; i < padlen; i++)
+				*p++ = eay_random() & 0xff;
+		}
+        }
+        memcpy(buf->v, pl, len);
+
+	/* make pad into tail */
+	if (lcconf->pad_excltail)
+		buf->v[len + padlen - 1] = padlen - 1;
+	else
+		buf->v[len + padlen - 1] = padlen;
+
+	plogdump(LLV_DEBUG, buf->v, buf->l);
+
+	/* do encrypt */
+	new = alg_oakley_encdef_encrypt(iph1->approval->enctype,
+					buf, iph1->key, ivep);
+	if (new == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"encryption %d failed.\n", iph1->approval->enctype);
+		goto end;
+	}
+	plog(LLV_DEBUG, LOCATION, NULL, "with key:\n");
+	plogdump(LLV_DEBUG, iph1->key->v, iph1->key->l);
+
+	vfree(buf);
+	buf = NULL;
+
+	plog(LLV_DEBUG, LOCATION, NULL, "encrypted payload by IV:\n");
+	plogdump(LLV_DEBUG, ivep->v, ivep->l);
+
+	/* save IV for next */
+	memset(ivp->v, 0, ivp->l);
+	memcpy(ivp->v, (caddr_t)&new->v[new->l - blen], blen);
+
+	plog(LLV_DEBUG, LOCATION, NULL, "save IV for next:\n");
+	plogdump(LLV_DEBUG, ivp->v, ivp->l);
+
+	/* create new buffer */
+	len = sizeof(struct isakmp) + new->l;
+	buf = vmalloc(len);
+	if (buf == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"failed to get buffer to encrypt.\n");
+		goto end;
+	}
+	memcpy(buf->v, msg->v, sizeof(struct isakmp));
+	memcpy(buf->v + sizeof(struct isakmp), new->v, new->l);
+	((struct isakmp *)buf->v)->len = htonl(buf->l);
+
+	error = 0;
+
+	plog(LLV_DEBUG, LOCATION, NULL, "encrypted.\n");
+
+end:
+	if (error && buf != NULL) {
+		vfree(buf);
+		buf = NULL;
+	}
+	if (new != NULL)
+		vfree(new);
+
+	return buf;
+}
+
+/* culculate padding length */
+static int
+oakley_padlen(len, base)
+	int len, base;
+{
+	int padlen;
+
+	padlen = base - len % base;
+
+	if (lcconf->pad_randomlen)
+		padlen += ((eay_random() % (lcconf->pad_maxsize + 1) + 1) *
+		    base);
+
+	return padlen;
+}
+
diff --git a/src/racoon/oakley.h b/src/racoon/oakley.h
new file mode 100644
index 0000000..a8dbbd2
--- /dev/null
+++ b/src/racoon/oakley.h
@@ -0,0 +1,243 @@
+/*	$NetBSD: oakley.h,v 1.5 2006/10/06 12:02:27 manu Exp $	*/
+
+/* Id: oakley.h,v 1.13 2005/05/30 20:12:43 fredsen Exp */
+
+/*
+ * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _OAKLEY_H
+#define _OAKLEY_H
+
+#include "vmbuf.h"
+
+/* refer to RFC 2409 */
+
+/* Attribute Classes */
+#define OAKLEY_ATTR_ENC_ALG		1 /* B */
+#define   OAKLEY_ATTR_ENC_ALG_DES		1
+#define   OAKLEY_ATTR_ENC_ALG_IDEA		2
+#define   OAKLEY_ATTR_ENC_ALG_BLOWFISH		3
+#define   OAKLEY_ATTR_ENC_ALG_RC5		4
+#define   OAKLEY_ATTR_ENC_ALG_3DES		5
+#define   OAKLEY_ATTR_ENC_ALG_CAST		6
+#define   OAKLEY_ATTR_ENC_ALG_AES		7
+#define   OAKLEY_ATTR_ENC_ALG_CAMELLIA		8	
+					/*	65001 - 65535 Private Use */
+#define OAKLEY_ATTR_HASH_ALG		2 /* B */
+#define   OAKLEY_ATTR_HASH_ALG_MD5		1
+#define   OAKLEY_ATTR_HASH_ALG_SHA		2
+#define   OAKLEY_ATTR_HASH_ALG_TIGER		3
+#if defined(WITH_SHA2)
+#define   OAKLEY_ATTR_HASH_ALG_SHA2_256		4
+#define   OAKLEY_ATTR_HASH_ALG_SHA2_384		5
+#define   OAKLEY_ATTR_HASH_ALG_SHA2_512		6
+#endif
+					/*	65001 - 65535 Private Use */
+#define OAKLEY_ATTR_AUTH_METHOD		3 /* B */
+#define   OAKLEY_ATTR_AUTH_METHOD_PSKEY		1
+#define   OAKLEY_ATTR_AUTH_METHOD_DSSSIG	2
+#define   OAKLEY_ATTR_AUTH_METHOD_RSASIG	3
+#define   OAKLEY_ATTR_AUTH_METHOD_RSAENC	4
+#define   OAKLEY_ATTR_AUTH_METHOD_RSAREV	5
+#define   OAKLEY_ATTR_AUTH_METHOD_EGENC		6
+#define   OAKLEY_ATTR_AUTH_METHOD_EGREV		7
+	/* Hybrid Auth */
+#ifdef ENABLE_HYBRID    
+#define   OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_I	64221
+#define	  OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_R	64222
+#define   OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_I	64223
+#define   OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_R	64224
+
+					/*	65001 - 65535 Private Use */
+
+        /* Plain Xauth */
+#define OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_I	65001
+#define OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_R	65002
+#define OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_I	65003
+#define OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_R	65004
+#define OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_I	65005
+#define OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_R	65006
+#define OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAENC_I	65007
+#define OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAENC_R	65008
+#define OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAREV_I	65009
+#define OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAREV_R	65010
+#endif
+
+					/*	65500 -> still private
+					 * to avoid clash with GSSAPI_KRB below 
+					 */
+#define FICTIVE_AUTH_METHOD_XAUTH_PSKEY_I	65500
+
+
+	/*
+	 * The following are valid when the Vendor ID is one of
+	 * the following:
+	 *
+	 *	MD5("A GSS-API Authentication Method for IKE")
+	 *	MD5("GSSAPI") (recognized by Windows 2000)
+	 *	MD5("MS NT5 ISAKMPOAKLEY") (sent by Windows 2000)
+	 */
+#define   OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB	65001
+#define OAKLEY_ATTR_GRP_DESC		4 /* B */
+#define   OAKLEY_ATTR_GRP_DESC_MODP768		1
+#define   OAKLEY_ATTR_GRP_DESC_MODP1024		2
+#define   OAKLEY_ATTR_GRP_DESC_EC2N155		3
+#define   OAKLEY_ATTR_GRP_DESC_EC2N185		4
+#define   OAKLEY_ATTR_GRP_DESC_MODP1536		5
+#define   OAKLEY_ATTR_GRP_DESC_MODP2048		14
+#define   OAKLEY_ATTR_GRP_DESC_MODP3072		15
+#define   OAKLEY_ATTR_GRP_DESC_MODP4096		16
+#define   OAKLEY_ATTR_GRP_DESC_MODP6144		17
+#define   OAKLEY_ATTR_GRP_DESC_MODP8192		18
+					/*	32768 - 65535 Private Use */
+#define OAKLEY_ATTR_GRP_TYPE		5 /* B */
+#define   OAKLEY_ATTR_GRP_TYPE_MODP		1
+#define   OAKLEY_ATTR_GRP_TYPE_ECP		2
+#define   OAKLEY_ATTR_GRP_TYPE_EC2N		3
+					/*	65001 - 65535 Private Use */
+#define OAKLEY_ATTR_GRP_PI		6 /* V */
+#define OAKLEY_ATTR_GRP_GEN_ONE		7 /* V */
+#define OAKLEY_ATTR_GRP_GEN_TWO		8 /* V */
+#define OAKLEY_ATTR_GRP_CURVE_A		9 /* V */
+#define OAKLEY_ATTR_GRP_CURVE_B		10 /* V */
+#define OAKLEY_ATTR_SA_LD_TYPE		11 /* B */
+#define   OAKLEY_ATTR_SA_LD_TYPE_DEFAULT	1
+#define   OAKLEY_ATTR_SA_LD_TYPE_SEC		1
+#define   OAKLEY_ATTR_SA_LD_TYPE_KB		2
+#define   OAKLEY_ATTR_SA_LD_TYPE_MAX		3
+					/*	65001 - 65535 Private Use */
+#define OAKLEY_ATTR_SA_LD		12 /* V */
+#define   OAKLEY_ATTR_SA_LD_SEC_DEFAULT		28800 /* 8 hours */
+#define OAKLEY_ATTR_PRF			13 /* B */
+#define OAKLEY_ATTR_KEY_LEN		14 /* B */
+#define OAKLEY_ATTR_FIELD_SIZE		15 /* B */
+#define OAKLEY_ATTR_GRP_ORDER		16 /* V */
+#define OAKLEY_ATTR_BLOCK_SIZE		17 /* B */
+				/*	16384 - 32767 Private Use */
+
+	/*
+	 * The following are valid when the Vendor ID is one of
+	 * the following:
+	 *
+	 *	MD5("A GSS-API Authentication Method for IKE")
+	 *	MD5("GSSAPI") (recognized by Windows 2000)
+	 *	MD5("MS NT5 ISAKMPOAKLEY") (sent by Windows 2000)
+	 */
+#define OAKLEY_ATTR_GSS_ID		16384
+
+#define MAXPADLWORD	20
+
+struct dhgroup {
+	int type;
+	vchar_t *prime;
+	int gen1;
+	int gen2;
+	vchar_t *curve_a;
+	vchar_t *curve_b;
+	vchar_t *order;
+};
+
+/* certificate holder */
+typedef struct cert_t_tag {
+	u_int8_t type;		/* type of CERT, must be same to pl->v[0]*/
+	vchar_t cert;		/* pointer to the CERT */
+	vchar_t *pl;		/* CERT payload minus isakmp general header */
+} cert_t;
+
+struct ph1handle;
+struct ph2handle;
+struct isakmp_ivm;
+
+extern int oakley_get_defaultlifetime __P((void));
+
+extern int oakley_dhinit __P((void));
+extern void oakley_dhgrp_free __P((struct dhgroup *));
+extern int oakley_dh_compute __P((const struct dhgroup *,
+	vchar_t *, vchar_t *, vchar_t *, vchar_t **));
+extern int oakley_dh_generate __P((const struct dhgroup *,
+	vchar_t **, vchar_t **));
+extern int oakley_setdhgroup __P((int, struct dhgroup **));
+
+extern vchar_t *oakley_prf __P((vchar_t *, vchar_t *, struct ph1handle *));
+extern vchar_t *oakley_hash __P((vchar_t *, struct ph1handle *));
+
+extern int oakley_compute_keymat __P((struct ph2handle *, int));
+
+#if notyet
+extern vchar_t *oakley_compute_hashx __P((void));
+#endif
+extern vchar_t *oakley_compute_hash3 __P((struct ph1handle *,
+	u_int32_t, vchar_t *));
+extern vchar_t *oakley_compute_hash1 __P((struct ph1handle *,
+	u_int32_t, vchar_t *));
+extern vchar_t *oakley_ph1hash_common __P((struct ph1handle *, int));
+extern vchar_t *oakley_ph1hash_base_i __P((struct ph1handle *, int));
+extern vchar_t *oakley_ph1hash_base_r __P((struct ph1handle *, int));
+
+extern int oakley_validate_auth __P((struct ph1handle *));
+extern int oakley_getmycert __P((struct ph1handle *));
+extern int oakley_getsign __P((struct ph1handle *));
+extern vchar_t *oakley_getcr __P((struct ph1handle *));
+extern int oakley_checkcr __P((struct ph1handle *));
+extern int oakley_needcr __P((int));
+struct isakmp_gen;
+extern int oakley_savecert __P((struct ph1handle *, struct isakmp_gen *));
+extern int oakley_savecr __P((struct ph1handle *, struct isakmp_gen *));
+
+extern int oakley_skeyid __P((struct ph1handle *));
+extern int oakley_skeyid_dae __P((struct ph1handle *));
+
+extern int oakley_compute_enckey __P((struct ph1handle *));
+extern cert_t *oakley_newcert __P((void));
+extern void oakley_delcert __P((cert_t *));
+extern int oakley_newiv __P((struct ph1handle *));
+extern struct isakmp_ivm *oakley_newiv2 __P((struct ph1handle *, u_int32_t));
+extern void oakley_delivm __P((struct isakmp_ivm *));
+extern vchar_t *oakley_do_decrypt __P((struct ph1handle *,
+	vchar_t *, vchar_t *, vchar_t *));
+extern vchar_t *oakley_do_encrypt __P((struct ph1handle *,
+	vchar_t *, vchar_t *, vchar_t *));
+
+#ifdef ENABLE_HYBRID
+#define AUTHMETHOD(iph1)						     \
+    (((iph1)->rmconf->xauth &&						     \
+    (iph1)->approval->authmethod == OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_I) ? \
+	FICTIVE_AUTH_METHOD_XAUTH_PSKEY_I : (iph1)->approval->authmethod)
+#define RMAUTHMETHOD(iph1)						     \
+    (((iph1)->rmconf->xauth &&						     \
+    (iph1)->rmconf->proposal->authmethod ==                                  \
+	OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_I) ?                             \
+	FICTIVE_AUTH_METHOD_XAUTH_PSKEY_I :                                  \
+	(iph1)->rmconf->proposal->authmethod)
+#else
+#define AUTHMETHOD(iph1) (iph1)->approval->authmethod
+#define RMAUTHMETHOD(iph1) (iph1)->rmconf->proposal->authmethod
+#endif /* ENABLE_HYBRID */
+
+#endif /* _OAKLEY_H */
diff --git a/src/racoon/pfkey.c b/src/racoon/pfkey.c
new file mode 100644
index 0000000..7975a25
--- /dev/null
+++ b/src/racoon/pfkey.c
@@ -0,0 +1,3142 @@
+/*	$NetBSD: pfkey.c,v 1.18.4.5 2008/03/05 22:14:24 mgrooms Exp $	*/
+
+/* $Id: pfkey.c,v 1.18.4.5 2008/03/05 22:14:24 mgrooms Exp $ */
+
+/*
+ * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <netdb.h>
+#include <errno.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <netdb.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#ifdef ENABLE_NATT
+# ifdef __linux__
+#  include <linux/udp.h>
+# endif
+# if defined(__NetBSD__) || defined(__FreeBSD__) ||	\
+  (defined(__APPLE__) && defined(__MACH__))
+#  include <netinet/udp.h>
+# endif
+#endif
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <sys/queue.h>
+#ifndef ANDROID_CHANGES
+#include <sys/sysctl.h>
+#endif
+
+#include <net/route.h>
+#include <net/pfkeyv2.h>
+
+#include <netinet/in.h>
+#include PATH_IPSEC_H
+#include <fcntl.h>
+
+#include "libpfkey.h"
+
+#include "var.h"
+#include "misc.h"
+#include "vmbuf.h"
+#include "plog.h"
+#include "sockmisc.h"
+#include "debug.h"
+
+#include "schedule.h"
+#include "localconf.h"
+#include "remoteconf.h"
+#include "handler.h"
+#include "policy.h"
+#include "proposal.h"
+#include "isakmp_var.h"
+#include "isakmp.h"
+#include "isakmp_inf.h"
+#include "ipsec_doi.h"
+#include "oakley.h"
+#include "pfkey.h"
+#include "algorithm.h"
+#include "sainfo.h"
+#include "admin.h"
+#include "privsep.h"
+#include "strnames.h"
+#include "backupsa.h"
+#include "gcmalloc.h"
+#include "nattraversal.h"
+#include "crypto_openssl.h"
+#include "grabmyaddr.h"
+
+#if defined(SADB_X_EALG_RIJNDAELCBC) && !defined(SADB_X_EALG_AESCBC)
+#define SADB_X_EALG_AESCBC  SADB_X_EALG_RIJNDAELCBC
+#endif
+
+/* prototype */
+static u_int ipsecdoi2pfkey_aalg __P((u_int));
+static u_int ipsecdoi2pfkey_ealg __P((u_int));
+static u_int ipsecdoi2pfkey_calg __P((u_int));
+static u_int ipsecdoi2pfkey_alg __P((u_int, u_int));
+static u_int keylen_aalg __P((u_int));
+static u_int keylen_ealg __P((u_int, int));
+
+static int pk_recvgetspi __P((caddr_t *));
+static int pk_recvupdate __P((caddr_t *));
+static int pk_recvadd __P((caddr_t *));
+static int pk_recvdelete __P((caddr_t *));
+static int pk_recvacquire __P((caddr_t *));
+static int pk_recvexpire __P((caddr_t *));
+static int pk_recvflush __P((caddr_t *));
+static int getsadbpolicy __P((caddr_t *, int *, int, struct ph2handle *));
+static int pk_recvspdupdate __P((caddr_t *));
+static int pk_recvspdadd __P((caddr_t *));
+static int pk_recvspddelete __P((caddr_t *));
+static int pk_recvspdexpire __P((caddr_t *));
+static int pk_recvspdget __P((caddr_t *));
+static int pk_recvspddump __P((caddr_t *));
+static int pk_recvspdflush __P((caddr_t *));
+static struct sadb_msg *pk_recv __P((int, int *));
+
+static int (*pkrecvf[]) __P((caddr_t *)) = {
+NULL,
+pk_recvgetspi,
+pk_recvupdate,
+pk_recvadd,
+pk_recvdelete,
+NULL,	/* SADB_GET */
+pk_recvacquire,
+NULL,	/* SABD_REGISTER */
+pk_recvexpire,
+pk_recvflush,
+NULL,	/* SADB_DUMP */
+NULL,	/* SADB_X_PROMISC */
+NULL,	/* SADB_X_PCHANGE */
+pk_recvspdupdate,
+pk_recvspdadd,
+pk_recvspddelete,
+pk_recvspdget,
+NULL,	/* SADB_X_SPDACQUIRE */
+pk_recvspddump,
+pk_recvspdflush,
+NULL,	/* SADB_X_SPDSETIDX */
+pk_recvspdexpire,
+NULL,	/* SADB_X_SPDDELETE2 */
+NULL,	/* SADB_X_NAT_T_NEW_MAPPING */
+NULL,	/* SADB_X_MIGRATE */
+#if (SADB_MAX > 24)
+#error "SADB extra message?"
+#endif
+};
+
+static int addnewsp __P((caddr_t *));
+
+/* cope with old kame headers - ugly */
+#ifndef SADB_X_AALG_MD5
+#define SADB_X_AALG_MD5		SADB_AALG_MD5	
+#endif
+#ifndef SADB_X_AALG_SHA
+#define SADB_X_AALG_SHA		SADB_AALG_SHA
+#endif
+#ifndef SADB_X_AALG_NULL
+#define SADB_X_AALG_NULL	SADB_AALG_NULL
+#endif
+
+#ifndef SADB_X_EALG_BLOWFISHCBC
+#define SADB_X_EALG_BLOWFISHCBC	SADB_EALG_BLOWFISHCBC
+#endif
+#ifndef SADB_X_EALG_CAST128CBC
+#define SADB_X_EALG_CAST128CBC	SADB_EALG_CAST128CBC
+#endif
+#ifndef SADB_X_EALG_RC5CBC
+#ifdef SADB_EALG_RC5CBC
+#define SADB_X_EALG_RC5CBC	SADB_EALG_RC5CBC
+#endif
+#endif
+
+/*
+ * PF_KEY packet handler
+ *	0: success
+ *	-1: fail
+ */
+int
+pfkey_handler()
+{
+	struct sadb_msg *msg;
+	int len;
+	caddr_t mhp[SADB_EXT_MAX + 1];
+	int error = -1;
+
+	/* receive pfkey message. */
+	len = 0;
+	msg = (struct sadb_msg *)pk_recv(lcconf->sock_pfkey, &len);
+	if (msg == NULL) {
+		if (len < 0) {
+			plog(LLV_ERROR, LOCATION, NULL,
+				"failed to recv from pfkey (%s)\n",
+				strerror(errno));
+			goto end;
+		} else {
+			/* short message - msg not ready */
+			return 0;
+		}
+	}
+
+	plog(LLV_DEBUG, LOCATION, NULL, "get pfkey %s message\n",
+		s_pfkey_type(msg->sadb_msg_type));
+	plogdump(LLV_DEBUG2, msg, msg->sadb_msg_len << 3);
+
+	/* validity check */
+	if (msg->sadb_msg_errno) {
+		int pri;
+
+		/* when SPD is empty, treat the state as no error. */
+		if (msg->sadb_msg_type == SADB_X_SPDDUMP &&
+		    msg->sadb_msg_errno == ENOENT)
+			pri = LLV_DEBUG;
+		else
+			pri = LLV_ERROR;
+
+		plog(pri, LOCATION, NULL,
+			"pfkey %s failed: %s\n",
+			s_pfkey_type(msg->sadb_msg_type),
+			strerror(msg->sadb_msg_errno));
+
+		goto end;
+	}
+
+	/* check pfkey message. */
+	if (pfkey_align(msg, mhp)) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"libipsec failed pfkey align (%s)\n",
+			ipsec_strerror());
+		goto end;
+	}
+	if (pfkey_check(mhp)) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"libipsec failed pfkey check (%s)\n",
+			ipsec_strerror());
+		goto end;
+	}
+	msg = (struct sadb_msg *)mhp[0];
+
+	/* safety check */
+	if (msg->sadb_msg_type >= ARRAYLEN(pkrecvf)) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"unknown PF_KEY message type=%u\n",
+			msg->sadb_msg_type);
+		goto end;
+	}
+
+	if (pkrecvf[msg->sadb_msg_type] == NULL) {
+		plog(LLV_INFO, LOCATION, NULL,
+			"unsupported PF_KEY message %s\n",
+			s_pfkey_type(msg->sadb_msg_type));
+		goto end;
+	}
+
+	if ((pkrecvf[msg->sadb_msg_type])(mhp) < 0)
+		goto end;
+
+	error = 0;
+end:
+	if (msg)
+		racoon_free(msg);
+	return(error);
+}
+
+/*
+ * dump SADB
+ */
+vchar_t *
+pfkey_dump_sadb(satype)
+	int satype;
+{
+	int s = -1;
+	vchar_t *buf = NULL;
+	pid_t pid = getpid();
+	struct sadb_msg *msg = NULL;
+	size_t bl, ml;
+	int len;
+
+	if ((s = privsep_pfkey_open()) < 0) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"libipsec failed pfkey open: %s\n",
+			ipsec_strerror());
+		return NULL;
+	}
+
+	plog(LLV_DEBUG, LOCATION, NULL, "call pfkey_send_dump\n");
+	if (pfkey_send_dump(s, satype) < 0) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"libipsec failed dump: %s\n", ipsec_strerror());
+		goto fail;
+	}
+
+	while (1) {
+		if (msg)
+			racoon_free(msg);
+		msg = pk_recv(s, &len);
+		if (msg == NULL) {
+			if (len < 0)
+				goto done;
+			else
+				continue;
+		}
+
+		if (msg->sadb_msg_type != SADB_DUMP || msg->sadb_msg_pid != pid)
+		{
+		    plog(LLV_DEBUG, LOCATION, NULL,
+			 "discarding non-sadb dump msg %p, our pid=%i\n", msg, pid);
+		    plog(LLV_DEBUG, LOCATION, NULL,
+			 "type %i, pid %i\n", msg->sadb_msg_type, msg->sadb_msg_pid);
+		    continue;
+		}
+		
+
+		ml = msg->sadb_msg_len << 3;
+		bl = buf ? buf->l : 0;
+		buf = vrealloc(buf, bl + ml);
+		if (buf == NULL) {
+			plog(LLV_ERROR, LOCATION, NULL,
+				"failed to reallocate buffer to dump.\n");
+			goto fail;
+		}
+		memcpy(buf->v + bl, msg, ml);
+
+		if (msg->sadb_msg_seq == 0)
+			break;
+	}
+	goto done;
+
+fail:
+	if (buf)
+		vfree(buf);
+	buf = NULL;
+done:
+	if (msg)
+		racoon_free(msg);
+	if (s >= 0)
+		privsep_pfkey_close(s);
+	return buf;
+}
+
+#ifdef ENABLE_ADMINPORT
+/*
+ * flush SADB
+ */
+void
+pfkey_flush_sadb(proto)
+	u_int proto;
+{
+	int satype;
+
+	/* convert to SADB_SATYPE */
+	if ((satype = admin2pfkey_proto(proto)) < 0)
+		return;
+
+	plog(LLV_DEBUG, LOCATION, NULL, "call pfkey_send_flush\n");
+	if (pfkey_send_flush(lcconf->sock_pfkey, satype) < 0) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"libipsec failed send flush (%s)\n", ipsec_strerror());
+		return;
+	}
+
+	return;
+}
+#endif
+
+/*
+ * These are the SATYPEs that we manage.  We register to get
+ * PF_KEY messages related to these SATYPEs, and we also use
+ * this list to determine which SATYPEs to delete SAs for when
+ * we receive an INITIAL-CONTACT.
+ */
+const struct pfkey_satype pfkey_satypes[] = {
+	{ SADB_SATYPE_AH,	"AH" },
+	{ SADB_SATYPE_ESP,	"ESP" },
+	{ SADB_X_SATYPE_IPCOMP,	"IPCOMP" },
+};
+const int pfkey_nsatypes =
+    sizeof(pfkey_satypes) / sizeof(pfkey_satypes[0]);
+
+/*
+ * PF_KEY initialization
+ */
+int
+pfkey_init()
+{
+	int i, reg_fail;
+
+	if ((lcconf->sock_pfkey = privsep_pfkey_open()) < 0) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"libipsec failed pfkey open (%s)\n", ipsec_strerror());
+		return -1;
+	}
+	if (fcntl(lcconf->sock_pfkey, F_SETFL, O_NONBLOCK) == -1)
+		plog(LLV_WARNING, LOCATION, NULL,
+		    "failed to set the pfkey socket to NONBLOCK\n");
+
+	for (i = 0, reg_fail = 0; i < pfkey_nsatypes; i++) {
+		plog(LLV_DEBUG, LOCATION, NULL,
+		    "call pfkey_send_register for %s\n",
+		    pfkey_satypes[i].ps_name);
+		if (pfkey_send_register(lcconf->sock_pfkey,
+					pfkey_satypes[i].ps_satype) < 0 ||
+		    pfkey_recv_register(lcconf->sock_pfkey) < 0) {
+			plog(LLV_WARNING, LOCATION, NULL,
+			    "failed to register %s (%s)\n",
+			    pfkey_satypes[i].ps_name,
+			    ipsec_strerror());
+			reg_fail++;
+		}
+	}
+
+	if (reg_fail == pfkey_nsatypes) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"failed to regist any protocol.\n");
+		pfkey_close(lcconf->sock_pfkey);
+		return -1;
+	}
+
+	initsp();
+
+	if (pfkey_send_spddump(lcconf->sock_pfkey) < 0) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"libipsec sending spddump failed: %s\n",
+			ipsec_strerror());
+		pfkey_close(lcconf->sock_pfkey);
+		return -1;
+	}
+#if 0
+	if (pfkey_promisc_toggle(1) < 0) {
+		pfkey_close(lcconf->sock_pfkey);
+		return -1;
+	}
+#endif
+	return 0;
+}
+
+/* %%% for conversion */
+/* IPSECDOI_ATTR_AUTH -> SADB_AALG */
+static u_int
+ipsecdoi2pfkey_aalg(hashtype)
+	u_int hashtype;
+{
+	switch (hashtype) {
+	case IPSECDOI_ATTR_AUTH_HMAC_MD5:
+		return SADB_AALG_MD5HMAC;
+	case IPSECDOI_ATTR_AUTH_HMAC_SHA1:
+		return SADB_AALG_SHA1HMAC;
+	case IPSECDOI_ATTR_AUTH_HMAC_SHA2_256:
+#if (defined SADB_X_AALG_SHA2_256) && !defined(SADB_X_AALG_SHA2_256HMAC)
+		return SADB_X_AALG_SHA2_256;
+#else
+		return SADB_X_AALG_SHA2_256HMAC;
+#endif
+	case IPSECDOI_ATTR_AUTH_HMAC_SHA2_384:
+#if (defined SADB_X_AALG_SHA2_384) && !defined(SADB_X_AALG_SHA2_384HMAC)
+		return SADB_X_AALG_SHA2_384;
+#else
+		return SADB_X_AALG_SHA2_384HMAC;
+#endif
+	case IPSECDOI_ATTR_AUTH_HMAC_SHA2_512:
+#if (defined SADB_X_AALG_SHA2_512) && !defined(SADB_X_AALG_SHA2_512HMAC)
+		return SADB_X_AALG_SHA2_512;
+#else
+		return SADB_X_AALG_SHA2_512HMAC;
+#endif
+	case IPSECDOI_ATTR_AUTH_KPDK:		/* need special care */
+		return SADB_AALG_NONE;
+
+	/* not supported */
+	case IPSECDOI_ATTR_AUTH_DES_MAC:
+		plog(LLV_ERROR, LOCATION, NULL,
+			"Not supported hash type: %u\n", hashtype);
+		return ~0;
+
+	case 0: /* reserved */
+	default:
+		return SADB_AALG_NONE;
+
+		plog(LLV_ERROR, LOCATION, NULL,
+			"Invalid hash type: %u\n", hashtype);
+		return ~0;
+	}
+	/*NOTREACHED*/
+}
+
+/* IPSECDOI_ESP -> SADB_EALG */
+static u_int
+ipsecdoi2pfkey_ealg(t_id)
+	u_int t_id;
+{
+	switch (t_id) {
+	case IPSECDOI_ESP_DES_IV64:		/* sa_flags |= SADB_X_EXT_OLD */
+		return SADB_EALG_DESCBC;
+	case IPSECDOI_ESP_DES:
+		return SADB_EALG_DESCBC;
+	case IPSECDOI_ESP_3DES:
+		return SADB_EALG_3DESCBC;
+#ifdef SADB_X_EALG_RC5CBC
+	case IPSECDOI_ESP_RC5:
+		return SADB_X_EALG_RC5CBC;
+#endif
+	case IPSECDOI_ESP_CAST:
+		return SADB_X_EALG_CAST128CBC;
+	case IPSECDOI_ESP_BLOWFISH:
+		return SADB_X_EALG_BLOWFISHCBC;
+	case IPSECDOI_ESP_DES_IV32:	/* flags |= (SADB_X_EXT_OLD|
+							SADB_X_EXT_IV4B)*/
+		return SADB_EALG_DESCBC;
+	case IPSECDOI_ESP_NULL:
+		return SADB_EALG_NULL;
+#ifdef SADB_X_EALG_AESCBC
+	case IPSECDOI_ESP_AES:
+		return SADB_X_EALG_AESCBC;
+#endif
+#ifdef SADB_X_EALG_TWOFISHCBC
+	case IPSECDOI_ESP_TWOFISH:
+		return SADB_X_EALG_TWOFISHCBC;
+#endif
+#ifdef SADB_X_EALG_CAMELLIACBC
+	case IPSECDOI_ESP_CAMELLIA:
+		return SADB_X_EALG_CAMELLIACBC;
+#endif
+
+	/* not supported */
+	case IPSECDOI_ESP_3IDEA:
+	case IPSECDOI_ESP_IDEA:
+	case IPSECDOI_ESP_RC4:
+		plog(LLV_ERROR, LOCATION, NULL,
+			"Not supported transform: %u\n", t_id);
+		return ~0;
+
+	case 0: /* reserved */
+	default:
+		plog(LLV_ERROR, LOCATION, NULL,
+			"Invalid transform id: %u\n", t_id);
+		return ~0;
+	}
+	/*NOTREACHED*/
+}
+
+/* IPCOMP -> SADB_CALG */
+static u_int
+ipsecdoi2pfkey_calg(t_id)
+	u_int t_id;
+{
+	switch (t_id) {
+	case IPSECDOI_IPCOMP_OUI:
+		return SADB_X_CALG_OUI;
+	case IPSECDOI_IPCOMP_DEFLATE:
+		return SADB_X_CALG_DEFLATE;
+	case IPSECDOI_IPCOMP_LZS:
+		return SADB_X_CALG_LZS;
+
+	case 0: /* reserved */
+	default:
+		plog(LLV_ERROR, LOCATION, NULL,
+			"Invalid transform id: %u\n", t_id);
+		return ~0;
+	}
+	/*NOTREACHED*/
+}
+
+/* IPSECDOI_PROTO -> SADB_SATYPE */
+u_int
+ipsecdoi2pfkey_proto(proto)
+	u_int proto;
+{
+	switch (proto) {
+	case IPSECDOI_PROTO_IPSEC_AH:
+		return SADB_SATYPE_AH;
+	case IPSECDOI_PROTO_IPSEC_ESP:
+		return SADB_SATYPE_ESP;
+	case IPSECDOI_PROTO_IPCOMP:
+		return SADB_X_SATYPE_IPCOMP;
+
+	default:
+		plog(LLV_ERROR, LOCATION, NULL,
+			"Invalid ipsec_doi proto: %u\n", proto);
+		return ~0;
+	}
+	/*NOTREACHED*/
+}
+
+static u_int
+ipsecdoi2pfkey_alg(algclass, type)
+	u_int algclass, type;
+{
+	switch (algclass) {
+	case IPSECDOI_ATTR_AUTH:
+		return ipsecdoi2pfkey_aalg(type);
+	case IPSECDOI_PROTO_IPSEC_ESP:
+		return ipsecdoi2pfkey_ealg(type);
+	case IPSECDOI_PROTO_IPCOMP:
+		return ipsecdoi2pfkey_calg(type);
+	default:
+		plog(LLV_ERROR, LOCATION, NULL,
+			"Invalid ipsec_doi algclass: %u\n", algclass);
+		return ~0;
+	}
+	/*NOTREACHED*/
+}
+
+/* SADB_SATYPE -> IPSECDOI_PROTO */
+u_int
+pfkey2ipsecdoi_proto(satype)
+	u_int satype;
+{
+	switch (satype) {
+	case SADB_SATYPE_AH:
+		return IPSECDOI_PROTO_IPSEC_AH;
+	case SADB_SATYPE_ESP:
+		return IPSECDOI_PROTO_IPSEC_ESP;
+	case SADB_X_SATYPE_IPCOMP:
+		return IPSECDOI_PROTO_IPCOMP;
+
+	default:
+		plog(LLV_ERROR, LOCATION, NULL,
+			"Invalid pfkey proto: %u\n", satype);
+		return ~0;
+	}
+	/*NOTREACHED*/
+}
+
+/* IPSECDOI_ATTR_ENC_MODE -> IPSEC_MODE */
+u_int
+ipsecdoi2pfkey_mode(mode)
+	u_int mode;
+{
+	switch (mode) {
+	case IPSECDOI_ATTR_ENC_MODE_TUNNEL:
+#ifdef ENABLE_NATT
+	case IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_RFC:
+	case IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_DRAFT:
+#endif
+		return IPSEC_MODE_TUNNEL;
+	case IPSECDOI_ATTR_ENC_MODE_TRNS:
+#ifdef ENABLE_NATT
+	case IPSECDOI_ATTR_ENC_MODE_UDPTRNS_RFC:
+	case IPSECDOI_ATTR_ENC_MODE_UDPTRNS_DRAFT:
+#endif
+		return IPSEC_MODE_TRANSPORT;
+	default:
+		plog(LLV_ERROR, LOCATION, NULL, "Invalid mode type: %u\n", mode);
+		return ~0;
+	}
+	/*NOTREACHED*/
+}
+
+/* IPSECDOI_ATTR_ENC_MODE -> IPSEC_MODE */
+u_int
+pfkey2ipsecdoi_mode(mode)
+	u_int mode;
+{
+	switch (mode) {
+	case IPSEC_MODE_TUNNEL:
+		return IPSECDOI_ATTR_ENC_MODE_TUNNEL;
+	case IPSEC_MODE_TRANSPORT:
+		return IPSECDOI_ATTR_ENC_MODE_TRNS;
+	case IPSEC_MODE_ANY:
+		return IPSECDOI_ATTR_ENC_MODE_ANY;
+	default:
+		plog(LLV_ERROR, LOCATION, NULL, "Invalid mode type: %u\n", mode);
+		return ~0;
+	}
+	/*NOTREACHED*/
+}
+
+/* default key length for encryption algorithm */
+static u_int
+keylen_aalg(hashtype)
+	u_int hashtype;
+{
+	int res;
+
+	if (hashtype == 0)
+		return SADB_AALG_NONE;
+
+	res = alg_ipsec_hmacdef_hashlen(hashtype);
+	if (res == -1) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"invalid hmac algorithm %u.\n", hashtype);
+		return ~0;
+	}
+	return res;
+}
+
+/* default key length for encryption algorithm */
+static u_int
+keylen_ealg(enctype, encklen)
+	u_int enctype;
+	int encklen;
+{
+	int res;
+
+	res = alg_ipsec_encdef_keylen(enctype, encklen);
+	if (res == -1) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"invalid encryption algorithm %u.\n", enctype);
+		return ~0;
+	}
+	return res;
+}
+
+int
+pfkey_convertfromipsecdoi(proto_id, t_id, hashtype,
+		e_type, e_keylen, a_type, a_keylen, flags)
+	u_int proto_id;
+	u_int t_id;
+	u_int hashtype;
+	u_int *e_type;
+	u_int *e_keylen;
+	u_int *a_type;
+	u_int *a_keylen;
+	u_int *flags;
+{
+	*flags = 0;
+	switch (proto_id) {
+	case IPSECDOI_PROTO_IPSEC_ESP:
+		if ((*e_type = ipsecdoi2pfkey_ealg(t_id)) == ~0)
+			goto bad;
+		if ((*e_keylen = keylen_ealg(t_id, *e_keylen)) == ~0)
+			goto bad;
+		*e_keylen >>= 3;
+
+		if ((*a_type = ipsecdoi2pfkey_aalg(hashtype)) == ~0)
+			goto bad;
+		if ((*a_keylen = keylen_aalg(hashtype)) == ~0)
+			goto bad;
+		*a_keylen >>= 3;
+
+		if (*e_type == SADB_EALG_NONE) {
+			plog(LLV_ERROR, LOCATION, NULL, "no ESP algorithm.\n");
+			goto bad;
+		}
+		break;
+
+	case IPSECDOI_PROTO_IPSEC_AH:
+		if ((*a_type = ipsecdoi2pfkey_aalg(hashtype)) == ~0)
+			goto bad;
+		if ((*a_keylen = keylen_aalg(hashtype)) == ~0)
+			goto bad;
+		*a_keylen >>= 3;
+
+		if (t_id == IPSECDOI_ATTR_AUTH_HMAC_MD5 
+		 && hashtype == IPSECDOI_ATTR_AUTH_KPDK) {
+			/* AH_MD5 + Auth(KPDK) = RFC1826 keyed-MD5 */
+			*a_type = SADB_X_AALG_MD5;
+			*flags |= SADB_X_EXT_OLD;
+		}
+		*e_type = SADB_EALG_NONE;
+		*e_keylen = 0;
+		if (*a_type == SADB_AALG_NONE) {
+			plog(LLV_ERROR, LOCATION, NULL, "no AH algorithm.\n");
+			goto bad;
+		}
+		break;
+
+	case IPSECDOI_PROTO_IPCOMP:
+		if ((*e_type = ipsecdoi2pfkey_calg(t_id)) == ~0)
+			goto bad;
+		*e_keylen = 0;
+
+		*flags = SADB_X_EXT_RAWCPI;
+
+		*a_type = SADB_AALG_NONE;
+		*a_keylen = 0;
+		if (*e_type == SADB_X_CALG_NONE) {
+			plog(LLV_ERROR, LOCATION, NULL, "no IPCOMP algorithm.\n");
+			goto bad;
+		}
+		break;
+
+	default:
+		plog(LLV_ERROR, LOCATION, NULL, "unknown IPsec protocol.\n");
+		goto bad;
+	}
+
+	return 0;
+
+    bad:
+	errno = EINVAL;
+	return -1;
+}
+
+/* called from scheduler */
+void
+pfkey_timeover_stub(p)
+	void *p;
+{
+
+	pfkey_timeover((struct ph2handle *)p);
+}
+
+void
+pfkey_timeover(iph2)
+	struct ph2handle *iph2;
+{
+	plog(LLV_ERROR, LOCATION, NULL,
+		"%s give up to get IPsec-SA due to time up to wait.\n",
+		saddrwop2str(iph2->dst));
+	SCHED_KILL(iph2->sce);
+
+	/* If initiator side, send error to kernel by SADB_ACQUIRE. */
+	if (iph2->side == INITIATOR)
+		pk_sendeacquire(iph2);
+
+	unbindph12(iph2);
+	remph2(iph2);
+	delph2(iph2);
+
+	return;
+}
+
+/*%%%*/
+/* send getspi message per ipsec protocol per remote address */
+/*
+ * the local address and remote address in ph1handle are dealed
+ * with destination address and source address respectively.
+ * Because SPI is decided by responder.
+ */
+int
+pk_sendgetspi(iph2)
+	struct ph2handle *iph2;
+{
+	struct sockaddr *src = NULL, *dst = NULL;
+	u_int satype, mode;
+	struct saprop *pp;
+	struct saproto *pr;
+	u_int32_t minspi, maxspi;
+	int proxy = 0;
+
+	if (iph2->side == INITIATOR) {
+		pp = iph2->proposal;
+		proxy = iph2->ph1->rmconf->support_proxy;
+	} else {
+		pp = iph2->approval;
+		if (iph2->sainfo && iph2->sainfo->id_i)
+			proxy = 1;
+	}
+
+	/* for mobile IPv6 */
+	if (proxy && iph2->src_id && iph2->dst_id &&
+	    ipsecdoi_transportmode(pp)) {
+		src = iph2->src_id;
+		dst = iph2->dst_id;
+	} else {
+		src = iph2->src;
+		dst = iph2->dst;
+	}
+
+	for (pr = pp->head; pr != NULL; pr = pr->next) {
+
+		/* validity check */
+		satype = ipsecdoi2pfkey_proto(pr->proto_id);
+		if (satype == ~0) {
+			plog(LLV_ERROR, LOCATION, NULL,
+				"invalid proto_id %d\n", pr->proto_id);
+			return -1;
+		}
+		/* this works around a bug in Linux kernel where it allocates 4 byte
+		   spi's for IPCOMP */
+		else if (satype == SADB_X_SATYPE_IPCOMP) {
+			minspi = 0x100;
+			maxspi = 0xffff;
+		}
+		else {
+			minspi = 0;
+			maxspi = 0;
+		}
+		mode = ipsecdoi2pfkey_mode(pr->encmode);
+		if (mode == ~0) {
+			plog(LLV_ERROR, LOCATION, NULL,
+				"invalid encmode %d\n", pr->encmode);
+			return -1;
+		}
+
+#ifdef ENABLE_NATT
+		/* XXX should we do a copy of src/dst for each pr ?
+		 */
+		if (! pr->udp_encap) {
+			/* Remove port information, that SA doesn't use it */
+			set_port(src, 0);
+			set_port(dst, 0);
+		}
+#endif
+		plog(LLV_DEBUG, LOCATION, NULL, "call pfkey_send_getspi\n");
+		if (pfkey_send_getspi(
+				lcconf->sock_pfkey,
+				satype,
+				mode,
+				dst,			/* src of SA */
+				src,			/* dst of SA */
+				minspi, maxspi,
+				pr->reqid_in, iph2->seq) < 0) {
+			plog(LLV_ERROR, LOCATION, NULL,
+				"ipseclib failed send getspi (%s)\n",
+				ipsec_strerror());
+			return -1;
+		}
+		plog(LLV_DEBUG, LOCATION, NULL,
+			"pfkey GETSPI sent: %s\n",
+			sadbsecas2str(dst, src, satype, 0, mode));
+	}
+
+	return 0;
+}
+
+/*
+ * receive GETSPI from kernel.
+ */
+static int
+pk_recvgetspi(mhp) 
+	caddr_t *mhp;
+{
+	struct sadb_msg *msg;
+	struct sadb_sa *sa;
+	struct ph2handle *iph2;
+	struct sockaddr *dst;
+	int proto_id;
+	int allspiok, notfound;
+	struct saprop *pp;
+	struct saproto *pr;
+
+	/* validity check */
+	if (mhp[SADB_EXT_SA] == NULL
+	 || mhp[SADB_EXT_ADDRESS_DST] == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"inappropriate sadb getspi message passed.\n");
+		return -1;
+	}
+	msg = (struct sadb_msg *)mhp[0];
+	sa = (struct sadb_sa *)mhp[SADB_EXT_SA];
+	dst = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_SRC]); /* note SA dir */
+
+	/* the message has to be processed or not ? */
+	if (msg->sadb_msg_pid != getpid()) {
+		plog(LLV_DEBUG, LOCATION, NULL,
+			"%s message is not interesting "
+			"because pid %d is not mine.\n",
+			s_pfkey_type(msg->sadb_msg_type),
+			msg->sadb_msg_pid);
+		return -1;
+	}
+
+	iph2 = getph2byseq(msg->sadb_msg_seq);
+	if (iph2 == NULL) {
+		plog(LLV_DEBUG, LOCATION, NULL,
+			"seq %d of %s message not interesting.\n",
+			msg->sadb_msg_seq,
+			s_pfkey_type(msg->sadb_msg_type));
+		return -1;
+	}
+
+	if (iph2->status != PHASE2ST_GETSPISENT) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"status mismatch (db:%d msg:%d)\n",
+			iph2->status, PHASE2ST_GETSPISENT);
+		return -1;
+	}
+
+	/* set SPI, and check to get all spi whether or not */
+	allspiok = 1;
+	notfound = 1;
+	proto_id = pfkey2ipsecdoi_proto(msg->sadb_msg_satype);
+	pp = iph2->side == INITIATOR ? iph2->proposal : iph2->approval;
+
+	for (pr = pp->head; pr != NULL; pr = pr->next) {
+		if (pr->proto_id == proto_id && pr->spi == 0) {
+			pr->spi = sa->sadb_sa_spi;
+			notfound = 0;
+			plog(LLV_DEBUG, LOCATION, NULL,
+				"pfkey GETSPI succeeded: %s\n",
+				sadbsecas2str(iph2->dst, iph2->src,
+				    msg->sadb_msg_satype,
+				    sa->sadb_sa_spi,
+				    ipsecdoi2pfkey_mode(pr->encmode)));
+		}
+		if (pr->spi == 0)
+			allspiok = 0;	/* not get all spi */
+	}
+
+	if (notfound) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"get spi for unknown address %s\n",
+			saddrwop2str(iph2->dst));
+		return -1;
+	}
+
+	if (allspiok) {
+		/* update status */
+		iph2->status = PHASE2ST_GETSPIDONE;
+		if (isakmp_post_getspi(iph2) < 0) {
+			plog(LLV_ERROR, LOCATION, NULL,
+				"failed to start post getspi.\n");
+			unbindph12(iph2);
+			remph2(iph2);
+			delph2(iph2);
+			iph2 = NULL;
+			return -1;
+		}
+	}
+
+	return 0;
+}
+
+/*
+ * set inbound SA
+ */
+int
+pk_sendupdate(iph2)
+	struct ph2handle *iph2;
+{
+	struct saproto *pr;
+	struct pfkey_send_sa_args sa_args;
+	int proxy = 0;
+
+	/* sanity check */
+	if (iph2->approval == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"no approvaled SAs found.\n");
+	}
+
+	if (iph2->side == INITIATOR)
+		proxy = iph2->ph1->rmconf->support_proxy;
+	else if (iph2->sainfo && iph2->sainfo->id_i)
+		proxy = 1;
+
+	/* fill in some needed for pfkey_send_update2 */
+	memset (&sa_args, 0, sizeof (sa_args));
+	sa_args.so = lcconf->sock_pfkey;
+	sa_args.l_addtime = iph2->approval->lifetime;
+	sa_args.seq = iph2->seq; 
+	sa_args.wsize = 4;
+
+	/* for mobile IPv6 */
+	if (proxy && iph2->src_id && iph2->dst_id &&
+	    ipsecdoi_transportmode(iph2->approval)) {
+		sa_args.dst = iph2->src_id;
+		sa_args.src = iph2->dst_id;
+	} else {
+		sa_args.dst = iph2->src;
+		sa_args.src = iph2->dst;
+	}
+
+	for (pr = iph2->approval->head; pr != NULL; pr = pr->next) {
+		/* validity check */
+		sa_args.satype = ipsecdoi2pfkey_proto(pr->proto_id);
+		if (sa_args.satype == ~0) {
+			plog(LLV_ERROR, LOCATION, NULL,
+				"invalid proto_id %d\n", pr->proto_id);
+			return -1;
+		}
+		else if (sa_args.satype == SADB_X_SATYPE_IPCOMP) {
+			/* IPCOMP has no replay window */
+			sa_args.wsize = 0;
+		}
+#ifdef ENABLE_SAMODE_UNSPECIFIED
+		sa_args.mode = IPSEC_MODE_ANY;
+#else
+		sa_args.mode = ipsecdoi2pfkey_mode(pr->encmode);
+		if (sa_args.mode == ~0) {
+			plog(LLV_ERROR, LOCATION, NULL,
+				"invalid encmode %d\n", pr->encmode);
+			return -1;
+		}
+#endif
+		/* set algorithm type and key length */
+		sa_args.e_keylen = pr->head->encklen;
+		if (pfkey_convertfromipsecdoi(
+				pr->proto_id,
+				pr->head->trns_id,
+				pr->head->authtype,
+				&sa_args.e_type, &sa_args.e_keylen,
+				&sa_args.a_type, &sa_args.a_keylen, 
+				&sa_args.flags) < 0)
+			return -1;
+
+#if 0
+		sa_args.l_bytes = iph2->approval->lifebyte * 1024,
+#else
+		sa_args.l_bytes = 0;
+#endif
+
+#ifdef HAVE_SECCTX
+		if (*iph2->approval->sctx.ctx_str) {
+			sa_args.ctxdoi = iph2->approval->sctx.ctx_doi;
+			sa_args.ctxalg = iph2->approval->sctx.ctx_alg;
+			sa_args.ctxstrlen = iph2->approval->sctx.ctx_strlen;
+			sa_args.ctxstr = iph2->approval->sctx.ctx_str;
+		}
+#endif /* HAVE_SECCTX */
+
+#ifdef ENABLE_NATT
+		if (pr->udp_encap) {
+			sa_args.l_natt_type = iph2->ph1->natt_options->encaps_type;
+			sa_args.l_natt_sport = extract_port (iph2->ph1->remote);
+			sa_args.l_natt_dport = extract_port (iph2->ph1->local);
+			sa_args.l_natt_oa = NULL;  // FIXME: Here comes OA!!!
+#ifdef SADB_X_EXT_NAT_T_FRAG
+			sa_args.l_natt_frag = iph2->ph1->rmconf->esp_frag;
+#endif
+		} else {
+			/* Remove port information, that SA doesn't use it */
+			set_port(sa_args.src, 0);
+			set_port(sa_args.dst, 0);
+		}
+
+#endif
+		/* more info to fill in */
+		sa_args.spi = pr->spi;
+		sa_args.reqid = pr->reqid_in;
+		sa_args.keymat = pr->keymat->v;
+
+		plog(LLV_DEBUG, LOCATION, NULL, "call pfkey_send_update2\n");
+		if (pfkey_send_update2(&sa_args) < 0) {
+			plog(LLV_ERROR, LOCATION, NULL,
+				"libipsec failed send update (%s)\n",
+				ipsec_strerror());
+			return -1;
+		}
+
+		if (!lcconf->pathinfo[LC_PATHTYPE_BACKUPSA])
+			continue;
+
+		/*
+		 * It maybe good idea to call backupsa_to_file() after
+		 * racoon will receive the sadb_update messages.
+		 * But it is impossible because there is not key in the
+		 * information from the kernel.
+		 */
+		
+		/* change some things before backing up */
+		sa_args.wsize = 4;
+		sa_args.l_bytes = iph2->approval->lifebyte * 1024;
+		
+		if (backupsa_to_file(&sa_args) < 0) {
+			plog(LLV_ERROR, LOCATION, NULL,
+				"backuped SA failed: %s\n",
+				sadbsecas2str(sa_args.src, sa_args.dst,
+				sa_args.satype, sa_args.spi, sa_args.mode));
+		}
+		plog(LLV_DEBUG, LOCATION, NULL,
+			"backuped SA: %s\n",
+			sadbsecas2str(sa_args.src, sa_args.dst,
+			sa_args.satype, sa_args.spi, sa_args.mode));
+	}
+
+	return 0;
+}
+
+static int
+pk_recvupdate(mhp)
+	caddr_t *mhp;
+{
+	struct sadb_msg *msg;
+	struct sadb_sa *sa;
+	struct sockaddr *src, *dst;
+	struct ph2handle *iph2;
+	u_int proto_id, encmode, sa_mode;
+	int incomplete = 0;
+	struct saproto *pr;
+
+	/* ignore this message because of local test mode. */
+	if (f_local)
+		return 0;
+
+	/* sanity check */
+	if (mhp[0] == NULL
+	 || mhp[SADB_EXT_SA] == NULL
+	 || mhp[SADB_EXT_ADDRESS_SRC] == NULL
+	 || mhp[SADB_EXT_ADDRESS_DST] == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"inappropriate sadb update message passed.\n");
+		return -1;
+	}
+	msg = (struct sadb_msg *)mhp[0];
+	src = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_SRC]);
+	dst = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_DST]);
+	sa = (struct sadb_sa *)mhp[SADB_EXT_SA];
+
+	sa_mode = mhp[SADB_X_EXT_SA2] == NULL
+		? IPSEC_MODE_ANY
+		: ((struct sadb_x_sa2 *)mhp[SADB_X_EXT_SA2])->sadb_x_sa2_mode;
+
+	/* the message has to be processed or not ? */
+	if (msg->sadb_msg_pid != getpid()) {
+		plog(LLV_DEBUG, LOCATION, NULL,
+			"%s message is not interesting "
+			"because pid %d is not mine.\n",
+			s_pfkey_type(msg->sadb_msg_type),
+			msg->sadb_msg_pid);
+		return -1;
+	}
+
+	iph2 = getph2byseq(msg->sadb_msg_seq);
+	if (iph2 == NULL) {
+		plog(LLV_DEBUG, LOCATION, NULL,
+			"seq %d of %s message not interesting.\n",
+			msg->sadb_msg_seq,
+			s_pfkey_type(msg->sadb_msg_type));
+		return -1;
+	}
+
+	if (iph2->status != PHASE2ST_ADDSA) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"status mismatch (db:%d msg:%d)\n",
+			iph2->status, PHASE2ST_ADDSA);
+		return -1;
+	}
+
+	/* check to complete all keys ? */
+	for (pr = iph2->approval->head; pr != NULL; pr = pr->next) {
+		proto_id = pfkey2ipsecdoi_proto(msg->sadb_msg_satype);
+		if (proto_id == ~0) {
+			plog(LLV_ERROR, LOCATION, NULL,
+				"invalid proto_id %d\n", msg->sadb_msg_satype);
+			return -1;
+		}
+		encmode = pfkey2ipsecdoi_mode(sa_mode);
+		if (encmode == ~0) {
+			plog(LLV_ERROR, LOCATION, NULL,
+				"invalid encmode %d\n", sa_mode);
+			return -1;
+		}
+
+		if (pr->proto_id == proto_id
+		 && pr->spi == sa->sadb_sa_spi) {
+			pr->ok = 1;
+			plog(LLV_DEBUG, LOCATION, NULL,
+				"pfkey UPDATE succeeded: %s\n",
+				sadbsecas2str(iph2->dst, iph2->src,
+				    msg->sadb_msg_satype,
+				    sa->sadb_sa_spi,
+				    sa_mode));
+
+			plog(LLV_INFO, LOCATION, NULL,
+				"IPsec-SA established: %s\n",
+				sadbsecas2str(iph2->dst, iph2->src,
+					msg->sadb_msg_satype, sa->sadb_sa_spi,
+					sa_mode));
+		}
+
+		if (pr->ok == 0)
+			incomplete = 1;
+	}
+
+	if (incomplete)
+		return 0;
+
+	/* turn off the timer for calling pfkey_timeover() */
+	SCHED_KILL(iph2->sce);
+	
+	/* update status */
+	iph2->status = PHASE2ST_ESTABLISHED;
+
+#ifdef ENABLE_STATS
+	gettimeofday(&iph2->end, NULL);
+	syslog(LOG_NOTICE, "%s(%s): %8.6f",
+		"phase2", "quick", timedelta(&iph2->start, &iph2->end));
+#endif
+
+	/* count up */
+	iph2->ph1->ph2cnt++;
+
+	/* turn off schedule */
+	SCHED_KILL(iph2->scr);
+
+	/* Force the update of ph2's ports, as there is at least one
+	 * situation where they'll mismatch with ph1's values
+	 */
+
+#ifdef ENABLE_NATT
+	set_port(iph2->src, extract_port(iph2->ph1->local));
+	set_port(iph2->dst, extract_port(iph2->ph1->remote));
+#endif
+
+	/*
+	 * since we are going to reuse the phase2 handler, we need to
+	 * remain it and refresh all the references between ph1 and ph2 to use.
+	 */
+	unbindph12(iph2);
+
+	iph2->sce = sched_new(iph2->approval->lifetime,
+	    isakmp_ph2expire_stub, iph2);
+
+	plog(LLV_DEBUG, LOCATION, NULL, "===\n");
+	return 0;
+}
+
+/*
+ * set outbound SA
+ */
+int
+pk_sendadd(iph2)
+	struct ph2handle *iph2;
+{
+	struct saproto *pr;
+	int proxy = 0;
+	struct pfkey_send_sa_args sa_args;
+
+	/* sanity check */
+	if (iph2->approval == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"no approvaled SAs found.\n");
+		return -1;
+	}
+
+	if (iph2->side == INITIATOR)
+		proxy = iph2->ph1->rmconf->support_proxy;
+	else if (iph2->sainfo && iph2->sainfo->id_i)
+		proxy = 1;
+
+	/* fill in some needed for pfkey_send_update2 */
+	memset (&sa_args, 0, sizeof (sa_args));
+	sa_args.so = lcconf->sock_pfkey;
+	sa_args.l_addtime = iph2->approval->lifetime;
+	sa_args.seq = iph2->seq;
+	sa_args.wsize = 4;
+
+	/* for mobile IPv6 */
+	if (proxy && iph2->src_id && iph2->dst_id &&
+	    ipsecdoi_transportmode(iph2->approval)) {
+		sa_args.src = iph2->src_id;
+		sa_args.dst = iph2->dst_id;
+	} else {
+		sa_args.src = iph2->src;
+		sa_args.dst = iph2->dst;
+	}
+
+	for (pr = iph2->approval->head; pr != NULL; pr = pr->next) {
+		/* validity check */
+		sa_args.satype = ipsecdoi2pfkey_proto(pr->proto_id);
+		if (sa_args.satype == ~0) {
+			plog(LLV_ERROR, LOCATION, NULL,
+				"invalid proto_id %d\n", pr->proto_id);
+			return -1;
+		}
+		else if (sa_args.satype == SADB_X_SATYPE_IPCOMP) {
+			/* no replay window for IPCOMP */
+			sa_args.wsize = 0;
+		}
+#ifdef ENABLE_SAMODE_UNSPECIFIED
+		sa_args.mode = IPSEC_MODE_ANY;
+#else
+		sa_args.mode = ipsecdoi2pfkey_mode(pr->encmode);
+		if (sa_args.mode == ~0) {
+			plog(LLV_ERROR, LOCATION, NULL,
+				"invalid encmode %d\n", pr->encmode);
+			return -1;
+		}
+#endif
+
+		/* set algorithm type and key length */
+		sa_args.e_keylen = pr->head->encklen;
+		if (pfkey_convertfromipsecdoi(
+				pr->proto_id,
+				pr->head->trns_id,
+				pr->head->authtype,
+				&sa_args.e_type, &sa_args.e_keylen,
+				&sa_args.a_type, &sa_args.a_keylen, 
+				&sa_args.flags) < 0)
+			return -1;
+
+#if 0
+		sa_args.l_bytes = iph2->approval->lifebyte * 1024,
+#else
+		sa_args.l_bytes = 0;
+#endif
+
+#ifdef HAVE_SECCTX
+		if (*iph2->approval->sctx.ctx_str) {
+			sa_args.ctxdoi = iph2->approval->sctx.ctx_doi;
+			sa_args.ctxalg = iph2->approval->sctx.ctx_alg;
+			sa_args.ctxstrlen = iph2->approval->sctx.ctx_strlen;
+			sa_args.ctxstr = iph2->approval->sctx.ctx_str;
+		}
+#endif /* HAVE_SECCTX */
+
+#ifdef ENABLE_NATT
+		plog(LLV_DEBUG, LOCATION, NULL, "call pfkey_send_add2 "
+		    "(NAT flavor)\n");
+
+		if (pr->udp_encap) {
+			sa_args.l_natt_type = UDP_ENCAP_ESPINUDP;
+			sa_args.l_natt_sport = extract_port(iph2->ph1->local);
+			sa_args.l_natt_dport = extract_port(iph2->ph1->remote);
+			sa_args.l_natt_oa = NULL; // FIXME: Here comes OA!!!
+#ifdef SADB_X_EXT_NAT_T_FRAG
+			sa_args.l_natt_frag = iph2->ph1->rmconf->esp_frag;
+#endif
+		} else {
+			/* Remove port information, that SA doesn't use it */
+			set_port(sa_args.src, 0);
+			set_port(sa_args.dst, 0);
+		}
+
+#else
+		/* Remove port information, it is not used without NAT-T */
+		set_port(sa_args.src, 0);
+		set_port(sa_args.dst, 0);
+#endif
+
+		/* more info to fill in */
+		sa_args.spi = pr->spi_p;
+		sa_args.reqid = pr->reqid_out;
+		sa_args.keymat = pr->keymat_p->v;
+
+		plog(LLV_DEBUG, LOCATION, NULL, "call pfkey_send_add2\n");
+		if (pfkey_send_add2(&sa_args) < 0) {
+			plog(LLV_ERROR, LOCATION, NULL,
+				"libipsec failed send add (%s)\n",
+				ipsec_strerror());
+			return -1;
+		}
+
+		if (!lcconf->pathinfo[LC_PATHTYPE_BACKUPSA])
+			continue;
+
+		/*
+		 * It maybe good idea to call backupsa_to_file() after
+		 * racoon will receive the sadb_update messages.
+		 * But it is impossible because there is not key in the
+		 * information from the kernel.
+		 */
+		if (backupsa_to_file(&sa_args) < 0) {
+			plog(LLV_ERROR, LOCATION, NULL,
+				"backuped SA failed: %s\n",
+				sadbsecas2str(sa_args.src, sa_args.dst,
+				sa_args.satype, sa_args.spi, sa_args.mode));
+		}
+		plog(LLV_DEBUG, LOCATION, NULL,
+			"backuped SA: %s\n",
+			sadbsecas2str(sa_args.src, sa_args.dst,
+			sa_args.satype, sa_args.spi, sa_args.mode));
+	}
+	return 0;
+}
+
+static int
+pk_recvadd(mhp)
+	caddr_t *mhp;
+{
+	struct sadb_msg *msg;
+	struct sadb_sa *sa;
+	struct sockaddr *src, *dst;
+	struct ph2handle *iph2;
+	u_int sa_mode;
+
+	/* ignore this message because of local test mode. */
+	if (f_local)
+		return 0;
+
+	/* sanity check */
+	if (mhp[0] == NULL
+	 || mhp[SADB_EXT_SA] == NULL
+	 || mhp[SADB_EXT_ADDRESS_SRC] == NULL
+	 || mhp[SADB_EXT_ADDRESS_DST] == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"inappropriate sadb add message passed.\n");
+		return -1;
+	}
+	msg = (struct sadb_msg *)mhp[0];
+	src = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_SRC]);
+	dst = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_DST]);
+	sa = (struct sadb_sa *)mhp[SADB_EXT_SA];
+
+	sa_mode = mhp[SADB_X_EXT_SA2] == NULL
+		? IPSEC_MODE_ANY
+		: ((struct sadb_x_sa2 *)mhp[SADB_X_EXT_SA2])->sadb_x_sa2_mode;
+
+	/* the message has to be processed or not ? */
+	if (msg->sadb_msg_pid != getpid()) {
+		plog(LLV_DEBUG, LOCATION, NULL,
+			"%s message is not interesting "
+			"because pid %d is not mine.\n",
+			s_pfkey_type(msg->sadb_msg_type),
+			msg->sadb_msg_pid);
+		return -1;
+	}
+
+	iph2 = getph2byseq(msg->sadb_msg_seq);
+	if (iph2 == NULL) {
+		plog(LLV_DEBUG, LOCATION, NULL,
+			"seq %d of %s message not interesting.\n",
+			msg->sadb_msg_seq,
+			s_pfkey_type(msg->sadb_msg_type));
+		return -1;
+	}
+
+	/*
+	 * NOTE don't update any status of phase2 handle
+	 * because they must be updated by SADB_UPDATE message
+	 */
+
+	plog(LLV_INFO, LOCATION, NULL,
+		"IPsec-SA established: %s\n",
+		sadbsecas2str(iph2->src, iph2->dst,
+			msg->sadb_msg_satype, sa->sadb_sa_spi, sa_mode));
+
+	plog(LLV_DEBUG, LOCATION, NULL, "===\n");
+	return 0;
+}
+
+static int
+pk_recvexpire(mhp)
+	caddr_t *mhp;
+{
+	struct sadb_msg *msg;
+	struct sadb_sa *sa;
+	struct sockaddr *src, *dst;
+	struct ph2handle *iph2;
+	u_int proto_id, sa_mode;
+
+	/* sanity check */
+	if (mhp[0] == NULL
+	 || mhp[SADB_EXT_SA] == NULL
+	 || mhp[SADB_EXT_ADDRESS_SRC] == NULL
+	 || mhp[SADB_EXT_ADDRESS_DST] == NULL
+	 || (mhp[SADB_EXT_LIFETIME_HARD] != NULL
+	  && mhp[SADB_EXT_LIFETIME_SOFT] != NULL)) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"inappropriate sadb expire message passed.\n");
+		return -1;
+	}
+	msg = (struct sadb_msg *)mhp[0];
+	sa = (struct sadb_sa *)mhp[SADB_EXT_SA];
+	src = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_SRC]);
+	dst = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_DST]);
+
+	sa_mode = mhp[SADB_X_EXT_SA2] == NULL
+		? IPSEC_MODE_ANY
+		: ((struct sadb_x_sa2 *)mhp[SADB_X_EXT_SA2])->sadb_x_sa2_mode;
+
+	proto_id = pfkey2ipsecdoi_proto(msg->sadb_msg_satype);
+	if (proto_id == ~0) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"invalid proto_id %d\n", msg->sadb_msg_satype);
+		return -1;
+	}
+
+	plog(LLV_INFO, LOCATION, NULL,
+		"IPsec-SA expired: %s\n",
+		sadbsecas2str(src, dst,
+			msg->sadb_msg_satype, sa->sadb_sa_spi, sa_mode));
+
+	iph2 = getph2bysaidx(src, dst, proto_id, sa->sadb_sa_spi);
+	if (iph2 == NULL) {
+		/*
+		 * Ignore it because two expire messages are come up.
+		 * phase2 handler has been deleted already when 2nd message
+		 * is received.
+		 */
+		plog(LLV_DEBUG, LOCATION, NULL,
+			"no such a SA found: %s\n",
+			sadbsecas2str(src, dst,
+			    msg->sadb_msg_satype, sa->sadb_sa_spi,
+			    sa_mode));
+		return 0;
+	}
+	if (iph2->status != PHASE2ST_ESTABLISHED) {
+		/*
+		 * If the status is not equal to PHASE2ST_ESTABLISHED,
+		 * racoon ignores this expire message.  There are two reason.
+		 * One is that the phase 2 probably starts because there is
+		 * a potential that racoon receives the acquire message
+		 * without receiving a expire message.  Another is that racoon
+		 * may receive the multiple expire messages from the kernel.
+		 */
+		plog(LLV_WARNING, LOCATION, NULL,
+			"the expire message is received "
+			"but the handler has not been established.\n");
+		return 0;
+	}
+
+	/* turn off the timer for calling isakmp_ph2expire() */ 
+	SCHED_KILL(iph2->sce);
+
+	iph2->status = PHASE2ST_EXPIRED;
+
+	/* INITIATOR, begin phase 2 exchange. */
+	/* allocate buffer for status management of pfkey message */
+	if (iph2->side == INITIATOR) {
+
+		initph2(iph2);
+
+		/* update status for re-use */
+		iph2->status = PHASE2ST_STATUS2;
+
+		/* start isakmp initiation by using ident exchange */
+		if (isakmp_post_acquire(iph2) < 0) {
+			plog(LLV_ERROR, LOCATION, iph2->dst,
+				"failed to begin ipsec sa "
+				"re-negotication.\n");
+			unbindph12(iph2);
+			remph2(iph2);
+			delph2(iph2);
+			return -1;
+		}
+
+		return 0;
+		/*NOTREACHED*/
+	}
+
+	/* If not received SADB_EXPIRE, INITIATOR delete ph2handle. */
+	/* RESPONDER always delete ph2handle, keep silent.  RESPONDER doesn't
+	 * manage IPsec SA, so delete the list */
+	unbindph12(iph2);
+	remph2(iph2);
+	delph2(iph2);
+
+	return 0;
+}
+
+static int
+pk_recvacquire(mhp)
+	caddr_t *mhp;
+{
+	struct sadb_msg *msg;
+	struct sadb_x_policy *xpl;
+	struct secpolicy *sp_out = NULL, *sp_in = NULL;
+#define MAXNESTEDSA	5	/* XXX */
+	struct ph2handle *iph2[MAXNESTEDSA];
+	struct sockaddr *src, *dst;
+	int n;	/* # of phase 2 handler */
+	int remoteid=0;
+#ifdef HAVE_SECCTX
+	struct sadb_x_sec_ctx *m_sec_ctx;
+#endif /* HAVE_SECCTX */
+	struct policyindex spidx;
+
+
+	/* ignore this message because of local test mode. */
+	if (f_local)
+		return 0;
+
+	/* sanity check */
+	if (mhp[0] == NULL
+	 || mhp[SADB_EXT_ADDRESS_SRC] == NULL
+	 || mhp[SADB_EXT_ADDRESS_DST] == NULL
+	 || mhp[SADB_X_EXT_POLICY] == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"inappropriate sadb acquire message passed.\n");
+		return -1;
+	}
+	msg = (struct sadb_msg *)mhp[0];
+	xpl = (struct sadb_x_policy *)mhp[SADB_X_EXT_POLICY];
+	src = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_SRC]);
+	dst = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_DST]);
+
+#ifdef HAVE_SECCTX
+	m_sec_ctx = (struct sadb_x_sec_ctx *)mhp[SADB_X_EXT_SEC_CTX];
+
+	if (m_sec_ctx != NULL) {
+		plog(LLV_INFO, LOCATION, NULL, "security context doi: %u\n",
+		     m_sec_ctx->sadb_x_ctx_doi);
+		plog(LLV_INFO, LOCATION, NULL, 
+		     "security context algorithm: %u\n",
+		     m_sec_ctx->sadb_x_ctx_alg);
+		plog(LLV_INFO, LOCATION, NULL, "security context length: %u\n",
+		     m_sec_ctx->sadb_x_ctx_len);
+		plog(LLV_INFO, LOCATION, NULL, "security context: %s\n",
+		     ((char *)m_sec_ctx + sizeof(struct sadb_x_sec_ctx)));
+	}
+#endif /* HAVE_SECCTX */
+
+	/* ignore if type is not IPSEC_POLICY_IPSEC */
+	if (xpl->sadb_x_policy_type != IPSEC_POLICY_IPSEC) {
+		plog(LLV_DEBUG, LOCATION, NULL,
+			"ignore ACQUIRE message. type is not IPsec.\n");
+		return 0;
+	}
+
+	/* ignore it if src is multicast address */
+    {
+	struct sockaddr *sa = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_DST]);
+
+	if ((sa->sa_family == AF_INET
+	  && IN_MULTICAST(ntohl(((struct sockaddr_in *)sa)->sin_addr.s_addr)))
+#ifdef INET6
+	 || (sa->sa_family == AF_INET6
+	  && IN6_IS_ADDR_MULTICAST(&((struct sockaddr_in6 *)sa)->sin6_addr))
+#endif
+	) {
+		plog(LLV_DEBUG, LOCATION, NULL,
+			"ignore due to multicast address: %s.\n",
+			saddrwop2str(sa));
+		return 0;
+	}
+    }
+   	
+    	/* ignore, if we do not listen on source address */
+	{
+		/* reasons behind:
+		 * - if we'll contact peer from address we do not listen -
+		 *   we will be unable to complete negotiation;
+		 * - if we'll negotiate using address we're listening -
+		 *   remote peer will send packets to address different
+		 *   than one in the policy, so kernel will drop them;
+		 * => therefore this acquire is not for us! --Aidas
+		 */
+		struct sockaddr *sa = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_SRC]);
+		struct myaddrs *p;
+		int do_listen = 0;
+		for (p = lcconf->myaddrs; p; p = p->next) {
+			if (!cmpsaddrwop(p->addr, sa)) {
+				do_listen = 1;
+				break;
+			}
+		}
+
+		if (!do_listen) {
+			plog(LLV_DEBUG, LOCATION, NULL,
+				"ignore because do not listen on source address : %s.\n",
+				saddrwop2str(sa));
+			return 0;
+		}
+	}
+
+	/*
+	 * If there is a phase 2 handler against the policy identifier in
+	 * the acquire message, and if
+	 *    1. its state is less than PHASE2ST_ESTABLISHED, then racoon
+	 *       should ignore such a acquire message because the phase 2
+	 *       is just negotiating.
+	 *    2. its state is equal to PHASE2ST_ESTABLISHED, then racoon
+	 *       has to prcesss such a acquire message because racoon may
+	 *       lost the expire message.
+	 */
+	iph2[0] = getph2byid(src, dst, xpl->sadb_x_policy_id);
+	if (iph2[0] != NULL) {
+		if (iph2[0]->status < PHASE2ST_ESTABLISHED) {
+			plog(LLV_DEBUG, LOCATION, NULL,
+				"ignore the acquire because ph2 found\n");
+			return -1;
+		}
+		if (iph2[0]->status == PHASE2ST_EXPIRED)
+			iph2[0] = NULL;
+		/*FALLTHROUGH*/
+	}
+
+	/* search for proper policyindex */
+	sp_out = getspbyspid(xpl->sadb_x_policy_id);
+	if (sp_out == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL, "no policy found: id:%d.\n",
+			xpl->sadb_x_policy_id);
+		return -1;
+	}
+	plog(LLV_DEBUG, LOCATION, NULL,
+		"suitable outbound SP found: %s.\n", spidx2str(&sp_out->spidx));
+
+	/* get inbound policy */
+    {
+
+	memset(&spidx, 0, sizeof(spidx));
+	spidx.dir = IPSEC_DIR_INBOUND;
+	memcpy(&spidx.src, &sp_out->spidx.dst, sizeof(spidx.src));
+	memcpy(&spidx.dst, &sp_out->spidx.src, sizeof(spidx.dst));
+	spidx.prefs = sp_out->spidx.prefd;
+	spidx.prefd = sp_out->spidx.prefs;
+	spidx.ul_proto = sp_out->spidx.ul_proto;
+
+#ifdef HAVE_SECCTX
+	if (m_sec_ctx) {
+		spidx.sec_ctx.ctx_doi = m_sec_ctx->sadb_x_ctx_doi;
+		spidx.sec_ctx.ctx_alg = m_sec_ctx->sadb_x_ctx_alg;
+		spidx.sec_ctx.ctx_strlen = m_sec_ctx->sadb_x_ctx_len;
+		memcpy(spidx.sec_ctx.ctx_str,
+		      ((char *)m_sec_ctx + sizeof(struct sadb_x_sec_ctx)),
+		      spidx.sec_ctx.ctx_strlen);
+	}
+#endif /* HAVE_SECCTX */
+
+	sp_in = getsp(&spidx);
+	if (sp_in) {
+		plog(LLV_DEBUG, LOCATION, NULL,
+			"suitable inbound SP found: %s.\n",
+			spidx2str(&sp_in->spidx));
+	} else {
+		plog(LLV_NOTIFY, LOCATION, NULL,
+			"no in-bound policy found: %s\n",
+			spidx2str(&spidx));
+	}
+    }
+
+	memset(iph2, 0, MAXNESTEDSA);
+
+	n = 0;
+
+	/* allocate a phase 2 */
+	iph2[n] = newph2();
+	if (iph2[n] == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"failed to allocate phase2 entry.\n");
+		return -1;
+	}
+	iph2[n]->side = INITIATOR;
+	iph2[n]->spid = xpl->sadb_x_policy_id;
+	iph2[n]->satype = msg->sadb_msg_satype;
+	iph2[n]->seq = msg->sadb_msg_seq;
+	iph2[n]->status = PHASE2ST_STATUS2;
+
+	/* set end addresses of SA */
+	iph2[n]->dst = dupsaddr(PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_DST]));
+	if (iph2[n]->dst == NULL) {
+		delph2(iph2[n]);
+		return -1;
+	}
+	iph2[n]->src = dupsaddr(PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_SRC]));
+	if (iph2[n]->src == NULL) {
+		delph2(iph2[n]);
+		return -1;
+	}
+
+	plog(LLV_DEBUG, LOCATION, NULL,
+		"new acquire %s\n", spidx2str(&sp_out->spidx));
+
+	/* get sainfo */
+    {
+	vchar_t *idsrc, *iddst;
+
+	idsrc = ipsecdoi_sockaddr2id((struct sockaddr *)&sp_out->spidx.src,
+				sp_out->spidx.prefs, sp_out->spidx.ul_proto);
+	if (idsrc == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"failed to get ID for %s\n",
+			spidx2str(&sp_out->spidx));
+		delph2(iph2[n]);
+		return -1;
+	}
+	iddst = ipsecdoi_sockaddr2id((struct sockaddr *)&sp_out->spidx.dst,
+				sp_out->spidx.prefd, sp_out->spidx.ul_proto);
+	if (iddst == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"failed to get ID for %s\n",
+			spidx2str(&sp_out->spidx));
+		vfree(idsrc);
+		delph2(iph2[n]);
+		return -1;
+	}
+	{
+		struct remoteconf *conf;
+		conf = getrmconf(iph2[n]->dst);
+		if (conf != NULL)
+			remoteid=conf->ph1id;
+		else{
+			plog(LLV_DEBUG, LOCATION, NULL, "Warning: no valid rmconf !\n");
+			remoteid=0;
+		}
+	}
+	iph2[n]->sainfo = getsainfo(idsrc, iddst, NULL, remoteid);
+	vfree(idsrc);
+	vfree(iddst);
+	if (iph2[n]->sainfo == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"failed to get sainfo.\n");
+		delph2(iph2[n]);
+		return -1;
+		/* XXX should use the algorithm list from register message */
+	}
+
+	plog(LLV_DEBUG, LOCATION, NULL,
+		"selected sainfo: %s\n", sainfo2str(iph2[n]->sainfo));
+    }
+
+	if (set_proposal_from_policy(iph2[n], sp_out, sp_in) < 0) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"failed to create saprop.\n");
+		delph2(iph2[n]);
+		return -1;
+	}
+#ifdef HAVE_SECCTX
+	if (m_sec_ctx) {
+		set_secctx_in_proposal(iph2[n], spidx);
+	}
+#endif /* HAVE_SECCTX */
+
+	insph2(iph2[n]);
+
+	/* start isakmp initiation by using ident exchange */
+	/* XXX should be looped if there are multiple phase 2 handler. */
+	if (isakmp_post_acquire(iph2[n]) < 0) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"failed to begin ipsec sa negotication.\n");
+		goto err;
+	}
+
+	return 0;
+
+err:
+	while (n >= 0) {
+		unbindph12(iph2[n]);
+		remph2(iph2[n]);
+		delph2(iph2[n]);
+		iph2[n] = NULL;
+		n--;
+	}
+	return -1;
+}
+
+static int
+pk_recvdelete(mhp)
+	caddr_t *mhp;
+{
+	struct sadb_msg *msg;
+	struct sadb_sa *sa;
+	struct sockaddr *src, *dst;
+	struct ph2handle *iph2 = NULL;
+	u_int proto_id;
+
+	/* ignore this message because of local test mode. */
+	if (f_local)
+		return 0;
+
+	/* sanity check */
+	if (mhp[0] == NULL
+	 || mhp[SADB_EXT_SA] == NULL
+	 || mhp[SADB_EXT_ADDRESS_SRC] == NULL
+	 || mhp[SADB_EXT_ADDRESS_DST] == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"inappropriate sadb delete message passed.\n");
+		return -1;
+	}
+	msg = (struct sadb_msg *)mhp[0];
+	sa = (struct sadb_sa *)mhp[SADB_EXT_SA];
+	src = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_SRC]);
+	dst = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_DST]);
+
+	/* the message has to be processed or not ? */
+	if (msg->sadb_msg_pid == getpid()) {
+		plog(LLV_DEBUG, LOCATION, NULL,
+			"%s message is not interesting "
+			"because the message was originated by me.\n",
+			s_pfkey_type(msg->sadb_msg_type));
+		return -1;
+	}
+
+	proto_id = pfkey2ipsecdoi_proto(msg->sadb_msg_satype);
+	if (proto_id == ~0) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"invalid proto_id %d\n", msg->sadb_msg_satype);
+		return -1;
+	}
+
+	iph2 = getph2bysaidx(src, dst, proto_id, sa->sadb_sa_spi);
+	if (iph2 == NULL) {
+		/* ignore */
+		plog(LLV_ERROR, LOCATION, NULL,
+			"no iph2 found: %s\n",
+			sadbsecas2str(src, dst, msg->sadb_msg_satype,
+				sa->sadb_sa_spi, IPSEC_MODE_ANY));
+		return 0;
+	}
+
+	plog(LLV_ERROR, LOCATION, NULL,
+		"pfkey DELETE received: %s\n",
+		sadbsecas2str(iph2->src, iph2->dst,
+			msg->sadb_msg_satype, sa->sadb_sa_spi, IPSEC_MODE_ANY));
+
+	/* send delete information */
+	if (iph2->status == PHASE2ST_ESTABLISHED)
+		isakmp_info_send_d2(iph2);
+
+	unbindph12(iph2);
+	remph2(iph2);
+	delph2(iph2);
+
+	return 0;
+}
+
+static int
+pk_recvflush(mhp)
+	caddr_t *mhp;
+{
+	/* ignore this message because of local test mode. */
+	if (f_local)
+		return 0;
+
+	/* sanity check */
+	if (mhp[0] == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"inappropriate sadb flush message passed.\n");
+		return -1;
+	}
+
+	flushph2();
+
+	return 0;
+}
+
+static int
+getsadbpolicy(policy0, policylen0, type, iph2)
+	caddr_t *policy0;
+	int *policylen0, type;
+	struct ph2handle *iph2;
+{
+	struct policyindex *spidx = (struct policyindex *)iph2->spidx_gen;
+	struct sadb_x_policy *xpl;
+	struct sadb_x_ipsecrequest *xisr;
+	struct saproto *pr;
+	struct saproto **pr_rlist;
+	int rlist_len = 0;
+	caddr_t policy, p;
+	int policylen;
+	int xisrlen;
+	u_int satype, mode;
+	int len = 0;
+#ifdef HAVE_SECCTX
+	int ctxlen = 0;
+#endif /* HAVE_SECCTX */
+
+
+	/* get policy buffer size */
+	policylen = sizeof(struct sadb_x_policy);
+	if (type != SADB_X_SPDDELETE) {
+		for (pr = iph2->approval->head; pr; pr = pr->next) {
+			xisrlen = sizeof(*xisr);
+			if (pr->encmode == IPSECDOI_ATTR_ENC_MODE_TUNNEL) {
+				xisrlen += (sysdep_sa_len(iph2->src)
+				          + sysdep_sa_len(iph2->dst));
+			}
+
+			policylen += PFKEY_ALIGN8(xisrlen);
+		}
+	}
+
+#ifdef HAVE_SECCTX
+	if (*spidx->sec_ctx.ctx_str) {
+		ctxlen = sizeof(struct sadb_x_sec_ctx)
+				+ PFKEY_ALIGN8(spidx->sec_ctx.ctx_strlen);
+		policylen += ctxlen;
+	}
+#endif /* HAVE_SECCTX */
+
+	/* make policy structure */
+	policy = racoon_malloc(policylen);
+	memset((void*)policy, 0xcd, policylen);
+	if (!policy) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"buffer allocation failed.\n");
+		return -1;
+	}
+
+	xpl = (struct sadb_x_policy *)policy;
+	xpl->sadb_x_policy_len = PFKEY_UNIT64(policylen);
+	xpl->sadb_x_policy_exttype = SADB_X_EXT_POLICY;
+	xpl->sadb_x_policy_type = IPSEC_POLICY_IPSEC;
+	xpl->sadb_x_policy_dir = spidx->dir;
+	xpl->sadb_x_policy_id = 0;
+#ifdef HAVE_PFKEY_POLICY_PRIORITY
+	xpl->sadb_x_policy_priority = PRIORITY_DEFAULT;
+#endif
+	len++;
+
+#ifdef HAVE_SECCTX
+	if (*spidx->sec_ctx.ctx_str) {
+		struct sadb_x_sec_ctx *p;
+
+		p = (struct sadb_x_sec_ctx *)(xpl + len);
+		memset(p, 0, ctxlen);
+		p->sadb_x_sec_len = PFKEY_UNIT64(ctxlen);
+		p->sadb_x_sec_exttype = SADB_X_EXT_SEC_CTX;
+		p->sadb_x_ctx_len = spidx->sec_ctx.ctx_strlen;
+		p->sadb_x_ctx_doi = spidx->sec_ctx.ctx_doi;
+		p->sadb_x_ctx_alg = spidx->sec_ctx.ctx_alg;
+ 
+		memcpy(p + 1,spidx->sec_ctx.ctx_str,spidx->sec_ctx.ctx_strlen);
+		len += ctxlen;
+	}
+#endif /* HAVE_SECCTX */
+
+	/* no need to append policy information any more if type is SPDDELETE */
+	if (type == SADB_X_SPDDELETE)
+		goto end;
+
+	xisr = (struct sadb_x_ipsecrequest *)(xpl + len);
+
+	/* The order of things is reversed for use in add policy messages */
+	for (pr = iph2->approval->head; pr; pr = pr->next) rlist_len++;
+	pr_rlist = racoon_malloc((rlist_len+1)*sizeof(struct saproto*));
+	if (!pr_rlist) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"buffer allocation failed.\n");
+		return -1;
+	}
+	pr_rlist[rlist_len--] = NULL;
+	for (pr = iph2->approval->head; pr; pr = pr->next) pr_rlist[rlist_len--] = pr;
+	rlist_len = 0;
+
+	for (pr = pr_rlist[rlist_len++]; pr; pr = pr_rlist[rlist_len++]) {
+
+		satype = doi2ipproto(pr->proto_id);
+		if (satype == ~0) {
+			plog(LLV_ERROR, LOCATION, NULL,
+				"invalid proto_id %d\n", pr->proto_id);
+			goto err;
+		}
+		mode = ipsecdoi2pfkey_mode(pr->encmode);
+		if (mode == ~0) {
+			plog(LLV_ERROR, LOCATION, NULL,
+				"invalid encmode %d\n", pr->encmode);
+			goto err;
+		}
+
+		/* 
+		 * the policy level cannot be unique because the policy
+		 * is defined later than SA, so req_id cannot be bound to SA.
+		 */
+		xisr->sadb_x_ipsecrequest_proto = satype;
+		xisr->sadb_x_ipsecrequest_mode = mode;
+		if(iph2->proposal->head->reqid_in > 0){
+			xisr->sadb_x_ipsecrequest_level = IPSEC_LEVEL_UNIQUE;
+			xisr->sadb_x_ipsecrequest_reqid = iph2->proposal->head->reqid_in;
+		}else{
+			xisr->sadb_x_ipsecrequest_level = IPSEC_LEVEL_REQUIRE;
+			xisr->sadb_x_ipsecrequest_reqid = 0;
+		}
+		p = (caddr_t)(xisr + 1);
+
+		xisrlen = sizeof(*xisr);
+
+		if (pr->encmode == IPSECDOI_ATTR_ENC_MODE_TUNNEL) {
+			int src_len, dst_len;
+
+			src_len = sysdep_sa_len(iph2->src);
+			dst_len = sysdep_sa_len(iph2->dst);
+			xisrlen += src_len + dst_len;
+
+			memcpy(p, iph2->src, src_len);
+			p += src_len;
+
+			memcpy(p, iph2->dst, dst_len);
+			p += dst_len;
+		}
+
+		xisr->sadb_x_ipsecrequest_len = PFKEY_ALIGN8(xisrlen);
+		xisr = (struct sadb_x_ipsecrequest *)p;
+		
+	}
+	racoon_free(pr_rlist);
+
+end:
+	*policy0 = policy;
+	*policylen0 = policylen;
+
+	return 0;
+
+err:
+	if (policy)
+		racoon_free(policy);
+	if (pr_rlist) racoon_free(pr_rlist);
+
+	return -1;
+}
+
+int
+pk_sendspdupdate2(iph2)
+	struct ph2handle *iph2;
+{
+	struct policyindex *spidx = (struct policyindex *)iph2->spidx_gen;
+	caddr_t policy = NULL;
+	int policylen = 0;
+	u_int64_t ltime, vtime;
+
+	ltime = iph2->approval->lifetime;
+	vtime = 0;
+
+	if (getsadbpolicy(&policy, &policylen, SADB_X_SPDUPDATE, iph2)) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"getting sadb policy failed.\n");
+		return -1;
+	}
+
+	if (pfkey_send_spdupdate2(
+			lcconf->sock_pfkey,
+			(struct sockaddr *)&spidx->src,
+			spidx->prefs,
+			(struct sockaddr *)&spidx->dst,
+			spidx->prefd,
+			spidx->ul_proto,
+			ltime, vtime,
+			policy, policylen, 0) < 0) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"libipsec failed send spdupdate2 (%s)\n",
+			ipsec_strerror());
+		goto end;
+	}
+	plog(LLV_DEBUG, LOCATION, NULL, "call pfkey_send_spdupdate2\n");
+
+end:
+	if (policy)
+		racoon_free(policy);
+
+	return 0;
+}
+
+static int
+pk_recvspdupdate(mhp)
+	caddr_t *mhp;
+{
+	struct sadb_address *saddr, *daddr;
+	struct sadb_x_policy *xpl;
+ 	struct sadb_lifetime *lt;
+	struct policyindex spidx;
+	struct secpolicy *sp;
+ 	u_int64_t created;
+
+	/* sanity check */
+	if (mhp[0] == NULL
+	 || mhp[SADB_EXT_ADDRESS_SRC] == NULL
+	 || mhp[SADB_EXT_ADDRESS_DST] == NULL
+	 || mhp[SADB_X_EXT_POLICY] == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"inappropriate sadb spdupdate message passed.\n");
+		return -1;
+	}
+	saddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_SRC];
+	daddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_DST];
+	xpl = (struct sadb_x_policy *)mhp[SADB_X_EXT_POLICY];
+	lt = (struct sadb_lifetime*)mhp[SADB_EXT_LIFETIME_HARD];
+	if(lt != NULL)
+		created = lt->sadb_lifetime_addtime;
+	else
+		created = 0;
+
+#ifdef HAVE_PFKEY_POLICY_PRIORITY
+	KEY_SETSECSPIDX(xpl->sadb_x_policy_dir,
+			saddr + 1,
+			daddr + 1,
+			saddr->sadb_address_prefixlen,
+			daddr->sadb_address_prefixlen,
+			saddr->sadb_address_proto,
+			xpl->sadb_x_policy_priority,
+			created,
+			&spidx);
+#else
+	KEY_SETSECSPIDX(xpl->sadb_x_policy_dir,
+			saddr + 1,
+			daddr + 1,
+			saddr->sadb_address_prefixlen,
+			daddr->sadb_address_prefixlen,
+			saddr->sadb_address_proto,
+			created,
+			&spidx);
+#endif
+
+#ifdef HAVE_SECCTX
+	if (mhp[SADB_X_EXT_SEC_CTX] != NULL) {
+		struct sadb_x_sec_ctx *ctx;
+
+		ctx = (struct sadb_x_sec_ctx *)mhp[SADB_X_EXT_SEC_CTX];
+		spidx.sec_ctx.ctx_alg = ctx->sadb_x_ctx_alg;
+		spidx.sec_ctx.ctx_doi = ctx->sadb_x_ctx_doi;
+		spidx.sec_ctx.ctx_strlen = ctx->sadb_x_ctx_len;
+		memcpy(spidx.sec_ctx.ctx_str, ctx + 1, ctx->sadb_x_ctx_len);
+	}
+#endif /* HAVE_SECCTX */
+
+	sp = getsp(&spidx);
+	if (sp == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"such policy does not already exist: \"%s\"\n",
+			spidx2str(&spidx));
+	} else {
+		remsp(sp);
+		delsp(sp);
+	}
+
+	if (addnewsp(mhp) < 0)
+		return -1;
+
+	return 0;
+}
+
+/*
+ * this function has to be used by responder side.
+ */
+int
+pk_sendspdadd2(iph2)
+	struct ph2handle *iph2;
+{
+	struct policyindex *spidx = (struct policyindex *)iph2->spidx_gen;
+	caddr_t policy = NULL;
+	int policylen = 0;
+	u_int64_t ltime, vtime;
+
+	ltime = iph2->approval->lifetime;
+	vtime = 0;
+
+	if (getsadbpolicy(&policy, &policylen, SADB_X_SPDADD, iph2)) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"getting sadb policy failed.\n");
+		return -1;
+	}
+
+	if (pfkey_send_spdadd2(
+			lcconf->sock_pfkey,
+			(struct sockaddr *)&spidx->src,
+			spidx->prefs,
+			(struct sockaddr *)&spidx->dst,
+			spidx->prefd,
+			spidx->ul_proto,
+			ltime, vtime,
+			policy, policylen, 0) < 0) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"libipsec failed send spdadd2 (%s)\n",
+			ipsec_strerror());
+		goto end;
+	}
+	plog(LLV_DEBUG, LOCATION, NULL, "call pfkey_send_spdadd2\n");
+
+end:
+	if (policy)
+		racoon_free(policy);
+
+	return 0;
+}
+
+static int
+pk_recvspdadd(mhp)
+	caddr_t *mhp;
+{
+	struct sadb_address *saddr, *daddr;
+	struct sadb_x_policy *xpl;
+	struct sadb_lifetime *lt;
+	struct policyindex spidx;
+	struct secpolicy *sp;
+	u_int64_t created;
+
+	/* sanity check */
+	if (mhp[0] == NULL
+	 || mhp[SADB_EXT_ADDRESS_SRC] == NULL
+	 || mhp[SADB_EXT_ADDRESS_DST] == NULL
+	 || mhp[SADB_X_EXT_POLICY] == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"inappropriate sadb spdadd message passed.\n");
+		return -1;
+	}
+	saddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_SRC];
+	daddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_DST];
+	xpl = (struct sadb_x_policy *)mhp[SADB_X_EXT_POLICY];
+	lt = (struct sadb_lifetime*)mhp[SADB_EXT_LIFETIME_HARD];
+	if(lt != NULL)
+		created = lt->sadb_lifetime_addtime;
+	else
+		created = 0;
+
+#ifdef HAVE_PFKEY_POLICY_PRIORITY
+	KEY_SETSECSPIDX(xpl->sadb_x_policy_dir,
+			saddr + 1,
+			daddr + 1,
+			saddr->sadb_address_prefixlen,
+			daddr->sadb_address_prefixlen,
+			saddr->sadb_address_proto,
+			xpl->sadb_x_policy_priority,
+			created,
+			&spidx);
+#else
+	KEY_SETSECSPIDX(xpl->sadb_x_policy_dir,
+			saddr + 1,
+			daddr + 1,
+			saddr->sadb_address_prefixlen,
+			daddr->sadb_address_prefixlen,
+			saddr->sadb_address_proto,
+			created,
+			&spidx);
+#endif
+
+#ifdef HAVE_SECCTX
+	if (mhp[SADB_X_EXT_SEC_CTX] != NULL) {
+		struct sadb_x_sec_ctx *ctx;
+
+		ctx = (struct sadb_x_sec_ctx *)mhp[SADB_X_EXT_SEC_CTX];
+		spidx.sec_ctx.ctx_alg = ctx->sadb_x_ctx_alg;
+		spidx.sec_ctx.ctx_doi = ctx->sadb_x_ctx_doi;
+		spidx.sec_ctx.ctx_strlen = ctx->sadb_x_ctx_len;
+		memcpy(spidx.sec_ctx.ctx_str, ctx + 1, ctx->sadb_x_ctx_len);
+	}
+#endif /* HAVE_SECCTX */
+
+	sp = getsp(&spidx);
+	if (sp != NULL) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"such policy already exists. "
+			"anyway replace it: %s\n",
+			spidx2str(&spidx));
+		remsp(sp);
+		delsp(sp);
+	}
+
+	if (addnewsp(mhp) < 0)
+		return -1;
+
+	return 0;
+}
+
+/*
+ * this function has to be used by responder side.
+ */
+int
+pk_sendspddelete(iph2)
+	struct ph2handle *iph2;
+{
+	struct policyindex *spidx = (struct policyindex *)iph2->spidx_gen;
+	caddr_t policy = NULL;
+	int policylen;
+
+	if (getsadbpolicy(&policy, &policylen, SADB_X_SPDDELETE, iph2)) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"getting sadb policy failed.\n");
+		return -1;
+	}
+
+	if (pfkey_send_spddelete(
+			lcconf->sock_pfkey,
+			(struct sockaddr *)&spidx->src,
+			spidx->prefs,
+			(struct sockaddr *)&spidx->dst,
+			spidx->prefd,
+			spidx->ul_proto,
+			policy, policylen, 0) < 0) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"libipsec failed send spddelete (%s)\n",
+			ipsec_strerror());
+		goto end;
+	}
+	plog(LLV_DEBUG, LOCATION, NULL, "call pfkey_send_spddelete\n");
+
+end:
+	if (policy)
+		racoon_free(policy);
+
+	return 0;
+}
+
+static int
+pk_recvspddelete(mhp)
+	caddr_t *mhp;
+{
+	struct sadb_address *saddr, *daddr;
+	struct sadb_x_policy *xpl;
+	struct sadb_lifetime *lt;
+	struct policyindex spidx;
+	struct secpolicy *sp;
+	u_int64_t created;
+
+	/* sanity check */
+	if (mhp[0] == NULL
+	 || mhp[SADB_EXT_ADDRESS_SRC] == NULL
+	 || mhp[SADB_EXT_ADDRESS_DST] == NULL
+	 || mhp[SADB_X_EXT_POLICY] == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"inappropriate sadb spddelete message passed.\n");
+		return -1;
+	}
+	saddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_SRC];
+	daddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_DST];
+	xpl = (struct sadb_x_policy *)mhp[SADB_X_EXT_POLICY];
+	lt = (struct sadb_lifetime*)mhp[SADB_EXT_LIFETIME_HARD];
+	if(lt != NULL)
+		created = lt->sadb_lifetime_addtime;
+	else
+		created = 0;
+
+#ifdef HAVE_PFKEY_POLICY_PRIORITY
+	KEY_SETSECSPIDX(xpl->sadb_x_policy_dir,
+			saddr + 1,
+			daddr + 1,
+			saddr->sadb_address_prefixlen,
+			daddr->sadb_address_prefixlen,
+			saddr->sadb_address_proto,
+			xpl->sadb_x_policy_priority,
+			created,
+			&spidx);
+#else
+	KEY_SETSECSPIDX(xpl->sadb_x_policy_dir,
+			saddr + 1,
+			daddr + 1,
+			saddr->sadb_address_prefixlen,
+			daddr->sadb_address_prefixlen,
+			saddr->sadb_address_proto,
+			created,
+			&spidx);
+#endif
+
+#ifdef HAVE_SECCTX
+	if (mhp[SADB_X_EXT_SEC_CTX] != NULL) {
+		struct sadb_x_sec_ctx *ctx;
+
+		ctx = (struct sadb_x_sec_ctx *)mhp[SADB_X_EXT_SEC_CTX];
+		spidx.sec_ctx.ctx_alg = ctx->sadb_x_ctx_alg;
+		spidx.sec_ctx.ctx_doi = ctx->sadb_x_ctx_doi;
+		spidx.sec_ctx.ctx_strlen = ctx->sadb_x_ctx_len;
+		memcpy(spidx.sec_ctx.ctx_str, ctx + 1, ctx->sadb_x_ctx_len);
+	}
+#endif /* HAVE_SECCTX */
+
+	sp = getsp(&spidx);
+	if (sp == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"no policy found: %s\n",
+			spidx2str(&spidx));
+		return -1;
+	}
+
+	remsp(sp);
+	delsp(sp);
+
+	return 0;
+}
+
+static int
+pk_recvspdexpire(mhp)
+	caddr_t *mhp;
+{
+	struct sadb_address *saddr, *daddr;
+	struct sadb_x_policy *xpl;
+	struct sadb_lifetime *lt;
+	struct policyindex spidx;
+	struct secpolicy *sp;
+	u_int64_t created;
+
+	/* sanity check */
+	if (mhp[0] == NULL
+	 || mhp[SADB_EXT_ADDRESS_SRC] == NULL
+	 || mhp[SADB_EXT_ADDRESS_DST] == NULL
+	 || mhp[SADB_X_EXT_POLICY] == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"inappropriate sadb spdexpire message passed.\n");
+		return -1;
+	}
+	saddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_SRC];
+	daddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_DST];
+	xpl = (struct sadb_x_policy *)mhp[SADB_X_EXT_POLICY];
+	lt = (struct sadb_lifetime*)mhp[SADB_EXT_LIFETIME_HARD];
+	if(lt != NULL)
+		created = lt->sadb_lifetime_addtime;
+	else
+		created = 0;
+
+#ifdef HAVE_PFKEY_POLICY_PRIORITY
+	KEY_SETSECSPIDX(xpl->sadb_x_policy_dir,
+			saddr + 1,
+			daddr + 1,
+			saddr->sadb_address_prefixlen,
+			daddr->sadb_address_prefixlen,
+			saddr->sadb_address_proto,
+			xpl->sadb_x_policy_priority,
+			created,
+			&spidx);
+#else
+	KEY_SETSECSPIDX(xpl->sadb_x_policy_dir,
+			saddr + 1,
+			daddr + 1,
+			saddr->sadb_address_prefixlen,
+			daddr->sadb_address_prefixlen,
+			saddr->sadb_address_proto,
+			created,
+			&spidx);
+#endif
+
+#ifdef HAVE_SECCTX
+	if (mhp[SADB_X_EXT_SEC_CTX] != NULL) {
+		struct sadb_x_sec_ctx *ctx;
+
+		ctx = (struct sadb_x_sec_ctx *)mhp[SADB_X_EXT_SEC_CTX];
+		spidx.sec_ctx.ctx_alg = ctx->sadb_x_ctx_alg;
+		spidx.sec_ctx.ctx_doi = ctx->sadb_x_ctx_doi;
+		spidx.sec_ctx.ctx_strlen = ctx->sadb_x_ctx_len;
+		memcpy(spidx.sec_ctx.ctx_str, ctx + 1, ctx->sadb_x_ctx_len);
+	}
+#endif /* HAVE_SECCTX */
+
+	sp = getsp(&spidx);
+	if (sp == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"no policy found: %s\n",
+			spidx2str(&spidx));
+		return -1;
+	}
+
+	remsp(sp);
+	delsp(sp);
+
+	return 0;
+}
+
+static int
+pk_recvspdget(mhp)
+	caddr_t *mhp;
+{
+	/* sanity check */
+	if (mhp[0] == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"inappropriate sadb spdget message passed.\n");
+		return -1;
+	}
+
+	return 0;
+}
+
+static int
+pk_recvspddump(mhp)
+	caddr_t *mhp;
+{
+	struct sadb_msg *msg;
+	struct sadb_address *saddr, *daddr;
+	struct sadb_x_policy *xpl;
+	struct sadb_lifetime *lt;
+	struct policyindex spidx;
+	struct secpolicy *sp;
+	u_int64_t created;
+
+	/* sanity check */
+	if (mhp[0] == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"inappropriate sadb spddump message passed.\n");
+		return -1;
+	}
+	msg = (struct sadb_msg *)mhp[0];
+
+	saddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_SRC];
+	daddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_DST];
+	xpl = (struct sadb_x_policy *)mhp[SADB_X_EXT_POLICY];
+	lt = (struct sadb_lifetime*)mhp[SADB_EXT_LIFETIME_HARD];
+	if(lt != NULL)
+		created = lt->sadb_lifetime_addtime;
+	else
+		created = 0;
+
+	if (saddr == NULL || daddr == NULL || xpl == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"inappropriate sadb spddump message passed.\n");
+		return -1;
+	}
+
+#ifdef HAVE_PFKEY_POLICY_PRIORITY
+	KEY_SETSECSPIDX(xpl->sadb_x_policy_dir,
+			saddr + 1,
+			daddr + 1,
+			saddr->sadb_address_prefixlen,
+			daddr->sadb_address_prefixlen,
+			saddr->sadb_address_proto,
+			xpl->sadb_x_policy_priority,
+			created,
+			&spidx);
+#else
+	KEY_SETSECSPIDX(xpl->sadb_x_policy_dir,
+			saddr + 1,
+			daddr + 1,
+			saddr->sadb_address_prefixlen,
+			daddr->sadb_address_prefixlen,
+			saddr->sadb_address_proto,
+			created,
+			&spidx);
+#endif
+
+#ifdef HAVE_SECCTX
+	if (mhp[SADB_X_EXT_SEC_CTX] != NULL) {
+		struct sadb_x_sec_ctx *ctx;
+
+		ctx = (struct sadb_x_sec_ctx *)mhp[SADB_X_EXT_SEC_CTX];
+		spidx.sec_ctx.ctx_alg = ctx->sadb_x_ctx_alg;
+		spidx.sec_ctx.ctx_doi = ctx->sadb_x_ctx_doi;
+		spidx.sec_ctx.ctx_strlen = ctx->sadb_x_ctx_len;
+		memcpy(spidx.sec_ctx.ctx_str, ctx + 1, ctx->sadb_x_ctx_len);
+	}
+#endif /* HAVE_SECCTX */
+
+	sp = getsp(&spidx);
+	if (sp != NULL) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"such policy already exists. "
+			"anyway replace it: %s\n",
+			spidx2str(&spidx));
+		remsp(sp);
+		delsp(sp);
+	}
+
+	if (addnewsp(mhp) < 0)
+		return -1;
+
+	return 0;
+}
+
+static int
+pk_recvspdflush(mhp)
+	caddr_t *mhp;
+{
+	/* sanity check */
+	if (mhp[0] == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"inappropriate sadb spdflush message passed.\n");
+		return -1;
+	}
+
+	flushsp();
+
+	return 0;
+}
+
+/*
+ * send error against acquire message to kenrel.
+ */
+int
+pk_sendeacquire(iph2)
+	struct ph2handle *iph2;
+{
+	struct sadb_msg *newmsg;
+	int len;
+
+	len = sizeof(struct sadb_msg);
+	newmsg = racoon_calloc(1, len);
+	if (newmsg == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"failed to get buffer to send acquire.\n");
+		return -1;
+	}
+
+	memset(newmsg, 0, len);
+	newmsg->sadb_msg_version = PF_KEY_V2;
+	newmsg->sadb_msg_type = SADB_ACQUIRE;
+	newmsg->sadb_msg_errno = ENOENT;	/* XXX */
+	newmsg->sadb_msg_satype = iph2->satype;
+	newmsg->sadb_msg_len = PFKEY_UNIT64(len);
+	newmsg->sadb_msg_reserved = 0;
+	newmsg->sadb_msg_seq = iph2->seq;
+	newmsg->sadb_msg_pid = (u_int32_t)getpid();
+
+	/* send message */
+	len = pfkey_send(lcconf->sock_pfkey, newmsg, len);
+
+	racoon_free(newmsg);
+
+	return 0;
+}
+
+/*
+ * check if the algorithm is supported or not.
+ * OUT	 0: ok
+ *	-1: ng
+ */
+int
+pk_checkalg(class, calg, keylen)
+	int class, calg, keylen;
+{
+	int sup, error;
+	u_int alg;
+	struct sadb_alg alg0;
+
+	switch (algclass2doi(class)) {
+	case IPSECDOI_PROTO_IPSEC_ESP:
+		sup = SADB_EXT_SUPPORTED_ENCRYPT;
+		break;
+	case IPSECDOI_ATTR_AUTH:
+		sup = SADB_EXT_SUPPORTED_AUTH;
+		break;
+	case IPSECDOI_PROTO_IPCOMP:
+		plog(LLV_DEBUG, LOCATION, NULL,
+			"compression algorithm can not be checked "
+			"because sadb message doesn't support it.\n");
+		return 0;
+	default:
+		plog(LLV_ERROR, LOCATION, NULL,
+			"invalid algorithm class.\n");
+		return -1;
+	}
+	alg = ipsecdoi2pfkey_alg(algclass2doi(class), algtype2doi(class, calg));
+	if (alg == ~0)
+		return -1;
+
+	if (keylen == 0) {
+		if (ipsec_get_keylen(sup, alg, &alg0)) {
+			plog(LLV_ERROR, LOCATION, NULL,
+				"%s.\n", ipsec_strerror());
+			return -1;
+		}
+		keylen = alg0.sadb_alg_minbits;
+	}
+
+	error = ipsec_check_keylen(sup, alg, keylen);
+	if (error)
+		plog(LLV_ERROR, LOCATION, NULL,
+			"%s.\n", ipsec_strerror());
+
+	return error;
+}
+
+/*
+ * differences with pfkey_recv() in libipsec/pfkey.c:
+ * - never performs busy wait loop.
+ * - returns NULL and set *lenp to negative on fatal failures
+ * - returns NULL and set *lenp to non-negative on non-fatal failures
+ * - returns non-NULL on success
+ */
+static struct sadb_msg *
+pk_recv(so, lenp)
+	int so;
+	int *lenp;
+{
+	struct sadb_msg buf, *newmsg;
+	int reallen;
+	int retry = 0;
+
+	*lenp = -1;
+	do
+	{
+	    plog(LLV_DEBUG, LOCATION, NULL, "pk_recv: retry[%d] recv() \n", retry );
+	    *lenp = recv(so, (caddr_t)&buf, sizeof(buf), MSG_PEEK | MSG_DONTWAIT);
+	    retry++;
+	}
+	while (*lenp < 0 && errno == EAGAIN && retry < 3);
+
+	if (*lenp < 0)
+		return NULL;	/*fatal*/
+
+	else if (*lenp < sizeof(buf))
+		return NULL;
+
+	reallen = PFKEY_UNUNIT64(buf.sadb_msg_len);
+	if ((newmsg = racoon_calloc(1, reallen)) == NULL)
+		return NULL;
+
+	*lenp = recv(so, (caddr_t)newmsg, reallen, MSG_PEEK);
+	if (*lenp < 0) {
+		racoon_free(newmsg);
+		return NULL;	/*fatal*/
+	} else if (*lenp != reallen) {
+		racoon_free(newmsg);
+		return NULL;
+	}
+
+	*lenp = recv(so, (caddr_t)newmsg, reallen, 0);
+	if (*lenp < 0) {
+		racoon_free(newmsg);
+		return NULL;	/*fatal*/
+	} else if (*lenp != reallen) {
+		racoon_free(newmsg);
+		return NULL;
+	}
+
+	return newmsg;
+}
+
+/* see handler.h */
+u_int32_t
+pk_getseq()
+{
+	return eay_random();
+}
+
+static int
+addnewsp(mhp)
+	caddr_t *mhp;
+{
+	struct secpolicy *new = NULL;
+	struct sadb_address *saddr, *daddr;
+	struct sadb_x_policy *xpl;
+	struct sadb_lifetime *lt;
+	u_int64_t created;
+
+	/* sanity check */
+	if (mhp[SADB_EXT_ADDRESS_SRC] == NULL
+	 || mhp[SADB_EXT_ADDRESS_DST] == NULL
+	 || mhp[SADB_X_EXT_POLICY] == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"inappropriate sadb spd management message passed.\n");
+		goto bad;
+	}
+
+	saddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_SRC];
+	daddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_DST];
+	xpl = (struct sadb_x_policy *)mhp[SADB_X_EXT_POLICY];
+	lt = (struct sadb_lifetime*)mhp[SADB_EXT_LIFETIME_HARD];
+	if(lt != NULL)
+		created = lt->sadb_lifetime_addtime;
+	else
+		created = 0;
+	lt = (struct sadb_lifetime*)mhp[SADB_EXT_LIFETIME_HARD];
+	if(lt != NULL)
+		created = lt->sadb_lifetime_addtime;
+	else
+		created = 0;
+
+#ifdef __linux__
+	/* bsd skips over per-socket policies because there will be no
+	 * src and dst extensions in spddump messages. On Linux the only
+	 * way to achieve the same is check for policy id.
+	 */
+	if (xpl->sadb_x_policy_id % 8 >= 3) return 0;
+#endif
+
+	new = newsp();
+	if (new == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"failed to allocate buffer\n");
+		goto bad;
+	}
+
+	new->spidx.dir = xpl->sadb_x_policy_dir;
+	new->id = xpl->sadb_x_policy_id;
+	new->policy = xpl->sadb_x_policy_type;
+	new->req = NULL;
+
+	/* check policy */
+	switch (xpl->sadb_x_policy_type) {
+	case IPSEC_POLICY_DISCARD:
+	case IPSEC_POLICY_NONE:
+	case IPSEC_POLICY_ENTRUST:
+	case IPSEC_POLICY_BYPASS:
+		break;
+
+	case IPSEC_POLICY_IPSEC:
+	    {
+		int tlen;
+		struct sadb_x_ipsecrequest *xisr;
+		struct ipsecrequest **p_isr = &new->req;
+
+		/* validity check */
+		if (PFKEY_EXTLEN(xpl) < sizeof(*xpl)) {
+			plog(LLV_ERROR, LOCATION, NULL,
+				"invalid msg length.\n");
+			goto bad;
+		}
+
+		tlen = PFKEY_EXTLEN(xpl) - sizeof(*xpl);
+		xisr = (struct sadb_x_ipsecrequest *)(xpl + 1);
+
+		while (tlen > 0) {
+
+			/* length check */
+			if (xisr->sadb_x_ipsecrequest_len < sizeof(*xisr)) {
+				plog(LLV_ERROR, LOCATION, NULL,
+					"invalid msg length.\n");
+				goto bad;
+			}
+
+			/* allocate request buffer */
+			*p_isr = newipsecreq();
+			if (*p_isr == NULL) {
+				plog(LLV_ERROR, LOCATION, NULL,
+					"failed to get new ipsecreq.\n");
+				goto bad;
+			}
+
+			/* set values */
+			(*p_isr)->next = NULL;
+
+			switch (xisr->sadb_x_ipsecrequest_proto) {
+			case IPPROTO_ESP:
+			case IPPROTO_AH:
+			case IPPROTO_IPCOMP:
+				break;
+			default:
+				plog(LLV_ERROR, LOCATION, NULL,
+					"invalid proto type: %u\n",
+					xisr->sadb_x_ipsecrequest_proto);
+				goto bad;
+			}
+			(*p_isr)->saidx.proto = xisr->sadb_x_ipsecrequest_proto;
+
+			switch (xisr->sadb_x_ipsecrequest_mode) {
+			case IPSEC_MODE_TRANSPORT:
+			case IPSEC_MODE_TUNNEL:
+				break;
+			case IPSEC_MODE_ANY:
+			default:
+				plog(LLV_ERROR, LOCATION, NULL,
+					"invalid mode: %u\n",
+					xisr->sadb_x_ipsecrequest_mode);
+				goto bad;
+			}
+			(*p_isr)->saidx.mode = xisr->sadb_x_ipsecrequest_mode;
+
+			switch (xisr->sadb_x_ipsecrequest_level) {
+			case IPSEC_LEVEL_DEFAULT:
+			case IPSEC_LEVEL_USE:
+			case IPSEC_LEVEL_REQUIRE:
+				break;
+			case IPSEC_LEVEL_UNIQUE:
+				(*p_isr)->saidx.reqid =
+					xisr->sadb_x_ipsecrequest_reqid;
+				break;
+
+			default:
+				plog(LLV_ERROR, LOCATION, NULL,
+					"invalid level: %u\n",
+					xisr->sadb_x_ipsecrequest_level);
+				goto bad;
+			}
+			(*p_isr)->level = xisr->sadb_x_ipsecrequest_level;
+
+			/* set IP addresses if there */
+			if (xisr->sadb_x_ipsecrequest_len > sizeof(*xisr)) {
+				struct sockaddr *paddr;
+
+				paddr = (struct sockaddr *)(xisr + 1);
+				bcopy(paddr, &(*p_isr)->saidx.src,
+					sysdep_sa_len(paddr));
+
+				paddr = (struct sockaddr *)((caddr_t)paddr
+							+ sysdep_sa_len(paddr));
+				bcopy(paddr, &(*p_isr)->saidx.dst,
+					sysdep_sa_len(paddr));
+			}
+
+			(*p_isr)->sp = new;
+
+			/* initialization for the next. */
+			p_isr = &(*p_isr)->next;
+			tlen -= xisr->sadb_x_ipsecrequest_len;
+
+			/* validity check */
+			if (tlen < 0) {
+				plog(LLV_ERROR, LOCATION, NULL,
+					"becoming tlen < 0\n");
+			}
+
+			xisr = (struct sadb_x_ipsecrequest *)((caddr_t)xisr
+			                 + xisr->sadb_x_ipsecrequest_len);
+		}
+	    }
+		break;
+	default:
+		plog(LLV_ERROR, LOCATION, NULL,
+			"invalid policy type.\n");
+		goto bad;
+	}
+
+#ifdef HAVE_PFKEY_POLICY_PRIORITY
+	KEY_SETSECSPIDX(xpl->sadb_x_policy_dir,
+			saddr + 1,
+			daddr + 1,
+			saddr->sadb_address_prefixlen,
+			daddr->sadb_address_prefixlen,
+			saddr->sadb_address_proto,
+			xpl->sadb_x_policy_priority,
+			created,
+			&new->spidx);
+#else
+	KEY_SETSECSPIDX(xpl->sadb_x_policy_dir,
+			saddr + 1,
+			daddr + 1,
+			saddr->sadb_address_prefixlen,
+			daddr->sadb_address_prefixlen,
+			saddr->sadb_address_proto,
+			created,
+			&new->spidx);
+#endif
+
+#ifdef HAVE_SECCTX
+	if (mhp[SADB_X_EXT_SEC_CTX] != NULL) {
+		struct sadb_x_sec_ctx *ctx;
+
+		ctx = (struct sadb_x_sec_ctx *)mhp[SADB_X_EXT_SEC_CTX];
+		new->spidx.sec_ctx.ctx_alg = ctx->sadb_x_ctx_alg;
+		new->spidx.sec_ctx.ctx_doi = ctx->sadb_x_ctx_doi;
+		new->spidx.sec_ctx.ctx_strlen = ctx->sadb_x_ctx_len;
+		memcpy(new->spidx.sec_ctx.ctx_str,ctx + 1,ctx->sadb_x_ctx_len);
+	}
+#endif /* HAVE_SECCTX */
+
+	inssp(new);
+
+	return 0;
+bad:
+	if (new != NULL) {
+		if (new->req != NULL)
+			racoon_free(new->req);
+		racoon_free(new);
+	}
+	return -1;
+}
+
+/* proto/mode/src->dst spi */
+const char *
+sadbsecas2str(src, dst, proto, spi, mode)
+	struct sockaddr *src, *dst;
+	int proto;
+	u_int32_t spi;
+	int mode;
+{
+	static char buf[256];
+	u_int doi_proto, doi_mode = 0;
+	char *p;
+	int blen, i;
+
+	doi_proto = pfkey2ipsecdoi_proto(proto);
+	if (doi_proto == ~0)
+		return NULL;
+	if (mode) {
+		doi_mode = pfkey2ipsecdoi_mode(mode);
+		if (doi_mode == ~0)
+			return NULL;
+	}
+
+	blen = sizeof(buf) - 1;
+	p = buf;
+
+	i = snprintf(p, blen, "%s%s%s ",
+		s_ipsecdoi_proto(doi_proto),
+		mode ? "/" : "",
+		mode ? s_ipsecdoi_encmode(doi_mode) : "");
+	if (i < 0 || i >= blen)
+		return NULL;
+	p += i;
+	blen -= i;
+
+	i = snprintf(p, blen, "%s->", saddr2str(src));
+	if (i < 0 || i >= blen)
+		return NULL;
+	p += i;
+	blen -= i;
+
+	i = snprintf(p, blen, "%s ", saddr2str(dst));
+	if (i < 0 || i >= blen)
+		return NULL;
+	p += i;
+	blen -= i;
+
+	if (spi) {
+		snprintf(p, blen, "spi=%lu(0x%lx)", (unsigned long)ntohl(spi),
+		    (unsigned long)ntohl(spi));
+	}
+
+	return buf;
+}
diff --git a/src/racoon/pfkey.h b/src/racoon/pfkey.h
new file mode 100644
index 0000000..547f94a
--- /dev/null
+++ b/src/racoon/pfkey.h
@@ -0,0 +1,77 @@
+/*	$NetBSD: pfkey.h,v 1.4 2006/09/09 16:22:10 manu Exp $	*/
+
+/* Id: pfkey.h,v 1.3 2004/06/11 16:00:17 ludvigm Exp */
+
+/*
+ * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _PFKEY_H
+#define _PFKEY_H
+
+struct pfkey_satype {
+	u_int8_t	ps_satype;
+	const char	*ps_name;
+};
+
+extern const struct pfkey_satype pfkey_satypes[];
+extern const int pfkey_nsatypes;
+
+extern int pfkey_handler __P((void));
+extern vchar_t *pfkey_dump_sadb __P((int));
+extern void pfkey_flush_sadb __P((u_int));
+extern int pfkey_init __P((void));
+
+extern struct pfkey_st *pfkey_getpst __P((caddr_t *, int, int));
+
+extern int pk_checkalg __P((int, int, int));
+
+struct ph2handle;
+extern int pk_sendgetspi __P((struct ph2handle *));
+extern int pk_sendupdate __P((struct ph2handle *));
+extern int pk_sendadd __P((struct ph2handle *));
+extern int pk_sendeacquire __P((struct ph2handle *));
+extern int pk_sendspdupdate2 __P((struct ph2handle *));
+extern int pk_sendspdadd2 __P((struct ph2handle *));
+extern int pk_sendspddelete __P((struct ph2handle *));
+
+extern void pfkey_timeover_stub __P((void *));
+extern void pfkey_timeover __P((struct ph2handle *));
+
+extern u_int pfkey2ipsecdoi_proto __P((u_int));
+extern u_int ipsecdoi2pfkey_proto __P((u_int));
+extern u_int pfkey2ipsecdoi_mode __P((u_int));
+extern u_int ipsecdoi2pfkey_mode __P((u_int));
+
+extern int pfkey_convertfromipsecdoi __P(( u_int, u_int, u_int,
+	u_int *, u_int *, u_int *, u_int *, u_int *));
+extern u_int32_t pk_getseq __P((void));
+extern const char *sadbsecas2str
+	__P((struct sockaddr *, struct sockaddr *, int, u_int32_t, int));
+
+#endif /* _PFKEY_H */
diff --git a/src/racoon/plainrsa-gen.8 b/src/racoon/plainrsa-gen.8
new file mode 100644
index 0000000..377de2d
--- /dev/null
+++ b/src/racoon/plainrsa-gen.8
@@ -0,0 +1,138 @@
+.\"	$NetBSD: plainrsa-gen.8,v 1.13 2006/09/19 18:54:39 wiz Exp $
+.\"
+.\" Id: plainrsa-gen.8,v 1.4 2005/04/18 11:07:55 manubsd Exp
+.\"
+.\" Copyright (C) 2004 SuSE Linux AG, Nuernberg, Germany.
+.\" Contributed by: Michal Ludvig <mludvig@suse.cz>, SUSE Labs
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\" 3. Neither the name of the project nor the names of its contributors
+.\"    may be used to endorse or promote products derived from this software
+.\"    without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.Dd June 14, 2004
+.Dt PLAINRSA-GEN 8
+.Os
+.\"
+.Sh NAME
+.Nm plainrsa-gen
+.Nd generator for Plain RSA keys
+.\"
+.Sh SYNOPSIS
+.Nm plainrsa-gen
+.Bk -words
+.Op Fl b Ar bits
+.Op Fl e Ar pubexp
+.Op Fl f Ar outfile
+.Op Fl h
+.Ek
+.\"
+.Sh DESCRIPTION
+.Nm
+can be used to generate
+.Li Plain RSA keys
+for authentication purposes.
+Using
+.Li Plain RSA keys
+is optional.
+Other possibilities are
+.Li Pre-shared keys
+or
+.Li X.509 certificates .
+.\"
+.Bl -tag -width Ds
+.It Fl b Ar bits
+bit length of the key.
+Default is
+.Li 1024 ,
+recommended length is
+.Li 2048
+or even
+.Li 4096
+bits.
+Note that generating longer keys takes longer time.
+.It Fl e Ar pubexp
+value of RSA public exponent.
+Default is
+.Li 0x3 .
+Don't change this unless you really know what you are doing!
+.It Fl f Ar outfile
+.Ar outfile
+instead of
+.Li stdout .
+If the file already exists it won't be overwritten.
+You wouldn't like to lose your private key by accident, would you?
+.El
+.\"
+.Sh OUTPUT FILE FORMAT
+This is the secret
+.Li private key
+that should
+.Ic never
+leave your computer:
+.Bd -literal
+: RSA	{
+	# RSA 1024 bits
+	# pubkey=0sAQOrWlcwbAIdNSMhDt...
+	Modulus: 0xab5a57306c021d3523...
+	PublicExponent: 0x03
+	PrivateExponent: 0x723c3a2048...
+	Prime1: 0xd309b30e6adf9d85c01...
+	Prime2: 0xcfdc2a8aa5b2b3c90e3...
+	Exponent1: 0x8cb122099c9513ae...
+	Exponent2: 0x8a92c7071921cd30...
+	Coefficient: 0x722751305eafe9...
+  }
+.Ed
+.Pp
+The line
+.Li pubkey=0sAQOrW...
+of the
+.Li private key
+contains a
+.Li public key
+that should be stored in the other peer's configuration in this format:
+.Bd -literal
+: PUB 0sAQOrWlcwbAIdNSMhDt...
+.Ed
+.\"
+.Pp
+You can also specify
+.Li from
+and
+.Li to
+addresses for which the key is valid:
+.Bd -literal
+0.0.0.0/0 10.20.30.0/24 : PUB 0sAQOrWlcwbAIdNSMhDt...
+.Ed
+.\"
+.Sh SEE ALSO
+.Xr racoon.conf 5 ,
+.Xr racoon 8
+.\"
+.Sh HISTORY
+.Nm
+was written by
+.An Michal Ludvig Aq michal@logix.cz
+and first appeared in
+.Ic ipsec-tools 0.4 .
diff --git a/src/racoon/plainrsa-gen.c b/src/racoon/plainrsa-gen.c
new file mode 100644
index 0000000..1bd5f67
--- /dev/null
+++ b/src/racoon/plainrsa-gen.c
@@ -0,0 +1,208 @@
+/*	$NetBSD: plainrsa-gen.c,v 1.4 2006/09/09 16:22:10 manu Exp $	*/
+
+/* Id: plainrsa-gen.c,v 1.6 2005/04/21 09:08:40 monas Exp */
+/*
+ * Copyright (C) 2004 SuSE Linux AG, Nuernberg, Germany.
+ * Contributed by: Michal Ludvig <mludvig@suse.cz>, SUSE Labs
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* This file contains a generator for FreeS/WAN-style ipsec.secrets RSA keys. */
+
+#include "config.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
+#include <unistd.h>
+
+#include <openssl/bio.h>
+#include <openssl/bn.h>
+#include <openssl/err.h>
+#include <openssl/objects.h>
+#include <openssl/rsa.h>
+#include <openssl/evp.h>
+#ifdef HAVE_OPENSSL_ENGINE_H
+#include <openssl/engine.h>
+#endif
+
+#include "misc.h"
+#include "vmbuf.h"
+#include "plog.h"
+#include "crypto_openssl.h"
+
+#include "package_version.h"
+
+void
+usage (char *argv0)
+{
+	fprintf(stderr, "Plain RSA key generator, part of %s\n", TOP_PACKAGE_STRING);
+	fprintf(stderr, "By Michal Ludvig (http://www.logix.cz/michal)\n");
+	fprintf(stderr, "\n");
+	fprintf(stderr, "Usage: %s [options]\n", argv0);
+	fprintf(stderr, "\n");
+	fprintf(stderr, "  -b bits       Generate <bits> long RSA key (default=1024)\n");
+	fprintf(stderr, "  -e pubexp     Public exponent to use (default=0x3)\n");
+	fprintf(stderr, "  -f filename   Filename to store the key to (default=stdout)\n");
+	fprintf(stderr, "  -h            Help\n");
+	fprintf(stderr, "\n");
+	fprintf(stderr, "Report bugs to <ipsec-tools-devel@lists.sourceforge.net>\n");
+	exit(1);
+}
+
+/*
+ * See RFC 2065, section 3.5 for details about the output format.
+ */
+vchar_t *
+mix_b64_pubkey(RSA *key)
+{
+	char *binbuf;
+	long binlen, ret;
+	vchar_t *res;
+	
+	binlen = 1 + BN_num_bytes(key->e) + BN_num_bytes(key->n);
+	binbuf = malloc(binlen);
+	memset(binbuf, 0, binlen);
+	binbuf[0] = BN_bn2bin(key->e, (unsigned char *) &binbuf[1]);
+	ret = BN_bn2bin(key->n, (unsigned char *) (&binbuf[binbuf[0] + 1]));
+	if (1 + binbuf[0] + ret != binlen) {
+		plog(LLV_ERROR, LOCATION, NULL,
+		     "Pubkey generation failed. This is really strange...\n");
+		return NULL;
+	}
+
+	return base64_encode(binbuf, binlen);
+}
+
+char *
+lowercase(char *input)
+{
+	char *ptr = input;
+	while (*ptr) {
+		if (*ptr >= 'A' && *ptr <= 'F')
+			*ptr -= 'A' - 'a';
+		*ptr++;
+	}
+
+	return input;
+}
+
+int
+gen_rsa_key(FILE *fp, size_t bits, unsigned long exp)
+{
+	RSA *key;
+	vchar_t *pubkey64 = NULL;
+
+	key = RSA_generate_key(bits, exp, NULL, NULL);
+	if (!key) {
+		fprintf(stderr, "RSA_generate_key(): %s\n", eay_strerror());
+		return -1;
+	}
+	
+	pubkey64 = mix_b64_pubkey(key);
+	if (!pubkey64) {
+		fprintf(stderr, "mix_b64_pubkey(): %s\n", eay_strerror());
+		return -1;
+	}
+	
+	fprintf(fp, "# : PUB 0s%s\n", pubkey64->v);
+	fprintf(fp, ": RSA\t{\n");
+	fprintf(fp, "\t# RSA %zu bits\n", bits);
+	fprintf(fp, "\t# pubkey=0s%s\n", pubkey64->v);
+	fprintf(fp, "\tModulus: 0x%s\n", lowercase(BN_bn2hex(key->n)));
+	fprintf(fp, "\tPublicExponent: 0x%s\n", lowercase(BN_bn2hex(key->e)));
+	fprintf(fp, "\tPrivateExponent: 0x%s\n", lowercase(BN_bn2hex(key->d)));
+	fprintf(fp, "\tPrime1: 0x%s\n", lowercase(BN_bn2hex(key->p)));
+	fprintf(fp, "\tPrime2: 0x%s\n", lowercase(BN_bn2hex(key->q)));
+	fprintf(fp, "\tExponent1: 0x%s\n", lowercase(BN_bn2hex(key->dmp1)));
+	fprintf(fp, "\tExponent2: 0x%s\n", lowercase(BN_bn2hex(key->dmq1)));
+	fprintf(fp, "\tCoefficient: 0x%s\n", lowercase(BN_bn2hex(key->iqmp)));
+	fprintf(fp, "  }\n");
+
+	vfree(pubkey64);
+
+	return 0;
+}
+
+int
+main (int argc, char *argv[])
+{
+	FILE *fp = stdout;
+	size_t bits = 1024;
+	unsigned int pubexp = 0x3;
+	struct stat st;
+	extern char *optarg;
+	extern int optind;
+	int c;
+	char *fname = NULL;
+
+	while ((c = getopt(argc, argv, "e:b:f:h")) != -1)
+		switch (c) {
+			case 'e':
+				if (strncmp(optarg, "0x", 2) == 0)
+					sscanf(optarg, "0x%x", &pubexp);
+				else
+					pubexp = atoi(optarg);
+				break;
+			case 'b':
+				bits = atoi(optarg);
+				break;
+			case 'f':
+				fname = optarg;
+				break;
+			case 'h':
+			default:
+				usage(argv[0]);
+		}
+
+	if (fname) {
+		if (stat(fname, &st) >= 0) {
+			fprintf(stderr, "%s: file exists! Please use a different name.\n", fname);
+			exit(1);
+		}
+
+		umask(0077);
+		fp = fopen(fname, "w");
+		if (fp == NULL) {
+			fprintf(stderr, "%s: %s\n", fname, strerror(errno));
+			exit(1);
+		}
+	}
+
+	ploginit();
+	eay_init();
+
+	gen_rsa_key(fp, bits, pubexp);
+
+	fclose(fp);
+
+	return 0;
+}
diff --git a/src/racoon/plog.c b/src/racoon/plog.c
new file mode 100644
index 0000000..ccc8011
--- /dev/null
+++ b/src/racoon/plog.c
@@ -0,0 +1,265 @@
+/*	$NetBSD: plog.c,v 1.4.6.1 2007/11/06 16:41:27 vanhu Exp $	*/
+
+/* Id: plog.c,v 1.11 2006/06/20 09:57:31 vanhu Exp */
+
+/*
+ * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include <sys/types.h>
+#include <sys/param.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#ifdef HAVE_STDARG_H
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
+#if TIME_WITH_SYS_TIME
+# include <sys/time.h>
+# include <time.h>
+#else
+# if HAVE_SYS_TIME_H
+#  include <sys/time.h>
+# else
+#  include <time.h>
+# endif
+#endif
+#include <ctype.h>
+#include <err.h>
+
+#include "var.h"
+#include "misc.h"
+#include "plog.h"
+#include "logger.h"
+#include "debug.h"
+#include "gcmalloc.h"
+
+#ifndef VA_COPY
+# define VA_COPY(dst,src) memcpy(&(dst), &(src), sizeof(va_list))
+#endif
+
+char *pname = NULL;
+u_int32_t loglevel = LLV_BASE;
+int f_foreground = 0;
+
+int print_location = 0;
+
+static struct log *logp = NULL;
+static char *logfile = NULL;
+
+static char *plog_common __P((int, const char *, const char *));
+
+static struct plogtags {
+	char *name;
+	int priority;
+} ptab[] = {
+	{ "(not defined)",	0, },
+	{ "ERROR",		LOG_INFO, },
+	{ "WARNING",		LOG_INFO, },
+	{ "NOTIFY",		LOG_INFO, },
+	{ "INFO",		LOG_INFO, },
+	{ "DEBUG",		LOG_DEBUG, },
+	{ "DEBUG2",		LOG_DEBUG, },
+};
+
+static char *
+plog_common(pri, fmt, func)
+	int pri;
+	const char *fmt, *func;
+{
+	static char buf[800];	/* XXX shoule be allocated every time ? */
+	char *p;
+	int reslen, len;
+
+	p = buf;
+	reslen = sizeof(buf);
+
+	if (logfile || f_foreground) {
+		time_t t;
+		struct tm *tm;
+
+		t = time(0);
+		tm = localtime(&t);
+		len = strftime(p, reslen, "%Y-%m-%d %T: ", tm);
+		p += len;
+		reslen -= len;
+	}
+
+	if (pri < ARRAYLEN(ptab)) {
+		len = snprintf(p, reslen, "%s: ", ptab[pri].name);
+		if (len >= 0 && len < reslen) {
+			p += len;
+			reslen -= len;
+		} else
+			*p = '\0';
+	}
+
+	if (print_location)
+		snprintf(p, reslen, "%s: %s", func, fmt);
+	else
+		snprintf(p, reslen, "%s", fmt);
+#ifdef BROKEN_PRINTF
+	while ((p = strstr(buf,"%z")) != NULL)
+		p[1] = 'l';
+#endif
+
+	return buf;
+}
+
+void
+_plog(int pri, const char *func, struct sockaddr *sa, const char *fmt, ...)
+{
+	va_list ap;
+
+	va_start(ap, fmt);
+	plogv(pri, func, sa, fmt, ap);
+	va_end(ap);
+}
+
+void
+plogv(int pri, const char *func, struct sockaddr *sa,
+	const char *fmt, va_list ap)
+{
+	char *newfmt;
+	va_list ap_bak;
+
+	if (pri > loglevel)
+		return;
+
+	newfmt = plog_common(pri, fmt, func);
+
+	VA_COPY(ap_bak, ap);
+	
+	if (f_foreground)
+		vprintf(newfmt, ap);
+
+	if (logfile)
+		log_vaprint(logp, newfmt, ap_bak);
+	else {
+		if (pri < ARRAYLEN(ptab))
+			vsyslog(ptab[pri].priority, newfmt, ap_bak);
+		else
+			vsyslog(LOG_ALERT, newfmt, ap_bak);
+	}
+}
+
+void
+plogdump(pri, data, len)
+	int pri;
+	void *data;
+	size_t len;
+{
+	caddr_t buf;
+	size_t buflen;
+	int i, j;
+
+	if (pri > loglevel)
+		return;
+
+	/*
+	 * 2 words a bytes + 1 space 4 bytes + 1 newline 32 bytes
+	 * + 2 newline + '\0'
+	 */
+	buflen = (len * 2) + (len / 4) + (len / 32) + 3;
+	buf = racoon_malloc(buflen);
+
+	i = 0;
+	j = 0;
+	while (j < len) {
+		if (j % 32 == 0)
+			buf[i++] = '\n';
+		else
+		if (j % 4 == 0)
+			buf[i++] = ' ';
+		snprintf(&buf[i], buflen - i, "%02x",
+			((unsigned char *)data)[j] & 0xff);
+		i += 2;
+		j++;
+	}
+	if (buflen - i >= 2) {
+		buf[i++] = '\n';
+		buf[i] = '\0';
+	}
+	plog(pri, LOCATION, NULL, "%s", buf);
+
+	racoon_free(buf);
+}
+
+void
+ploginit()
+{
+	if (logfile) {
+		logp = log_open(250, logfile);
+		if (logp == NULL)
+			errx(1, "ERROR: failed to open log file %s.", logfile);
+		return;
+	}
+
+        openlog(pname, LOG_NDELAY, LOG_DAEMON);
+}
+
+void
+plogset(file)
+	char *file;
+{
+	if (logfile != NULL)
+		racoon_free(logfile);
+	logfile = racoon_strdup(file);
+	STRDUP_FATAL(logfile);
+}
+
+/*
+   Returns a printable string from (possibly) binary data ;
+   concatenates all unprintable chars to one space.
+   XXX Maybe the printable chars range is too large...
+ */
+char*
+binsanitize(binstr, n)
+	char *binstr;
+	size_t n;
+{
+	int p,q;
+	char* d;
+	for (p = 0, q = 0; p < n; p++) {
+                 if (isgraph((int)binstr[p])) {
+			binstr[q++] = binstr[p];
+		} else {
+			if (q && binstr[q - 1] != ' ')
+				 binstr[q++] = ' ';
+		}
+	}
+	binstr[q++] = '\0';
+	return binstr;
+}
+	
diff --git a/src/racoon/plog.h b/src/racoon/plog.h
new file mode 100644
index 0000000..7bd6cf7
--- /dev/null
+++ b/src/racoon/plog.h
@@ -0,0 +1,82 @@
+/*	$NetBSD: plog.h,v 1.4.6.1 2007/11/06 16:41:27 vanhu Exp $	*/
+
+/* Id: plog.h,v 1.7 2006/06/20 09:57:31 vanhu Exp */
+
+/*
+ * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _PLOG_H
+#define _PLOG_H
+
+#ifdef HAVE_STDARG_H
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
+#include <syslog.h>
+
+/*
+ * INFO: begin negotiation, SA establishment/deletion/expiration.
+ * NOTIFY: just notifiable.
+ * WARNING: not error strictly.
+ * ERROR: system call error. also invalid parameter/format.
+ * DEBUG1: debugging informatioin.
+ * DEBUG2: too more verbose. e.g. parsing config.
+ */
+#define LLV_ERROR	1
+#define LLV_WARNING	2
+#define LLV_NOTIFY	3
+#define LLV_INFO	4
+#define LLV_DEBUG	5
+#define LLV_DEBUG2	6
+ 
+#define LLV_BASE	LLV_INFO /* by default log less than this value. */
+
+extern char *pname;
+extern u_int32_t loglevel;
+extern int f_foreground;
+extern int print_location;
+
+struct sockaddr;
+#define plog(pri, ...) \
+	do { \
+		if ((pri) <= loglevel) \
+			_plog((pri), __VA_ARGS__); \
+	} while (0)
+extern void _plog __P((int, const char *, struct sockaddr *, const char *, ...))
+	__attribute__ ((__format__ (__printf__, 4, 5)));
+extern void plogv __P((int, const char *, struct sockaddr *,
+	const char *, va_list));
+extern void plogdump __P((int, void *, size_t));
+extern void ploginit __P((void));
+extern void plogset __P((char *));
+
+extern char* binsanitize __P((char*, size_t));
+
+#endif /* _PLOG_H */
diff --git a/src/racoon/policy.c b/src/racoon/policy.c
new file mode 100644
index 0000000..29a6818
--- /dev/null
+++ b/src/racoon/policy.c
@@ -0,0 +1,488 @@
+/*	$NetBSD: policy.c,v 1.6.4.1 2007/08/01 11:52:21 vanhu Exp $	*/
+
+/*	$KAME: policy.c,v 1.46 2001/11/16 04:08:10 sakane Exp $	*/
+
+/*
+ * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/queue.h>
+
+#include <netinet/in.h>
+#include PATH_IPSEC_H
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+
+#include "var.h"
+#include "misc.h"
+#include "vmbuf.h"
+#include "plog.h"
+#include "sockmisc.h"
+#include "debug.h"
+
+#include "policy.h"
+#include "localconf.h"
+#include "isakmp_var.h"
+#include "isakmp.h"
+#include "oakley.h"
+#include "handler.h"
+#include "strnames.h"
+#include "gcmalloc.h"
+
+static TAILQ_HEAD(_sptree, secpolicy) sptree;
+
+/* perform exact match against security policy table. */
+struct secpolicy *
+getsp(spidx)
+	struct policyindex *spidx;
+{
+	struct secpolicy *p;
+
+	for (p = TAILQ_FIRST(&sptree); p; p = TAILQ_NEXT(p, chain)) {
+		if (!cmpspidxstrict(spidx, &p->spidx))
+			return p;
+	}
+
+	return NULL;
+}
+
+/*
+ * perform non-exact match against security policy table, only if this is
+ * transport mode SA negotiation.  for example, 0.0.0.0/0 -> 0.0.0.0/0
+ * entry in policy.txt can be returned when we're negotiating transport
+ * mode SA.  this is how the kernel works.
+ */
+#if 1
+struct secpolicy *
+getsp_r(spidx)
+	struct policyindex *spidx;
+{
+	struct secpolicy *p;
+
+	for (p = TAILQ_FIRST(&sptree); p; p = TAILQ_NEXT(p, chain)) {
+		if (!cmpspidxwild(spidx, &p->spidx))
+			return p;
+	}
+
+	return NULL;
+}
+#else
+struct secpolicy *
+getsp_r(spidx, iph2)
+	struct policyindex *spidx;
+	struct ph2handle *iph2;
+{
+	struct secpolicy *p;
+	u_int8_t prefixlen;
+
+	plog(LLV_DEBUG, LOCATION, NULL, "checking for transport mode\n");
+
+	if (spidx->src.ss_family != spidx->dst.ss_family) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"address family mismatch, src:%d dst:%d\n",
+				spidx->src.ss_family,
+				spidx->dst.ss_family);
+		return NULL;
+	}
+	switch (spidx->src.ss_family) {
+	case AF_INET:
+		prefixlen = sizeof(struct in_addr) << 3;
+		break;
+#ifdef INET6
+	case AF_INET6:
+		prefixlen = sizeof(struct in6_addr) << 3;
+		break;
+#endif
+	default:
+		plog(LLV_ERROR, LOCATION, NULL,
+			"invalid family: %d\n", spidx->src.ss_family);
+		return NULL;
+	}
+
+	/* is it transport mode SA negotiation? */
+	plog(LLV_DEBUG, LOCATION, NULL, "src1: %s\n",
+		saddr2str(iph2->src));
+	plog(LLV_DEBUG, LOCATION, NULL, "src2: %s\n",
+		saddr2str((struct sockaddr *)&spidx->src));
+	if (cmpsaddrwop(iph2->src, (struct sockaddr *)&spidx->src)
+	 || spidx->prefs != prefixlen)
+		return NULL;
+
+	plog(LLV_DEBUG, LOCATION, NULL, "dst1: %s\n",
+		saddr2str(iph2->dst));
+	plog(LLV_DEBUG, LOCATION, NULL, "dst2: %s\n",
+		saddr2str((struct sockaddr *)&spidx->dst));
+	if (cmpsaddrwop(iph2->dst, (struct sockaddr *)&spidx->dst)
+	 || spidx->prefd != prefixlen)
+		return NULL;
+
+	plog(LLV_DEBUG, LOCATION, NULL, "looks to be transport mode\n");
+
+	for (p = TAILQ_FIRST(&sptree); p; p = TAILQ_NEXT(p, chain)) {
+		if (!cmpspidx_wild(spidx, &p->spidx))
+			return p;
+	}
+
+	return NULL;
+}
+#endif
+
+struct secpolicy *
+getspbyspid(spid)
+	u_int32_t spid;
+{
+	struct secpolicy *p;
+
+	for (p = TAILQ_FIRST(&sptree); p; p = TAILQ_NEXT(p, chain)) {
+		if (p->id == spid)
+			return p;
+	}
+
+	return NULL;
+}
+
+/*
+ * compare policyindex.
+ * a: subject b: db
+ * OUT:	0:	equal
+ *	1:	not equal
+ */
+int
+cmpspidxstrict(a, b)
+	struct policyindex *a, *b;
+{
+	plog(LLV_DEBUG, LOCATION, NULL, "sub:%p: %s\n", a, spidx2str(a));
+	plog(LLV_DEBUG, LOCATION, NULL, "db :%p: %s\n", b, spidx2str(b));
+
+	/* XXX don't check direction now, but it's to be checked carefully. */
+	if (a->dir != b->dir
+	 || a->prefs != b->prefs
+	 || a->prefd != b->prefd
+	 || a->ul_proto != b->ul_proto)
+		return 1;
+
+	if (cmpsaddrstrict((struct sockaddr *)&a->src,
+			   (struct sockaddr *)&b->src))
+		return 1;
+	if (cmpsaddrstrict((struct sockaddr *)&a->dst,
+			   (struct sockaddr *)&b->dst))
+		return 1;
+
+#ifdef HAVE_SECCTX
+	if (a->sec_ctx.ctx_alg != b->sec_ctx.ctx_alg
+	    || a->sec_ctx.ctx_doi != b->sec_ctx.ctx_doi
+	    || !within_range(a->sec_ctx.ctx_str, b->sec_ctx.ctx_str))
+		return 1;
+#endif
+	return 0;
+}
+
+/*
+ * compare policyindex, with wildcard address/protocol match.
+ * a: subject b: db, can contain wildcard things.
+ * OUT:	0:	equal
+ *	1:	not equal
+ */
+int
+cmpspidxwild(a, b)
+	struct policyindex *a, *b;
+{
+	struct sockaddr_storage sa1, sa2;
+
+	plog(LLV_DEBUG, LOCATION, NULL, "sub:%p: %s\n", a, spidx2str(a));
+	plog(LLV_DEBUG, LOCATION, NULL, "db: %p: %s\n", b, spidx2str(b));
+
+	if (!(b->dir == IPSEC_DIR_ANY || a->dir == b->dir))
+		return 1;
+
+	if (!(a->ul_proto == IPSEC_ULPROTO_ANY ||
+	      b->ul_proto == IPSEC_ULPROTO_ANY ||
+	      a->ul_proto == b->ul_proto))
+		return 1;
+
+	if (a->src.ss_family != b->src.ss_family)
+		return 1;
+	if (a->dst.ss_family != b->dst.ss_family)
+		return 1;
+
+#ifndef __linux__
+	/* compare src address */
+	if (sizeof(sa1) < a->src.ss_len || sizeof(sa2) < b->src.ss_len) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"unexpected error: "
+			"src.ss_len:%d dst.ss_len:%d\n",
+			a->src.ss_len, b->src.ss_len);
+		return 1;
+	}
+#endif
+	mask_sockaddr((struct sockaddr *)&sa1, (struct sockaddr *)&a->src,
+		b->prefs);
+	mask_sockaddr((struct sockaddr *)&sa2, (struct sockaddr *)&b->src,
+		b->prefs);
+	plog(LLV_DEBUG, LOCATION, NULL, "%p masked with /%d: %s\n",
+		a, b->prefs, saddr2str((struct sockaddr *)&sa1));
+	plog(LLV_DEBUG, LOCATION, NULL, "%p masked with /%d: %s\n",
+		b, b->prefs, saddr2str((struct sockaddr *)&sa2));
+	if (cmpsaddrwild((struct sockaddr *)&sa1, (struct sockaddr *)&sa2))
+		return 1;
+
+#ifndef __linux__
+	/* compare dst address */
+	if (sizeof(sa1) < a->dst.ss_len || sizeof(sa2) < b->dst.ss_len) {
+		plog(LLV_ERROR, LOCATION, NULL, "unexpected error\n");
+		exit(1);
+	}
+#endif
+	mask_sockaddr((struct sockaddr *)&sa1, (struct sockaddr *)&a->dst,
+		b->prefd);
+	mask_sockaddr((struct sockaddr *)&sa2, (struct sockaddr *)&b->dst,
+		b->prefd);
+	plog(LLV_DEBUG, LOCATION, NULL, "%p masked with /%d: %s\n",
+		a, b->prefd, saddr2str((struct sockaddr *)&sa1));
+	plog(LLV_DEBUG, LOCATION, NULL, "%p masked with /%d: %s\n",
+		b, b->prefd, saddr2str((struct sockaddr *)&sa2));
+	if (cmpsaddrwild((struct sockaddr *)&sa1, (struct sockaddr *)&sa2))
+		return 1;
+
+#ifdef HAVE_SECCTX
+	if (a->sec_ctx.ctx_alg != b->sec_ctx.ctx_alg
+	    || a->sec_ctx.ctx_doi != b->sec_ctx.ctx_doi
+	    || !within_range(a->sec_ctx.ctx_str, b->sec_ctx.ctx_str))
+		return 1;
+#endif
+	return 0;
+}
+
+struct secpolicy *
+newsp()
+{
+	struct secpolicy *new;
+
+	new = racoon_calloc(1, sizeof(*new));
+	if (new == NULL)
+		return NULL;
+
+	return new;
+}
+
+void
+delsp(sp)
+	struct secpolicy *sp;
+{
+	struct ipsecrequest *req = NULL, *next;
+
+	for (req = sp->req; req; req = next) {
+		next = req->next;
+		racoon_free(req);
+	}
+	
+	racoon_free(sp);
+}
+
+void
+delsp_bothdir(spidx0)
+	struct policyindex *spidx0;
+{
+	struct policyindex spidx;
+	struct secpolicy *sp;
+	struct sockaddr_storage src, dst;
+	u_int8_t prefs, prefd;
+
+	memcpy(&spidx, spidx0, sizeof(spidx));
+	switch (spidx.dir) {
+	case IPSEC_DIR_INBOUND:
+#ifdef HAVE_POLICY_FWD
+	case IPSEC_DIR_FWD:
+#endif
+		src   = spidx.src;
+		dst   = spidx.dst;
+		prefs = spidx.prefs;
+		prefd = spidx.prefd;
+		break;
+	case IPSEC_DIR_OUTBOUND:
+		src   = spidx.dst;
+		dst   = spidx.src;
+		prefs = spidx.prefd;
+		prefd = spidx.prefs;
+		break;
+	default:
+		return;
+	}
+
+	spidx.src   = src;
+	spidx.dst   = dst;
+	spidx.prefs = prefs;
+	spidx.prefd = prefd;
+	spidx.dir   = IPSEC_DIR_INBOUND;
+
+	sp = getsp(&spidx);
+	if (sp) {
+		remsp(sp);
+		delsp(sp);
+	}
+
+#ifdef HAVE_POLICY_FWD
+	spidx.dir   = IPSEC_DIR_FWD;
+
+	sp = getsp(&spidx);
+	if (sp) {
+		remsp(sp);
+		delsp(sp);
+	}
+#endif
+
+	spidx.src   = dst;
+	spidx.dst   = src;
+	spidx.prefs = prefd;
+	spidx.prefd = prefs;
+	spidx.dir   = IPSEC_DIR_OUTBOUND;
+
+	sp = getsp(&spidx);
+	if (sp) {
+		remsp(sp);
+		delsp(sp);
+	}
+}
+
+void
+inssp(new)
+	struct secpolicy *new;
+{
+#ifdef HAVE_PFKEY_POLICY_PRIORITY
+	struct secpolicy *p;
+
+	TAILQ_FOREACH(p, &sptree, chain) {
+		if (new->spidx.priority < p->spidx.priority) {
+			TAILQ_INSERT_BEFORE(p, new, chain);
+			return;
+		}
+	}
+	if (p == NULL)
+#endif
+		TAILQ_INSERT_TAIL(&sptree, new, chain);
+
+	return;
+}
+
+void
+remsp(sp)
+	struct secpolicy *sp;
+{
+	TAILQ_REMOVE(&sptree, sp, chain);
+}
+
+void
+flushsp()
+{
+	struct secpolicy *p, *next;
+
+	for (p = TAILQ_FIRST(&sptree); p; p = next) {
+		next = TAILQ_NEXT(p, chain);
+		remsp(p);
+		delsp(p);
+	}
+}
+
+void
+initsp()
+{
+	TAILQ_INIT(&sptree);
+}
+
+struct ipsecrequest *
+newipsecreq()
+{
+	struct ipsecrequest *new;
+
+	new = racoon_calloc(1, sizeof(*new));
+	if (new == NULL)
+		return NULL;
+
+	return new;
+}
+
+const char *
+spidx2str(spidx)
+	const struct policyindex *spidx;
+{
+	/* addr/pref[port] addr/pref[port] ul dir act */
+	static char buf[256];
+	char *p, *a, *b;
+	int blen, i;
+
+	blen = sizeof(buf) - 1;
+	p = buf;
+
+	a = saddr2str((const struct sockaddr *)&spidx->src);
+	for (b = a; *b != '\0'; b++)
+		if (*b == '[') {
+			*b = '\0';
+			b++;
+			break;
+		}
+	i = snprintf(p, blen, "%s/%d[%s ", a, spidx->prefs, b);
+	if (i < 0 || i >= blen)
+		return NULL;
+	p += i;
+	blen -= i;
+
+	a = saddr2str((const struct sockaddr *)&spidx->dst);
+	for (b = a; *b != '\0'; b++)
+		if (*b == '[') {
+			*b = '\0';
+			b++;
+			break;
+		}
+	i = snprintf(p, blen, "%s/%d[%s ", a, spidx->prefd, b);
+	if (i < 0 || i >= blen)
+		return NULL;
+	p += i;
+	blen -= i;
+
+	i = snprintf(p, blen, "proto=%s dir=%s",
+		s_proto(spidx->ul_proto), s_direction(spidx->dir));
+
+#ifdef HAVE_SECCTX
+	if (spidx->sec_ctx.ctx_strlen) {
+		p += i;
+		blen -= i;
+		snprintf(p, blen, " sec_ctx:doi=%d,alg=%d,len=%d,str=%s",
+			 spidx->sec_ctx.ctx_doi, spidx->sec_ctx.ctx_alg,
+			 spidx->sec_ctx.ctx_strlen, spidx->sec_ctx.ctx_str);
+	}
+#endif
+	return buf;
+}
diff --git a/src/racoon/policy.h b/src/racoon/policy.h
new file mode 100644
index 0000000..8c38392
--- /dev/null
+++ b/src/racoon/policy.h
@@ -0,0 +1,163 @@
+/*	$NetBSD: policy.h,v 1.5.4.2 2007/06/07 20:34:19 manu Exp $	*/
+
+/* Id: policy.h,v 1.5 2004/06/11 16:00:17 ludvigm Exp */
+
+/*
+ * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _POLICY_H
+#define _POLICY_H
+
+#include <sys/queue.h>
+
+
+#ifdef HAVE_SECCTX
+#define MAX_CTXSTR_SIZE 50
+struct security_ctx {
+	u_int8_t ctx_doi;       /* Security Context DOI */
+	u_int8_t ctx_alg;       /* Security Context Algorithm */
+	u_int16_t ctx_strlen;   /* Security Context stringlength
+				 * (includes terminating NULL)
+				 */
+	char ctx_str[MAX_CTXSTR_SIZE];  /* Security Context string */
+};
+#endif
+
+/* refs. ipsec.h */
+/*
+ * Security Policy Index
+ * NOTE: Ensure to be same address family and upper layer protocol.
+ * NOTE: ul_proto, port number, uid, gid:
+ *	ANY: reserved for waldcard.
+ *	0 to (~0 - 1): is one of the number of each value.
+ */
+struct policyindex {
+	u_int8_t dir;			/* direction of packet flow, see blow */
+	struct sockaddr_storage src;	/* IP src address for SP */
+	struct sockaddr_storage dst;	/* IP dst address for SP */
+	u_int8_t prefs;			/* prefix length in bits for src */
+	u_int8_t prefd;			/* prefix length in bits for dst */
+	u_int16_t ul_proto;		/* upper layer Protocol */
+	u_int32_t priority;		/* priority for the policy */
+ 	u_int64_t created;		/* Used for generated SPD entries deletion */
+#ifdef HAVE_SECCTX
+	struct security_ctx sec_ctx;    /* Security Context */
+#endif
+};
+
+/* Security Policy Data Base */
+struct secpolicy {
+	TAILQ_ENTRY(secpolicy) chain;
+
+	struct policyindex spidx;	/* selector */
+	u_int32_t id;			/* It's unique number on the system. */
+
+	u_int policy;		/* DISCARD, NONE or IPSEC, see keyv2.h */
+	struct ipsecrequest *req;
+				/* pointer to the ipsec request tree, */
+				/* if policy == IPSEC else this value == NULL.*/
+};
+
+/* Security Assocciation Index */
+/* NOTE: Ensure to be same address family */
+struct secasindex {
+	struct sockaddr_storage src;	/* srouce address for SA */
+	struct sockaddr_storage dst;	/* destination address for SA */
+	u_int16_t proto;		/* IPPROTO_ESP or IPPROTO_AH */
+	u_int8_t mode;			/* mode of protocol, see ipsec.h */
+	u_int32_t reqid;		/* reqid id who owned this SA */
+					/* see IPSEC_MANUAL_REQID_MAX. */
+};
+
+/* Request for IPsec */
+struct ipsecrequest {
+	struct ipsecrequest *next;
+				/* pointer to next structure */
+				/* If NULL, it means the end of chain. */
+
+	struct secasindex saidx;/* hint for search proper SA */
+				/* if __ss_len == 0 then no address specified.*/
+	u_int level;		/* IPsec level defined below. */
+
+	struct secpolicy *sp;	/* back pointer to SP */
+};
+
+#ifdef HAVE_PFKEY_POLICY_PRIORITY
+#define KEY_SETSECSPIDX(_dir, s, d, ps, pd, ulp, _priority, _created, idx)              \
+do {                                                                         \
+	bzero((idx), sizeof(struct policyindex));                            \
+	(idx)->dir = (_dir);                                                 \
+	(idx)->prefs = (ps);                                                 \
+	(idx)->prefd = (pd);                                                 \
+	(idx)->ul_proto = (ulp);                                             \
+	(idx)->priority = (_priority);                                        \
+	(idx)->created = (_created);                                        \
+	memcpy(&(idx)->src, (s), sysdep_sa_len((struct sockaddr *)(s)));          \
+	memcpy(&(idx)->dst, (d), sysdep_sa_len((struct sockaddr *)(d)));          \
+} while (0)
+#else
+#define KEY_SETSECSPIDX(_dir, s, d, ps, pd, ulp, _created, idx)              \
+do {                                                                         \
+	bzero((idx), sizeof(struct policyindex));                            \
+	(idx)->dir = (_dir);                                                 \
+	(idx)->prefs = (ps);                                                 \
+	(idx)->prefd = (pd);                                                 \
+	(idx)->ul_proto = (ulp);                                             \
+	(idx)->created = (_created);                                        \
+	memcpy(&(idx)->src, (s), sysdep_sa_len((struct sockaddr *)(s)));          \
+	memcpy(&(idx)->dst, (d), sysdep_sa_len((struct sockaddr *)(d)));          \
+} while (0)
+#endif
+
+struct ph2handle;
+struct policyindex;
+extern struct secpolicy *getsp __P((struct policyindex *));
+extern struct secpolicy *getsp_r __P((struct policyindex *));
+struct secpolicy *getspbyspid __P((u_int32_t));
+extern int cmpspidxstrict __P((struct policyindex *, struct policyindex *));
+extern int cmpspidxwild __P((struct policyindex *, struct policyindex *));
+extern struct secpolicy *newsp __P((void));
+extern void delsp __P((struct secpolicy *));
+extern void delsp_bothdir __P((struct policyindex *));
+extern void inssp __P((struct secpolicy *));
+extern void remsp __P((struct secpolicy *));
+extern void flushsp __P((void));
+extern void initsp __P((void));
+extern struct ipsecrequest *newipsecreq __P((void));
+
+extern const char *spidx2str __P((const struct policyindex *));
+#ifdef HAVE_SECCTX
+#include <selinux/selinux.h>
+extern int get_security_context __P((vchar_t *, struct policyindex *));
+extern void init_avc __P((void));
+extern int within_range __P((security_context_t, security_context_t));
+extern void set_secctx_in_proposal __P((struct ph2handle *, struct policyindex));
+#endif
+
+#endif /* _POLICY_H */
diff --git a/src/racoon/privsep.c b/src/racoon/privsep.c
new file mode 100644
index 0000000..9e60b89
--- /dev/null
+++ b/src/racoon/privsep.c
@@ -0,0 +1,1339 @@
+/*	$NetBSD: privsep.c,v 1.6 2006/09/09 16:22:10 manu Exp $	*/
+
+/* Id: privsep.c,v 1.15 2005/08/08 11:23:44 vanhu Exp */
+
+/*
+ * Copyright (C) 2004 Emmanuel Dreyfus
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include <unistd.h>
+#include <string.h>
+#ifdef __NetBSD__
+#include <stdlib.h>	/* for setproctitle */
+#endif
+#include <errno.h>
+#include <signal.h>
+#include <pwd.h>
+
+#include <sys/socket.h>
+#include <sys/param.h>
+
+#include "gcmalloc.h"
+#include "vmbuf.h"
+#include "misc.h"
+#include "plog.h"
+#include "var.h"
+#include "libpfkey.h"
+
+#include "crypto_openssl.h"
+#include "isakmp_var.h"
+#include "isakmp.h"
+#ifdef ENABLE_HYBRID
+#include "resolv.h"
+#include "isakmp_xauth.h"
+#include "isakmp_cfg.h"
+#endif
+#include "localconf.h"
+#include "remoteconf.h"
+#include "admin.h"
+#include "sockmisc.h"
+#include "privsep.h"
+
+static int privsep_sock[2] = { -1, -1 };
+
+static int privsep_recv(int, struct privsep_com_msg **, size_t *);
+static int privsep_send(int, struct privsep_com_msg *, size_t);
+static int safety_check(struct privsep_com_msg *, int i);
+static int port_check(int);
+static int unsafe_env(char *const *);
+static int unknown_name(int);
+static int unsafe_path(char *, int);
+
+static int
+privsep_send(sock, buf, len)
+	int sock;
+	struct privsep_com_msg *buf;
+	size_t len;
+{
+	if (buf == NULL)
+		return 0;
+
+	if (sendto(sock, (char *)buf, len, 0, NULL, 0) == -1) {
+		plog(LLV_ERROR, LOCATION, NULL,
+		    "privsep_send failed: %s\n", 
+		    strerror(errno));
+		return -1;
+	}
+
+	racoon_free((char *)buf);
+
+	return 0;
+}
+
+
+static int
+privsep_recv(sock, bufp, lenp)
+	int sock;
+	struct privsep_com_msg **bufp;
+	size_t *lenp;
+{
+	struct admin_com com;
+	struct admin_com *combuf;
+	size_t len;
+
+	*bufp = NULL;
+	*lenp = 0;
+
+	/* Get the header */
+	while ((len = recvfrom(sock, (char *)&com, 
+	    sizeof(com), MSG_PEEK, NULL, NULL)) == -1) {
+		if (errno == EINTR)
+			continue;
+
+		plog(LLV_ERROR, LOCATION, NULL,
+		    "privsep_recv failed: %s\n",
+		    strerror(errno));
+		return -1;
+	}
+	
+	/* Check for short packets */
+	if (len < sizeof(com)) {
+		plog(LLV_ERROR, LOCATION, NULL,
+		    "corrupted privsep message (short header)\n");
+		return -1;
+	}
+
+	/* Allocate buffer for the whole message */
+	if ((combuf = (struct admin_com *)racoon_malloc(com.ac_len)) == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL,
+		    "failed to allocate memory: %s\n", strerror(errno));
+		return -1;
+	}
+
+	/* Get the whole buffer */
+	while ((len = recvfrom(sock, (char *)combuf, 
+	    com.ac_len, 0, NULL, NULL)) == -1) {
+		if (errno == EINTR)
+			continue;
+		plog(LLV_ERROR, LOCATION, NULL,
+		    "failed to recv privsep command: %s\n", 
+		    strerror(errno));
+		return -1;
+	}
+
+	/* We expect len to match */
+	if (len != com.ac_len) {
+		plog(LLV_ERROR, LOCATION, NULL,
+		    "corrupted privsep message (short packet)\n");
+		return -1;
+	}
+
+	*bufp = (struct privsep_com_msg *)combuf;
+	*lenp = len;
+
+	return 0;
+}
+
+int
+privsep_init(void)
+{
+	int i;
+	pid_t child_pid;
+
+	/* If running as root, we don't use the privsep code path */
+	if (lcconf->uid == 0)
+		return 0;
+
+	/* 
+	 * When running privsep, certificate and script paths 
+	 * are mandatory, as they enable us to check path safety
+	 * in the privilegied instance
+	 */
+	if ((lcconf->pathinfo[LC_PATHTYPE_CERT] == NULL) ||
+	    (lcconf->pathinfo[LC_PATHTYPE_SCRIPT] == NULL)) {
+		plog(LLV_ERROR, LOCATION, NULL, "privilege separation "
+		   "require path cert and path script in the config file\n");
+		return -1;
+	}
+
+	if (socketpair(PF_LOCAL, SOCK_DGRAM, 0, privsep_sock) != 0) {
+		plog(LLV_ERROR, LOCATION, NULL, 
+		    "Cannot allocate privsep_sock: %s\n", strerror(errno));
+		return -1;
+	}
+
+	switch (child_pid = fork()) {
+	case -1:
+		plog(LLV_ERROR, LOCATION, NULL, "Cannot fork privsep: %s\n", 
+		    strerror(errno));
+		return -1;
+		break;
+
+	case 0: /* Child: drop privileges */
+		if (lcconf->chroot != NULL) {
+			if (chdir(lcconf->chroot) != 0) {
+				plog(LLV_ERROR, LOCATION, NULL, 
+				    "Cannot chdir(%s): %s\n", lcconf->chroot, 
+				    strerror(errno));
+				return -1;
+			}
+			if (chroot(lcconf->chroot) != 0) {
+				plog(LLV_ERROR, LOCATION, NULL, 
+				    "Cannot chroot(%s): %s\n", lcconf->chroot, 
+				    strerror(errno));
+				return -1;
+			}
+		}
+
+		if (setgid(lcconf->gid) != 0) {
+			plog(LLV_ERROR, LOCATION, NULL, 
+			    "Cannot setgid(%d): %s\n", lcconf->gid,
+			    strerror(errno));
+			return -1;
+		}
+
+		if (setegid(lcconf->gid) != 0) {
+			plog(LLV_ERROR, LOCATION, NULL, 
+			    "Cannot setegid(%d): %s\n", lcconf->gid,
+			    strerror(errno));
+			return -1;
+		}
+
+		if (setuid(lcconf->uid) != 0) {
+			plog(LLV_ERROR, LOCATION, NULL, 
+			    "Cannot setuid(%d): %s\n", lcconf->uid,
+			    strerror(errno));
+			return -1;
+		}
+
+		if (seteuid(lcconf->uid) != 0) {
+			plog(LLV_ERROR, LOCATION, NULL, 
+			    "Cannot seteuid(%d): %s\n", lcconf->uid,
+			    strerror(errno));
+			return -1;
+		}
+
+		return 0;
+		break;
+
+	default: /* Parent: privilegied process */
+		break;
+	}
+
+	/* 
+	 * Close everything except the socketpair, 
+	 * and stdout if running in the forground.
+	 */
+	for (i = sysconf(_SC_OPEN_MAX); i > 0; i--) {
+		if (i == privsep_sock[0])
+			continue;
+		if (i == privsep_sock[1])
+			continue;
+		if ((f_foreground) && (i == 1))
+			continue;
+		(void)close(i);
+	}
+
+	/* Above trickery closed the log file, reopen it */
+	ploginit();
+
+	plog(LLV_INFO, LOCATION, NULL, 
+	    "racoon privilegied process running with PID %d\n", getpid());
+
+#ifdef __NetBSD__
+	setproctitle("[priv]");
+#endif
+	
+	/* 
+	 * Don't catch any signal 
+	 * This duplicate session:signals[], which is static...
+	 */
+	signal(SIGHUP, SIG_DFL);
+	signal(SIGINT, SIG_DFL);
+	signal(SIGTERM, SIG_DFL);
+	signal(SIGUSR1, SIG_DFL);
+	signal(SIGUSR2, SIG_DFL);
+	signal(SIGCHLD, SIG_DFL);
+
+	while (1) {
+		size_t len;
+		struct privsep_com_msg *combuf;
+		struct privsep_com_msg *reply;
+		char *data;
+		size_t *buflen;
+		size_t totallen;
+		char *bufs[PRIVSEP_NBUF_MAX];
+		int i;
+
+		if (privsep_recv(privsep_sock[0], &combuf, &len) != 0)
+			goto out;
+
+		/* Safety checks and gather the data */
+		if (len < sizeof(*combuf)) {
+			plog(LLV_ERROR, LOCATION, NULL,
+			    "corrupted privsep message (short buflen)\n");
+			goto out;
+		}
+
+		data = (char *)(combuf + 1);
+		totallen = sizeof(*combuf);
+		for (i = 0; i < PRIVSEP_NBUF_MAX; i++) {
+			bufs[i] = (char *)data;
+			data += combuf->bufs.buflen[i];
+			totallen += combuf->bufs.buflen[i];
+		}
+
+		if (totallen > len) {
+			plog(LLV_ERROR, LOCATION, NULL,
+			    "corrupted privsep message (bufs too big)\n");
+			goto out;
+		}
+	
+		/* Prepare the reply buffer */
+		if ((reply = racoon_malloc(sizeof(*reply))) == NULL) {
+			plog(LLV_ERROR, LOCATION, NULL,
+			    "Cannot allocate reply buffer: %s\n", 
+			    strerror(errno));
+			goto out;
+		}
+		bzero(reply, sizeof(*reply));
+		reply->hdr.ac_cmd = combuf->hdr.ac_cmd;
+		reply->hdr.ac_len = sizeof(*reply);
+
+		switch(combuf->hdr.ac_cmd) {
+		/* 
+		 * XXX Improvement: instead of returning the key, 
+		 * stuff eay_get_pkcs1privkey and eay_get_x509sign
+		 * together and sign the hash in the privilegied 
+		 * instance? 
+		 * pro: the key remains inaccessible to unpriv
+		 * con: a compromised unpriv racoon can still sign anything
+		 */
+		case PRIVSEP_EAY_GET_PKCS1PRIVKEY: {
+			vchar_t *privkey;
+
+			/* Make sure the string is NULL terminated */
+			if (safety_check(combuf, 0) != 0)
+				break;
+			bufs[0][combuf->bufs.buflen[0] - 1] = '\0';
+
+			if (unsafe_path(bufs[0], LC_PATHTYPE_CERT) != 0) {
+				plog(LLV_ERROR, LOCATION, NULL, 
+				    "privsep_eay_get_pkcs1privkey: "
+				    "unsafe cert \"%s\"\n", bufs[0]);
+			}
+
+			plog(LLV_DEBUG, LOCATION, NULL, 
+			    "eay_get_pkcs1privkey(\"%s\")\n", bufs[0]);
+
+			if ((privkey = eay_get_pkcs1privkey(bufs[0])) == NULL){
+				reply->hdr.ac_errno = errno;
+				break;
+			}
+
+			reply->bufs.buflen[0] = privkey->l;
+			reply->hdr.ac_len = sizeof(*reply) + privkey->l;
+			reply = racoon_realloc(reply, reply->hdr.ac_len);
+			if (reply == NULL) {
+				plog(LLV_ERROR, LOCATION, NULL,
+				    "Cannot allocate reply buffer: %s\n", 
+				    strerror(errno));
+				goto out;
+			}
+
+			memcpy(reply + 1, privkey->v, privkey->l);
+			vfree(privkey);
+			break;
+		}
+		
+		case PRIVSEP_SCRIPT_EXEC: {
+			char *script;
+			int name;
+			char **envp = NULL;
+			int envc = 0;
+			int count = 0;
+			int i;
+
+			/*
+			 * First count the bufs, and make sure strings
+			 * are NULL terminated. 
+			 *
+			 * We expect: script, name, envp[], void
+			 */ 
+			if (safety_check(combuf, 0) != 0)
+				break;
+			bufs[0][combuf->bufs.buflen[0] - 1] = '\0';
+			count++;	/* script */
+
+			count++;	/* name */
+
+			for (; count < PRIVSEP_NBUF_MAX; count++) {
+				if (combuf->bufs.buflen[count] == 0)
+					break;
+				bufs[count]
+				    [combuf->bufs.buflen[count] - 1] = '\0';
+				envc++;
+			}
+
+			/* count a void buf and perform safety check */
+			count++;
+			if (count >= PRIVSEP_NBUF_MAX) {
+				plog(LLV_ERROR, LOCATION, NULL, 
+				    "privsep_script_exec: too many args\n");
+				goto out;
+			}
+
+
+			/* 
+			 * Allocate the arrays for envp 
+			 */
+			envp = racoon_malloc((envc + 1) * sizeof(char *));
+			if (envp == NULL) {
+				plog(LLV_ERROR, LOCATION, NULL, 
+				    "cannot allocate memory: %s\n",
+				    strerror(errno));
+				goto out;
+			}
+			bzero(envp, (envc + 1) * sizeof(char *));
+
+	
+			/*
+			 * Populate script, name and envp 
+			 */
+			count = 0;
+			script = bufs[count++];
+
+			if (combuf->bufs.buflen[count] != sizeof(name)) {
+				plog(LLV_ERROR, LOCATION, NULL, 
+				    "privsep_script_exec: corrupted message\n");
+				goto out;
+			}
+			memcpy((char *)&name, bufs[count++], sizeof(name));
+
+			for (i = 0; combuf->bufs.buflen[count]; count++)
+				envp[i++] = bufs[count];
+
+			count++;		/* void */
+
+			plog(LLV_DEBUG, LOCATION, NULL, 
+			    "script_exec(\"%s\", %d, %p)\n", 
+			    script, name, envp);
+
+			/* 
+			 * Check env for dangerous variables
+			 * Check script path and name
+			 * Perform fork and execve
+			 */
+			if ((unsafe_env(envp) == 0) &&
+			    (unknown_name(name) == 0) &&
+			    (unsafe_path(script, LC_PATHTYPE_SCRIPT) == 0))
+				(void)script_exec(script, name, envp);
+			else
+				plog(LLV_ERROR, LOCATION, NULL, 
+				    "privsep_script_exec: "
+				    "unsafe script \"%s\"\n", script);
+
+			racoon_free(envp);
+			break;
+		}
+
+		case PRIVSEP_GETPSK: {
+			vchar_t *psk;
+			int keylen;
+
+			/* Make sure the string is NULL terminated */
+			if (safety_check(combuf, 0) != 0)
+				break;
+			bufs[0][combuf->bufs.buflen[0] - 1] = '\0';
+
+			if (combuf->bufs.buflen[1] != sizeof(keylen)) {
+				plog(LLV_ERROR, LOCATION, NULL, 
+				    "privsep_getpsk: corrupted message\n");
+				goto out;
+			}
+			memcpy(&keylen, bufs[1], sizeof(keylen));
+
+			plog(LLV_DEBUG, LOCATION, NULL, 
+			    "getpsk(\"%s\", %d)\n", bufs[0], keylen);
+
+			if ((psk = getpsk(bufs[0], keylen)) == NULL) {
+				reply->hdr.ac_errno = errno;
+				break;
+			}
+
+			reply->bufs.buflen[0] = psk->l;
+			reply->hdr.ac_len = sizeof(*reply) + psk->l;
+			reply = racoon_realloc(reply, reply->hdr.ac_len); 
+			if (reply == NULL) {
+				plog(LLV_ERROR, LOCATION, NULL,
+				    "Cannot allocate reply buffer: %s\n", 
+				    strerror(errno));
+				goto out;
+			}
+
+			memcpy(reply + 1, psk->v, psk->l);
+			vfree(psk);
+			break;
+		}
+
+#ifdef ENABLE_HYBRID
+		case PRIVSEP_ACCOUNTING_SYSTEM: {
+			int pool_size;
+			int port;
+			int inout;
+			struct sockaddr *raddr;
+
+			if (safety_check(combuf, 0) != 0)
+				break;
+			if (safety_check(combuf, 1) != 0)
+				break;
+			if (safety_check(combuf, 2) != 0)
+				break;
+			if (safety_check(combuf, 3) != 0)
+				break;
+
+			memcpy(&port, bufs[0], sizeof(port));
+			raddr = (struct sockaddr *)bufs[1];
+
+			bufs[2][combuf->bufs.buflen[2] - 1] = '\0';
+			memcpy(&inout, bufs[3], sizeof(port));
+
+			if (port_check(port) != 0)
+				break;
+
+			plog(LLV_DEBUG, LOCATION, NULL, 
+			    "accounting_system(%d, %s, %s)\n", 
+			    port, saddr2str(raddr), bufs[2]); 
+
+			errno = 0;
+			if (isakmp_cfg_accounting_system(port, 
+			    raddr, bufs[2], inout) != 0) {
+				if (errno == 0)
+					reply->hdr.ac_errno = EINVAL;
+				else
+					reply->hdr.ac_errno = errno;
+			}
+			break;
+		}
+		case PRIVSEP_XAUTH_LOGIN_SYSTEM: {
+			if (safety_check(combuf, 0) != 0)
+				break;
+			bufs[0][combuf->bufs.buflen[0] - 1] = '\0';
+
+			if (safety_check(combuf, 1) != 0)
+				break;
+			bufs[1][combuf->bufs.buflen[1] - 1] = '\0';
+
+			plog(LLV_DEBUG, LOCATION, NULL, 
+			    "xauth_login_system(\"%s\", <password>)\n", 
+			    bufs[0]);
+
+			errno = 0;
+			if (xauth_login_system(bufs[0], bufs[1]) != 0) {
+				if (errno == 0)
+					reply->hdr.ac_errno = EINVAL;
+				else
+					reply->hdr.ac_errno = errno;
+			}
+			break;
+		}
+#ifdef HAVE_LIBPAM
+		case PRIVSEP_ACCOUNTING_PAM: {
+			int port;
+			int inout;
+			int pool_size;
+
+			if (safety_check(combuf, 0) != 0)
+				break;
+			if (safety_check(combuf, 1) != 0)
+				break;
+			if (safety_check(combuf, 2) != 0)
+				break;
+
+			memcpy(&port, bufs[0], sizeof(port));
+			memcpy(&inout, bufs[1], sizeof(inout));
+			memcpy(&pool_size, bufs[2], sizeof(pool_size));
+
+			if (pool_size != isakmp_cfg_config.pool_size)
+				if (isakmp_cfg_resize_pool(pool_size) != 0)
+					break;
+
+			if (port_check(port) != 0)
+				break;
+
+			plog(LLV_DEBUG, LOCATION, NULL, 
+			    "isakmp_cfg_accounting_pam(%d, %d)\n", 
+			    port, inout); 
+
+			errno = 0;
+			if (isakmp_cfg_accounting_pam(port, inout) != 0) {
+				if (errno == 0)
+					reply->hdr.ac_errno = EINVAL;
+				else
+					reply->hdr.ac_errno = errno;
+			}
+			break;
+		}
+
+		case PRIVSEP_XAUTH_LOGIN_PAM: {
+			int port;
+			int pool_size;
+			struct sockaddr *raddr;
+
+			if (safety_check(combuf, 0) != 0)
+				break;
+			if (safety_check(combuf, 1) != 0)
+				break;
+			if (safety_check(combuf, 2) != 0)
+				break;
+			if (safety_check(combuf, 3) != 0)
+				break;
+			if (safety_check(combuf, 4) != 0)
+				break;
+
+			memcpy(&port, bufs[0], sizeof(port));
+			memcpy(&pool_size, bufs[1], sizeof(pool_size));
+			raddr = (struct sockaddr *)bufs[2];
+			
+			bufs[3][combuf->bufs.buflen[3] - 1] = '\0';
+			bufs[4][combuf->bufs.buflen[4] - 1] = '\0';
+
+			if (pool_size != isakmp_cfg_config.pool_size)
+				if (isakmp_cfg_resize_pool(pool_size) != 0)
+					break;
+
+			if (port_check(port) != 0)
+				break;
+
+			plog(LLV_DEBUG, LOCATION, NULL, 
+			    "xauth_login_pam(%d, %s, \"%s\", <password>)\n", 
+			    port, saddr2str(raddr), bufs[3]); 
+
+			errno = 0;
+			if (xauth_login_pam(port, 
+			    raddr, bufs[3], bufs[4]) != 0) {
+				if (errno == 0)
+					reply->hdr.ac_errno = EINVAL;
+				else
+					reply->hdr.ac_errno = errno;
+			}
+			break;
+		}
+
+		case PRIVSEP_CLEANUP_PAM: {
+			int port;
+			int pool_size;
+
+			if (safety_check(combuf, 0) != 0)
+				break;
+			if (safety_check(combuf, 1) != 0)
+				break;
+
+			memcpy(&port, bufs[0], sizeof(port));
+			memcpy(&pool_size, bufs[1], sizeof(pool_size));
+
+			if (pool_size != isakmp_cfg_config.pool_size)
+				if (isakmp_cfg_resize_pool(pool_size) != 0)
+					break;
+
+			if (port_check(port) != 0)
+				break;
+
+			plog(LLV_DEBUG, LOCATION, NULL, 
+			    "cleanup_pam(%d)\n", port);
+
+			cleanup_pam(port);
+			reply->hdr.ac_errno = 0;
+
+			break;
+		}
+#endif /* HAVE_LIBPAM */
+#endif /* ENABLE_HYBRID */
+
+		default:
+			plog(LLV_ERROR, LOCATION, NULL,
+			    "unexpected privsep command %d\n", 
+			    combuf->hdr.ac_cmd);
+			goto out;
+			break;
+		}
+
+		/* This frees reply */
+		if (privsep_send(privsep_sock[0], 
+		    reply, reply->hdr.ac_len) != 0)
+			goto out;
+
+		racoon_free(combuf);
+	}
+
+out:
+	plog(LLV_INFO, LOCATION, NULL, "privsep exit\n");
+	_exit(0);
+}
+
+
+vchar_t *
+privsep_eay_get_pkcs1privkey(path) 
+	char *path;
+{
+	vchar_t *privkey;
+	struct privsep_com_msg *msg;
+	size_t len;
+
+	if (geteuid() == 0)
+		return eay_get_pkcs1privkey(path);
+
+	len = sizeof(*msg) + strlen(path) + 1;
+	if ((msg = racoon_malloc(len)) == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL, 
+		    "Cannot allocate memory: %s\n", strerror(errno));
+		return NULL;
+	}
+	bzero(msg, len);
+	msg->hdr.ac_cmd = PRIVSEP_EAY_GET_PKCS1PRIVKEY;
+	msg->hdr.ac_len = len;
+	msg->bufs.buflen[0] = len - sizeof(*msg);
+	memcpy(msg + 1, path, msg->bufs.buflen[0]);
+
+	if (privsep_send(privsep_sock[1], msg, len) != 0)
+		return NULL;
+
+	if (privsep_recv(privsep_sock[1], &msg, &len) != 0)
+		return NULL;
+
+	if (msg->hdr.ac_errno != 0) {
+		errno = msg->hdr.ac_errno;
+		goto out;
+	}
+
+	if ((privkey = vmalloc(len - sizeof(*msg))) == NULL)
+		goto out;
+
+	memcpy(privkey->v, msg + 1, privkey->l);
+	racoon_free(msg);
+	return privkey;
+
+out:
+	racoon_free(msg);
+	return NULL;
+}
+
+/*
+ * No prigilege separation trick here, we just open PFKEY before
+ * dropping root privs and we remember it later.
+ */
+static int  pfkey_socket = -1;
+int
+privsep_pfkey_open(void)
+{
+	int ps;
+
+	if (pfkey_socket != -1)
+		return pfkey_socket;
+
+	ps = pfkey_open();
+	if (ps != -1)
+		pfkey_socket = ps;
+
+	return ps;
+}
+
+/*
+ * Consequence of the above trickery: don't 
+ * really close PFKEY as we never re-open it.
+ */
+void
+privsep_pfkey_close(ps)
+	int ps;
+{
+	return;
+}
+
+int
+privsep_script_exec(script, name, envp)
+	char *script;
+	int name;
+	char *const envp[];
+{
+	int count = 0;
+	char *const *c;
+	char *data;
+	size_t len;
+	struct privsep_com_msg *msg;
+
+	if (geteuid() == 0)
+		return script_exec(script, name, envp);
+
+	if ((msg = racoon_malloc(sizeof(*msg))) == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL, 
+		    "Cannot allocate memory: %s\n", strerror(errno));
+		return -1;
+	}
+
+	bzero(msg, sizeof(*msg));
+	msg->hdr.ac_cmd = PRIVSEP_SCRIPT_EXEC;
+	msg->hdr.ac_len = sizeof(*msg);
+
+	/*
+	 * We send: 
+	 * script, name, envp[0], ... envp[N], void
+	 */
+
+	/*
+	 * Safety check on the counts: PRIVSEP_NBUF_MAX max
+	 */
+	count = 0;
+	count++;					/* script */
+	count++;					/* name */
+	for (c = envp; *c; c++)				/* envp */
+		count++;
+	count++;					/* void */
+
+	if (count > PRIVSEP_NBUF_MAX) {
+		plog(LLV_ERROR, LOCATION, NULL, "Unexpected error: "
+		    "privsep_script_exec count > PRIVSEP_NBUF_MAX\n");
+		racoon_free(msg);
+		return -1;
+	}
+
+
+	/*
+	 * Compute the length
+	 */
+	count = 0;
+	msg->bufs.buflen[count] = strlen(script) + 1;	/* script */
+	msg->hdr.ac_len += msg->bufs.buflen[count++];
+
+	msg->bufs.buflen[count] = sizeof(name);		/* name */
+	msg->hdr.ac_len += msg->bufs.buflen[count++];
+
+	for (c = envp; *c; c++) {			/* envp */
+		msg->bufs.buflen[count] = strlen(*c) + 1;
+		msg->hdr.ac_len += msg->bufs.buflen[count++];
+	}
+
+	msg->bufs.buflen[count] = 0; 			/* void */
+	msg->hdr.ac_len += msg->bufs.buflen[count++];
+
+	if ((msg = racoon_realloc(msg, msg->hdr.ac_len)) == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL, 
+		    "Cannot allocate memory: %s\n", strerror(errno));
+		return -1;
+	}
+	
+	/*
+	 * Now copy the data
+	 */
+	data = (char *)(msg + 1);
+	count = 0;
+
+	memcpy(data, (char *)script, msg->bufs.buflen[count]);	/* script */
+	data += msg->bufs.buflen[count++];
+
+	memcpy(data, (char *)&name, msg->bufs.buflen[count]);	/* name */
+	data += msg->bufs.buflen[count++];
+
+	for (c = envp; *c; c++) {				/* envp */
+		memcpy(data, *c, msg->bufs.buflen[count]); 
+		data += msg->bufs.buflen[count++];
+	}
+
+	count++;						/* void */
+
+	/*
+	 * And send it!
+	 */
+	if (privsep_send(privsep_sock[1], msg, msg->hdr.ac_len) != 0)
+		return -1;
+
+	if (privsep_recv(privsep_sock[1], &msg, &len) != 0)
+		return -1;
+
+	if (msg->hdr.ac_errno != 0) {
+		errno = msg->hdr.ac_errno;
+		racoon_free(msg);
+		return -1;
+	}
+
+	racoon_free(msg);
+	return 0;
+}
+
+vchar_t *
+privsep_getpsk(str, keylen)
+	const char *str;
+	int keylen;
+{
+	vchar_t *psk;
+	struct privsep_com_msg *msg;
+	size_t len;
+	int *keylenp;
+	char *data;
+
+	if (geteuid() == 0)
+		return getpsk(str, keylen);
+
+	len = sizeof(*msg) + strlen(str) + 1 + sizeof(keylen);
+	if ((msg = racoon_malloc(len)) == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL, 
+		    "Cannot allocate memory: %s\n", strerror(errno));
+		return NULL;
+	}
+	bzero(msg, len);
+	msg->hdr.ac_cmd = PRIVSEP_GETPSK;
+	msg->hdr.ac_len = len;
+
+	data = (char *)(msg + 1);
+	msg->bufs.buflen[0] = strlen(str) + 1;
+	memcpy(data, str, msg->bufs.buflen[0]);
+
+	data += msg->bufs.buflen[0];
+	msg->bufs.buflen[1] = sizeof(keylen);
+	memcpy(data, &keylen, sizeof(keylen));
+
+	if (privsep_send(privsep_sock[1], msg, len) != 0)
+		return NULL;
+
+	if (privsep_recv(privsep_sock[1], &msg, &len) != 0)
+		return NULL;
+
+	if (msg->hdr.ac_errno != 0) {
+		errno = msg->hdr.ac_errno;
+		goto out;
+	}
+
+	if ((psk = vmalloc(len - sizeof(*msg))) == NULL)
+		goto out;
+
+	memcpy(psk->v, msg + 1, psk->l);
+	racoon_free(msg);
+	return psk;
+
+out:
+	racoon_free(msg);
+	return NULL;
+}
+
+#ifdef ENABLE_HYBRID
+int
+privsep_xauth_login_system(usr, pwd)
+	char *usr;
+	char *pwd;
+{
+	struct privsep_com_msg *msg;
+	size_t len;
+	char *data;
+
+	if (geteuid() == 0)
+		return xauth_login_system(usr, pwd);
+
+	len = sizeof(*msg) + strlen(usr) + 1 + strlen(pwd) + 1;
+	if ((msg = racoon_malloc(len)) == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL, 
+		    "Cannot allocate memory: %s\n", strerror(errno));
+		return -1;
+	}
+	bzero(msg, len);
+	msg->hdr.ac_cmd = PRIVSEP_XAUTH_LOGIN_SYSTEM;
+	msg->hdr.ac_len = len;
+
+	data = (char *)(msg + 1);
+	msg->bufs.buflen[0] = strlen(usr) + 1;
+	memcpy(data, usr, msg->bufs.buflen[0]);
+	data += msg->bufs.buflen[0];
+
+	msg->bufs.buflen[1] = strlen(pwd) + 1;
+	memcpy(data, pwd, msg->bufs.buflen[1]);
+	
+	if (privsep_send(privsep_sock[1], msg, len) != 0)
+		return -1;
+
+	if (privsep_recv(privsep_sock[1], &msg, &len) != 0)
+		return -1;
+
+	if (msg->hdr.ac_errno != 0) {
+		racoon_free(msg);
+		return -1;
+	}
+
+	racoon_free(msg);
+	return 0;
+}
+
+int 
+privsep_accounting_system(port, raddr, usr, inout)
+	int port;
+	struct sockaddr *raddr;
+	char *usr;
+	int inout;
+{
+	struct privsep_com_msg *msg;
+	size_t len;
+	char *data;
+	int result;
+
+	if (geteuid() == 0)
+		return isakmp_cfg_accounting_system(port, raddr,
+						    usr, inout);
+
+	len = sizeof(*msg) 
+	    + sizeof(port)
+	    + sysdep_sa_len(raddr) 
+	    + strlen(usr) + 1
+	    + sizeof(inout);
+
+	if ((msg = racoon_malloc(len)) == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL, 
+		    "Cannot allocate memory: %s\n", strerror(errno));
+		return -1;
+	}
+	bzero(msg, len);
+	msg->hdr.ac_cmd = PRIVSEP_ACCOUNTING_SYSTEM;
+	msg->hdr.ac_len = len;
+	msg->bufs.buflen[0] = sizeof(port);
+	msg->bufs.buflen[1] = sysdep_sa_len(raddr);
+	msg->bufs.buflen[2] = strlen(usr) + 1;
+	msg->bufs.buflen[3] = sizeof(inout);
+
+	data = (char *)(msg + 1);
+	memcpy(data, &port, msg->bufs.buflen[0]);
+
+	data += msg->bufs.buflen[0];
+	memcpy(data, raddr, msg->bufs.buflen[1]);
+
+	data += msg->bufs.buflen[1];
+	memcpy(data, usr, msg->bufs.buflen[2]);
+
+	data += msg->bufs.buflen[2];
+	memcpy(data, &inout, msg->bufs.buflen[3]);
+
+	if (privsep_send(privsep_sock[1], msg, len) != 0)
+		return -1;
+
+	if (privsep_recv(privsep_sock[1], &msg, &len) != 0)
+		return -1;
+
+	if (msg->hdr.ac_errno != 0) {
+		errno = msg->hdr.ac_errno;
+		goto out;
+	}
+
+	racoon_free(msg);
+	return 0;
+
+out:
+	racoon_free(msg);
+	return -1;
+}
+
+static int
+port_check(port)
+	int port;
+{
+	if ((port < 0) || (port >= isakmp_cfg_config.pool_size)) {
+		plog(LLV_ERROR, LOCATION, NULL, 
+		    "privsep: port %d outside of allowed range [0,%zu]\n",
+		    port, isakmp_cfg_config.pool_size - 1);
+		return -1;
+	}
+
+	return 0;
+}
+#endif
+
+static int 
+safety_check(msg, index)
+	struct privsep_com_msg *msg;
+	int index;
+{
+	if (index >= PRIVSEP_NBUF_MAX) {
+		plog(LLV_ERROR, LOCATION, NULL, 
+		    "privsep: Corrupted message, too many buffers\n");
+		return -1;
+	}
+		
+	if (msg->bufs.buflen[index] == 0) {
+		plog(LLV_ERROR, LOCATION, NULL, 
+		    "privsep: Corrupted message, unexpected void buffer\n");
+		return -1;
+	}
+
+	return 0;
+}
+
+/*
+ * Filter unsafe environement variables
+ */
+static int
+unsafe_env(envp)
+	char *const *envp;
+{
+	char *const *e;
+	char *const *be;
+	char *const bad_env[] = { "PATH=", "LD_LIBRARY_PATH=", "IFS=", NULL };
+
+	for (e = envp; *e; e++) {
+		for (be = bad_env; *be; be++) {
+			if (strncmp(*e, *be, strlen(*be)) == 0) {
+				goto found;
+			}
+		}
+	}
+
+	return 0;
+found:
+	plog(LLV_ERROR, LOCATION, NULL, 
+	    "privsep_script_exec: unsafe environement variable\n");
+	return -1;
+}
+
+/*
+ * Check path safety
+ */
+static int 
+unsafe_path(script, pathtype)
+	char *script;
+	int pathtype;
+{
+	char *path;
+	char rpath[MAXPATHLEN + 1];
+	size_t len;
+
+	if (script == NULL) 
+		return -1;
+
+	path = lcconf->pathinfo[pathtype];
+
+	/* No path was given for scripts: skip the check */
+	if (path == NULL)
+		return 0;
+
+	if (realpath(script, rpath) == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL,
+		    "script path \"%s\" is invalid\n", script);
+		return -1;
+	}
+
+	len = strlen(path);
+	if (strncmp(path, rpath, len) != 0)
+		return -1;
+
+	return 0;
+}
+
+static int 
+unknown_name(name)
+	int name;
+{
+	if ((name < 0) || (name > SCRIPT_MAX)) {
+		plog(LLV_ERROR, LOCATION, NULL, 
+		    "privsep_script_exec: unsafe name index\n");
+		return -1;
+	}
+
+	return 0;
+}
+
+#ifdef HAVE_LIBPAM
+int 
+privsep_accounting_pam(port, inout)
+	int port;
+	int inout;
+{
+	struct privsep_com_msg *msg;
+	size_t len;
+	int *port_data;
+	int *inout_data;
+	int *pool_size_data;
+	int result;
+
+	if (geteuid() == 0)
+		return isakmp_cfg_accounting_pam(port, inout);
+
+	len = sizeof(*msg) 
+	    + sizeof(port) 
+	    + sizeof(inout)
+	    + sizeof(isakmp_cfg_config.pool_size);
+
+	if ((msg = racoon_malloc(len)) == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL, 
+		    "Cannot allocate memory: %s\n", strerror(errno));
+		return -1;
+	}
+	bzero(msg, len);
+	msg->hdr.ac_cmd = PRIVSEP_ACCOUNTING_PAM;
+	msg->hdr.ac_len = len;
+	msg->bufs.buflen[0] = sizeof(port);
+	msg->bufs.buflen[1] = sizeof(inout);
+	msg->bufs.buflen[2] = sizeof(isakmp_cfg_config.pool_size);
+
+	port_data = (int *)(msg + 1);
+	inout_data = (int *)(port_data + 1);
+	pool_size_data = (int *)(inout_data + 1);
+
+	*port_data = port;
+	*inout_data = inout;
+	*pool_size_data = isakmp_cfg_config.pool_size;
+
+	if (privsep_send(privsep_sock[1], msg, len) != 0)
+		return -1;
+
+	if (privsep_recv(privsep_sock[1], &msg, &len) != 0)
+		return -1;
+
+	if (msg->hdr.ac_errno != 0) {
+		errno = msg->hdr.ac_errno;
+		goto out;
+	}
+
+	racoon_free(msg);
+	return 0;
+
+out:
+	racoon_free(msg);
+	return -1;
+}
+
+int 
+privsep_xauth_login_pam(port, raddr, usr, pwd)
+	int port;
+	struct sockaddr *raddr;
+	char *usr;
+	char *pwd;
+{
+	struct privsep_com_msg *msg;
+	size_t len;
+	char *data;
+	int result;
+
+	if (geteuid() == 0)
+		return xauth_login_pam(port, raddr, usr, pwd);
+
+	len = sizeof(*msg) 
+	    + sizeof(port)
+	    + sizeof(isakmp_cfg_config.pool_size)
+	    + sysdep_sa_len(raddr) 
+	    + strlen(usr) + 1
+	    + strlen(pwd) + 1;
+
+	if ((msg = racoon_malloc(len)) == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL, 
+		    "Cannot allocate memory: %s\n", strerror(errno));
+		return -1;
+	}
+	bzero(msg, len);
+	msg->hdr.ac_cmd = PRIVSEP_XAUTH_LOGIN_PAM;
+	msg->hdr.ac_len = len;
+	msg->bufs.buflen[0] = sizeof(port);
+	msg->bufs.buflen[1] = sizeof(isakmp_cfg_config.pool_size);
+	msg->bufs.buflen[2] = sysdep_sa_len(raddr);
+	msg->bufs.buflen[3] = strlen(usr) + 1;
+	msg->bufs.buflen[4] = strlen(pwd) + 1;
+
+	data = (char *)(msg + 1);
+	memcpy(data, &port, msg->bufs.buflen[0]);
+
+	data += msg->bufs.buflen[0];
+	memcpy(data, &isakmp_cfg_config.pool_size, msg->bufs.buflen[1]);
+
+	data += msg->bufs.buflen[1];
+	memcpy(data, raddr, msg->bufs.buflen[2]);
+
+	data += msg->bufs.buflen[2];
+	memcpy(data, usr, msg->bufs.buflen[3]);
+
+	data += msg->bufs.buflen[3];
+	memcpy(data, pwd, msg->bufs.buflen[4]);
+
+	if (privsep_send(privsep_sock[1], msg, len) != 0)
+		return -1;
+
+	if (privsep_recv(privsep_sock[1], &msg, &len) != 0)
+		return -1;
+
+	if (msg->hdr.ac_errno != 0) {
+		errno = msg->hdr.ac_errno;
+		goto out;
+	}
+
+	racoon_free(msg);
+	return 0;
+
+out:
+	racoon_free(msg);
+	return -1;
+}
+
+void
+privsep_cleanup_pam(port)
+	int port;
+{
+	struct privsep_com_msg *msg;
+	size_t len;
+	char *data;
+	int result;
+
+	if (geteuid() == 0)
+		return cleanup_pam(port);
+
+	len = sizeof(*msg) 
+	    + sizeof(port)
+	    + sizeof(isakmp_cfg_config.pool_size);
+
+	if ((msg = racoon_malloc(len)) == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL, 
+		    "Cannot allocate memory: %s\n", strerror(errno));
+		return;
+	}
+	bzero(msg, len);
+	msg->hdr.ac_cmd = PRIVSEP_CLEANUP_PAM;
+	msg->hdr.ac_len = len;
+	msg->bufs.buflen[0] = sizeof(port);
+	msg->bufs.buflen[1] = sizeof(isakmp_cfg_config.pool_size);
+
+	data = (char *)(msg + 1);
+	memcpy(data, &port, msg->bufs.buflen[0]);
+
+	data += msg->bufs.buflen[0];
+	memcpy(data, &isakmp_cfg_config.pool_size, msg->bufs.buflen[1]);
+
+	if (privsep_send(privsep_sock[1], msg, len) != 0)
+		return;
+
+	if (privsep_recv(privsep_sock[1], &msg, &len) != 0)
+		return;
+
+	if (msg->hdr.ac_errno != 0)
+		errno = msg->hdr.ac_errno;
+
+	racoon_free(msg);
+	return;
+}
+#endif
diff --git a/src/racoon/privsep.h b/src/racoon/privsep.h
new file mode 100644
index 0000000..0fa4363
--- /dev/null
+++ b/src/racoon/privsep.h
@@ -0,0 +1,72 @@
+/*	$NetBSD: privsep.h,v 1.4 2006/09/09 16:22:10 manu Exp $	*/
+
+/* Id: privsep.h,v 1.5 2005/06/07 12:22:11 fredsen Exp */
+
+/*
+ * Copyright (C) 2004 Emmanuel Dreyfus
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _PRIVSEP_H
+#define _PRIVSEP_H
+
+#define PRIVSEP_EAY_GET_PKCS1PRIVKEY	0x0801	/* admin_com_bufs follows */
+#define PRIVSEP_SCRIPT_EXEC		0x0803	/* admin_com_bufs follows */
+#define PRIVSEP_GETPSK			0x0804	/* admin_com_bufs follows */
+#define PRIVSEP_XAUTH_LOGIN_SYSTEM	0x0805	/* admin_com_bufs follows */
+#define PRIVSEP_ACCOUNTING_PAM		0x0806	/* admin_com_bufs follows */
+#define PRIVSEP_XAUTH_LOGIN_PAM		0x0807	/* admin_com_bufs follows */
+#define PRIVSEP_CLEANUP_PAM		0x0808	/* admin_com_bufs follows */
+#define PRIVSEP_ACCOUNTING_SYSTEM	0x0809	/* admin_com_bufs follows */
+
+#define PRIVSEP_NBUF_MAX 24
+#define PRIVSEP_BUFLEN_MAX 4096
+struct admin_com_bufs {
+	size_t buflen[PRIVSEP_NBUF_MAX];
+	/* Followed by the buffers */
+};
+
+struct privsep_com_msg {
+	struct admin_com hdr;
+	struct admin_com_bufs bufs;
+};
+
+int privsep_init __P((void));
+
+vchar_t *privsep_eay_get_pkcs1privkey __P((char *));
+int privsep_pfkey_open __P((void));
+void privsep_pfkey_close __P((int));
+int privsep_script_exec __P((char *, int, char * const *));
+vchar_t *privsep_getpsk __P((const char *, const int));
+int privsep_xauth_login_system __P((char *, char *));
+#ifdef HAVE_LIBPAM
+int privsep_accounting_pam __P((int, int));
+int privsep_xauth_login_pam __P((int, struct sockaddr *, char *, char *));
+void privsep_cleanup_pam __P((int));
+#endif
+int privsep_accounting_system __P((int, struct sockaddr *, char *, int));
+#endif /* _PRIVSEP_H */
diff --git a/src/racoon/proposal.c b/src/racoon/proposal.c
new file mode 100644
index 0000000..26c9274
--- /dev/null
+++ b/src/racoon/proposal.c
@@ -0,0 +1,1294 @@
+/*	$NetBSD: proposal.c,v 1.13.4.2 2008/07/22 13:25:42 vanhu Exp $	*/
+
+/* $Id: proposal.c,v 1.13.4.2 2008/07/22 13:25:42 vanhu Exp $ */
+
+/*
+ * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/queue.h>
+
+#include <netinet/in.h>
+#include PATH_IPSEC_H
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+
+#include "var.h"
+#include "misc.h"
+#include "vmbuf.h"
+#include "plog.h"
+#include "sockmisc.h"
+#include "debug.h"
+
+#include "policy.h"
+#include "pfkey.h"
+#include "isakmp_var.h"
+#include "isakmp.h"
+#include "ipsec_doi.h"
+#include "algorithm.h"
+#include "proposal.h"
+#include "sainfo.h"
+#include "localconf.h"
+#include "remoteconf.h"
+#include "oakley.h"
+#include "handler.h"
+#include "strnames.h"
+#include "gcmalloc.h"
+#ifdef ENABLE_NATT
+#include "nattraversal.h"
+#endif
+
+static uint g_nextreqid = 1;
+
+/* %%%
+ * modules for ipsec sa spec
+ */
+struct saprop *
+newsaprop()
+{
+	struct saprop *new;
+
+	new = racoon_calloc(1, sizeof(*new));
+	if (new == NULL)
+		return NULL;
+
+	return new;
+}
+
+struct saproto *
+newsaproto()
+{
+	struct saproto *new;
+
+	new = racoon_calloc(1, sizeof(*new));
+	if (new == NULL)
+		return NULL;
+
+	return new;
+}
+
+/* set saprop to last part of the prop tree */
+void
+inssaprop(head, new)
+	struct saprop **head;
+	struct saprop *new;
+{
+	struct saprop *p;
+
+	if (*head == NULL) {
+		*head = new;
+		return;
+	}
+
+	for (p = *head; p->next; p = p->next)
+		;
+	p->next = new;
+
+	return;
+}
+
+/* set saproto to the end of the proto tree in saprop */
+void
+inssaproto(pp, new)
+	struct saprop *pp;
+	struct saproto *new;
+{
+	struct saproto *p;
+
+	for (p = pp->head; p && p->next; p = p->next)
+		;
+	if (p == NULL)
+		pp->head = new;
+	else
+		p->next = new;
+
+	return;
+}
+
+/* set saproto to the top of the proto tree in saprop */
+void
+inssaprotorev(pp, new)
+      struct saprop *pp;
+      struct saproto *new;
+{
+      new->next = pp->head;
+      pp->head = new;
+
+      return;
+}
+
+struct satrns *
+newsatrns()
+{
+	struct satrns *new;
+
+	new = racoon_calloc(1, sizeof(*new));
+	if (new == NULL)
+		return NULL;
+
+	return new;
+}
+
+/* set saproto to last part of the proto tree in saprop */
+void
+inssatrns(pr, new)
+	struct saproto *pr;
+	struct satrns *new;
+{
+	struct satrns *tr;
+
+	for (tr = pr->head; tr && tr->next; tr = tr->next)
+		;
+	if (tr == NULL)
+		pr->head = new;
+	else
+		tr->next = new;
+
+	return;
+}
+
+/*
+ * take a single match between saprop.  allocate a new proposal and return it
+ * for future use (like picking single proposal from a bundle).
+ *	pp1: peer's proposal.
+ *	pp2: my proposal.
+ * NOTE: In the case of initiator, must be ensured that there is no
+ * modification of the proposal by calling cmp_aproppair_i() before
+ * this function.
+ * XXX cannot understand the comment!
+ */
+struct saprop *
+cmpsaprop_alloc(ph1, pp1, pp2, side)
+	struct ph1handle *ph1;
+	const struct saprop *pp1, *pp2;
+	int side;
+{
+	struct saprop *newpp = NULL;
+	struct saproto *pr1, *pr2, *newpr = NULL;
+	struct satrns *tr1, *tr2, *newtr;
+	const int ordermatters = 0;
+	int npr1, npr2;
+	int spisizematch;
+
+	newpp = newsaprop();
+	if (newpp == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"failed to allocate saprop.\n");
+		return NULL;
+	}
+	newpp->prop_no = pp1->prop_no;
+
+	/* see proposal.h about lifetime/key length and PFS selection. */
+
+	/* check time/bytes lifetime and PFS */
+	switch (ph1->rmconf->pcheck_level) {
+	case PROP_CHECK_OBEY:
+		newpp->lifetime = pp1->lifetime;
+		newpp->lifebyte = pp1->lifebyte;
+		newpp->pfs_group = pp1->pfs_group;
+		break;
+
+	case PROP_CHECK_STRICT:
+		if (pp1->lifetime > pp2->lifetime) {
+			plog(LLV_ERROR, LOCATION, NULL,
+				"long lifetime proposed: "
+				"my:%d peer:%d\n",
+				(int)pp2->lifetime, (int)pp1->lifetime);
+			goto err;
+		}
+		if (pp1->lifebyte > pp2->lifebyte) {
+			plog(LLV_ERROR, LOCATION, NULL,
+				"long lifebyte proposed: "
+				"my:%d peer:%d\n",
+				pp2->lifebyte, pp1->lifebyte);
+			goto err;
+		}
+		newpp->lifetime = pp1->lifetime;
+		newpp->lifebyte = pp1->lifebyte;
+
+    prop_pfs_check:
+		if (pp2->pfs_group != 0 && pp1->pfs_group != pp2->pfs_group) {
+			plog(LLV_ERROR, LOCATION, NULL,
+				"pfs group mismatched: "
+				"my:%d peer:%d\n",
+				pp2->pfs_group, pp1->pfs_group);
+			goto err;
+		}
+		newpp->pfs_group = pp1->pfs_group;
+		break;
+
+	case PROP_CHECK_CLAIM:
+		/* lifetime */
+		if (pp1->lifetime <= pp2->lifetime) {
+			newpp->lifetime = pp1->lifetime;
+		} else {
+			newpp->lifetime = pp2->lifetime;
+			newpp->claim |= IPSECDOI_ATTR_SA_LD_TYPE_SEC;
+			plog(LLV_NOTIFY, LOCATION, NULL,
+				"use own lifetime: "
+				"my:%d peer:%d\n",
+				(int)pp2->lifetime, (int)pp1->lifetime);
+		}
+
+		/* lifebyte */
+		if (pp1->lifebyte > pp2->lifebyte) {
+			newpp->lifebyte = pp2->lifebyte;
+			newpp->claim |= IPSECDOI_ATTR_SA_LD_TYPE_SEC;
+			plog(LLV_NOTIFY, LOCATION, NULL,
+				"use own lifebyte: "
+				"my:%d peer:%d\n",
+				pp2->lifebyte, pp1->lifebyte);
+		}
+		newpp->lifebyte = pp1->lifebyte;
+
+    		goto prop_pfs_check;
+		break;
+
+	case PROP_CHECK_EXACT:
+		if (pp1->lifetime != pp2->lifetime) {
+			plog(LLV_ERROR, LOCATION, NULL,
+				"lifetime mismatched: "
+				"my:%d peer:%d\n",
+				(int)pp2->lifetime, (int)pp1->lifetime);
+			goto err;
+		}
+
+		if (pp1->lifebyte != pp2->lifebyte) {
+			plog(LLV_ERROR, LOCATION, NULL,
+				"lifebyte mismatched: "
+				"my:%d peer:%d\n",
+				pp2->lifebyte, pp1->lifebyte);
+			goto err;
+		}
+		if (pp1->pfs_group != pp2->pfs_group) {
+			plog(LLV_ERROR, LOCATION, NULL,
+				"pfs group mismatched: "
+				"my:%d peer:%d\n",
+				pp2->pfs_group, pp1->pfs_group);
+			goto err;
+		}
+		newpp->lifetime = pp1->lifetime;
+		newpp->lifebyte = pp1->lifebyte;
+		newpp->pfs_group = pp1->pfs_group;
+		break;
+
+	default:
+		plog(LLV_ERROR, LOCATION, NULL,
+			"invalid pcheck_level why?.\n");
+		goto err;
+	}
+
+#ifdef HAVE_SECCTX
+	/* check the security_context properties.
+	 * It is possible for one side to have a security context
+	 * and the other side doesn't. If so, this is an error.
+	 */
+
+	if (*pp1->sctx.ctx_str && !(*pp2->sctx.ctx_str)) {
+		plog(LLV_ERROR, LOCATION, NULL,
+		     "My proposal missing security context\n");
+		goto err;
+	}
+	if (!(*pp1->sctx.ctx_str) && *pp2->sctx.ctx_str) {
+		plog(LLV_ERROR, LOCATION, NULL, 
+		     "Peer is missing security context\n");
+		goto err;
+	}
+
+	if (*pp1->sctx.ctx_str && *pp2->sctx.ctx_str) {
+		if (pp1->sctx.ctx_doi == pp2->sctx.ctx_doi)
+			newpp->sctx.ctx_doi = pp1->sctx.ctx_doi;
+		else {
+			plog(LLV_ERROR, LOCATION, NULL, 
+			     "sec doi mismatched: my:%d peer:%d\n",
+			     pp2->sctx.ctx_doi, pp1->sctx.ctx_doi);
+			     goto err;
+		}
+
+		if (pp1->sctx.ctx_alg == pp2->sctx.ctx_alg)
+			newpp->sctx.ctx_alg = pp1->sctx.ctx_alg;
+		else {
+			plog(LLV_ERROR, LOCATION, NULL,
+			     "sec alg mismatched: my:%d peer:%d\n",
+			     pp2->sctx.ctx_alg, pp1->sctx.ctx_alg);
+			goto err;
+		}
+
+		if ((pp1->sctx.ctx_strlen != pp2->sctx.ctx_strlen) ||
+		     memcmp(pp1->sctx.ctx_str, pp2->sctx.ctx_str,
+		     pp1->sctx.ctx_strlen) != 0) {
+			plog(LLV_ERROR, LOCATION, NULL,
+			     "sec ctx string mismatched: my:%s peer:%s\n",
+			     pp2->sctx.ctx_str, pp1->sctx.ctx_str);
+				goto err;
+		} else {
+			newpp->sctx.ctx_strlen = pp1->sctx.ctx_strlen;
+			memcpy(newpp->sctx.ctx_str, pp1->sctx.ctx_str,
+				pp1->sctx.ctx_strlen);
+		}
+	}
+#endif /* HAVE_SECCTX */
+
+	npr1 = npr2 = 0;
+	for (pr1 = pp1->head; pr1; pr1 = pr1->next)
+		npr1++;
+	for (pr2 = pp2->head; pr2; pr2 = pr2->next)
+		npr2++;
+	if (npr1 != npr2)
+		goto err;
+
+	/* check protocol order */
+	pr1 = pp1->head;
+	pr2 = pp2->head;
+
+	while (1) {
+		if (!ordermatters) {
+			/*
+			 * XXX does not work if we have multiple proposals
+			 * with the same proto_id
+			 */
+			switch (side) {
+			case RESPONDER:
+				if (!pr2)
+					break;
+				for (pr1 = pp1->head; pr1; pr1 = pr1->next) {
+					if (pr1->proto_id == pr2->proto_id)
+						break;
+				}
+				break;
+			case INITIATOR:
+				if (!pr1)
+					break;
+				for (pr2 = pp2->head; pr2; pr2 = pr2->next) {
+					if (pr2->proto_id == pr1->proto_id)
+						break;
+				}
+				break;
+			}
+		}
+		if (!pr1 || !pr2)
+			break;
+
+		if (pr1->proto_id != pr2->proto_id) {
+			plog(LLV_ERROR, LOCATION, NULL,
+				"proto_id mismatched: "
+				"my:%s peer:%s\n",
+				s_ipsecdoi_proto(pr2->proto_id),
+				s_ipsecdoi_proto(pr1->proto_id));
+			goto err;
+		}
+		spisizematch = 0;
+		if (pr1->spisize == pr2->spisize)
+			spisizematch = 1;
+		else if (pr1->proto_id == IPSECDOI_PROTO_IPCOMP) {
+			/*
+			 * draft-shacham-ippcp-rfc2393bis-05.txt:
+			 * need to accept 16bit and 32bit SPI (CPI) for IPComp.
+			 */
+			if (pr1->spisize == sizeof(u_int16_t) &&
+			    pr2->spisize == sizeof(u_int32_t)) {
+				spisizematch = 1;
+			} else if (pr2->spisize == sizeof(u_int16_t) &&
+				 pr1->spisize == sizeof(u_int32_t)) {
+				spisizematch = 1;
+			}
+			if (spisizematch) {
+				plog(LLV_ERROR, LOCATION, NULL,
+				    "IPComp SPI size promoted "
+				    "from 16bit to 32bit\n");
+			}
+		}
+		if (!spisizematch) {
+			plog(LLV_ERROR, LOCATION, NULL,
+				"spisize mismatched: "
+				"my:%d peer:%d\n",
+				(int)pr2->spisize, (int)pr1->spisize);
+			goto err;
+		}
+
+#ifdef ENABLE_NATT
+		if ((ph1->natt_flags & NAT_DETECTED) && 
+		    natt_udp_encap (pr2->encmode))
+		{
+			plog(LLV_INFO, LOCATION, NULL, "Adjusting my encmode %s->%s\n",
+			     s_ipsecdoi_encmode(pr2->encmode),
+			     s_ipsecdoi_encmode(pr2->encmode - ph1->natt_options->mode_udp_diff));
+			pr2->encmode -= ph1->natt_options->mode_udp_diff;
+			pr2->udp_encap = 1;
+		}
+
+		if ((ph1->natt_flags & NAT_DETECTED) &&
+		    natt_udp_encap (pr1->encmode))
+		{
+			plog(LLV_INFO, LOCATION, NULL, "Adjusting peer's encmode %s(%d)->%s(%d)\n",
+			     s_ipsecdoi_encmode(pr1->encmode),
+			     pr1->encmode,
+			     s_ipsecdoi_encmode(pr1->encmode - ph1->natt_options->mode_udp_diff),
+			     pr1->encmode - ph1->natt_options->mode_udp_diff);
+			pr1->encmode -= ph1->natt_options->mode_udp_diff;
+			pr1->udp_encap = 1;
+		}
+#endif
+
+		if (pr1->encmode != pr2->encmode) {
+			plog(LLV_ERROR, LOCATION, NULL,
+				"encmode mismatched: "
+				"my:%s peer:%s\n",
+				s_ipsecdoi_encmode(pr2->encmode),
+				s_ipsecdoi_encmode(pr1->encmode));
+			goto err;
+		}
+
+		for (tr1 = pr1->head; tr1; tr1 = tr1->next) {
+			for (tr2 = pr2->head; tr2; tr2 = tr2->next) {
+				if (cmpsatrns(pr1->proto_id, tr1, tr2, ph1->rmconf->pcheck_level) == 0)
+					goto found;
+			}
+		}
+
+		goto err;
+
+	    found:
+		newpr = newsaproto();
+		if (newpr == NULL) {
+			plog(LLV_ERROR, LOCATION, NULL,
+				"failed to allocate saproto.\n");
+			goto err;
+		}
+		newpr->proto_id = pr1->proto_id;
+		newpr->spisize = pr1->spisize;
+		newpr->encmode = pr1->encmode;
+		newpr->spi = pr2->spi;		/* copy my SPI */
+		newpr->spi_p = pr1->spi;	/* copy peer's SPI */
+		newpr->reqid_in = pr2->reqid_in;
+		newpr->reqid_out = pr2->reqid_out;
+#ifdef ENABLE_NATT
+		newpr->udp_encap = pr1->udp_encap | pr2->udp_encap;
+#endif
+
+		newtr = newsatrns();
+		if (newtr == NULL) {
+			plog(LLV_ERROR, LOCATION, NULL,
+				"failed to allocate satrns.\n");
+			racoon_free(newpr);
+			goto err;
+		}
+		newtr->trns_no = tr1->trns_no;
+		newtr->trns_id = tr1->trns_id;
+		newtr->encklen = tr1->encklen;
+		newtr->authtype = tr1->authtype;
+
+		inssatrns(newpr, newtr);
+		inssaproto(newpp, newpr);
+
+		pr1 = pr1->next;
+		pr2 = pr2->next;
+	}
+
+	/* XXX should check if we have visited all items or not */
+	if (!ordermatters) {
+		switch (side) {
+		case RESPONDER:
+			if (!pr2)
+				pr1 = NULL;
+			break;
+		case INITIATOR:
+			if (!pr1)
+				pr2 = NULL;
+			break;
+		}
+	}
+
+	/* should be matched all protocols in a proposal */
+	if (pr1 != NULL || pr2 != NULL)
+		goto err;
+
+	return newpp;
+
+err:
+	flushsaprop(newpp);
+	return NULL;
+}
+
+/* take a single match between saprop.  returns 0 if pp1 equals to pp2. */
+int
+cmpsaprop(pp1, pp2)
+	const struct saprop *pp1, *pp2;
+{
+	if (pp1->pfs_group != pp2->pfs_group) {
+		plog(LLV_WARNING, LOCATION, NULL,
+			"pfs_group mismatch. mine:%d peer:%d\n",
+			pp1->pfs_group, pp2->pfs_group);
+		/* FALLTHRU */
+	}
+
+	if (pp1->lifetime > pp2->lifetime) {
+		plog(LLV_WARNING, LOCATION, NULL,
+			"less lifetime proposed. mine:%d peer:%d\n",
+			(int)pp1->lifetime, (int)pp2->lifetime);
+		/* FALLTHRU */
+	}
+	if (pp1->lifebyte > pp2->lifebyte) {
+		plog(LLV_WARNING, LOCATION, NULL,
+			"less lifebyte proposed. mine:%d peer:%d\n",
+			pp1->lifebyte, pp2->lifebyte);
+		/* FALLTHRU */
+	}
+
+	return 0;
+}
+
+/*
+ * take a single match between satrns.  returns 0 if tr1 equals to tr2.
+ * tr1: peer's satrns
+ * tr2: my satrns
+ */
+int
+cmpsatrns(proto_id, tr1, tr2, check_level)
+	int proto_id;
+	const struct satrns *tr1, *tr2;
+	int check_level;
+{
+	if (tr1->trns_id != tr2->trns_id) {
+		plog(LLV_WARNING, LOCATION, NULL,
+			"trns_id mismatched: "
+			"my:%s peer:%s\n",
+			s_ipsecdoi_trns(proto_id, tr2->trns_id),
+			s_ipsecdoi_trns(proto_id, tr1->trns_id));
+		return 1;
+	}
+
+	if (tr1->authtype != tr2->authtype) {
+		plog(LLV_WARNING, LOCATION, NULL,
+			"authtype mismatched: "
+			"my:%s peer:%s\n",
+			s_ipsecdoi_attr_v(IPSECDOI_ATTR_AUTH, tr2->authtype),
+			s_ipsecdoi_attr_v(IPSECDOI_ATTR_AUTH, tr1->authtype));
+		return 1;
+	}
+
+	/* Check key length regarding checkmode
+	 * XXX Shall we send some kind of notify message when key length rejected ?
+	 */
+	switch(check_level){
+	case PROP_CHECK_OBEY:
+		return 0;
+		break;
+
+	case PROP_CHECK_STRICT:
+		/* FALLTHROUGH */
+	case PROP_CHECK_CLAIM:
+		if (tr1->encklen < tr2->encklen) {
+		plog(LLV_WARNING, LOCATION, NULL,
+				 "low key length proposed, "
+				 "mine:%d peer:%d.\n",
+			tr2->encklen, tr1->encklen);
+			return 1;
+		}
+		break;
+	case PROP_CHECK_EXACT:
+		if (tr1->encklen != tr2->encklen) {
+			plog(LLV_WARNING, LOCATION, NULL,
+				 "key length mismatched, "
+				 "mine:%d peer:%d.\n",
+				 tr2->encklen, tr1->encklen);
+			return 1;
+		}
+		break;
+	}
+
+	return 0;
+}
+
+int
+set_satrnsbysainfo(pr, sainfo)
+	struct saproto *pr;
+	struct sainfo *sainfo;
+{
+	struct sainfoalg *a, *b;
+	struct satrns *newtr;
+	int t;
+
+	switch (pr->proto_id) {
+	case IPSECDOI_PROTO_IPSEC_AH:
+		if (sainfo->algs[algclass_ipsec_auth] == NULL) {
+			plog(LLV_ERROR, LOCATION, NULL,
+				"no auth algorithm found\n");
+			goto err;
+		}
+		t = 1;
+		for (a = sainfo->algs[algclass_ipsec_auth]; a; a = a->next) {
+
+			if (a->alg == IPSECDOI_ATTR_AUTH_NONE)
+				continue;
+				
+			/* allocate satrns */
+			newtr = newsatrns();
+			if (newtr == NULL) {
+				plog(LLV_ERROR, LOCATION, NULL,
+					"failed to allocate satrns.\n");
+				goto err;
+			}
+
+			newtr->trns_no = t++;
+			newtr->trns_id = ipsecdoi_authalg2trnsid(a->alg);
+			newtr->authtype = a->alg;
+
+			inssatrns(pr, newtr);
+		}
+		break;
+	case IPSECDOI_PROTO_IPSEC_ESP:
+		if (sainfo->algs[algclass_ipsec_enc] == NULL) {
+			plog(LLV_ERROR, LOCATION, NULL,
+				"no encryption algorithm found\n");
+			goto err;
+		}
+		t = 1;
+		for (a = sainfo->algs[algclass_ipsec_enc]; a; a = a->next) {
+			for (b = sainfo->algs[algclass_ipsec_auth]; b; b = b->next) {
+				/* allocate satrns */
+				newtr = newsatrns();
+				if (newtr == NULL) {
+					plog(LLV_ERROR, LOCATION, NULL,
+						"failed to allocate satrns.\n");
+					goto err;
+				}
+
+				newtr->trns_no = t++;
+				newtr->trns_id = a->alg;
+				newtr->encklen = a->encklen;
+				newtr->authtype = b->alg;
+
+				inssatrns(pr, newtr);
+			}
+		}
+		break;
+	case IPSECDOI_PROTO_IPCOMP:
+		if (sainfo->algs[algclass_ipsec_comp] == NULL) {
+			plog(LLV_ERROR, LOCATION, NULL,
+				"no ipcomp algorithm found\n");
+			goto err;
+		}
+		t = 1;
+		for (a = sainfo->algs[algclass_ipsec_comp]; a; a = a->next) {
+
+			/* allocate satrns */
+			newtr = newsatrns();
+			if (newtr == NULL) {
+				plog(LLV_ERROR, LOCATION, NULL,
+					"failed to allocate satrns.\n");
+				goto err;
+			}
+
+			newtr->trns_no = t++;
+			newtr->trns_id = a->alg;
+			newtr->authtype = IPSECDOI_ATTR_AUTH_NONE; /*no auth*/
+
+			inssatrns(pr, newtr);
+		}
+		break;
+	default:
+		plog(LLV_ERROR, LOCATION, NULL,
+			"unknown proto_id (%d).\n", pr->proto_id);
+		goto err;
+	}
+
+	/* no proposal found */
+	if (pr->head == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL, "no algorithms found.\n");
+		return -1;
+	}
+
+	return 0;
+
+err:
+	flushsatrns(pr->head);
+	return -1;
+}
+
+struct saprop *
+aproppair2saprop(p0)
+	struct prop_pair *p0;
+{
+	struct prop_pair *p, *t;
+	struct saprop *newpp;
+	struct saproto *newpr;
+	struct satrns *newtr;
+	u_int8_t *spi;
+
+	if (p0 == NULL)
+		return NULL;
+
+	/* allocate ipsec a sa proposal */
+	newpp = newsaprop();
+	if (newpp == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"failed to allocate saprop.\n");
+		return NULL;
+	}
+	newpp->prop_no = p0->prop->p_no;
+	/* lifetime & lifebyte must be updated later */
+
+	for (p = p0; p; p = p->next) {
+
+		/* allocate ipsec sa protocol */
+		newpr = newsaproto();
+		if (newpr == NULL) {
+			plog(LLV_ERROR, LOCATION, NULL,
+				"failed to allocate saproto.\n");
+			goto err;
+		}
+
+		/* check spi size */
+		/* XXX should be handled isakmp cookie */
+		if (sizeof(newpr->spi) < p->prop->spi_size) {
+			plog(LLV_ERROR, LOCATION, NULL,
+				"invalid spi size %d.\n", p->prop->spi_size);
+			racoon_free(newpr);
+			goto err;
+		}
+
+		/*
+		 * XXX SPI bits are left-filled, for use with IPComp.
+		 * we should be switching to variable-length spi field...
+		 */
+		newpr->proto_id = p->prop->proto_id;
+		newpr->spisize = p->prop->spi_size;
+		memset(&newpr->spi, 0, sizeof(newpr->spi));
+		spi = (u_int8_t *)&newpr->spi;
+		spi += sizeof(newpr->spi);
+		spi -= p->prop->spi_size;
+		memcpy(spi, p->prop + 1, p->prop->spi_size);
+		newpr->reqid_in = 0;
+		newpr->reqid_out = 0;
+
+		for (t = p; t; t = t->tnext) {
+
+			plog(LLV_DEBUG, LOCATION, NULL,
+				"prop#=%d prot-id=%s spi-size=%d "
+				"#trns=%d trns#=%d trns-id=%s\n",
+				t->prop->p_no,
+				s_ipsecdoi_proto(t->prop->proto_id),
+				t->prop->spi_size, t->prop->num_t,
+				t->trns->t_no,
+				s_ipsecdoi_trns(t->prop->proto_id,
+				t->trns->t_id));
+
+			/* allocate ipsec sa transform */
+			newtr = newsatrns();
+			if (newtr == NULL) {
+				plog(LLV_ERROR, LOCATION, NULL,
+					"failed to allocate satrns.\n");
+				racoon_free(newpr);
+				goto err;
+			}
+
+			if (ipsecdoi_t2satrns(t->trns, 
+			    newpp, newpr, newtr) < 0) {
+				flushsaprop(newpp);
+				racoon_free(newtr);
+				racoon_free(newpr);
+				return NULL;
+			}
+
+			inssatrns(newpr, newtr);
+		}
+
+		/*
+		 * If the peer does not specify encryption mode, use 
+		 * transport mode by default.  This is to conform to
+		 * draft-shacham-ippcp-rfc2393bis-08.txt (explicitly specifies
+		 * that unspecified == transport), as well as RFC2407
+		 * (unspecified == implementation dependent default).
+		 */
+		if (newpr->encmode == 0)
+			newpr->encmode = IPSECDOI_ATTR_ENC_MODE_TRNS;
+
+		inssaproto(newpp, newpr);
+	}
+
+	return newpp;
+
+err:
+	flushsaprop(newpp);
+	return NULL;
+}
+
+void
+flushsaprop(head)
+	struct saprop *head;
+{
+	struct saprop *p, *save;
+
+	for (p = head; p != NULL; p = save) {
+		save = p->next;
+		flushsaproto(p->head);
+		racoon_free(p);
+	}
+
+	return;
+}
+
+void
+flushsaproto(head)
+	struct saproto *head;
+{
+	struct saproto *p, *save;
+
+	for (p = head; p != NULL; p = save) {
+		save = p->next;
+		flushsatrns(p->head);
+		vfree(p->keymat);
+		vfree(p->keymat_p);
+		racoon_free(p);
+	}
+
+	return;
+}
+
+void
+flushsatrns(head)
+	struct satrns *head;
+{
+	struct satrns *p, *save;
+
+	for (p = head; p != NULL; p = save) {
+		save = p->next;
+		racoon_free(p);
+	}
+
+	return;
+}
+
+/*
+ * print multiple proposals
+ */
+void
+printsaprop(pri, pp)
+	const int pri;
+	const struct saprop *pp;
+{
+	const struct saprop *p;
+
+	if (pp == NULL) {
+		plog(pri, LOCATION, NULL, "(null)");
+		return;
+	}
+
+	for (p = pp; p; p = p->next) {
+		printsaprop0(pri, p);
+	}
+
+	return;
+}
+
+/*
+ * print one proposal.
+ */
+void
+printsaprop0(pri, pp)
+	int pri;
+	const struct saprop *pp;
+{
+	const struct saproto *p;
+
+	if (pp == NULL)
+		return;
+
+	for (p = pp->head; p; p = p->next) {
+		printsaproto(pri, p);
+	}
+
+	return;
+}
+
+void
+printsaproto(pri, pr)
+	const int pri;
+	const struct saproto *pr;
+{
+	struct satrns *tr;
+
+	if (pr == NULL)
+		return;
+
+	plog(pri, LOCATION, NULL,
+		" (proto_id=%s spisize=%d spi=%08lx spi_p=%08lx "
+		"encmode=%s reqid=%d:%d)\n",
+		s_ipsecdoi_proto(pr->proto_id),
+		(int)pr->spisize,
+		(unsigned long)ntohl(pr->spi),
+		(unsigned long)ntohl(pr->spi_p),
+		s_ipsecdoi_attr_v(IPSECDOI_ATTR_ENC_MODE, pr->encmode),
+		(int)pr->reqid_in, (int)pr->reqid_out);
+
+	for (tr = pr->head; tr; tr = tr->next) {
+		printsatrns(pri, pr->proto_id, tr);
+	}
+
+	return;
+}
+
+void
+printsatrns(pri, proto_id, tr)
+	const int pri;
+	const int proto_id;
+	const struct satrns *tr;
+{
+	if (tr == NULL)
+		return;
+
+	switch (proto_id) {
+	case IPSECDOI_PROTO_IPSEC_AH:
+		plog(pri, LOCATION, NULL,
+			"  (trns_id=%s authtype=%s)\n",
+			s_ipsecdoi_trns(proto_id, tr->trns_id),
+			s_ipsecdoi_attr_v(IPSECDOI_ATTR_AUTH, tr->authtype));
+		break;
+	case IPSECDOI_PROTO_IPSEC_ESP:
+		plog(pri, LOCATION, NULL,
+			"  (trns_id=%s encklen=%d authtype=%s)\n",
+			s_ipsecdoi_trns(proto_id, tr->trns_id),
+			tr->encklen,
+			s_ipsecdoi_attr_v(IPSECDOI_ATTR_AUTH, tr->authtype));
+		break;
+	case IPSECDOI_PROTO_IPCOMP:
+		plog(pri, LOCATION, NULL,
+			"  (trns_id=%s)\n",
+			s_ipsecdoi_trns(proto_id, tr->trns_id));
+		break;
+	default:
+		plog(pri, LOCATION, NULL,
+			"(unknown proto_id %d)\n", proto_id);
+	}
+
+	return;
+}
+
+void
+print_proppair0(pri, p, level)
+	int pri; 
+	struct prop_pair *p;
+	int level;
+{
+	char spc[21];
+
+	memset(spc, ' ', sizeof(spc));
+	spc[sizeof(spc) - 1] = '\0';
+	if (level < 20) {
+		spc[level] = '\0';
+	}
+
+	plog(pri, LOCATION, NULL,
+		"%s%p: next=%p tnext=%p\n", spc, p, p->next, p->tnext);
+	if (p->next)
+		print_proppair0(pri, p->next, level + 1);
+	if (p->tnext)
+		print_proppair0(pri, p->tnext, level + 1);
+}
+
+void
+print_proppair(pri, p)
+	int pri;
+	struct prop_pair *p;
+{
+	print_proppair0(pri, p, 1);
+}
+
+int
+set_proposal_from_policy(iph2, sp_main, sp_sub)
+	struct ph2handle *iph2;
+	struct secpolicy *sp_main, *sp_sub;
+{
+	struct saprop *newpp;
+	struct ipsecrequest *req;
+	int encmodesv = IPSECDOI_ATTR_ENC_MODE_TRNS; /* use only when complex_bundle */
+
+	newpp = newsaprop();
+	if (newpp == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"failed to allocate saprop.\n");
+		goto err;
+	}
+	newpp->prop_no = 1;
+	newpp->lifetime = iph2->sainfo->lifetime;
+	newpp->lifebyte = iph2->sainfo->lifebyte;
+	newpp->pfs_group = iph2->sainfo->pfs_group;
+
+	if (lcconf->complex_bundle)
+		goto skip1;
+
+	/*
+	 * decide the encryption mode of this SA bundle.
+	 * the mode becomes tunnel mode when there is even one policy
+	 * of tunnel mode in the SPD.  otherwise the mode becomes
+	 * transport mode.
+	 */
+	for (req = sp_main->req; req; req = req->next) {
+		if (req->saidx.mode == IPSEC_MODE_TUNNEL) {
+			encmodesv = pfkey2ipsecdoi_mode(req->saidx.mode);
+#ifdef ENABLE_NATT
+			if (iph2->ph1 && (iph2->ph1->natt_flags & NAT_DETECTED))
+				encmodesv += iph2->ph1->natt_options->mode_udp_diff;
+#endif
+			break;
+		}
+	}
+
+    skip1:
+	for (req = sp_main->req; req; req = req->next) {
+		struct saproto *newpr;
+		caddr_t paddr = NULL;
+
+		/*
+		 * check if SA bundle ?
+		 * nested SAs negotiation is NOT supported.
+		 *       me +--- SA1 ---+ peer1
+		 *       me +--- SA2 --------------+ peer2
+		 */
+#ifdef __linux__
+		if (req->saidx.src.ss_family && req->saidx.dst.ss_family) {
+#else
+		if (req->saidx.src.ss_len && req->saidx.dst.ss_len) {
+#endif
+			/* check the end of ip addresses of SA */
+			if (iph2->side == INITIATOR)
+				paddr = (caddr_t)&req->saidx.dst;
+			else
+				paddr = (caddr_t)&req->saidx.src;
+		}
+
+		/* allocate ipsec sa protocol */
+		newpr = newsaproto();
+		if (newpr == NULL) {
+			plog(LLV_ERROR, LOCATION, NULL,
+				"failed to allocate saproto.\n");
+			goto err;
+		}
+
+		newpr->proto_id = ipproto2doi(req->saidx.proto);
+		if (newpr->proto_id == IPSECDOI_PROTO_IPCOMP)
+			newpr->spisize = 2;
+		else
+			newpr->spisize = 4;
+		if (lcconf->complex_bundle) {
+			newpr->encmode = pfkey2ipsecdoi_mode(req->saidx.mode);
+#ifdef ENABLE_NATT
+			if (iph2->ph1 && (iph2->ph1->natt_flags & NAT_DETECTED))
+				newpr->encmode += 
+				    iph2->ph1->natt_options->mode_udp_diff;
+#endif
+		}
+		else
+			newpr->encmode = encmodesv;
+
+		if (iph2->side == INITIATOR)
+			newpr->reqid_out = req->saidx.reqid;
+		else
+			newpr->reqid_in = req->saidx.reqid;
+
+		if (set_satrnsbysainfo(newpr, iph2->sainfo) < 0) {
+			plog(LLV_ERROR, LOCATION, NULL,
+				"failed to get algorithms.\n");
+			racoon_free(newpr);
+			goto err;
+		}
+
+		/* set new saproto */
+		inssaprotorev(newpp, newpr);
+	}
+
+	/* get reqid_in from inbound policy */
+	if (sp_sub) {
+		struct saproto *pr;
+
+		req = sp_sub->req;
+		pr = newpp->head;
+		while (req && pr) {
+			if (iph2->side == INITIATOR)
+				pr->reqid_in = req->saidx.reqid;
+			else
+				pr->reqid_out = req->saidx.reqid;
+			pr = pr->next;
+			req = req->next;
+		}
+		if (pr || req) {
+			plog(LLV_NOTIFY, LOCATION, NULL,
+				"There is a difference "
+				"between the in/out bound policies in SPD.\n");
+		}
+	}
+
+	iph2->proposal = newpp;
+
+	printsaprop0(LLV_DEBUG, newpp);
+
+	return 0;
+err:
+	flushsaprop(newpp);
+	return -1;
+}
+
+/*
+ * generate a policy from peer's proposal.
+ * this function unconditionally choices first proposal in SA payload
+ * passed by peer.
+ */
+int
+set_proposal_from_proposal(iph2)
+	struct ph2handle *iph2;
+{
+        struct saprop *newpp = NULL, *pp0, *pp_peer = NULL;
+	struct saproto *newpr = NULL, *pr;
+	struct prop_pair **pair;
+	int error = -1;
+	int i;
+
+	/* get proposal pair */
+	pair = get_proppair(iph2->sa, IPSECDOI_TYPE_PH2);
+	if (pair == NULL)
+		goto end;
+
+	/*
+	 * make my proposal according as the client proposal.
+	 * XXX assumed there is only one proposal even if it's the SA bundle.
+	 */
+        for (i = 0; i < MAXPROPPAIRLEN; i++) {
+                if (pair[i] == NULL)
+                        continue;
+
+		if (pp_peer != NULL)
+			flushsaprop(pp_peer);
+
+		pp_peer = aproppair2saprop(pair[i]);
+		if (pp_peer == NULL)
+			goto end;
+
+		pp0 = newsaprop();
+		if (pp0 == NULL) {
+			plog(LLV_ERROR, LOCATION, NULL,
+				"failed to allocate saprop.\n");
+			goto end;
+		}
+		pp0->prop_no = 1;
+		pp0->lifetime = iph2->sainfo->lifetime;
+		pp0->lifebyte = iph2->sainfo->lifebyte;
+		pp0->pfs_group = iph2->sainfo->pfs_group;
+
+#ifdef HAVE_SECCTX
+		if (*pp_peer->sctx.ctx_str) {
+			pp0->sctx.ctx_doi = pp_peer->sctx.ctx_doi;
+			pp0->sctx.ctx_alg = pp_peer->sctx.ctx_alg;
+			pp0->sctx.ctx_strlen = pp_peer->sctx.ctx_strlen;
+			memcpy(pp0->sctx.ctx_str, pp_peer->sctx.ctx_str,
+			       pp_peer->sctx.ctx_strlen);
+		}
+#endif /* HAVE_SECCTX */
+
+		if (pp_peer->next != NULL) {
+			plog(LLV_ERROR, LOCATION, NULL,
+				"pp_peer is inconsistency, ignore it.\n");
+			/*FALLTHROUGH*/
+		}
+
+		for (pr = pp_peer->head; pr; pr = pr->next)
+		{
+			struct remoteconf *conf;
+
+			newpr = newsaproto();
+			if (newpr == NULL)
+			{
+				plog(LLV_ERROR, LOCATION, NULL,
+					"failed to allocate saproto.\n");
+				racoon_free(pp0);
+				goto end;
+			}
+			newpr->proto_id = pr->proto_id;
+			newpr->spisize = pr->spisize;
+			newpr->encmode = pr->encmode;
+			newpr->spi = 0;
+			newpr->spi_p = pr->spi;     /* copy peer's SPI */
+			newpr->reqid_in = 0;
+			newpr->reqid_out = 0;
+
+			conf = getrmconf(iph2->dst);
+			if (conf != NULL &&
+				conf->gen_policy == GENERATE_POLICY_UNIQUE){
+				newpr->reqid_in = g_nextreqid ;
+				newpr->reqid_out = g_nextreqid ++;
+				/* 
+				 * XXX there is a (very limited) 
+				 * risk of reusing the same reqid
+				 * as another SP entry for the same peer
+				 */
+				if(g_nextreqid >= IPSEC_MANUAL_REQID_MAX)
+					g_nextreqid = 1;
+			}else{
+				newpr->reqid_in = 0;
+				newpr->reqid_out = 0;
+			}
+ 
+			if (set_satrnsbysainfo(newpr, iph2->sainfo) < 0)
+			{
+				plog(LLV_ERROR, LOCATION, NULL,
+					"failed to get algorithms.\n");
+				racoon_free(newpr);
+				racoon_free(pp0);
+				goto end;
+			}
+			inssaproto(pp0, newpr);
+		}
+
+		inssaprop(&newpp, pp0);
+        }
+
+	plog(LLV_DEBUG, LOCATION, NULL, "make a proposal from peer's:\n");
+	printsaprop0(LLV_DEBUG, newpp);  
+
+	iph2->proposal = newpp;
+
+	error = 0;
+
+end:
+	if (error && newpp)
+		flushsaprop(newpp);
+
+	if (pp_peer)
+		flushsaprop(pp_peer);
+	if (pair)
+		free_proppair(pair);
+	return error;
+}
diff --git a/src/racoon/proposal.h b/src/racoon/proposal.h
new file mode 100644
index 0000000..60fc531
--- /dev/null
+++ b/src/racoon/proposal.h
@@ -0,0 +1,214 @@
+/*	$NetBSD: proposal.h,v 1.6 2006/12/09 05:52:57 manu Exp $	*/
+
+/* Id: proposal.h,v 1.5 2004/06/11 16:00:17 ludvigm Exp */
+
+/*
+ * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _PROPOSAL_H
+#define _PROPOSAL_H
+
+#include <sys/queue.h>
+
+/*
+ *   A. chained list of transform, only for single proto_id
+ *      (this is same as set of transforms in single proposal payload)
+ *   B. proposal.  this will point to multiple (A) items (order is important
+ *      here so pointer to (A) must be ordered array, or chained list). 
+ *      this covers multiple proposal on a packet if proposal # is the same.
+ *   C. finally, (B) needs to be connected as chained list.
+ * 
+ * 	head ---> prop[.......] ---> prop[...] ---> prop[...] ---> ...
+ * 	               | | | |
+ * 	               | | | +- proto4  <== must preserve order here
+ * 	               | | +--- proto3
+ * 	               | +----- proto2
+ * 	               +------- proto1[trans1, trans2, trans3, ...]
+ *
+ *   incoming packets needs to be parsed to construct the same structure
+ *   (check "prop_pair" too).
+ */
+/* SA proposal specification */
+struct saprop {
+	int prop_no;
+	time_t lifetime;
+	int lifebyte;
+	int pfs_group;			/* pfs group */
+	int claim;			/* flag to send RESPONDER-LIFETIME. */
+					/* XXX assumed DOI values are 1 or 2. */
+#ifdef HAVE_SECCTX
+	struct security_ctx sctx;       /* security context structure */
+#endif
+	struct saproto *head;
+	struct saprop *next;
+};
+
+/* SA protocol specification */
+struct saproto {
+	int proto_id;
+	size_t spisize;			/* spi size */
+	int encmode;			/* encryption mode */
+
+	int udp_encap;			/* UDP encapsulation */
+
+	/* XXX should be vchar_t * */
+	/* these are network byte order */
+	u_int32_t spi;			/* inbound. i.e. --SA-> me */
+	u_int32_t spi_p;		/* outbound. i.e. me -SA-> */
+
+	vchar_t *keymat;		/* KEYMAT */
+	vchar_t *keymat_p;		/* peer's KEYMAT */
+
+	int reqid_out;			/* request id (outbound) */
+	int reqid_in;			/* request id (inbound) */
+
+	int ok;				/* if 1, success to set SA in kenrel */
+
+	struct satrns *head;		/* header of transform */
+	struct saproto *next;		/* next protocol */
+};
+
+/* SA algorithm specification */
+struct satrns {
+	int trns_no;
+	int trns_id;			/* transform id */
+	int encklen;			/* key length of encryption algorithm */
+	int authtype;			/* authentication algorithm if ESP */
+
+	struct satrns *next;		/* next transform */
+};
+
+/*
+ * prop_pair: (proposal number, transform number)
+ *
+ *	(SA (P1 (T1 T2)) (P1' (T1' T2')) (P2 (T1" T2")))
+ *
+ *              p[1]      p[2]
+ *      top     (P1,T1)   (P2",T1")
+ *		 |  |tnext     |tnext
+ *		 |  v          v
+ *		 | (P1, T2)   (P2", T2")
+ *		 v next
+ *		(P1', T1')
+ *		    |tnext
+ *		    v
+ *		   (P1', T2')
+ *
+ * when we convert it to saprop in prop2saprop(), it should become like:
+ * 
+ * 		 (next)
+ * 	saprop --------------------> saprop	
+ * 	 | (head)                     | (head)
+ * 	 +-> saproto                  +-> saproto
+ * 	      | | (head)                     | (head)
+ * 	      | +-> satrns(P1 T1)            +-> satrns(P2" T1")
+ * 	      |      | (next)                     | (next)
+ * 	      |      v                            v
+ * 	      |     satrns(P1, T2)               satrns(P2", T2")
+ * 	      v (next)
+ * 	     saproto
+ * 		| (head)
+ * 		+-> satrns(P1' T1')
+ * 		     | (next)
+ * 		     v
+ * 		    satrns(P1', T2')
+ */
+struct prop_pair {
+	struct isakmp_pl_p *prop;
+	struct isakmp_pl_t *trns;
+	struct prop_pair *next;	/* next prop_pair with same proposal # */
+				/* (bundle case) */
+	struct prop_pair *tnext; /* next prop_pair in same proposal payload */
+				/* (multiple tranform case) */
+};
+#define MAXPROPPAIRLEN	256	/* It's enough because field size is 1 octet. */
+
+/*
+ * Lifetime length selection refered to the section 4.5.4 of RFC2407.  It does
+ * not completely conform to the description of RFC.  There are four types of
+ * the behavior.  If the value of "proposal_check" in "remote" directive is;
+ *     "obey"
+ *         the responder obey the initiator anytime.
+ *     "strict"
+ *         If the responder's length is longer than the initiator's one, the
+ *         responder uses the intitiator's one.  Otherwise rejects the proposal.
+ *         If PFS is not required by the responder, the responder obeys the
+ *         proposal.  If PFS is required by both sides and if the responder's
+ *         group is not equal to the initiator's one, then the responder reject
+ *         the proposal.
+ *     "claim"
+ *         If the responder's length is longer than the initiator's one, the
+ *         responder use the intitiator's one.  If the responder's length is
+ *         shorter than the initiator's one, the responder uses own length
+ *         AND send RESPONDER-LIFETIME notify message to a initiator in the
+ *         case of lifetime.
+ *         About PFS, this directive is same as "strict".
+ *     "exact"
+ *         If the initiator's length is not equal to the responder's one, the
+ *         responder rejects the proposal.
+ *         If PFS is required and if the responder's group is not equal to
+ *         the initiator's one, then the responder reject the proposal.
+ * XXX should be defined the behavior of key length.
+ */
+#define PROP_CHECK_OBEY		1
+#define PROP_CHECK_STRICT	2
+#define PROP_CHECK_CLAIM	3
+#define PROP_CHECK_EXACT	4
+
+struct sainfo;
+struct ph1handle;
+struct secpolicy;
+extern struct saprop *newsaprop __P((void));
+extern struct saproto *newsaproto __P((void));
+extern void inssaprop __P((struct saprop **, struct saprop *));
+extern void inssaproto __P((struct saprop *, struct saproto *));
+extern void inssaprotorev __P((struct saprop *, struct saproto *));
+extern struct satrns *newsatrns __P((void));
+extern void inssatrns __P((struct saproto *, struct satrns *));
+extern struct saprop *cmpsaprop_alloc __P((struct ph1handle *,
+	const struct saprop *, const struct saprop *, int));
+extern int cmpsaprop __P((const struct saprop *, const struct saprop *));
+extern int cmpsatrns __P((int, const struct satrns *, const struct satrns *, int));
+extern int set_satrnsbysainfo __P((struct saproto *, struct sainfo *));
+extern struct saprop *aproppair2saprop __P((struct prop_pair *));
+extern void free_proppair __P((struct prop_pair **));
+extern void flushsaprop __P((struct saprop *));
+extern void flushsaproto __P((struct saproto *));
+extern void flushsatrns __P((struct satrns *));
+extern void printsaprop __P((const int, const struct saprop *));
+extern void printsaprop0 __P((const int, const struct saprop *));
+extern void printsaproto __P((const int, const struct saproto *));
+extern void printsatrns __P((const int, const int, const struct satrns *));
+extern void print_proppair0 __P((int, struct prop_pair *, int));
+extern void print_proppair __P((int, struct prop_pair *));
+extern int set_proposal_from_policy __P((struct ph2handle *,
+	struct secpolicy *, struct secpolicy *));
+extern int set_proposal_from_proposal __P((struct ph2handle *));
+
+#endif /* _PROPOSAL_H */
diff --git a/src/racoon/prsa_par.c b/src/racoon/prsa_par.c
new file mode 100644
index 0000000..a8fb8b4
--- /dev/null
+++ b/src/racoon/prsa_par.c
@@ -0,0 +1,1966 @@
+/* A Bison parser, made by GNU Bison 2.3.  */
+
+/* Skeleton implementation for Bison's Yacc-like parsers in C
+
+   Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
+   Free Software Foundation, Inc.
+
+   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, or (at your option)
+   any later version.
+
+   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.
+
+   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., 51 Franklin Street, Fifth Floor,
+   Boston, MA 02110-1301, USA.  */
+
+/* As a special exception, you may create a larger work that contains
+   part or all of the Bison parser skeleton and distribute that work
+   under terms of your choice, so long as that work isn't itself a
+   parser generator using the skeleton or a modified version thereof
+   as a parser skeleton.  Alternatively, if you modify or redistribute
+   the parser skeleton itself, you may (at your option) remove this
+   special exception, which will cause the skeleton and the resulting
+   Bison output files to be licensed under the GNU General Public
+   License without this special exception.
+
+   This special exception was added by the Free Software Foundation in
+   version 2.2 of Bison.  */
+
+/* C LALR(1) parser skeleton written by Richard Stallman, by
+   simplifying the original so-called "semantic" parser.  */
+
+/* All symbols defined below should begin with yy or YY, to avoid
+   infringing on user name space.  This should be done even for local
+   variables, as they might otherwise be expanded by user macros.
+   There are some unavoidable exceptions within include files to
+   define necessary library symbols; they are noted "INFRINGES ON
+   USER NAME SPACE" below.  */
+
+/* Identify Bison output.  */
+#define YYBISON 1
+
+/* Bison version.  */
+#define YYBISON_VERSION "2.3"
+
+/* Skeleton name.  */
+#define YYSKELETON_NAME "yacc.c"
+
+/* Pure parsers.  */
+#define YYPURE 0
+
+/* Using locations.  */
+#define YYLSP_NEEDED 0
+
+/* Substitute the variable and function names.  */
+#define yyparse prsaparse
+#define yylex   prsalex
+#define yyerror prsaerror
+#define yylval  prsalval
+#define yychar  prsachar
+#define yydebug prsadebug
+#define yynerrs prsanerrs
+
+
+/* Tokens.  */
+#ifndef YYTOKENTYPE
+# define YYTOKENTYPE
+   /* Put the tokens into the symbol table, so that GDB and other debuggers
+      know about them.  */
+   enum yytokentype {
+     COLON = 258,
+     HEX = 259,
+     OBRACE = 260,
+     EBRACE = 261,
+     TAG_RSA = 262,
+     TAG_PUB = 263,
+     TAG_PSK = 264,
+     MODULUS = 265,
+     PUBLIC_EXPONENT = 266,
+     PRIVATE_EXPONENT = 267,
+     PRIME1 = 268,
+     PRIME2 = 269,
+     EXPONENT1 = 270,
+     EXPONENT2 = 271,
+     COEFFICIENT = 272,
+     ADDR4 = 273,
+     ADDR6 = 274,
+     ADDRANY = 275,
+     SLASH = 276,
+     NUMBER = 277,
+     BASE64 = 278
+   };
+#endif
+/* Tokens.  */
+#define COLON 258
+#define HEX 259
+#define OBRACE 260
+#define EBRACE 261
+#define TAG_RSA 262
+#define TAG_PUB 263
+#define TAG_PSK 264
+#define MODULUS 265
+#define PUBLIC_EXPONENT 266
+#define PRIVATE_EXPONENT 267
+#define PRIME1 268
+#define PRIME2 269
+#define EXPONENT1 270
+#define EXPONENT2 271
+#define COEFFICIENT 272
+#define ADDR4 273
+#define ADDR6 274
+#define ADDRANY 275
+#define SLASH 276
+#define NUMBER 277
+#define BASE64 278
+
+
+
+
+/* Copy the first part of user declarations.  */
+#line 5 "prsa_par.y"
+
+/*
+ * Copyright (C) 2004 SuSE Linux AG, Nuernberg, Germany.
+ * Contributed by: Michal Ludvig <mludvig@suse.cz>, SUSE Labs
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* This file contains a parser for FreeS/WAN-style ipsec.secrets RSA keys. */
+
+#include "config.h"
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+
+#ifdef HAVE_STDARG_H
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
+
+#include <netdb.h>
+#include <netinet/in.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+#include <sys/types.h>
+
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include <openssl/bn.h>
+#include <openssl/rsa.h>
+
+#include "misc.h"
+#include "vmbuf.h"
+#include "plog.h"
+#include "oakley.h"
+#include "isakmp_var.h"
+#include "handler.h"
+#include "crypto_openssl.h"
+#include "sockmisc.h"
+#include "rsalist.h"
+
+extern void prsaerror(const char *str, ...);
+extern int prsawrap (void);
+extern int prsalex (void);
+
+extern char *prsatext;
+extern int prsa_cur_lineno;
+extern char *prsa_cur_fname;
+extern FILE *prsain;
+
+int prsa_cur_lineno = 0;
+char *prsa_cur_fname = NULL;
+struct genlist *prsa_cur_list = NULL;
+enum rsa_key_type prsa_cur_type = RSA_TYPE_ANY;
+
+static RSA *rsa_cur;
+
+void
+prsaerror(const char *s, ...)
+{
+	char fmt[512];
+
+	va_list ap;
+#ifdef HAVE_STDARG_H
+	va_start(ap, s);
+#else
+	va_start(ap);
+#endif
+	snprintf(fmt, sizeof(fmt), "%s:%d: %s",
+		prsa_cur_fname, prsa_cur_lineno, s);
+	plogv(LLV_ERROR, LOCATION, NULL, fmt, ap);
+	va_end(ap);
+}
+
+void
+prsawarning(const char *s, ...)
+{
+	char fmt[512];
+
+	va_list ap;
+#ifdef HAVE_STDARG_H
+	va_start(ap, s);
+#else
+	va_start(ap);
+#endif
+	snprintf(fmt, sizeof(fmt), "%s:%d: %s",
+		prsa_cur_fname, prsa_cur_lineno, s);
+	plogv(LLV_WARNING, LOCATION, NULL, fmt, ap);
+	va_end(ap);
+}
+
+int
+prsawrap()
+{
+	return 1;
+} 
+
+
+/* Enabling traces.  */
+#ifndef YYDEBUG
+# define YYDEBUG 0
+#endif
+
+/* Enabling verbose error messages.  */
+#ifdef YYERROR_VERBOSE
+# undef YYERROR_VERBOSE
+# define YYERROR_VERBOSE 1
+#else
+# define YYERROR_VERBOSE 0
+#endif
+
+/* Enabling the token table.  */
+#ifndef YYTOKEN_TABLE
+# define YYTOKEN_TABLE 0
+#endif
+
+#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
+typedef union YYSTYPE
+#line 130 "prsa_par.y"
+{
+	BIGNUM *bn;
+	RSA *rsa;
+	char *chr;
+	long num;
+	struct netaddr *naddr;
+}
+/* Line 187 of yacc.c.  */
+#line 284 "prsa_par.c"
+	YYSTYPE;
+# define yystype YYSTYPE /* obsolescent; will be withdrawn */
+# define YYSTYPE_IS_DECLARED 1
+# define YYSTYPE_IS_TRIVIAL 1
+#endif
+
+
+
+/* Copy the second part of user declarations.  */
+
+
+/* Line 216 of yacc.c.  */
+#line 297 "prsa_par.c"
+
+#ifdef short
+# undef short
+#endif
+
+#ifdef YYTYPE_UINT8
+typedef YYTYPE_UINT8 yytype_uint8;
+#else
+typedef unsigned char yytype_uint8;
+#endif
+
+#ifdef YYTYPE_INT8
+typedef YYTYPE_INT8 yytype_int8;
+#elif (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+typedef signed char yytype_int8;
+#else
+typedef short int yytype_int8;
+#endif
+
+#ifdef YYTYPE_UINT16
+typedef YYTYPE_UINT16 yytype_uint16;
+#else
+typedef unsigned short int yytype_uint16;
+#endif
+
+#ifdef YYTYPE_INT16
+typedef YYTYPE_INT16 yytype_int16;
+#else
+typedef short int yytype_int16;
+#endif
+
+#ifndef YYSIZE_T
+# ifdef __SIZE_TYPE__
+#  define YYSIZE_T __SIZE_TYPE__
+# elif defined size_t
+#  define YYSIZE_T size_t
+# elif ! defined YYSIZE_T && (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+#  include <stddef.h> /* INFRINGES ON USER NAME SPACE */
+#  define YYSIZE_T size_t
+# else
+#  define YYSIZE_T unsigned int
+# endif
+#endif
+
+#define YYSIZE_MAXIMUM ((YYSIZE_T) -1)
+
+#ifndef YY_
+# if YYENABLE_NLS
+#  if ENABLE_NLS
+#   include <libintl.h> /* INFRINGES ON USER NAME SPACE */
+#   define YY_(msgid) dgettext ("bison-runtime", msgid)
+#  endif
+# endif
+# ifndef YY_
+#  define YY_(msgid) msgid
+# endif
+#endif
+
+/* Suppress unused-variable warnings by "using" E.  */
+#if ! defined lint || defined __GNUC__
+# define YYUSE(e) ((void) (e))
+#else
+# define YYUSE(e) /* empty */
+#endif
+
+/* Identity function, used to suppress warnings about constant conditions.  */
+#ifndef lint
+# define YYID(n) (n)
+#else
+#if (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+static int
+YYID (int i)
+#else
+static int
+YYID (i)
+    int i;
+#endif
+{
+  return i;
+}
+#endif
+
+#if ! defined yyoverflow || YYERROR_VERBOSE
+
+/* The parser invokes alloca or malloc; define the necessary symbols.  */
+
+# ifdef YYSTACK_USE_ALLOCA
+#  if YYSTACK_USE_ALLOCA
+#   ifdef __GNUC__
+#    define YYSTACK_ALLOC __builtin_alloca
+#   elif defined __BUILTIN_VA_ARG_INCR
+#    include <alloca.h> /* INFRINGES ON USER NAME SPACE */
+#   elif defined _AIX
+#    define YYSTACK_ALLOC __alloca
+#   elif defined _MSC_VER
+#    include <malloc.h> /* INFRINGES ON USER NAME SPACE */
+#    define alloca _alloca
+#   else
+#    define YYSTACK_ALLOC alloca
+#    if ! defined _ALLOCA_H && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+#     include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
+#     ifndef _STDLIB_H
+#      define _STDLIB_H 1
+#     endif
+#    endif
+#   endif
+#  endif
+# endif
+
+# ifdef YYSTACK_ALLOC
+   /* Pacify GCC's `empty if-body' warning.  */
+#  define YYSTACK_FREE(Ptr) do { /* empty */; } while (YYID (0))
+#  ifndef YYSTACK_ALLOC_MAXIMUM
+    /* The OS might guarantee only one guard page at the bottom of the stack,
+       and a page size can be as small as 4096 bytes.  So we cannot safely
+       invoke alloca (N) if N exceeds 4096.  Use a slightly smaller number
+       to allow for a few compiler-allocated temporary stack slots.  */
+#   define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */
+#  endif
+# else
+#  define YYSTACK_ALLOC YYMALLOC
+#  define YYSTACK_FREE YYFREE
+#  ifndef YYSTACK_ALLOC_MAXIMUM
+#   define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM
+#  endif
+#  if (defined __cplusplus && ! defined _STDLIB_H \
+       && ! ((defined YYMALLOC || defined malloc) \
+	     && (defined YYFREE || defined free)))
+#   include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
+#   ifndef _STDLIB_H
+#    define _STDLIB_H 1
+#   endif
+#  endif
+#  ifndef YYMALLOC
+#   define YYMALLOC malloc
+#   if ! defined malloc && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */
+#   endif
+#  endif
+#  ifndef YYFREE
+#   define YYFREE free
+#   if ! defined free && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+void free (void *); /* INFRINGES ON USER NAME SPACE */
+#   endif
+#  endif
+# endif
+#endif /* ! defined yyoverflow || YYERROR_VERBOSE */
+
+
+#if (! defined yyoverflow \
+     && (! defined __cplusplus \
+	 || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL)))
+
+/* A type that is properly aligned for any stack member.  */
+union yyalloc
+{
+  yytype_int16 yyss;
+  YYSTYPE yyvs;
+  };
+
+/* The size of the maximum gap between one aligned stack and the next.  */
+# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1)
+
+/* The size of an array large to enough to hold all stacks, each with
+   N elements.  */
+# define YYSTACK_BYTES(N) \
+     ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \
+      + YYSTACK_GAP_MAXIMUM)
+
+/* Copy COUNT objects from FROM to TO.  The source and destination do
+   not overlap.  */
+# ifndef YYCOPY
+#  if defined __GNUC__ && 1 < __GNUC__
+#   define YYCOPY(To, From, Count) \
+      __builtin_memcpy (To, From, (Count) * sizeof (*(From)))
+#  else
+#   define YYCOPY(To, From, Count)		\
+      do					\
+	{					\
+	  YYSIZE_T yyi;				\
+	  for (yyi = 0; yyi < (Count); yyi++)	\
+	    (To)[yyi] = (From)[yyi];		\
+	}					\
+      while (YYID (0))
+#  endif
+# endif
+
+/* Relocate STACK from its old location to the new one.  The
+   local variables YYSIZE and YYSTACKSIZE give the old and new number of
+   elements in the stack, and YYPTR gives the new location of the
+   stack.  Advance YYPTR to a properly aligned location for the next
+   stack.  */
+# define YYSTACK_RELOCATE(Stack)					\
+    do									\
+      {									\
+	YYSIZE_T yynewbytes;						\
+	YYCOPY (&yyptr->Stack, Stack, yysize);				\
+	Stack = &yyptr->Stack;						\
+	yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
+	yyptr += yynewbytes / sizeof (*yyptr);				\
+      }									\
+    while (YYID (0))
+
+#endif
+
+/* YYFINAL -- State number of the termination state.  */
+#define YYFINAL  16
+/* YYLAST -- Last index in YYTABLE.  */
+#define YYLAST   60
+
+/* YYNTOKENS -- Number of terminals.  */
+#define YYNTOKENS  24
+/* YYNNTS -- Number of nonterminals.  */
+#define YYNNTS  10
+/* YYNRULES -- Number of rules.  */
+#define YYNRULES  26
+/* YYNRULES -- Number of states.  */
+#define YYNSTATES  55
+
+/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX.  */
+#define YYUNDEFTOK  2
+#define YYMAXUTOK   278
+
+#define YYTRANSLATE(YYX)						\
+  ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
+
+/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX.  */
+static const yytype_uint8 yytranslate[] =
+{
+       0,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     1,     2,     3,     4,
+       5,     6,     7,     8,     9,    10,    11,    12,    13,    14,
+      15,    16,    17,    18,    19,    20,    21,    22,    23
+};
+
+#if YYDEBUG
+/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in
+   YYRHS.  */
+static const yytype_uint8 yyprhs[] =
+{
+       0,     0,     3,     6,     8,    13,    17,    20,    25,    28,
+      31,    33,    35,    37,    40,    43,    44,    47,    50,    52,
+      56,    60,    64,    68,    72,    76,    80
+};
+
+/* YYRHS -- A `-1'-separated list of the rules' RHS.  */
+static const yytype_int8 yyrhs[] =
+{
+      25,     0,    -1,    25,    26,    -1,    26,    -1,    28,    28,
+       3,    27,    -1,    28,     3,    27,    -1,     3,    27,    -1,
+       7,     5,    32,     6,    -1,     8,    23,    -1,     8,     4,
+      -1,    29,    -1,    30,    -1,    20,    -1,    18,    31,    -1,
+      19,    31,    -1,    -1,    21,    22,    -1,    32,    33,    -1,
+      33,    -1,    10,     3,     4,    -1,    11,     3,     4,    -1,
+      12,     3,     4,    -1,    13,     3,     4,    -1,    14,     3,
+       4,    -1,    15,     3,     4,    -1,    16,     3,     4,    -1,
+      17,     3,     4,    -1
+};
+
+/* YYRLINE[YYN] -- source line where rule number YYN was defined.  */
+static const yytype_uint16 yyrline[] =
+{
+       0,   155,   155,   156,   160,   164,   168,   175,   207,   215,
+     226,   227,   228,   235,   258,   281,   282,   285,   286,   290,
+     292,   294,   296,   298,   300,   302,   304
+};
+#endif
+
+#if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE
+/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
+   First, the terminals, then, starting at YYNTOKENS, nonterminals.  */
+static const char *const yytname[] =
+{
+  "$end", "error", "$undefined", "COLON", "HEX", "OBRACE", "EBRACE",
+  "TAG_RSA", "TAG_PUB", "TAG_PSK", "MODULUS", "PUBLIC_EXPONENT",
+  "PRIVATE_EXPONENT", "PRIME1", "PRIME2", "EXPONENT1", "EXPONENT2",
+  "COEFFICIENT", "ADDR4", "ADDR6", "ADDRANY", "SLASH", "NUMBER", "BASE64",
+  "$accept", "statements", "statement", "rsa_statement", "addr", "addr4",
+  "addr6", "prefix", "params", "param", 0
+};
+#endif
+
+# ifdef YYPRINT
+/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to
+   token YYLEX-NUM.  */
+static const yytype_uint16 yytoknum[] =
+{
+       0,   256,   257,   258,   259,   260,   261,   262,   263,   264,
+     265,   266,   267,   268,   269,   270,   271,   272,   273,   274,
+     275,   276,   277,   278
+};
+# endif
+
+/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives.  */
+static const yytype_uint8 yyr1[] =
+{
+       0,    24,    25,    25,    26,    26,    26,    27,    27,    27,
+      28,    28,    28,    29,    30,    31,    31,    32,    32,    33,
+      33,    33,    33,    33,    33,    33,    33
+};
+
+/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN.  */
+static const yytype_uint8 yyr2[] =
+{
+       0,     2,     2,     1,     4,     3,     2,     4,     2,     2,
+       1,     1,     1,     2,     2,     0,     2,     2,     1,     3,
+       3,     3,     3,     3,     3,     3,     3
+};
+
+/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state
+   STATE-NUM when YYTABLE doesn't specify something else to do.  Zero
+   means the default is an error.  */
+static const yytype_uint8 yydefact[] =
+{
+       0,     0,    15,    15,    12,     0,     3,     0,    10,    11,
+       0,     0,     6,     0,    13,    14,     1,     2,     0,     0,
+       0,     9,     8,    16,     5,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,    18,     4,     0,     0,     0,
+       0,     0,     0,     0,     0,     7,    17,    19,    20,    21,
+      22,    23,    24,    25,    26
+};
+
+/* YYDEFGOTO[NTERM-NUM].  */
+static const yytype_int8 yydefgoto[] =
+{
+      -1,     5,     6,    12,     7,     8,     9,    14,    34,    35
+};
+
+/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
+   STATE-NUM.  */
+#define YYPACT_NINF -18
+static const yytype_int8 yypact[] =
+{
+       4,    -3,   -15,   -15,   -18,     0,   -18,     7,   -18,   -18,
+       6,    -2,   -18,   -13,   -18,   -18,   -18,   -18,    -3,     9,
+      30,   -18,   -18,   -18,   -18,    -3,    10,    11,    12,    13,
+      14,    26,    27,    28,    22,   -18,   -18,    44,    45,    46,
+      47,    48,    49,    50,    51,   -18,   -18,   -18,   -18,   -18,
+     -18,   -18,   -18,   -18,   -18
+};
+
+/* YYPGOTO[NTERM-NUM].  */
+static const yytype_int8 yypgoto[] =
+{
+     -18,   -18,    52,   -17,    53,   -18,   -18,    55,   -18,    25
+};
+
+/* YYTABLE[YYPACT[STATE-NUM]].  What to do in state STATE-NUM.  If
+   positive, shift that token.  If negative, reduce the rule which
+   number is the opposite.  If zero, do what YYDEFACT says.
+   If YYTABLE_NINF, syntax error.  */
+#define YYTABLE_NINF -1
+static const yytype_uint8 yytable[] =
+{
+      16,    24,    21,     1,    10,    11,    13,     1,    36,    23,
+      18,    20,    25,    37,    38,    39,    40,    41,     2,     3,
+       4,    22,     2,     3,     4,     2,     3,     4,    45,    42,
+      43,    44,    26,    27,    28,    29,    30,    31,    32,    33,
+      26,    27,    28,    29,    30,    31,    32,    33,    47,    48,
+      49,    50,    51,    52,    53,    54,     0,    17,    15,    46,
+      19
+};
+
+static const yytype_int8 yycheck[] =
+{
+       0,    18,     4,     3,     7,     8,    21,     3,    25,    22,
+       3,     5,     3,     3,     3,     3,     3,     3,    18,    19,
+      20,    23,    18,    19,    20,    18,    19,    20,     6,     3,
+       3,     3,    10,    11,    12,    13,    14,    15,    16,    17,
+      10,    11,    12,    13,    14,    15,    16,    17,     4,     4,
+       4,     4,     4,     4,     4,     4,    -1,     5,     3,    34,
+       7
+};
+
+/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
+   symbol of state STATE-NUM.  */
+static const yytype_uint8 yystos[] =
+{
+       0,     3,    18,    19,    20,    25,    26,    28,    29,    30,
+       7,     8,    27,    21,    31,    31,     0,    26,     3,    28,
+       5,     4,    23,    22,    27,     3,    10,    11,    12,    13,
+      14,    15,    16,    17,    32,    33,    27,     3,     3,     3,
+       3,     3,     3,     3,     3,     6,    33,     4,     4,     4,
+       4,     4,     4,     4,     4
+};
+
+#define yyerrok		(yyerrstatus = 0)
+#define yyclearin	(yychar = YYEMPTY)
+#define YYEMPTY		(-2)
+#define YYEOF		0
+
+#define YYACCEPT	goto yyacceptlab
+#define YYABORT		goto yyabortlab
+#define YYERROR		goto yyerrorlab
+
+
+/* Like YYERROR except do call yyerror.  This remains here temporarily
+   to ease the transition to the new meaning of YYERROR, for GCC.
+   Once GCC version 2 has supplanted version 1, this can go.  */
+
+#define YYFAIL		goto yyerrlab
+
+#define YYRECOVERING()  (!!yyerrstatus)
+
+#define YYBACKUP(Token, Value)					\
+do								\
+  if (yychar == YYEMPTY && yylen == 1)				\
+    {								\
+      yychar = (Token);						\
+      yylval = (Value);						\
+      yytoken = YYTRANSLATE (yychar);				\
+      YYPOPSTACK (1);						\
+      goto yybackup;						\
+    }								\
+  else								\
+    {								\
+      yyerror (YY_("syntax error: cannot back up")); \
+      YYERROR;							\
+    }								\
+while (YYID (0))
+
+
+#define YYTERROR	1
+#define YYERRCODE	256
+
+
+/* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N].
+   If N is 0, then set CURRENT to the empty location which ends
+   the previous symbol: RHS[0] (always defined).  */
+
+#define YYRHSLOC(Rhs, K) ((Rhs)[K])
+#ifndef YYLLOC_DEFAULT
+# define YYLLOC_DEFAULT(Current, Rhs, N)				\
+    do									\
+      if (YYID (N))                                                    \
+	{								\
+	  (Current).first_line   = YYRHSLOC (Rhs, 1).first_line;	\
+	  (Current).first_column = YYRHSLOC (Rhs, 1).first_column;	\
+	  (Current).last_line    = YYRHSLOC (Rhs, N).last_line;		\
+	  (Current).last_column  = YYRHSLOC (Rhs, N).last_column;	\
+	}								\
+      else								\
+	{								\
+	  (Current).first_line   = (Current).last_line   =		\
+	    YYRHSLOC (Rhs, 0).last_line;				\
+	  (Current).first_column = (Current).last_column =		\
+	    YYRHSLOC (Rhs, 0).last_column;				\
+	}								\
+    while (YYID (0))
+#endif
+
+
+/* YY_LOCATION_PRINT -- Print the location on the stream.
+   This macro was not mandated originally: define only if we know
+   we won't break user code: when these are the locations we know.  */
+
+#ifndef YY_LOCATION_PRINT
+# if YYLTYPE_IS_TRIVIAL
+#  define YY_LOCATION_PRINT(File, Loc)			\
+     fprintf (File, "%d.%d-%d.%d",			\
+	      (Loc).first_line, (Loc).first_column,	\
+	      (Loc).last_line,  (Loc).last_column)
+# else
+#  define YY_LOCATION_PRINT(File, Loc) ((void) 0)
+# endif
+#endif
+
+
+/* YYLEX -- calling `yylex' with the right arguments.  */
+
+#ifdef YYLEX_PARAM
+# define YYLEX yylex (YYLEX_PARAM)
+#else
+# define YYLEX yylex ()
+#endif
+
+/* Enable debugging if requested.  */
+#if YYDEBUG
+
+# ifndef YYFPRINTF
+#  include <stdio.h> /* INFRINGES ON USER NAME SPACE */
+#  define YYFPRINTF fprintf
+# endif
+
+# define YYDPRINTF(Args)			\
+do {						\
+  if (yydebug)					\
+    YYFPRINTF Args;				\
+} while (YYID (0))
+
+# define YY_SYMBOL_PRINT(Title, Type, Value, Location)			  \
+do {									  \
+  if (yydebug)								  \
+    {									  \
+      YYFPRINTF (stderr, "%s ", Title);					  \
+      yy_symbol_print (stderr,						  \
+		  Type, Value); \
+      YYFPRINTF (stderr, "\n");						  \
+    }									  \
+} while (YYID (0))
+
+
+/*--------------------------------.
+| Print this symbol on YYOUTPUT.  |
+`--------------------------------*/
+
+/*ARGSUSED*/
+#if (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+static void
+yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep)
+#else
+static void
+yy_symbol_value_print (yyoutput, yytype, yyvaluep)
+    FILE *yyoutput;
+    int yytype;
+    YYSTYPE const * const yyvaluep;
+#endif
+{
+  if (!yyvaluep)
+    return;
+# ifdef YYPRINT
+  if (yytype < YYNTOKENS)
+    YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep);
+# else
+  YYUSE (yyoutput);
+# endif
+  switch (yytype)
+    {
+      default:
+	break;
+    }
+}
+
+
+/*--------------------------------.
+| Print this symbol on YYOUTPUT.  |
+`--------------------------------*/
+
+#if (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+static void
+yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep)
+#else
+static void
+yy_symbol_print (yyoutput, yytype, yyvaluep)
+    FILE *yyoutput;
+    int yytype;
+    YYSTYPE const * const yyvaluep;
+#endif
+{
+  if (yytype < YYNTOKENS)
+    YYFPRINTF (yyoutput, "token %s (", yytname[yytype]);
+  else
+    YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]);
+
+  yy_symbol_value_print (yyoutput, yytype, yyvaluep);
+  YYFPRINTF (yyoutput, ")");
+}
+
+/*------------------------------------------------------------------.
+| yy_stack_print -- Print the state stack from its BOTTOM up to its |
+| TOP (included).                                                   |
+`------------------------------------------------------------------*/
+
+#if (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+static void
+yy_stack_print (yytype_int16 *bottom, yytype_int16 *top)
+#else
+static void
+yy_stack_print (bottom, top)
+    yytype_int16 *bottom;
+    yytype_int16 *top;
+#endif
+{
+  YYFPRINTF (stderr, "Stack now");
+  for (; bottom <= top; ++bottom)
+    YYFPRINTF (stderr, " %d", *bottom);
+  YYFPRINTF (stderr, "\n");
+}
+
+# define YY_STACK_PRINT(Bottom, Top)				\
+do {								\
+  if (yydebug)							\
+    yy_stack_print ((Bottom), (Top));				\
+} while (YYID (0))
+
+
+/*------------------------------------------------.
+| Report that the YYRULE is going to be reduced.  |
+`------------------------------------------------*/
+
+#if (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+static void
+yy_reduce_print (YYSTYPE *yyvsp, int yyrule)
+#else
+static void
+yy_reduce_print (yyvsp, yyrule)
+    YYSTYPE *yyvsp;
+    int yyrule;
+#endif
+{
+  int yynrhs = yyr2[yyrule];
+  int yyi;
+  unsigned long int yylno = yyrline[yyrule];
+  YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n",
+	     yyrule - 1, yylno);
+  /* The symbols being reduced.  */
+  for (yyi = 0; yyi < yynrhs; yyi++)
+    {
+      fprintf (stderr, "   $%d = ", yyi + 1);
+      yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi],
+		       &(yyvsp[(yyi + 1) - (yynrhs)])
+		       		       );
+      fprintf (stderr, "\n");
+    }
+}
+
+# define YY_REDUCE_PRINT(Rule)		\
+do {					\
+  if (yydebug)				\
+    yy_reduce_print (yyvsp, Rule); \
+} while (YYID (0))
+
+/* Nonzero means print parse trace.  It is left uninitialized so that
+   multiple parsers can coexist.  */
+int yydebug;
+#else /* !YYDEBUG */
+# define YYDPRINTF(Args)
+# define YY_SYMBOL_PRINT(Title, Type, Value, Location)
+# define YY_STACK_PRINT(Bottom, Top)
+# define YY_REDUCE_PRINT(Rule)
+#endif /* !YYDEBUG */
+
+
+/* YYINITDEPTH -- initial size of the parser's stacks.  */
+#ifndef	YYINITDEPTH
+# define YYINITDEPTH 200
+#endif
+
+/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only
+   if the built-in stack extension method is used).
+
+   Do not make this value too large; the results are undefined if
+   YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH)
+   evaluated with infinite-precision integer arithmetic.  */
+
+#ifndef YYMAXDEPTH
+# define YYMAXDEPTH 10000
+#endif
+
+
+
+#if YYERROR_VERBOSE
+
+# ifndef yystrlen
+#  if defined __GLIBC__ && defined _STRING_H
+#   define yystrlen strlen
+#  else
+/* Return the length of YYSTR.  */
+#if (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+static YYSIZE_T
+yystrlen (const char *yystr)
+#else
+static YYSIZE_T
+yystrlen (yystr)
+    const char *yystr;
+#endif
+{
+  YYSIZE_T yylen;
+  for (yylen = 0; yystr[yylen]; yylen++)
+    continue;
+  return yylen;
+}
+#  endif
+# endif
+
+# ifndef yystpcpy
+#  if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE
+#   define yystpcpy stpcpy
+#  else
+/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in
+   YYDEST.  */
+#if (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+static char *
+yystpcpy (char *yydest, const char *yysrc)
+#else
+static char *
+yystpcpy (yydest, yysrc)
+    char *yydest;
+    const char *yysrc;
+#endif
+{
+  char *yyd = yydest;
+  const char *yys = yysrc;
+
+  while ((*yyd++ = *yys++) != '\0')
+    continue;
+
+  return yyd - 1;
+}
+#  endif
+# endif
+
+# ifndef yytnamerr
+/* Copy to YYRES the contents of YYSTR after stripping away unnecessary
+   quotes and backslashes, so that it's suitable for yyerror.  The
+   heuristic is that double-quoting is unnecessary unless the string
+   contains an apostrophe, a comma, or backslash (other than
+   backslash-backslash).  YYSTR is taken from yytname.  If YYRES is
+   null, do not copy; instead, return the length of what the result
+   would have been.  */
+static YYSIZE_T
+yytnamerr (char *yyres, const char *yystr)
+{
+  if (*yystr == '"')
+    {
+      YYSIZE_T yyn = 0;
+      char const *yyp = yystr;
+
+      for (;;)
+	switch (*++yyp)
+	  {
+	  case '\'':
+	  case ',':
+	    goto do_not_strip_quotes;
+
+	  case '\\':
+	    if (*++yyp != '\\')
+	      goto do_not_strip_quotes;
+	    /* Fall through.  */
+	  default:
+	    if (yyres)
+	      yyres[yyn] = *yyp;
+	    yyn++;
+	    break;
+
+	  case '"':
+	    if (yyres)
+	      yyres[yyn] = '\0';
+	    return yyn;
+	  }
+    do_not_strip_quotes: ;
+    }
+
+  if (! yyres)
+    return yystrlen (yystr);
+
+  return yystpcpy (yyres, yystr) - yyres;
+}
+# endif
+
+/* Copy into YYRESULT an error message about the unexpected token
+   YYCHAR while in state YYSTATE.  Return the number of bytes copied,
+   including the terminating null byte.  If YYRESULT is null, do not
+   copy anything; just return the number of bytes that would be
+   copied.  As a special case, return 0 if an ordinary "syntax error"
+   message will do.  Return YYSIZE_MAXIMUM if overflow occurs during
+   size calculation.  */
+static YYSIZE_T
+yysyntax_error (char *yyresult, int yystate, int yychar)
+{
+  int yyn = yypact[yystate];
+
+  if (! (YYPACT_NINF < yyn && yyn <= YYLAST))
+    return 0;
+  else
+    {
+      int yytype = YYTRANSLATE (yychar);
+      YYSIZE_T yysize0 = yytnamerr (0, yytname[yytype]);
+      YYSIZE_T yysize = yysize0;
+      YYSIZE_T yysize1;
+      int yysize_overflow = 0;
+      enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 };
+      char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM];
+      int yyx;
+
+# if 0
+      /* This is so xgettext sees the translatable formats that are
+	 constructed on the fly.  */
+      YY_("syntax error, unexpected %s");
+      YY_("syntax error, unexpected %s, expecting %s");
+      YY_("syntax error, unexpected %s, expecting %s or %s");
+      YY_("syntax error, unexpected %s, expecting %s or %s or %s");
+      YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s");
+# endif
+      char *yyfmt;
+      char const *yyf;
+      static char const yyunexpected[] = "syntax error, unexpected %s";
+      static char const yyexpecting[] = ", expecting %s";
+      static char const yyor[] = " or %s";
+      char yyformat[sizeof yyunexpected
+		    + sizeof yyexpecting - 1
+		    + ((YYERROR_VERBOSE_ARGS_MAXIMUM - 2)
+		       * (sizeof yyor - 1))];
+      char const *yyprefix = yyexpecting;
+
+      /* Start YYX at -YYN if negative to avoid negative indexes in
+	 YYCHECK.  */
+      int yyxbegin = yyn < 0 ? -yyn : 0;
+
+      /* Stay within bounds of both yycheck and yytname.  */
+      int yychecklim = YYLAST - yyn + 1;
+      int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
+      int yycount = 1;
+
+      yyarg[0] = yytname[yytype];
+      yyfmt = yystpcpy (yyformat, yyunexpected);
+
+      for (yyx = yyxbegin; yyx < yyxend; ++yyx)
+	if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR)
+	  {
+	    if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM)
+	      {
+		yycount = 1;
+		yysize = yysize0;
+		yyformat[sizeof yyunexpected - 1] = '\0';
+		break;
+	      }
+	    yyarg[yycount++] = yytname[yyx];
+	    yysize1 = yysize + yytnamerr (0, yytname[yyx]);
+	    yysize_overflow |= (yysize1 < yysize);
+	    yysize = yysize1;
+	    yyfmt = yystpcpy (yyfmt, yyprefix);
+	    yyprefix = yyor;
+	  }
+
+      yyf = YY_(yyformat);
+      yysize1 = yysize + yystrlen (yyf);
+      yysize_overflow |= (yysize1 < yysize);
+      yysize = yysize1;
+
+      if (yysize_overflow)
+	return YYSIZE_MAXIMUM;
+
+      if (yyresult)
+	{
+	  /* Avoid sprintf, as that infringes on the user's name space.
+	     Don't have undefined behavior even if the translation
+	     produced a string with the wrong number of "%s"s.  */
+	  char *yyp = yyresult;
+	  int yyi = 0;
+	  while ((*yyp = *yyf) != '\0')
+	    {
+	      if (*yyp == '%' && yyf[1] == 's' && yyi < yycount)
+		{
+		  yyp += yytnamerr (yyp, yyarg[yyi++]);
+		  yyf += 2;
+		}
+	      else
+		{
+		  yyp++;
+		  yyf++;
+		}
+	    }
+	}
+      return yysize;
+    }
+}
+#endif /* YYERROR_VERBOSE */
+
+
+/*-----------------------------------------------.
+| Release the memory associated to this symbol.  |
+`-----------------------------------------------*/
+
+/*ARGSUSED*/
+#if (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+static void
+yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep)
+#else
+static void
+yydestruct (yymsg, yytype, yyvaluep)
+    const char *yymsg;
+    int yytype;
+    YYSTYPE *yyvaluep;
+#endif
+{
+  YYUSE (yyvaluep);
+
+  if (!yymsg)
+    yymsg = "Deleting";
+  YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp);
+
+  switch (yytype)
+    {
+
+      default:
+	break;
+    }
+}
+
+
+/* Prevent warnings from -Wmissing-prototypes.  */
+
+#ifdef YYPARSE_PARAM
+#if defined __STDC__ || defined __cplusplus
+int yyparse (void *YYPARSE_PARAM);
+#else
+int yyparse ();
+#endif
+#else /* ! YYPARSE_PARAM */
+#if defined __STDC__ || defined __cplusplus
+int yyparse (void);
+#else
+int yyparse ();
+#endif
+#endif /* ! YYPARSE_PARAM */
+
+
+
+/* The look-ahead symbol.  */
+int yychar;
+
+/* The semantic value of the look-ahead symbol.  */
+YYSTYPE yylval;
+
+/* Number of syntax errors so far.  */
+int yynerrs;
+
+
+
+/*----------.
+| yyparse.  |
+`----------*/
+
+#ifdef YYPARSE_PARAM
+#if (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+int
+yyparse (void *YYPARSE_PARAM)
+#else
+int
+yyparse (YYPARSE_PARAM)
+    void *YYPARSE_PARAM;
+#endif
+#else /* ! YYPARSE_PARAM */
+#if (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+int
+yyparse (void)
+#else
+int
+yyparse ()
+
+#endif
+#endif
+{
+  
+  int yystate;
+  int yyn;
+  int yyresult;
+  /* Number of tokens to shift before error messages enabled.  */
+  int yyerrstatus;
+  /* Look-ahead token as an internal (translated) token number.  */
+  int yytoken = 0;
+#if YYERROR_VERBOSE
+  /* Buffer for error messages, and its allocated size.  */
+  char yymsgbuf[128];
+  char *yymsg = yymsgbuf;
+  YYSIZE_T yymsg_alloc = sizeof yymsgbuf;
+#endif
+
+  /* Three stacks and their tools:
+     `yyss': related to states,
+     `yyvs': related to semantic values,
+     `yyls': related to locations.
+
+     Refer to the stacks thru separate pointers, to allow yyoverflow
+     to reallocate them elsewhere.  */
+
+  /* The state stack.  */
+  yytype_int16 yyssa[YYINITDEPTH];
+  yytype_int16 *yyss = yyssa;
+  yytype_int16 *yyssp;
+
+  /* The semantic value stack.  */
+  YYSTYPE yyvsa[YYINITDEPTH];
+  YYSTYPE *yyvs = yyvsa;
+  YYSTYPE *yyvsp;
+
+
+
+#define YYPOPSTACK(N)   (yyvsp -= (N), yyssp -= (N))
+
+  YYSIZE_T yystacksize = YYINITDEPTH;
+
+  /* The variables used to return semantic value and location from the
+     action routines.  */
+  YYSTYPE yyval;
+
+
+  /* The number of symbols on the RHS of the reduced rule.
+     Keep to zero when no symbol should be popped.  */
+  int yylen = 0;
+
+  YYDPRINTF ((stderr, "Starting parse\n"));
+
+  yystate = 0;
+  yyerrstatus = 0;
+  yynerrs = 0;
+  yychar = YYEMPTY;		/* Cause a token to be read.  */
+
+  /* Initialize stack pointers.
+     Waste one element of value and location stack
+     so that they stay on the same level as the state stack.
+     The wasted elements are never initialized.  */
+
+  yyssp = yyss;
+  yyvsp = yyvs;
+
+  goto yysetstate;
+
+/*------------------------------------------------------------.
+| yynewstate -- Push a new state, which is found in yystate.  |
+`------------------------------------------------------------*/
+ yynewstate:
+  /* In all cases, when you get here, the value and location stacks
+     have just been pushed.  So pushing a state here evens the stacks.  */
+  yyssp++;
+
+ yysetstate:
+  *yyssp = yystate;
+
+  if (yyss + yystacksize - 1 <= yyssp)
+    {
+      /* Get the current used size of the three stacks, in elements.  */
+      YYSIZE_T yysize = yyssp - yyss + 1;
+
+#ifdef yyoverflow
+      {
+	/* Give user a chance to reallocate the stack.  Use copies of
+	   these so that the &'s don't force the real ones into
+	   memory.  */
+	YYSTYPE *yyvs1 = yyvs;
+	yytype_int16 *yyss1 = yyss;
+
+
+	/* Each stack pointer address is followed by the size of the
+	   data in use in that stack, in bytes.  This used to be a
+	   conditional around just the two extra args, but that might
+	   be undefined if yyoverflow is a macro.  */
+	yyoverflow (YY_("memory exhausted"),
+		    &yyss1, yysize * sizeof (*yyssp),
+		    &yyvs1, yysize * sizeof (*yyvsp),
+
+		    &yystacksize);
+
+	yyss = yyss1;
+	yyvs = yyvs1;
+      }
+#else /* no yyoverflow */
+# ifndef YYSTACK_RELOCATE
+      goto yyexhaustedlab;
+# else
+      /* Extend the stack our own way.  */
+      if (YYMAXDEPTH <= yystacksize)
+	goto yyexhaustedlab;
+      yystacksize *= 2;
+      if (YYMAXDEPTH < yystacksize)
+	yystacksize = YYMAXDEPTH;
+
+      {
+	yytype_int16 *yyss1 = yyss;
+	union yyalloc *yyptr =
+	  (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
+	if (! yyptr)
+	  goto yyexhaustedlab;
+	YYSTACK_RELOCATE (yyss);
+	YYSTACK_RELOCATE (yyvs);
+
+#  undef YYSTACK_RELOCATE
+	if (yyss1 != yyssa)
+	  YYSTACK_FREE (yyss1);
+      }
+# endif
+#endif /* no yyoverflow */
+
+      yyssp = yyss + yysize - 1;
+      yyvsp = yyvs + yysize - 1;
+
+
+      YYDPRINTF ((stderr, "Stack size increased to %lu\n",
+		  (unsigned long int) yystacksize));
+
+      if (yyss + yystacksize - 1 <= yyssp)
+	YYABORT;
+    }
+
+  YYDPRINTF ((stderr, "Entering state %d\n", yystate));
+
+  goto yybackup;
+
+/*-----------.
+| yybackup.  |
+`-----------*/
+yybackup:
+
+  /* Do appropriate processing given the current state.  Read a
+     look-ahead token if we need one and don't already have one.  */
+
+  /* First try to decide what to do without reference to look-ahead token.  */
+  yyn = yypact[yystate];
+  if (yyn == YYPACT_NINF)
+    goto yydefault;
+
+  /* Not known => get a look-ahead token if don't already have one.  */
+
+  /* YYCHAR is either YYEMPTY or YYEOF or a valid look-ahead symbol.  */
+  if (yychar == YYEMPTY)
+    {
+      YYDPRINTF ((stderr, "Reading a token: "));
+      yychar = YYLEX;
+    }
+
+  if (yychar <= YYEOF)
+    {
+      yychar = yytoken = YYEOF;
+      YYDPRINTF ((stderr, "Now at end of input.\n"));
+    }
+  else
+    {
+      yytoken = YYTRANSLATE (yychar);
+      YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc);
+    }
+
+  /* If the proper action on seeing token YYTOKEN is to reduce or to
+     detect an error, take that action.  */
+  yyn += yytoken;
+  if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken)
+    goto yydefault;
+  yyn = yytable[yyn];
+  if (yyn <= 0)
+    {
+      if (yyn == 0 || yyn == YYTABLE_NINF)
+	goto yyerrlab;
+      yyn = -yyn;
+      goto yyreduce;
+    }
+
+  if (yyn == YYFINAL)
+    YYACCEPT;
+
+  /* Count tokens shifted since error; after three, turn off error
+     status.  */
+  if (yyerrstatus)
+    yyerrstatus--;
+
+  /* Shift the look-ahead token.  */
+  YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc);
+
+  /* Discard the shifted token unless it is eof.  */
+  if (yychar != YYEOF)
+    yychar = YYEMPTY;
+
+  yystate = yyn;
+  *++yyvsp = yylval;
+
+  goto yynewstate;
+
+
+/*-----------------------------------------------------------.
+| yydefault -- do the default action for the current state.  |
+`-----------------------------------------------------------*/
+yydefault:
+  yyn = yydefact[yystate];
+  if (yyn == 0)
+    goto yyerrlab;
+  goto yyreduce;
+
+
+/*-----------------------------.
+| yyreduce -- Do a reduction.  |
+`-----------------------------*/
+yyreduce:
+  /* yyn is the number of a rule to reduce with.  */
+  yylen = yyr2[yyn];
+
+  /* If YYLEN is nonzero, implement the default value of the action:
+     `$$ = $1'.
+
+     Otherwise, the following line sets YYVAL to garbage.
+     This behavior is undocumented and Bison
+     users should not rely upon it.  Assigning to YYVAL
+     unconditionally makes the parser a bit smaller, and it avoids a
+     GCC warning that YYVAL may be used uninitialized.  */
+  yyval = yyvsp[1-yylen];
+
+
+  YY_REDUCE_PRINT (yyn);
+  switch (yyn)
+    {
+        case 4:
+#line 161 "prsa_par.y"
+    {
+		rsa_key_insert(prsa_cur_list, (yyvsp[(1) - (4)].naddr), (yyvsp[(2) - (4)].naddr), (yyvsp[(4) - (4)].rsa));
+	}
+    break;
+
+  case 5:
+#line 165 "prsa_par.y"
+    {
+		rsa_key_insert(prsa_cur_list, NULL, (yyvsp[(1) - (3)].naddr), (yyvsp[(3) - (3)].rsa));
+	}
+    break;
+
+  case 6:
+#line 169 "prsa_par.y"
+    {
+		rsa_key_insert(prsa_cur_list, NULL, NULL, (yyvsp[(2) - (2)].rsa));
+	}
+    break;
+
+  case 7:
+#line 176 "prsa_par.y"
+    {
+		if (prsa_cur_type == RSA_TYPE_PUBLIC) {
+			prsawarning("Using private key for public key purpose.\n");
+			if (!rsa_cur->n || !rsa_cur->e) {
+				prsaerror("Incomplete key. Mandatory parameters are missing!\n");
+				YYABORT;
+			}
+		}
+		else {
+			if (!rsa_cur->n || !rsa_cur->e || !rsa_cur->d) {
+				prsaerror("Incomplete key. Mandatory parameters are missing!\n");
+				YYABORT;
+			}
+			if (!rsa_cur->p || !rsa_cur->q || !rsa_cur->dmp1
+			    || !rsa_cur->dmq1 || !rsa_cur->iqmp) {
+				if (rsa_cur->p) BN_clear_free(rsa_cur->p);
+				if (rsa_cur->q) BN_clear_free(rsa_cur->q);
+				if (rsa_cur->dmp1) BN_clear_free(rsa_cur->dmp1);
+				if (rsa_cur->dmq1) BN_clear_free(rsa_cur->dmq1);
+				if (rsa_cur->iqmp) BN_clear_free(rsa_cur->iqmp);
+
+				rsa_cur->p = NULL;
+				rsa_cur->q = NULL;
+				rsa_cur->dmp1 = NULL;
+				rsa_cur->dmq1 = NULL;
+				rsa_cur->iqmp = NULL;
+			}
+		}
+		(yyval.rsa) = rsa_cur;
+		rsa_cur = RSA_new();
+	}
+    break;
+
+  case 8:
+#line 208 "prsa_par.y"
+    {
+		if (prsa_cur_type == RSA_TYPE_PRIVATE) {
+			prsaerror("Public key in private-key file!\n");
+			YYABORT;
+		}
+		(yyval.rsa) = base64_pubkey2rsa((yyvsp[(2) - (2)].chr));
+	}
+    break;
+
+  case 9:
+#line 216 "prsa_par.y"
+    {
+		if (prsa_cur_type == RSA_TYPE_PRIVATE) {
+			prsaerror("Public key in private-key file!\n");
+			YYABORT;
+		}
+		(yyval.rsa) = bignum_pubkey2rsa((yyvsp[(2) - (2)].bn));
+	}
+    break;
+
+  case 12:
+#line 229 "prsa_par.y"
+    {
+		(yyval.naddr) = NULL;
+	}
+    break;
+
+  case 13:
+#line 236 "prsa_par.y"
+    {
+		int err;
+		struct sockaddr_in *sap;
+		
+		if ((yyvsp[(2) - (2)].num) == -1) (yyvsp[(2) - (2)].num) = 32;
+		if ((yyvsp[(2) - (2)].num) < 0 || (yyvsp[(2) - (2)].num) > 32) {
+			prsaerror ("Invalid IPv4 prefix\n");
+			YYABORT;
+		}
+		(yyval.naddr) = calloc (sizeof(struct netaddr), 1);
+		(yyval.naddr)->prefix = (yyvsp[(2) - (2)].num);
+		sap = (struct sockaddr_in *)(&(yyval.naddr)->sa);
+		sap->sin_family = AF_INET;
+		err = inet_pton(AF_INET, (yyvsp[(1) - (2)].chr), (struct in_addr*)(&sap->sin_addr));
+		if (err <= 0) {
+			prsaerror("inet_pton(%s): %s\n", (yyvsp[(1) - (2)].chr), strerror(errno));
+			YYABORT;
+		}
+	}
+    break;
+
+  case 14:
+#line 259 "prsa_par.y"
+    {
+		int err;
+		struct sockaddr_in6 *sap;
+		
+		if ((yyvsp[(2) - (2)].num) == -1) (yyvsp[(2) - (2)].num) = 128;
+		if ((yyvsp[(2) - (2)].num) < 0 || (yyvsp[(2) - (2)].num) > 128) {
+			prsaerror ("Invalid IPv6 prefix\n");
+			YYABORT;
+		}
+		(yyval.naddr) = calloc (sizeof(struct netaddr), 1);
+		(yyval.naddr)->prefix = (yyvsp[(2) - (2)].num);
+		sap = (struct sockaddr_in6 *)(&(yyval.naddr)->sa);
+		sap->sin6_family = AF_INET6;
+		err = inet_pton(AF_INET6, (yyvsp[(1) - (2)].chr), (struct in6_addr*)(&sap->sin6_addr));
+		if (err <= 0) {
+			prsaerror("inet_pton(%s): %s\n", (yyvsp[(1) - (2)].chr), strerror(errno));
+			YYABORT;
+		}
+	}
+    break;
+
+  case 15:
+#line 281 "prsa_par.y"
+    { (yyval.num) = -1; }
+    break;
+
+  case 16:
+#line 282 "prsa_par.y"
+    { (yyval.num) = (yyvsp[(2) - (2)].num); }
+    break;
+
+  case 19:
+#line 291 "prsa_par.y"
+    { if (!rsa_cur->n) rsa_cur->n = (yyvsp[(3) - (3)].bn); else { prsaerror ("Modulus already defined\n"); YYABORT; } }
+    break;
+
+  case 20:
+#line 293 "prsa_par.y"
+    { if (!rsa_cur->e) rsa_cur->e = (yyvsp[(3) - (3)].bn); else { prsaerror ("PublicExponent already defined\n"); YYABORT; } }
+    break;
+
+  case 21:
+#line 295 "prsa_par.y"
+    { if (!rsa_cur->d) rsa_cur->d = (yyvsp[(3) - (3)].bn); else { prsaerror ("PrivateExponent already defined\n"); YYABORT; } }
+    break;
+
+  case 22:
+#line 297 "prsa_par.y"
+    { if (!rsa_cur->p) rsa_cur->p = (yyvsp[(3) - (3)].bn); else { prsaerror ("Prime1 already defined\n"); YYABORT; } }
+    break;
+
+  case 23:
+#line 299 "prsa_par.y"
+    { if (!rsa_cur->q) rsa_cur->q = (yyvsp[(3) - (3)].bn); else { prsaerror ("Prime2 already defined\n"); YYABORT; } }
+    break;
+
+  case 24:
+#line 301 "prsa_par.y"
+    { if (!rsa_cur->dmp1) rsa_cur->dmp1 = (yyvsp[(3) - (3)].bn); else { prsaerror ("Exponent1 already defined\n"); YYABORT; } }
+    break;
+
+  case 25:
+#line 303 "prsa_par.y"
+    { if (!rsa_cur->dmq1) rsa_cur->dmq1 = (yyvsp[(3) - (3)].bn); else { prsaerror ("Exponent2 already defined\n"); YYABORT; } }
+    break;
+
+  case 26:
+#line 305 "prsa_par.y"
+    { if (!rsa_cur->iqmp) rsa_cur->iqmp = (yyvsp[(3) - (3)].bn); else { prsaerror ("Coefficient already defined\n"); YYABORT; } }
+    break;
+
+
+/* Line 1267 of yacc.c.  */
+#line 1708 "prsa_par.c"
+      default: break;
+    }
+  YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
+
+  YYPOPSTACK (yylen);
+  yylen = 0;
+  YY_STACK_PRINT (yyss, yyssp);
+
+  *++yyvsp = yyval;
+
+
+  /* Now `shift' the result of the reduction.  Determine what state
+     that goes to, based on the state we popped back to and the rule
+     number reduced by.  */
+
+  yyn = yyr1[yyn];
+
+  yystate = yypgoto[yyn - YYNTOKENS] + *yyssp;
+  if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp)
+    yystate = yytable[yystate];
+  else
+    yystate = yydefgoto[yyn - YYNTOKENS];
+
+  goto yynewstate;
+
+
+/*------------------------------------.
+| yyerrlab -- here on detecting error |
+`------------------------------------*/
+yyerrlab:
+  /* If not already recovering from an error, report this error.  */
+  if (!yyerrstatus)
+    {
+      ++yynerrs;
+#if ! YYERROR_VERBOSE
+      yyerror (YY_("syntax error"));
+#else
+      {
+	YYSIZE_T yysize = yysyntax_error (0, yystate, yychar);
+	if (yymsg_alloc < yysize && yymsg_alloc < YYSTACK_ALLOC_MAXIMUM)
+	  {
+	    YYSIZE_T yyalloc = 2 * yysize;
+	    if (! (yysize <= yyalloc && yyalloc <= YYSTACK_ALLOC_MAXIMUM))
+	      yyalloc = YYSTACK_ALLOC_MAXIMUM;
+	    if (yymsg != yymsgbuf)
+	      YYSTACK_FREE (yymsg);
+	    yymsg = (char *) YYSTACK_ALLOC (yyalloc);
+	    if (yymsg)
+	      yymsg_alloc = yyalloc;
+	    else
+	      {
+		yymsg = yymsgbuf;
+		yymsg_alloc = sizeof yymsgbuf;
+	      }
+	  }
+
+	if (0 < yysize && yysize <= yymsg_alloc)
+	  {
+	    (void) yysyntax_error (yymsg, yystate, yychar);
+	    yyerror (yymsg);
+	  }
+	else
+	  {
+	    yyerror (YY_("syntax error"));
+	    if (yysize != 0)
+	      goto yyexhaustedlab;
+	  }
+      }
+#endif
+    }
+
+
+
+  if (yyerrstatus == 3)
+    {
+      /* If just tried and failed to reuse look-ahead token after an
+	 error, discard it.  */
+
+      if (yychar <= YYEOF)
+	{
+	  /* Return failure if at end of input.  */
+	  if (yychar == YYEOF)
+	    YYABORT;
+	}
+      else
+	{
+	  yydestruct ("Error: discarding",
+		      yytoken, &yylval);
+	  yychar = YYEMPTY;
+	}
+    }
+
+  /* Else will try to reuse look-ahead token after shifting the error
+     token.  */
+  goto yyerrlab1;
+
+
+/*---------------------------------------------------.
+| yyerrorlab -- error raised explicitly by YYERROR.  |
+`---------------------------------------------------*/
+yyerrorlab:
+
+  /* Pacify compilers like GCC when the user code never invokes
+     YYERROR and the label yyerrorlab therefore never appears in user
+     code.  */
+  if (/*CONSTCOND*/ 0)
+     goto yyerrorlab;
+
+  /* Do not reclaim the symbols of the rule which action triggered
+     this YYERROR.  */
+  YYPOPSTACK (yylen);
+  yylen = 0;
+  YY_STACK_PRINT (yyss, yyssp);
+  yystate = *yyssp;
+  goto yyerrlab1;
+
+
+/*-------------------------------------------------------------.
+| yyerrlab1 -- common code for both syntax error and YYERROR.  |
+`-------------------------------------------------------------*/
+yyerrlab1:
+  yyerrstatus = 3;	/* Each real token shifted decrements this.  */
+
+  for (;;)
+    {
+      yyn = yypact[yystate];
+      if (yyn != YYPACT_NINF)
+	{
+	  yyn += YYTERROR;
+	  if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR)
+	    {
+	      yyn = yytable[yyn];
+	      if (0 < yyn)
+		break;
+	    }
+	}
+
+      /* Pop the current state because it cannot handle the error token.  */
+      if (yyssp == yyss)
+	YYABORT;
+
+
+      yydestruct ("Error: popping",
+		  yystos[yystate], yyvsp);
+      YYPOPSTACK (1);
+      yystate = *yyssp;
+      YY_STACK_PRINT (yyss, yyssp);
+    }
+
+  if (yyn == YYFINAL)
+    YYACCEPT;
+
+  *++yyvsp = yylval;
+
+
+  /* Shift the error token.  */
+  YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp);
+
+  yystate = yyn;
+  goto yynewstate;
+
+
+/*-------------------------------------.
+| yyacceptlab -- YYACCEPT comes here.  |
+`-------------------------------------*/
+yyacceptlab:
+  yyresult = 0;
+  goto yyreturn;
+
+/*-----------------------------------.
+| yyabortlab -- YYABORT comes here.  |
+`-----------------------------------*/
+yyabortlab:
+  yyresult = 1;
+  goto yyreturn;
+
+#ifndef yyoverflow
+/*-------------------------------------------------.
+| yyexhaustedlab -- memory exhaustion comes here.  |
+`-------------------------------------------------*/
+yyexhaustedlab:
+  yyerror (YY_("memory exhausted"));
+  yyresult = 2;
+  /* Fall through.  */
+#endif
+
+yyreturn:
+  if (yychar != YYEOF && yychar != YYEMPTY)
+     yydestruct ("Cleanup: discarding lookahead",
+		 yytoken, &yylval);
+  /* Do not reclaim the symbols of the rule which action triggered
+     this YYABORT or YYACCEPT.  */
+  YYPOPSTACK (yylen);
+  YY_STACK_PRINT (yyss, yyssp);
+  while (yyssp != yyss)
+    {
+      yydestruct ("Cleanup: popping",
+		  yystos[*yyssp], yyvsp);
+      YYPOPSTACK (1);
+    }
+#ifndef yyoverflow
+  if (yyss != yyssa)
+    YYSTACK_FREE (yyss);
+#endif
+#if YYERROR_VERBOSE
+  if (yymsg != yymsgbuf)
+    YYSTACK_FREE (yymsg);
+#endif
+  /* Make sure YYID is used.  */
+  return YYID (yyresult);
+}
+
+
+#line 307 "prsa_par.y"
+
+
+int prsaparse(void);
+
+int
+prsa_parse_file(struct genlist *list, char *fname, enum rsa_key_type type)
+{
+	FILE *fp = NULL;
+	int ret;
+	
+	if (!fname)
+		return -1;
+	if (type == RSA_TYPE_PRIVATE) {
+		struct stat st;
+		if (stat(fname, &st) < 0)
+			return -1;
+		if (st.st_mode & (S_IRWXG | S_IRWXO)) {
+			plog(LLV_ERROR, LOCATION, NULL,
+				"Too slack permissions on private key '%s'\n", 
+				fname);
+			plog(LLV_ERROR, LOCATION, NULL,
+				"Should be at most 0600, now is 0%o\n",
+				st.st_mode & 0777);
+			return -1;
+		}
+	}
+	fp = fopen(fname, "r");
+	if (!fp)
+		return -1;
+	prsain = fp;
+	prsa_cur_lineno = 1;
+	prsa_cur_fname = fname;
+	prsa_cur_list = list;
+	prsa_cur_type = type;
+	rsa_cur = RSA_new();
+	ret = prsaparse();
+	if (rsa_cur) {
+		RSA_free(rsa_cur);
+		rsa_cur = NULL;
+	}
+	fclose (fp);
+	prsain = NULL;
+	return ret;
+}
+
diff --git a/src/racoon/prsa_par.h b/src/racoon/prsa_par.h
new file mode 100644
index 0000000..3bdb11d
--- /dev/null
+++ b/src/racoon/prsa_par.h
@@ -0,0 +1,110 @@
+/* A Bison parser, made by GNU Bison 2.3.  */
+
+/* Skeleton interface for Bison's Yacc-like parsers in C
+
+   Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
+   Free Software Foundation, Inc.
+
+   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, or (at your option)
+   any later version.
+
+   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.
+
+   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., 51 Franklin Street, Fifth Floor,
+   Boston, MA 02110-1301, USA.  */
+
+/* As a special exception, you may create a larger work that contains
+   part or all of the Bison parser skeleton and distribute that work
+   under terms of your choice, so long as that work isn't itself a
+   parser generator using the skeleton or a modified version thereof
+   as a parser skeleton.  Alternatively, if you modify or redistribute
+   the parser skeleton itself, you may (at your option) remove this
+   special exception, which will cause the skeleton and the resulting
+   Bison output files to be licensed under the GNU General Public
+   License without this special exception.
+
+   This special exception was added by the Free Software Foundation in
+   version 2.2 of Bison.  */
+
+/* Tokens.  */
+#ifndef YYTOKENTYPE
+# define YYTOKENTYPE
+   /* Put the tokens into the symbol table, so that GDB and other debuggers
+      know about them.  */
+   enum yytokentype {
+     COLON = 258,
+     HEX = 259,
+     OBRACE = 260,
+     EBRACE = 261,
+     TAG_RSA = 262,
+     TAG_PUB = 263,
+     TAG_PSK = 264,
+     MODULUS = 265,
+     PUBLIC_EXPONENT = 266,
+     PRIVATE_EXPONENT = 267,
+     PRIME1 = 268,
+     PRIME2 = 269,
+     EXPONENT1 = 270,
+     EXPONENT2 = 271,
+     COEFFICIENT = 272,
+     ADDR4 = 273,
+     ADDR6 = 274,
+     ADDRANY = 275,
+     SLASH = 276,
+     NUMBER = 277,
+     BASE64 = 278
+   };
+#endif
+/* Tokens.  */
+#define COLON 258
+#define HEX 259
+#define OBRACE 260
+#define EBRACE 261
+#define TAG_RSA 262
+#define TAG_PUB 263
+#define TAG_PSK 264
+#define MODULUS 265
+#define PUBLIC_EXPONENT 266
+#define PRIVATE_EXPONENT 267
+#define PRIME1 268
+#define PRIME2 269
+#define EXPONENT1 270
+#define EXPONENT2 271
+#define COEFFICIENT 272
+#define ADDR4 273
+#define ADDR6 274
+#define ADDRANY 275
+#define SLASH 276
+#define NUMBER 277
+#define BASE64 278
+
+
+
+
+#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
+typedef union YYSTYPE
+#line 130 "prsa_par.y"
+{
+	BIGNUM *bn;
+	RSA *rsa;
+	char *chr;
+	long num;
+	struct netaddr *naddr;
+}
+/* Line 1489 of yacc.c.  */
+#line 103 "prsa_par.h"
+	YYSTYPE;
+# define yystype YYSTYPE /* obsolescent; will be withdrawn */
+# define YYSTYPE_IS_DECLARED 1
+# define YYSTYPE_IS_TRIVIAL 1
+#endif
+
+extern YYSTYPE prsalval;
+
diff --git a/src/racoon/prsa_par.y b/src/racoon/prsa_par.y
new file mode 100644
index 0000000..f21a82b
--- /dev/null
+++ b/src/racoon/prsa_par.y
@@ -0,0 +1,350 @@
+/*	$NetBSD: prsa_par.y,v 1.4 2006/09/09 16:22:10 manu Exp $	*/
+
+/* Id: prsa_par.y,v 1.3 2004/11/08 12:04:23 ludvigm Exp */
+
+%{
+/*
+ * Copyright (C) 2004 SuSE Linux AG, Nuernberg, Germany.
+ * Contributed by: Michal Ludvig <mludvig@suse.cz>, SUSE Labs
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* This file contains a parser for FreeS/WAN-style ipsec.secrets RSA keys. */
+
+#include "config.h"
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+
+#ifdef HAVE_STDARG_H
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
+
+#include <netdb.h>
+#include <netinet/in.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+#include <sys/types.h>
+
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include <openssl/bn.h>
+#include <openssl/rsa.h>
+
+#include "misc.h"
+#include "vmbuf.h"
+#include "plog.h"
+#include "oakley.h"
+#include "isakmp_var.h"
+#include "handler.h"
+#include "crypto_openssl.h"
+#include "sockmisc.h"
+#include "rsalist.h"
+
+extern void prsaerror(const char *str, ...);
+extern int prsawrap (void);
+extern int prsalex (void);
+
+extern char *prsatext;
+extern int prsa_cur_lineno;
+extern char *prsa_cur_fname;
+extern FILE *prsain;
+
+int prsa_cur_lineno = 0;
+char *prsa_cur_fname = NULL;
+struct genlist *prsa_cur_list = NULL;
+enum rsa_key_type prsa_cur_type = RSA_TYPE_ANY;
+
+static RSA *rsa_cur;
+
+void
+prsaerror(const char *s, ...)
+{
+	char fmt[512];
+
+	va_list ap;
+#ifdef HAVE_STDARG_H
+	va_start(ap, s);
+#else
+	va_start(ap);
+#endif
+	snprintf(fmt, sizeof(fmt), "%s:%d: %s",
+		prsa_cur_fname, prsa_cur_lineno, s);
+	plogv(LLV_ERROR, LOCATION, NULL, fmt, ap);
+	va_end(ap);
+}
+
+void
+prsawarning(const char *s, ...)
+{
+	char fmt[512];
+
+	va_list ap;
+#ifdef HAVE_STDARG_H
+	va_start(ap, s);
+#else
+	va_start(ap);
+#endif
+	snprintf(fmt, sizeof(fmt), "%s:%d: %s",
+		prsa_cur_fname, prsa_cur_lineno, s);
+	plogv(LLV_WARNING, LOCATION, NULL, fmt, ap);
+	va_end(ap);
+}
+
+int
+prsawrap()
+{
+	return 1;
+} 
+%}
+%union {
+	BIGNUM *bn;
+	RSA *rsa;
+	char *chr;
+	long num;
+	struct netaddr *naddr;
+}
+
+%token COLON HEX
+%token OBRACE EBRACE COLON HEX
+%token TAG_RSA TAG_PUB TAG_PSK
+%token MODULUS PUBLIC_EXPONENT PRIVATE_EXPONENT 
+%token PRIME1 PRIME2 EXPONENT1 EXPONENT2 COEFFICIENT
+%token ADDR4 ADDR6 ADDRANY SLASH NUMBER BASE64
+
+%type <bn>	HEX
+%type <num>	NUMBER
+%type <chr>	ADDR4 ADDR6 BASE64
+
+%type <rsa>	rsa_statement
+%type <num>	prefix
+%type <naddr>	addr4 addr6 addr
+
+%%
+statements:
+	statements statement
+	| statement
+	;
+
+statement:
+	addr addr COLON rsa_statement
+	{
+		rsa_key_insert(prsa_cur_list, $1, $2, $4);
+	}
+	| addr COLON rsa_statement 
+	{
+		rsa_key_insert(prsa_cur_list, NULL, $1, $3);
+	}
+	| COLON rsa_statement 
+	{
+		rsa_key_insert(prsa_cur_list, NULL, NULL, $2);
+	}
+	;
+
+rsa_statement:
+	TAG_RSA OBRACE params EBRACE
+	{
+		if (prsa_cur_type == RSA_TYPE_PUBLIC) {
+			prsawarning("Using private key for public key purpose.\n");
+			if (!rsa_cur->n || !rsa_cur->e) {
+				prsaerror("Incomplete key. Mandatory parameters are missing!\n");
+				YYABORT;
+			}
+		}
+		else {
+			if (!rsa_cur->n || !rsa_cur->e || !rsa_cur->d) {
+				prsaerror("Incomplete key. Mandatory parameters are missing!\n");
+				YYABORT;
+			}
+			if (!rsa_cur->p || !rsa_cur->q || !rsa_cur->dmp1
+			    || !rsa_cur->dmq1 || !rsa_cur->iqmp) {
+				if (rsa_cur->p) BN_clear_free(rsa_cur->p);
+				if (rsa_cur->q) BN_clear_free(rsa_cur->q);
+				if (rsa_cur->dmp1) BN_clear_free(rsa_cur->dmp1);
+				if (rsa_cur->dmq1) BN_clear_free(rsa_cur->dmq1);
+				if (rsa_cur->iqmp) BN_clear_free(rsa_cur->iqmp);
+
+				rsa_cur->p = NULL;
+				rsa_cur->q = NULL;
+				rsa_cur->dmp1 = NULL;
+				rsa_cur->dmq1 = NULL;
+				rsa_cur->iqmp = NULL;
+			}
+		}
+		$$ = rsa_cur;
+		rsa_cur = RSA_new();
+	}
+	| TAG_PUB BASE64
+	{
+		if (prsa_cur_type == RSA_TYPE_PRIVATE) {
+			prsaerror("Public key in private-key file!\n");
+			YYABORT;
+		}
+		$$ = base64_pubkey2rsa($2);
+	}
+	| TAG_PUB HEX
+	{
+		if (prsa_cur_type == RSA_TYPE_PRIVATE) {
+			prsaerror("Public key in private-key file!\n");
+			YYABORT;
+		}
+		$$ = bignum_pubkey2rsa($2);
+	}
+	;
+
+addr:
+	addr4
+	| addr6
+	| ADDRANY
+	{
+		$$ = NULL;
+	}
+	;
+
+addr4:
+	ADDR4 prefix
+	{
+		int err;
+		struct sockaddr_in *sap;
+		
+		if ($2 == -1) $2 = 32;
+		if ($2 < 0 || $2 > 32) {
+			prsaerror ("Invalid IPv4 prefix\n");
+			YYABORT;
+		}
+		$$ = calloc (sizeof(struct netaddr), 1);
+		$$->prefix = $2;
+		sap = (struct sockaddr_in *)(&$$->sa);
+		sap->sin_family = AF_INET;
+		err = inet_pton(AF_INET, $1, (struct in_addr*)(&sap->sin_addr));
+		if (err <= 0) {
+			prsaerror("inet_pton(%s): %s\n", $1, strerror(errno));
+			YYABORT;
+		}
+	}
+	;
+
+addr6:
+	ADDR6 prefix
+	{
+		int err;
+		struct sockaddr_in6 *sap;
+		
+		if ($2 == -1) $2 = 128;
+		if ($2 < 0 || $2 > 128) {
+			prsaerror ("Invalid IPv6 prefix\n");
+			YYABORT;
+		}
+		$$ = calloc (sizeof(struct netaddr), 1);
+		$$->prefix = $2;
+		sap = (struct sockaddr_in6 *)(&$$->sa);
+		sap->sin6_family = AF_INET6;
+		err = inet_pton(AF_INET6, $1, (struct in6_addr*)(&sap->sin6_addr));
+		if (err <= 0) {
+			prsaerror("inet_pton(%s): %s\n", $1, strerror(errno));
+			YYABORT;
+		}
+	}
+	;
+
+prefix:
+	/* nothing */ { $$ = -1; }
+	| SLASH NUMBER { $$ = $2; }
+	;
+params:
+	params param
+	| param
+	;
+
+param:
+	MODULUS COLON HEX 
+	{ if (!rsa_cur->n) rsa_cur->n = $3; else { prsaerror ("Modulus already defined\n"); YYABORT; } }
+	| PUBLIC_EXPONENT COLON HEX 
+	{ if (!rsa_cur->e) rsa_cur->e = $3; else { prsaerror ("PublicExponent already defined\n"); YYABORT; } }
+	| PRIVATE_EXPONENT COLON HEX 
+	{ if (!rsa_cur->d) rsa_cur->d = $3; else { prsaerror ("PrivateExponent already defined\n"); YYABORT; } }
+	| PRIME1 COLON HEX 
+	{ if (!rsa_cur->p) rsa_cur->p = $3; else { prsaerror ("Prime1 already defined\n"); YYABORT; } }
+	| PRIME2 COLON HEX 
+	{ if (!rsa_cur->q) rsa_cur->q = $3; else { prsaerror ("Prime2 already defined\n"); YYABORT; } }
+	| EXPONENT1 COLON HEX 
+	{ if (!rsa_cur->dmp1) rsa_cur->dmp1 = $3; else { prsaerror ("Exponent1 already defined\n"); YYABORT; } }
+	| EXPONENT2 COLON HEX 
+	{ if (!rsa_cur->dmq1) rsa_cur->dmq1 = $3; else { prsaerror ("Exponent2 already defined\n"); YYABORT; } }
+	| COEFFICIENT COLON HEX 
+	{ if (!rsa_cur->iqmp) rsa_cur->iqmp = $3; else { prsaerror ("Coefficient already defined\n"); YYABORT; } }
+	;
+%%
+
+int prsaparse(void);
+
+int
+prsa_parse_file(struct genlist *list, char *fname, enum rsa_key_type type)
+{
+	FILE *fp = NULL;
+	int ret;
+	
+	if (!fname)
+		return -1;
+	if (type == RSA_TYPE_PRIVATE) {
+		struct stat st;
+		if (stat(fname, &st) < 0)
+			return -1;
+		if (st.st_mode & (S_IRWXG | S_IRWXO)) {
+			plog(LLV_ERROR, LOCATION, NULL,
+				"Too slack permissions on private key '%s'\n", 
+				fname);
+			plog(LLV_ERROR, LOCATION, NULL,
+				"Should be at most 0600, now is 0%o\n",
+				st.st_mode & 0777);
+			return -1;
+		}
+	}
+	fp = fopen(fname, "r");
+	if (!fp)
+		return -1;
+	prsain = fp;
+	prsa_cur_lineno = 1;
+	prsa_cur_fname = fname;
+	prsa_cur_list = list;
+	prsa_cur_type = type;
+	rsa_cur = RSA_new();
+	ret = prsaparse();
+	if (rsa_cur) {
+		RSA_free(rsa_cur);
+		rsa_cur = NULL;
+	}
+	fclose (fp);
+	prsain = NULL;
+	return ret;
+}
diff --git a/src/racoon/prsa_tok.c b/src/racoon/prsa_tok.c
new file mode 100644
index 0000000..17d30db
--- /dev/null
+++ b/src/racoon/prsa_tok.c
@@ -0,0 +1,2143 @@
+#line 2 "prsa_tok.c"
+
+#line 4 "prsa_tok.c"
+
+#define  YY_INT_ALIGNED short int
+
+/* A lexical scanner generated by flex */
+
+#define yy_create_buffer prsa_create_buffer
+#define yy_delete_buffer prsa_delete_buffer
+#define yy_flex_debug prsa_flex_debug
+#define yy_init_buffer prsa_init_buffer
+#define yy_flush_buffer prsa_flush_buffer
+#define yy_load_buffer_state prsa_load_buffer_state
+#define yy_switch_to_buffer prsa_switch_to_buffer
+#define yyin prsain
+#define yyleng prsaleng
+#define yylex prsalex
+#define yylineno prsalineno
+#define yyout prsaout
+#define yyrestart prsarestart
+#define yytext prsatext
+#define yywrap prsawrap
+#define yyalloc prsaalloc
+#define yyrealloc prsarealloc
+#define yyfree prsafree
+
+#define FLEX_SCANNER
+#define YY_FLEX_MAJOR_VERSION 2
+#define YY_FLEX_MINOR_VERSION 5
+#define YY_FLEX_SUBMINOR_VERSION 35
+#if YY_FLEX_SUBMINOR_VERSION > 0
+#define FLEX_BETA
+#endif
+
+/* First, we deal with  platform-specific or compiler-specific issues. */
+
+/* begin standard C headers. */
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <stdlib.h>
+
+/* end standard C headers. */
+
+/* flex integer type definitions */
+
+#ifndef FLEXINT_H
+#define FLEXINT_H
+
+/* C99 systems have <inttypes.h>. Non-C99 systems may or may not. */
+
+#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
+
+/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h,
+ * if you want the limit (max/min) macros for int types. 
+ */
+#ifndef __STDC_LIMIT_MACROS
+#define __STDC_LIMIT_MACROS 1
+#endif
+
+#include <inttypes.h>
+typedef int8_t flex_int8_t;
+typedef uint8_t flex_uint8_t;
+typedef int16_t flex_int16_t;
+typedef uint16_t flex_uint16_t;
+typedef int32_t flex_int32_t;
+typedef uint32_t flex_uint32_t;
+#else
+typedef signed char flex_int8_t;
+typedef short int flex_int16_t;
+typedef int flex_int32_t;
+typedef unsigned char flex_uint8_t; 
+typedef unsigned short int flex_uint16_t;
+typedef unsigned int flex_uint32_t;
+
+/* Limits of integral types. */
+#ifndef INT8_MIN
+#define INT8_MIN               (-128)
+#endif
+#ifndef INT16_MIN
+#define INT16_MIN              (-32767-1)
+#endif
+#ifndef INT32_MIN
+#define INT32_MIN              (-2147483647-1)
+#endif
+#ifndef INT8_MAX
+#define INT8_MAX               (127)
+#endif
+#ifndef INT16_MAX
+#define INT16_MAX              (32767)
+#endif
+#ifndef INT32_MAX
+#define INT32_MAX              (2147483647)
+#endif
+#ifndef UINT8_MAX
+#define UINT8_MAX              (255U)
+#endif
+#ifndef UINT16_MAX
+#define UINT16_MAX             (65535U)
+#endif
+#ifndef UINT32_MAX
+#define UINT32_MAX             (4294967295U)
+#endif
+
+#endif /* ! C99 */
+
+#endif /* ! FLEXINT_H */
+
+#ifdef __cplusplus
+
+/* The "const" storage-class-modifier is valid. */
+#define YY_USE_CONST
+
+#else	/* ! __cplusplus */
+
+/* C99 requires __STDC__ to be defined as 1. */
+#if defined (__STDC__)
+
+#define YY_USE_CONST
+
+#endif	/* defined (__STDC__) */
+#endif	/* ! __cplusplus */
+
+#ifdef YY_USE_CONST
+#define yyconst const
+#else
+#define yyconst
+#endif
+
+/* Returned upon end-of-file. */
+#define YY_NULL 0
+
+/* Promotes a possibly negative, possibly signed char to an unsigned
+ * integer for use as an array index.  If the signed char is negative,
+ * we want to instead treat it as an 8-bit unsigned char, hence the
+ * double cast.
+ */
+#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c)
+
+/* Enter a start condition.  This macro really ought to take a parameter,
+ * but we do it the disgusting crufty way forced on us by the ()-less
+ * definition of BEGIN.
+ */
+#define BEGIN (yy_start) = 1 + 2 *
+
+/* Translate the current start state into a value that can be later handed
+ * to BEGIN to return to the state.  The YYSTATE alias is for lex
+ * compatibility.
+ */
+#define YY_START (((yy_start) - 1) / 2)
+#define YYSTATE YY_START
+
+/* Action number for EOF rule of a given start state. */
+#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1)
+
+/* Special action meaning "start processing a new file". */
+#define YY_NEW_FILE prsarestart(prsain  )
+
+#define YY_END_OF_BUFFER_CHAR 0
+
+/* Size of default input buffer. */
+#ifndef YY_BUF_SIZE
+#define YY_BUF_SIZE 16384
+#endif
+
+/* The state buf must be large enough to hold one state per character in the main buffer.
+ */
+#define YY_STATE_BUF_SIZE   ((YY_BUF_SIZE + 2) * sizeof(yy_state_type))
+
+#ifndef YY_TYPEDEF_YY_BUFFER_STATE
+#define YY_TYPEDEF_YY_BUFFER_STATE
+typedef struct yy_buffer_state *YY_BUFFER_STATE;
+#endif
+
+extern int prsaleng;
+
+extern FILE *prsain, *prsaout;
+
+#define EOB_ACT_CONTINUE_SCAN 0
+#define EOB_ACT_END_OF_FILE 1
+#define EOB_ACT_LAST_MATCH 2
+
+    #define YY_LESS_LINENO(n)
+    
+/* Return all but the first "n" matched characters back to the input stream. */
+#define yyless(n) \
+	do \
+		{ \
+		/* Undo effects of setting up prsatext. */ \
+        int yyless_macro_arg = (n); \
+        YY_LESS_LINENO(yyless_macro_arg);\
+		*yy_cp = (yy_hold_char); \
+		YY_RESTORE_YY_MORE_OFFSET \
+		(yy_c_buf_p) = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \
+		YY_DO_BEFORE_ACTION; /* set up prsatext again */ \
+		} \
+	while ( 0 )
+
+#define unput(c) yyunput( c, (yytext_ptr)  )
+
+#ifndef YY_TYPEDEF_YY_SIZE_T
+#define YY_TYPEDEF_YY_SIZE_T
+typedef size_t yy_size_t;
+#endif
+
+#ifndef YY_STRUCT_YY_BUFFER_STATE
+#define YY_STRUCT_YY_BUFFER_STATE
+struct yy_buffer_state
+	{
+	FILE *yy_input_file;
+
+	char *yy_ch_buf;		/* input buffer */
+	char *yy_buf_pos;		/* current position in input buffer */
+
+	/* Size of input buffer in bytes, not including room for EOB
+	 * characters.
+	 */
+	yy_size_t yy_buf_size;
+
+	/* Number of characters read into yy_ch_buf, not including EOB
+	 * characters.
+	 */
+	int yy_n_chars;
+
+	/* Whether we "own" the buffer - i.e., we know we created it,
+	 * and can realloc() it to grow it, and should free() it to
+	 * delete it.
+	 */
+	int yy_is_our_buffer;
+
+	/* Whether this is an "interactive" input source; if so, and
+	 * if we're using stdio for input, then we want to use getc()
+	 * instead of fread(), to make sure we stop fetching input after
+	 * each newline.
+	 */
+	int yy_is_interactive;
+
+	/* Whether we're considered to be at the beginning of a line.
+	 * If so, '^' rules will be active on the next match, otherwise
+	 * not.
+	 */
+	int yy_at_bol;
+
+    int yy_bs_lineno; /**< The line count. */
+    int yy_bs_column; /**< The column count. */
+    
+	/* Whether to try to fill the input buffer when we reach the
+	 * end of it.
+	 */
+	int yy_fill_buffer;
+
+	int yy_buffer_status;
+
+#define YY_BUFFER_NEW 0
+#define YY_BUFFER_NORMAL 1
+	/* When an EOF's been seen but there's still some text to process
+	 * then we mark the buffer as YY_EOF_PENDING, to indicate that we
+	 * shouldn't try reading from the input source any more.  We might
+	 * still have a bunch of tokens to match, though, because of
+	 * possible backing-up.
+	 *
+	 * When we actually see the EOF, we change the status to "new"
+	 * (via prsarestart()), so that the user can continue scanning by
+	 * just pointing prsain at a new input file.
+	 */
+#define YY_BUFFER_EOF_PENDING 2
+
+	};
+#endif /* !YY_STRUCT_YY_BUFFER_STATE */
+
+/* Stack of input buffers. */
+static size_t yy_buffer_stack_top = 0; /**< index of top of stack. */
+static size_t yy_buffer_stack_max = 0; /**< capacity of stack. */
+static YY_BUFFER_STATE * yy_buffer_stack = 0; /**< Stack as an array. */
+
+/* We provide macros for accessing buffer states in case in the
+ * future we want to put the buffer states in a more general
+ * "scanner state".
+ *
+ * Returns the top of the stack, or NULL.
+ */
+#define YY_CURRENT_BUFFER ( (yy_buffer_stack) \
+                          ? (yy_buffer_stack)[(yy_buffer_stack_top)] \
+                          : NULL)
+
+/* Same as previous macro, but useful when we know that the buffer stack is not
+ * NULL or when we need an lvalue. For internal use only.
+ */
+#define YY_CURRENT_BUFFER_LVALUE (yy_buffer_stack)[(yy_buffer_stack_top)]
+
+/* yy_hold_char holds the character lost when prsatext is formed. */
+static char yy_hold_char;
+static int yy_n_chars;		/* number of characters read into yy_ch_buf */
+int prsaleng;
+
+/* Points to current character in buffer. */
+static char *yy_c_buf_p = (char *) 0;
+static int yy_init = 0;		/* whether we need to initialize */
+static int yy_start = 0;	/* start state number */
+
+/* Flag which is used to allow prsawrap()'s to do buffer switches
+ * instead of setting up a fresh prsain.  A bit of a hack ...
+ */
+static int yy_did_buffer_switch_on_eof;
+
+void prsarestart (FILE *input_file  );
+void prsa_switch_to_buffer (YY_BUFFER_STATE new_buffer  );
+YY_BUFFER_STATE prsa_create_buffer (FILE *file,int size  );
+void prsa_delete_buffer (YY_BUFFER_STATE b  );
+void prsa_flush_buffer (YY_BUFFER_STATE b  );
+void prsapush_buffer_state (YY_BUFFER_STATE new_buffer  );
+void prsapop_buffer_state (void );
+
+static void prsaensure_buffer_stack (void );
+static void prsa_load_buffer_state (void );
+static void prsa_init_buffer (YY_BUFFER_STATE b,FILE *file  );
+
+#define YY_FLUSH_BUFFER prsa_flush_buffer(YY_CURRENT_BUFFER )
+
+YY_BUFFER_STATE prsa_scan_buffer (char *base,yy_size_t size  );
+YY_BUFFER_STATE prsa_scan_string (yyconst char *yy_str  );
+YY_BUFFER_STATE prsa_scan_bytes (yyconst char *bytes,int len  );
+
+void *prsaalloc (yy_size_t  );
+void *prsarealloc (void *,yy_size_t  );
+void prsafree (void *  );
+
+#define yy_new_buffer prsa_create_buffer
+
+#define yy_set_interactive(is_interactive) \
+	{ \
+	if ( ! YY_CURRENT_BUFFER ){ \
+        prsaensure_buffer_stack (); \
+		YY_CURRENT_BUFFER_LVALUE =    \
+            prsa_create_buffer(prsain,YY_BUF_SIZE ); \
+	} \
+	YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \
+	}
+
+#define yy_set_bol(at_bol) \
+	{ \
+	if ( ! YY_CURRENT_BUFFER ){\
+        prsaensure_buffer_stack (); \
+		YY_CURRENT_BUFFER_LVALUE =    \
+            prsa_create_buffer(prsain,YY_BUF_SIZE ); \
+	} \
+	YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \
+	}
+
+#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol)
+
+/* Begin user sect3 */
+
+typedef unsigned char YY_CHAR;
+
+FILE *prsain = (FILE *) 0, *prsaout = (FILE *) 0;
+
+typedef int yy_state_type;
+
+extern int prsalineno;
+
+int prsalineno = 1;
+
+extern char *prsatext;
+#define yytext_ptr prsatext
+
+static yy_state_type yy_get_previous_state (void );
+static yy_state_type yy_try_NUL_trans (yy_state_type current_state  );
+static int yy_get_next_buffer (void );
+static void yy_fatal_error (yyconst char msg[]  );
+
+/* Done after the current pattern has been matched and before the
+ * corresponding action - sets up prsatext.
+ */
+#define YY_DO_BEFORE_ACTION \
+	(yytext_ptr) = yy_bp; \
+	prsaleng = (size_t) (yy_cp - yy_bp); \
+	(yy_hold_char) = *yy_cp; \
+	*yy_cp = '\0'; \
+	(yy_c_buf_p) = yy_cp;
+
+#define YY_NUM_RULES 25
+#define YY_END_OF_BUFFER 26
+/* This struct is not used in this scanner,
+   but its presence is necessary. */
+struct yy_trans_info
+	{
+	flex_int32_t yy_verify;
+	flex_int32_t yy_nxt;
+	};
+static yyconst flex_int16_t yy_accept[194] =
+    {   0,
+       22,   22,   26,   25,   22,   23,   24,   17,   18,   18,
+       18,   18,    3,   25,   25,   25,   25,   25,   25,   25,
+        1,    2,   22,   24,    0,   18,   21,    0,    0,    0,
+       18,   18,   18,   21,   21,   21,   21,   21,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+       18,    0,   21,    8,    7,   18,    0,   21,   21,   21,
+       21,   21,   21,   21,   21,   21,    0,    0,    0,    5,
+        6,    0,    0,    4,   19,    0,    0,    0,    0,   18,
+        0,    0,    0,    0,   21,   21,    0,   21,   21,   21,
+       21,   21,    0,    0,    0,    0,    0,    0,    0,    0,
+
+        0,   18,    0,    0,    0,    0,   21,    0,    0,    0,
+       21,   21,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,   12,   13,    0,    0,   20,   20,   20,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    9,    0,
+        0,   20,   20,   20,   21,   21,   21,    0,    0,    0,
+        0,    0,    0,    0,    0,   21,   21,   21,   21,   21,
+       21,    0,   14,   15,    0,    0,   21,   21,   21,    0,
+        0,    0,   16,    0,    0,    0,    0,    0,    0,    0,
+       10,   11,    0
+
+    } ;
+
+static yyconst flex_int32_t yy_ec[256] =
+    {   0,
+        1,    1,    1,    1,    1,    1,    1,    1,    2,    3,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    2,    1,    1,    4,    1,    1,    1,    1,    1,
+        1,    1,    5,    1,    1,    6,    7,    8,    9,   10,
+       11,   11,   12,   13,   13,   13,   13,   14,    1,    1,
+        5,    1,    1,    1,   15,   16,   17,   18,   19,   18,
+        5,    5,    5,    5,   20,    5,   21,    5,    5,   22,
+        5,   23,   24,    5,   25,    5,    5,    5,    5,    5,
+        1,    1,    1,    1,    1,    1,   26,   27,   28,   29,
+
+       30,   31,    5,    5,   32,    5,    5,   33,   34,   35,
+       36,   37,    5,   38,   39,   40,   41,   42,    5,   43,
+       44,    5,   45,    1,   46,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1
+    } ;
+
+static yyconst flex_int32_t yy_meta[47] =
+    {   0,
+        1,    1,    2,    1,    3,    4,    3,    5,    5,    5,
+        5,    5,    5,    6,    7,    7,    7,    7,    7,    3,
+        3,    3,    3,    3,    3,    7,    7,    7,    7,    7,
+        7,    3,    3,    3,    3,    3,    3,    3,    3,    3,
+        3,    3,    3,    3,    1,    1
+    } ;
+
+static yyconst flex_int16_t yy_base[213] =
+    {   0,
+        0,    0,  674,  675,  671,  675,    0,  675,   41,   22,
+       77,   65,  113,  122,  636,  628,  634,   54,  645,  633,
+      675,  675,  665,    0,   88,  130,  154,  163,    0,    0,
+        0,  653,   94,  171,  100,  142,  195,  204,  635,  627,
+      634,  642,  645,  628,  632,  643,  613,  650,  212,  649,
+      220,  246,    0,    0,    0,  648,  183,  254,  280,    0,
+      640,  646,  288,  232,  266,  314,  620,  614,  608,  675,
+      675,   49,  615,  675,  675,  300,  641,  322,  640,  631,
+      630,  637,  329,  636,  123,  164,  335,  343,  369,    0,
+      628,  634,  608,  603,  604,  606,  609,  602,  627,  377,
+
+      626,  355,  383,  625,  391,  624,  615,  622,  398,  621,
+      205,  247,  594,  595,  583,   53,  583,  594,  404,  615,
+      412,  614,  613,  419,  612,  425,  577,  433,  574,  550,
+      533,  482,  675,  675,  448,  452,  438,  444,  450,  456,
+      434,  464,  420,  413,  471,  399,  366,  344,  675,  357,
+      307,  477,  483,  675,  488,  494,  500,  506,  330,  514,
+      323,  291,   72,  252,  250,  519,  525,  675,  530,  536,
+      542,  244,  675,  675,  190,  119,  548,  554,  675,   79,
+       82,   82,  675,   80,   84,   64,   58,   31,   24,    8,
+      675,  675,  675,  566,  569,  574,  577,  580,  584,  586,
+
+      587,  590,  592,  594,  598,  600,  602,  604,  606,  608,
+      610,  612
+    } ;
+
+static yyconst flex_int16_t yy_def[213] =
+    {   0,
+      193,    1,  193,  193,  193,  193,  194,  193,  193,    9,
+        9,   11,  195,   11,   14,   14,  193,  193,  193,   14,
+      193,  193,  193,  194,  193,  193,  195,   26,  196,  197,
+       26,   26,   26,  193,   34,   35,  198,   35,  193,  193,
+      193,  193,  193,  193,  193,  193,  193,  199,  193,  200,
+      193,   51,   27,  196,  197,   51,  193,  193,   58,   58,
+       58,   59,  193,   63,   64,   64,  193,  193,  193,  193,
+      193,  193,  193,  193,  193,  193,  200,  193,  193,  201,
+      193,  202,  193,  203,  204,  204,  193,  193,   88,   88,
+       88,   89,  193,  193,  193,  193,  193,  193,  205,  193,
+
+      206,  193,  193,  203,  193,  193,  193,  207,  193,  208,
+      204,  204,  193,  193,  193,  193,  193,  193,  193,  206,
+      193,  193,  209,  193,  210,  193,  208,  193,  193,  193,
+      193,  193,  193,  193,  193,  193,  193,  193,  193,  193,
+      210,  193,  193,  211,  193,  212,  193,  193,  193,  193,
+      193,  193,  193,  193,  193,  193,  193,  193,  212,  193,
+      193,  193,  193,  193,  193,  193,  193,  193,  193,  193,
+      193,  193,  193,  193,  193,  193,  193,  193,  193,  193,
+      193,  193,  193,  193,  193,  193,  193,  193,  193,  193,
+      193,  193,    0,  193,  193,  193,  193,  193,  193,  193,
+
+      193,  193,  193,  193,  193,  193,  193,  193,  193,  193,
+      193,  193
+    } ;
+
+static yyconst flex_int16_t yy_nxt[722] =
+    {   0,
+        4,    5,    6,    7,    4,    4,    8,    9,   10,   11,
+       12,   12,   12,   13,   14,   14,   15,   14,   16,    4,
+       17,   18,   19,    4,    4,   20,   14,   14,   14,   14,
+       14,    4,    4,    4,    4,    4,    4,    4,    4,    4,
+        4,    4,    4,    4,   21,   22,   25,  192,   26,   26,
+       26,   26,   26,   26,   27,   28,   28,   28,   28,   28,
+      193,  133,  134,  191,  193,  190,   28,   28,   28,   28,
+       28,   28,   33,   33,   33,   33,   33,   42,   43,   29,
+      173,  174,   96,   30,   31,   31,   31,   31,   32,   33,
+       97,   44,  189,  188,   45,   48,   48,   49,   50,   50,
+
+       50,   56,   56,   56,   56,   56,   56,   60,   60,   60,
+       60,   61,   62,  187,  186,  193,  185,  184,  183,  193,
+       34,   34,   35,   36,   36,   36,   37,  193,   57,   28,
+       28,   28,   28,   28,   28,   25,   27,   51,   51,   51,
+       51,   51,   51,   27,   52,   52,   52,   52,   52,   62,
+       62,   62,   62,   62,  182,   52,   52,   52,   52,   52,
+       52,   34,   34,   35,   36,   36,   36,   53,  193,  193,
+       52,   52,   52,   52,   52,   52,   57,   27,   58,   58,
+       58,   58,   58,   58,   27,   59,   59,   59,   59,   59,
+       82,   82,   83,   84,   84,   84,   59,   59,   59,   59,
+
+       59,   59,   63,   63,   64,   65,   65,   65,   53,  193,
+       87,   59,   59,   59,   59,   59,   59,   76,   27,   77,
+       77,   77,   77,   78,   79,   25,  181,   80,   80,   80,
+       80,   80,   80,   27,   81,   81,   81,   81,   81,   90,
+       90,   90,   90,   91,   92,   81,   81,   81,   81,   81,
+       81,  193,  193,   81,   81,   81,   81,   81,   81,   57,
+       27,   85,   85,   85,   85,   85,   85,   27,   86,   86,
+       86,   86,   86,   92,   92,   92,   92,   92,  180,   86,
+       86,   86,   86,   86,   86,  193,  176,   86,   86,   86,
+       86,   86,   86,   87,  175,   88,   88,   88,   88,   88,
+
+       88,   27,   89,   89,   89,   89,   89,   99,   99,  100,
+      101,  101,  101,   89,   89,   89,   89,   89,   89,  193,
+      172,   89,   89,   89,   89,   89,   89,   76,  158,   79,
+       79,   79,   79,   79,  103,  158,  104,  104,  104,  104,
+      105,  106,  108,  108,  109,  110,  110,  110,   87,  165,
+      111,  111,  111,  111,  111,  111,   27,  112,  112,  112,
+      112,  112,  102,  102,  102,  102,  102,  102,  112,  112,
+      112,  112,  112,  112,  193,  164,  112,  112,  112,  112,
+      112,  112,  119,  163,  120,  120,  120,  120,  121,  122,
+      123,  123,  124,  125,  125,  125,  103,  162,  106,  106,
+
+      106,  106,  106,  126,  158,  127,  127,  127,  127,  128,
+      129,  137,  137,  138,  139,  139,  139,  119,  158,  122,
+      122,  122,  122,  122,  140,  140,  141,  141,  141,  141,
+      142,  143,  144,  144,  145,  146,  146,  146,  126,  140,
+      129,  129,  129,  129,  129,  139,  139,  139,  139,  139,
+      139,  152,  152,  152,  152,  153,  154,  154,  154,  154,
+      154,  154,  154,  155,  155,  156,  157,  157,  157,  140,
+      151,  143,  143,  143,  143,  143,  158,  150,  159,  159,
+      159,  159,  160,  161,  154,  154,  154,  154,  154,  154,
+      154,  154,  154,  154,  154,  157,  157,  157,  157,  157,
+
+      157,  166,  166,  166,  166,  167,  168,  168,  168,  168,
+      168,  168,  168,  169,  169,  170,  171,  171,  171,  158,
+      149,  161,  161,  161,  161,  161,  168,  168,  168,  168,
+      168,  168,  168,  168,  168,  168,  168,  171,  171,  171,
+      171,  171,  171,  177,  177,  177,  177,  178,  179,  179,
+      179,  179,  179,  179,  179,  179,  179,  179,  179,  179,
+      179,  179,  179,  179,  179,  179,   24,  148,   24,   24,
+       24,   24,   24,   38,   38,   38,   54,  147,   54,  126,
+       54,   55,  126,   55,   66,   66,   66,   50,   50,   79,
+       79,  102,  102,   84,   84,  106,  106,  107,  107,  107,
+
+      107,  101,  101,  122,  122,  110,  110,  129,  129,  125,
+      125,  143,  143,  146,  146,  161,  161,  140,  140,  119,
+      119,  136,  135,  132,  131,  130,  126,  126,   27,  103,
+      103,  119,  119,  118,  117,  116,  115,  114,  113,   87,
+      112,  103,  103,   27,   27,   76,   76,   98,   95,   94,
+       93,   57,   86,  193,   76,   76,   75,   74,   73,   72,
+       71,   70,   69,   68,   67,   56,   23,   47,   46,   41,
+       40,   39,   23,  193,    3,  193,  193,  193,  193,  193,
+      193,  193,  193,  193,  193,  193,  193,  193,  193,  193,
+      193,  193,  193,  193,  193,  193,  193,  193,  193,  193,
+
+      193,  193,  193,  193,  193,  193,  193,  193,  193,  193,
+      193,  193,  193,  193,  193,  193,  193,  193,  193,  193,
+      193
+    } ;
+
+static yyconst flex_int16_t yy_chk[722] =
+    {   0,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    9,  190,    9,    9,
+        9,    9,    9,    9,    9,    9,    9,    9,    9,    9,
+       10,  116,  116,  189,   10,  188,    9,    9,    9,    9,
+        9,    9,   12,   12,   12,   12,   12,   18,   18,    9,
+      163,  163,   72,    9,   11,   11,   11,   11,   11,   11,
+       72,   18,  187,  186,   18,   25,   25,   25,   25,   25,
+
+       25,   33,   33,   33,   33,   33,   33,   35,   35,   35,
+       35,   35,   35,  185,  184,   11,  182,  181,  180,   11,
+       13,   13,   13,   13,   13,   13,   13,   14,   85,   14,
+       14,   14,   14,   14,   14,   26,   85,   26,   26,   26,
+       26,   26,   26,   26,   26,   26,   26,   26,   26,   36,
+       36,   36,   36,   36,  176,   26,   26,   26,   26,   26,
+       26,   27,   27,   27,   27,   27,   27,   27,   28,   86,
+       28,   28,   28,   28,   28,   28,   34,   86,   34,   34,
+       34,   34,   34,   34,   34,   34,   34,   34,   34,   34,
+       57,   57,   57,   57,   57,   57,   34,   34,   34,   34,
+
+       34,   34,   37,   37,   37,   37,   37,   37,   37,   38,
+      111,   38,   38,   38,   38,   38,   38,   49,  111,   49,
+       49,   49,   49,   49,   49,   51,  175,   51,   51,   51,
+       51,   51,   51,   51,   51,   51,   51,   51,   51,   64,
+       64,   64,   64,   64,   64,   51,   51,   51,   51,   51,
+       51,   52,  112,   52,   52,   52,   52,   52,   52,   58,
+      112,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   65,   65,   65,   65,   65,  172,   58,
+       58,   58,   58,   58,   58,   59,  165,   59,   59,   59,
+       59,   59,   59,   63,  164,   63,   63,   63,   63,   63,
+
+       63,   63,   63,   63,   63,   63,   63,   76,   76,   76,
+       76,   76,   76,   63,   63,   63,   63,   63,   63,   66,
+      162,   66,   66,   66,   66,   66,   66,   78,  161,   78,
+       78,   78,   78,   78,   83,  159,   83,   83,   83,   83,
+       83,   83,   87,   87,   87,   87,   87,   87,   88,  151,
+       88,   88,   88,   88,   88,   88,   88,   88,   88,   88,
+       88,   88,  102,  102,  102,  102,  102,  102,   88,   88,
+       88,   88,   88,   88,   89,  150,   89,   89,   89,   89,
+       89,   89,  100,  148,  100,  100,  100,  100,  100,  100,
+      103,  103,  103,  103,  103,  103,  105,  147,  105,  105,
+
+      105,  105,  105,  109,  146,  109,  109,  109,  109,  109,
+      109,  119,  119,  119,  119,  119,  119,  121,  144,  121,
+      121,  121,  121,  121,  124,  143,  124,  124,  124,  124,
+      124,  124,  126,  126,  126,  126,  126,  126,  128,  141,
+      128,  128,  128,  128,  128,  137,  137,  137,  137,  137,
+      137,  138,  138,  138,  138,  138,  138,  139,  139,  139,
+      139,  139,  139,  140,  140,  140,  140,  140,  140,  142,
+      136,  142,  142,  142,  142,  142,  145,  135,  145,  145,
+      145,  145,  145,  145,  152,  152,  152,  152,  152,  152,
+      153,  153,  153,  153,  153,  155,  155,  155,  155,  155,
+
+      155,  156,  156,  156,  156,  156,  156,  157,  157,  157,
+      157,  157,  157,  158,  158,  158,  158,  158,  158,  160,
+      132,  160,  160,  160,  160,  160,  166,  166,  166,  166,
+      166,  166,  167,  167,  167,  167,  167,  169,  169,  169,
+      169,  169,  169,  170,  170,  170,  170,  170,  170,  171,
+      171,  171,  171,  171,  171,  177,  177,  177,  177,  177,
+      177,  178,  178,  178,  178,  178,  194,  131,  194,  194,
+      194,  194,  194,  195,  195,  195,  196,  130,  196,  129,
+      196,  197,  127,  197,  198,  198,  198,  199,  199,  200,
+      200,  201,  201,  202,  202,  203,  203,  204,  204,  204,
+
+      204,  205,  205,  206,  206,  207,  207,  208,  208,  209,
+      209,  210,  210,  211,  211,  212,  212,  125,  123,  122,
+      120,  118,  117,  115,  114,  113,  110,  108,  107,  106,
+      104,  101,   99,   98,   97,   96,   95,   94,   93,   92,
+       91,   84,   82,   81,   80,   79,   77,   73,   69,   68,
+       67,   62,   61,   56,   50,   48,   47,   46,   45,   44,
+       43,   42,   41,   40,   39,   32,   23,   20,   19,   17,
+       16,   15,    5,    3,  193,  193,  193,  193,  193,  193,
+      193,  193,  193,  193,  193,  193,  193,  193,  193,  193,
+      193,  193,  193,  193,  193,  193,  193,  193,  193,  193,
+
+      193,  193,  193,  193,  193,  193,  193,  193,  193,  193,
+      193,  193,  193,  193,  193,  193,  193,  193,  193,  193,
+      193
+    } ;
+
+static yy_state_type yy_last_accepting_state;
+static char *yy_last_accepting_cpos;
+
+extern int prsa_flex_debug;
+int prsa_flex_debug = 0;
+
+/* The intent behind this definition is that it'll catch
+ * any uses of REJECT which flex missed.
+ */
+#define REJECT reject_used_but_not_detected
+#define yymore() yymore_used_but_not_detected
+#define YY_MORE_ADJ 0
+#define YY_RESTORE_YY_MORE_OFFSET
+char *prsatext;
+#line 1 "prsa_tok.l"
+/*	$NetBSD: prsa_tok.l,v 1.4 2006/09/09 16:22:10 manu Exp $	*/
+/* Id: prsa_tok.l,v 1.2 2004/07/12 20:43:51 ludvigm Exp */
+#line 6 "prsa_tok.l"
+/*
+ * Copyright (C) 2004 SuSE Linux AG, Nuernberg, Germany.
+ * Contributed by: Michal Ludvig <mludvig@suse.cz>, SUSE Labs
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* This file contains a tokeniser for FreeS/WAN-style ipsec.secrets RSA keys. */
+
+#include <string.h>
+#include <openssl/bn.h>
+#include <openssl/rsa.h>
+#include "prsa_par.h"
+
+extern int prsalex (void);
+extern int prsa_cur_lineno;
+
+#line 742 "prsa_tok.c"
+
+#define INITIAL 0
+
+#ifndef YY_NO_UNISTD_H
+/* Special case for "unistd.h", since it is non-ANSI. We include it way
+ * down here because we want the user's section 1 to have been scanned first.
+ * The user has a chance to override it with an option.
+ */
+#include <unistd.h>
+#endif
+
+#ifndef YY_EXTRA_TYPE
+#define YY_EXTRA_TYPE void *
+#endif
+
+static int yy_init_globals (void );
+
+/* Accessor methods to globals.
+   These are made visible to non-reentrant scanners for convenience. */
+
+int prsalex_destroy (void );
+
+int prsaget_debug (void );
+
+void prsaset_debug (int debug_flag  );
+
+YY_EXTRA_TYPE prsaget_extra (void );
+
+void prsaset_extra (YY_EXTRA_TYPE user_defined  );
+
+FILE *prsaget_in (void );
+
+void prsaset_in  (FILE * in_str  );
+
+FILE *prsaget_out (void );
+
+void prsaset_out  (FILE * out_str  );
+
+int prsaget_leng (void );
+
+char *prsaget_text (void );
+
+int prsaget_lineno (void );
+
+void prsaset_lineno (int line_number  );
+
+/* Macros after this point can all be overridden by user definitions in
+ * section 1.
+ */
+
+#ifndef YY_SKIP_YYWRAP
+#ifdef __cplusplus
+extern "C" int prsawrap (void );
+#else
+extern int prsawrap (void );
+#endif
+#endif
+
+    static void yyunput (int c,char *buf_ptr  );
+    
+#ifndef yytext_ptr
+static void yy_flex_strncpy (char *,yyconst char *,int );
+#endif
+
+#ifdef YY_NEED_STRLEN
+static int yy_flex_strlen (yyconst char * );
+#endif
+
+#ifndef YY_NO_INPUT
+
+#ifdef __cplusplus
+static int yyinput (void );
+#else
+static int input (void );
+#endif
+
+#endif
+
+/* Amount of stuff to slurp up with each read. */
+#ifndef YY_READ_BUF_SIZE
+#define YY_READ_BUF_SIZE 8192
+#endif
+
+/* Copy whatever the last rule matched to the standard output. */
+#ifndef ECHO
+/* This used to be an fputs(), but since the string might contain NUL's,
+ * we now use fwrite().
+ */
+#define ECHO fwrite( prsatext, prsaleng, 1, prsaout )
+#endif
+
+/* Gets input and stuffs it into "buf".  number of characters read, or YY_NULL,
+ * is returned in "result".
+ */
+#ifndef YY_INPUT
+#define YY_INPUT(buf,result,max_size) \
+	if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \
+		{ \
+		int c = '*'; \
+		size_t n; \
+		for ( n = 0; n < max_size && \
+			     (c = getc( prsain )) != EOF && c != '\n'; ++n ) \
+			buf[n] = (char) c; \
+		if ( c == '\n' ) \
+			buf[n++] = (char) c; \
+		if ( c == EOF && ferror( prsain ) ) \
+			YY_FATAL_ERROR( "input in flex scanner failed" ); \
+		result = n; \
+		} \
+	else \
+		{ \
+		errno=0; \
+		while ( (result = fread(buf, 1, max_size, prsain))==0 && ferror(prsain)) \
+			{ \
+			if( errno != EINTR) \
+				{ \
+				YY_FATAL_ERROR( "input in flex scanner failed" ); \
+				break; \
+				} \
+			errno=0; \
+			clearerr(prsain); \
+			} \
+		}\
+\
+
+#endif
+
+/* No semi-colon after return; correct usage is to write "yyterminate();" -
+ * we don't want an extra ';' after the "return" because that will cause
+ * some compilers to complain about unreachable statements.
+ */
+#ifndef yyterminate
+#define yyterminate() return YY_NULL
+#endif
+
+/* Number of entries by which start-condition stack grows. */
+#ifndef YY_START_STACK_INCR
+#define YY_START_STACK_INCR 25
+#endif
+
+/* Report a fatal error. */
+#ifndef YY_FATAL_ERROR
+#define YY_FATAL_ERROR(msg) yy_fatal_error( msg )
+#endif
+
+/* end tables serialization structures and prototypes */
+
+/* Default declaration of generated scanner - a define so the user can
+ * easily add parameters.
+ */
+#ifndef YY_DECL
+#define YY_DECL_IS_OURS 1
+
+extern int prsalex (void);
+
+#define YY_DECL int prsalex (void)
+#endif /* !YY_DECL */
+
+/* Code executed at the beginning of each rule, after prsatext and prsaleng
+ * have been set up.
+ */
+#ifndef YY_USER_ACTION
+#define YY_USER_ACTION
+#endif
+
+/* Code executed at the end of each rule. */
+#ifndef YY_BREAK
+#define YY_BREAK break;
+#endif
+
+#define YY_RULE_SETUP \
+	YY_USER_ACTION
+
+/** The main scanner function which does all the work.
+ */
+YY_DECL
+{
+	register yy_state_type yy_current_state;
+	register char *yy_cp, *yy_bp;
+	register int yy_act;
+    
+#line 56 "prsa_tok.l"
+
+#line 926 "prsa_tok.c"
+
+	if ( !(yy_init) )
+		{
+		(yy_init) = 1;
+
+#ifdef YY_USER_INIT
+		YY_USER_INIT;
+#endif
+
+		if ( ! (yy_start) )
+			(yy_start) = 1;	/* first start state */
+
+		if ( ! prsain )
+			prsain = stdin;
+
+		if ( ! prsaout )
+			prsaout = stdout;
+
+		if ( ! YY_CURRENT_BUFFER ) {
+			prsaensure_buffer_stack ();
+			YY_CURRENT_BUFFER_LVALUE =
+				prsa_create_buffer(prsain,YY_BUF_SIZE );
+		}
+
+		prsa_load_buffer_state( );
+		}
+
+	while ( 1 )		/* loops until end-of-file is reached */
+		{
+		yy_cp = (yy_c_buf_p);
+
+		/* Support of prsatext. */
+		*yy_cp = (yy_hold_char);
+
+		/* yy_bp points to the position in yy_ch_buf of the start of
+		 * the current run.
+		 */
+		yy_bp = yy_cp;
+
+		yy_current_state = (yy_start);
+yy_match:
+		do
+			{
+			register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)];
+			if ( yy_accept[yy_current_state] )
+				{
+				(yy_last_accepting_state) = yy_current_state;
+				(yy_last_accepting_cpos) = yy_cp;
+				}
+			while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+				{
+				yy_current_state = (int) yy_def[yy_current_state];
+				if ( yy_current_state >= 194 )
+					yy_c = yy_meta[(unsigned int) yy_c];
+				}
+			yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+			++yy_cp;
+			}
+		while ( yy_base[yy_current_state] != 675 );
+
+yy_find_action:
+		yy_act = yy_accept[yy_current_state];
+		if ( yy_act == 0 )
+			{ /* have to back up */
+			yy_cp = (yy_last_accepting_cpos);
+			yy_current_state = (yy_last_accepting_state);
+			yy_act = yy_accept[yy_current_state];
+			}
+
+		YY_DO_BEFORE_ACTION;
+
+do_action:	/* This label is used only to access EOF actions. */
+
+		switch ( yy_act )
+	{ /* beginning of action switch */
+			case 0: /* must back up */
+			/* undo the effects of YY_DO_BEFORE_ACTION */
+			*yy_cp = (yy_hold_char);
+			yy_cp = (yy_last_accepting_cpos);
+			yy_current_state = (yy_last_accepting_state);
+			goto yy_find_action;
+
+case 1:
+YY_RULE_SETUP
+#line 57 "prsa_tok.l"
+{ return OBRACE; }
+	YY_BREAK
+case 2:
+YY_RULE_SETUP
+#line 58 "prsa_tok.l"
+{ return EBRACE; }
+	YY_BREAK
+case 3:
+YY_RULE_SETUP
+#line 59 "prsa_tok.l"
+{ return COLON; }
+	YY_BREAK
+case 4:
+YY_RULE_SETUP
+#line 60 "prsa_tok.l"
+{ return TAG_RSA; }
+	YY_BREAK
+case 5:
+YY_RULE_SETUP
+#line 61 "prsa_tok.l"
+{ return TAG_PSK; }
+	YY_BREAK
+case 6:
+YY_RULE_SETUP
+#line 62 "prsa_tok.l"
+{ return TAG_PUB; }
+	YY_BREAK
+case 7:
+YY_RULE_SETUP
+#line 63 "prsa_tok.l"
+{ 
+			BIGNUM *bn = BN_new();
+			BN_hex2bn(&bn, prsatext+2);
+			prsalval.bn = bn;
+			return HEX;
+		}
+	YY_BREAK
+case 8:
+YY_RULE_SETUP
+#line 69 "prsa_tok.l"
+{
+			prsalval.chr = strdup(prsatext);
+			return BASE64;
+		}
+	YY_BREAK
+case 9:
+YY_RULE_SETUP
+#line 73 "prsa_tok.l"
+{ return MODULUS; }
+	YY_BREAK
+case 10:
+YY_RULE_SETUP
+#line 74 "prsa_tok.l"
+{ return PUBLIC_EXPONENT; }
+	YY_BREAK
+case 11:
+YY_RULE_SETUP
+#line 75 "prsa_tok.l"
+{ return PRIVATE_EXPONENT; }
+	YY_BREAK
+case 12:
+YY_RULE_SETUP
+#line 76 "prsa_tok.l"
+{ return PRIME1; }
+	YY_BREAK
+case 13:
+YY_RULE_SETUP
+#line 77 "prsa_tok.l"
+{ return PRIME2; }
+	YY_BREAK
+case 14:
+YY_RULE_SETUP
+#line 78 "prsa_tok.l"
+{ return EXPONENT1; }
+	YY_BREAK
+case 15:
+YY_RULE_SETUP
+#line 79 "prsa_tok.l"
+{ return EXPONENT2; }
+	YY_BREAK
+case 16:
+YY_RULE_SETUP
+#line 80 "prsa_tok.l"
+{ return COEFFICIENT; }
+	YY_BREAK
+case 17:
+YY_RULE_SETUP
+#line 81 "prsa_tok.l"
+{ return SLASH; }
+	YY_BREAK
+case 18:
+YY_RULE_SETUP
+#line 82 "prsa_tok.l"
+{ prsalval.num = atol(prsatext); return NUMBER; }
+	YY_BREAK
+case 19:
+YY_RULE_SETUP
+#line 83 "prsa_tok.l"
+{ return ADDRANY; }
+	YY_BREAK
+case 20:
+YY_RULE_SETUP
+#line 84 "prsa_tok.l"
+{ prsalval.chr = strdup(prsatext); return ADDR4; }
+	YY_BREAK
+case 21:
+YY_RULE_SETUP
+#line 85 "prsa_tok.l"
+{ prsalval.chr = strdup(prsatext); return ADDR6; }
+	YY_BREAK
+case 22:
+YY_RULE_SETUP
+#line 86 "prsa_tok.l"
+;
+	YY_BREAK
+case 23:
+/* rule 23 can match eol */
+YY_RULE_SETUP
+#line 87 "prsa_tok.l"
+{ prsa_cur_lineno++; }
+	YY_BREAK
+case 24:
+YY_RULE_SETUP
+#line 88 "prsa_tok.l"
+;
+	YY_BREAK
+case 25:
+YY_RULE_SETUP
+#line 89 "prsa_tok.l"
+ECHO;
+	YY_BREAK
+#line 1143 "prsa_tok.c"
+case YY_STATE_EOF(INITIAL):
+	yyterminate();
+
+	case YY_END_OF_BUFFER:
+		{
+		/* Amount of text matched not including the EOB char. */
+		int yy_amount_of_matched_text = (int) (yy_cp - (yytext_ptr)) - 1;
+
+		/* Undo the effects of YY_DO_BEFORE_ACTION. */
+		*yy_cp = (yy_hold_char);
+		YY_RESTORE_YY_MORE_OFFSET
+
+		if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW )
+			{
+			/* We're scanning a new file or input source.  It's
+			 * possible that this happened because the user
+			 * just pointed prsain at a new source and called
+			 * prsalex().  If so, then we have to assure
+			 * consistency between YY_CURRENT_BUFFER and our
+			 * globals.  Here is the right place to do so, because
+			 * this is the first action (other than possibly a
+			 * back-up) that will match for the new input source.
+			 */
+			(yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
+			YY_CURRENT_BUFFER_LVALUE->yy_input_file = prsain;
+			YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL;
+			}
+
+		/* Note that here we test for yy_c_buf_p "<=" to the position
+		 * of the first EOB in the buffer, since yy_c_buf_p will
+		 * already have been incremented past the NUL character
+		 * (since all states make transitions on EOB to the
+		 * end-of-buffer state).  Contrast this with the test
+		 * in input().
+		 */
+		if ( (yy_c_buf_p) <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] )
+			{ /* This was really a NUL. */
+			yy_state_type yy_next_state;
+
+			(yy_c_buf_p) = (yytext_ptr) + yy_amount_of_matched_text;
+
+			yy_current_state = yy_get_previous_state(  );
+
+			/* Okay, we're now positioned to make the NUL
+			 * transition.  We couldn't have
+			 * yy_get_previous_state() go ahead and do it
+			 * for us because it doesn't know how to deal
+			 * with the possibility of jamming (and we don't
+			 * want to build jamming into it because then it
+			 * will run more slowly).
+			 */
+
+			yy_next_state = yy_try_NUL_trans( yy_current_state );
+
+			yy_bp = (yytext_ptr) + YY_MORE_ADJ;
+
+			if ( yy_next_state )
+				{
+				/* Consume the NUL. */
+				yy_cp = ++(yy_c_buf_p);
+				yy_current_state = yy_next_state;
+				goto yy_match;
+				}
+
+			else
+				{
+				yy_cp = (yy_c_buf_p);
+				goto yy_find_action;
+				}
+			}
+
+		else switch ( yy_get_next_buffer(  ) )
+			{
+			case EOB_ACT_END_OF_FILE:
+				{
+				(yy_did_buffer_switch_on_eof) = 0;
+
+				if ( prsawrap( ) )
+					{
+					/* Note: because we've taken care in
+					 * yy_get_next_buffer() to have set up
+					 * prsatext, we can now set up
+					 * yy_c_buf_p so that if some total
+					 * hoser (like flex itself) wants to
+					 * call the scanner after we return the
+					 * YY_NULL, it'll still work - another
+					 * YY_NULL will get returned.
+					 */
+					(yy_c_buf_p) = (yytext_ptr) + YY_MORE_ADJ;
+
+					yy_act = YY_STATE_EOF(YY_START);
+					goto do_action;
+					}
+
+				else
+					{
+					if ( ! (yy_did_buffer_switch_on_eof) )
+						YY_NEW_FILE;
+					}
+				break;
+				}
+
+			case EOB_ACT_CONTINUE_SCAN:
+				(yy_c_buf_p) =
+					(yytext_ptr) + yy_amount_of_matched_text;
+
+				yy_current_state = yy_get_previous_state(  );
+
+				yy_cp = (yy_c_buf_p);
+				yy_bp = (yytext_ptr) + YY_MORE_ADJ;
+				goto yy_match;
+
+			case EOB_ACT_LAST_MATCH:
+				(yy_c_buf_p) =
+				&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)];
+
+				yy_current_state = yy_get_previous_state(  );
+
+				yy_cp = (yy_c_buf_p);
+				yy_bp = (yytext_ptr) + YY_MORE_ADJ;
+				goto yy_find_action;
+			}
+		break;
+		}
+
+	default:
+		YY_FATAL_ERROR(
+			"fatal flex scanner internal error--no action found" );
+	} /* end of action switch */
+		} /* end of scanning one token */
+} /* end of prsalex */
+
+/* yy_get_next_buffer - try to read in a new buffer
+ *
+ * Returns a code representing an action:
+ *	EOB_ACT_LAST_MATCH -
+ *	EOB_ACT_CONTINUE_SCAN - continue scanning from current position
+ *	EOB_ACT_END_OF_FILE - end of file
+ */
+static int yy_get_next_buffer (void)
+{
+    	register char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf;
+	register char *source = (yytext_ptr);
+	register int number_to_move, i;
+	int ret_val;
+
+	if ( (yy_c_buf_p) > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] )
+		YY_FATAL_ERROR(
+		"fatal flex scanner internal error--end of buffer missed" );
+
+	if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 )
+		{ /* Don't try to fill the buffer, so this is an EOF. */
+		if ( (yy_c_buf_p) - (yytext_ptr) - YY_MORE_ADJ == 1 )
+			{
+			/* We matched a single character, the EOB, so
+			 * treat this as a final EOF.
+			 */
+			return EOB_ACT_END_OF_FILE;
+			}
+
+		else
+			{
+			/* We matched some text prior to the EOB, first
+			 * process it.
+			 */
+			return EOB_ACT_LAST_MATCH;
+			}
+		}
+
+	/* Try to read more data. */
+
+	/* First move last chars to start of buffer. */
+	number_to_move = (int) ((yy_c_buf_p) - (yytext_ptr)) - 1;
+
+	for ( i = 0; i < number_to_move; ++i )
+		*(dest++) = *(source++);
+
+	if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING )
+		/* don't do the read, it's not guaranteed to return an EOF,
+		 * just force an EOF
+		 */
+		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars) = 0;
+
+	else
+		{
+			int num_to_read =
+			YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1;
+
+		while ( num_to_read <= 0 )
+			{ /* Not enough room in the buffer - grow it. */
+
+			/* just a shorter name for the current buffer */
+			YY_BUFFER_STATE b = YY_CURRENT_BUFFER;
+
+			int yy_c_buf_p_offset =
+				(int) ((yy_c_buf_p) - b->yy_ch_buf);
+
+			if ( b->yy_is_our_buffer )
+				{
+				int new_size = b->yy_buf_size * 2;
+
+				if ( new_size <= 0 )
+					b->yy_buf_size += b->yy_buf_size / 8;
+				else
+					b->yy_buf_size *= 2;
+
+				b->yy_ch_buf = (char *)
+					/* Include room in for 2 EOB chars. */
+					prsarealloc((void *) b->yy_ch_buf,b->yy_buf_size + 2  );
+				}
+			else
+				/* Can't grow it, we don't own it. */
+				b->yy_ch_buf = 0;
+
+			if ( ! b->yy_ch_buf )
+				YY_FATAL_ERROR(
+				"fatal error - scanner input buffer overflow" );
+
+			(yy_c_buf_p) = &b->yy_ch_buf[yy_c_buf_p_offset];
+
+			num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size -
+						number_to_move - 1;
+
+			}
+
+		if ( num_to_read > YY_READ_BUF_SIZE )
+			num_to_read = YY_READ_BUF_SIZE;
+
+		/* Read in more data. */
+		YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]),
+			(yy_n_chars), (size_t) num_to_read );
+
+		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
+		}
+
+	if ( (yy_n_chars) == 0 )
+		{
+		if ( number_to_move == YY_MORE_ADJ )
+			{
+			ret_val = EOB_ACT_END_OF_FILE;
+			prsarestart(prsain  );
+			}
+
+		else
+			{
+			ret_val = EOB_ACT_LAST_MATCH;
+			YY_CURRENT_BUFFER_LVALUE->yy_buffer_status =
+				YY_BUFFER_EOF_PENDING;
+			}
+		}
+
+	else
+		ret_val = EOB_ACT_CONTINUE_SCAN;
+
+	if ((yy_size_t) ((yy_n_chars) + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) {
+		/* Extend the array by 50%, plus the number we really need. */
+		yy_size_t new_size = (yy_n_chars) + number_to_move + ((yy_n_chars) >> 1);
+		YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) prsarealloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size  );
+		if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
+			YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" );
+	}
+
+	(yy_n_chars) += number_to_move;
+	YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] = YY_END_OF_BUFFER_CHAR;
+	YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] = YY_END_OF_BUFFER_CHAR;
+
+	(yytext_ptr) = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0];
+
+	return ret_val;
+}
+
+/* yy_get_previous_state - get the state just before the EOB char was reached */
+
+    static yy_state_type yy_get_previous_state (void)
+{
+	register yy_state_type yy_current_state;
+	register char *yy_cp;
+    
+	yy_current_state = (yy_start);
+
+	for ( yy_cp = (yytext_ptr) + YY_MORE_ADJ; yy_cp < (yy_c_buf_p); ++yy_cp )
+		{
+		register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1);
+		if ( yy_accept[yy_current_state] )
+			{
+			(yy_last_accepting_state) = yy_current_state;
+			(yy_last_accepting_cpos) = yy_cp;
+			}
+		while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+			{
+			yy_current_state = (int) yy_def[yy_current_state];
+			if ( yy_current_state >= 194 )
+				yy_c = yy_meta[(unsigned int) yy_c];
+			}
+		yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+		}
+
+	return yy_current_state;
+}
+
+/* yy_try_NUL_trans - try to make a transition on the NUL character
+ *
+ * synopsis
+ *	next_state = yy_try_NUL_trans( current_state );
+ */
+    static yy_state_type yy_try_NUL_trans  (yy_state_type yy_current_state )
+{
+	register int yy_is_jam;
+    	register char *yy_cp = (yy_c_buf_p);
+
+	register YY_CHAR yy_c = 1;
+	if ( yy_accept[yy_current_state] )
+		{
+		(yy_last_accepting_state) = yy_current_state;
+		(yy_last_accepting_cpos) = yy_cp;
+		}
+	while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+		{
+		yy_current_state = (int) yy_def[yy_current_state];
+		if ( yy_current_state >= 194 )
+			yy_c = yy_meta[(unsigned int) yy_c];
+		}
+	yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+	yy_is_jam = (yy_current_state == 193);
+
+	return yy_is_jam ? 0 : yy_current_state;
+}
+
+    static void yyunput (int c, register char * yy_bp )
+{
+	register char *yy_cp;
+    
+    yy_cp = (yy_c_buf_p);
+
+	/* undo effects of setting up prsatext */
+	*yy_cp = (yy_hold_char);
+
+	if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 )
+		{ /* need to shift things up to make room */
+		/* +2 for EOB chars. */
+		register int number_to_move = (yy_n_chars) + 2;
+		register char *dest = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[
+					YY_CURRENT_BUFFER_LVALUE->yy_buf_size + 2];
+		register char *source =
+				&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move];
+
+		while ( source > YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
+			*--dest = *--source;
+
+		yy_cp += (int) (dest - source);
+		yy_bp += (int) (dest - source);
+		YY_CURRENT_BUFFER_LVALUE->yy_n_chars =
+			(yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_buf_size;
+
+		if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 )
+			YY_FATAL_ERROR( "flex scanner push-back overflow" );
+		}
+
+	*--yy_cp = (char) c;
+
+	(yytext_ptr) = yy_bp;
+	(yy_hold_char) = *yy_cp;
+	(yy_c_buf_p) = yy_cp;
+}
+
+#ifndef YY_NO_INPUT
+#ifdef __cplusplus
+    static int yyinput (void)
+#else
+    static int input  (void)
+#endif
+
+{
+	int c;
+    
+	*(yy_c_buf_p) = (yy_hold_char);
+
+	if ( *(yy_c_buf_p) == YY_END_OF_BUFFER_CHAR )
+		{
+		/* yy_c_buf_p now points to the character we want to return.
+		 * If this occurs *before* the EOB characters, then it's a
+		 * valid NUL; if not, then we've hit the end of the buffer.
+		 */
+		if ( (yy_c_buf_p) < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] )
+			/* This was really a NUL. */
+			*(yy_c_buf_p) = '\0';
+
+		else
+			{ /* need more input */
+			int offset = (yy_c_buf_p) - (yytext_ptr);
+			++(yy_c_buf_p);
+
+			switch ( yy_get_next_buffer(  ) )
+				{
+				case EOB_ACT_LAST_MATCH:
+					/* This happens because yy_g_n_b()
+					 * sees that we've accumulated a
+					 * token and flags that we need to
+					 * try matching the token before
+					 * proceeding.  But for input(),
+					 * there's no matching to consider.
+					 * So convert the EOB_ACT_LAST_MATCH
+					 * to EOB_ACT_END_OF_FILE.
+					 */
+
+					/* Reset buffer status. */
+					prsarestart(prsain );
+
+					/*FALLTHROUGH*/
+
+				case EOB_ACT_END_OF_FILE:
+					{
+					if ( prsawrap( ) )
+						return EOF;
+
+					if ( ! (yy_did_buffer_switch_on_eof) )
+						YY_NEW_FILE;
+#ifdef __cplusplus
+					return yyinput();
+#else
+					return input();
+#endif
+					}
+
+				case EOB_ACT_CONTINUE_SCAN:
+					(yy_c_buf_p) = (yytext_ptr) + offset;
+					break;
+				}
+			}
+		}
+
+	c = *(unsigned char *) (yy_c_buf_p);	/* cast for 8-bit char's */
+	*(yy_c_buf_p) = '\0';	/* preserve prsatext */
+	(yy_hold_char) = *++(yy_c_buf_p);
+
+	return c;
+}
+#endif	/* ifndef YY_NO_INPUT */
+
+/** Immediately switch to a different input stream.
+ * @param input_file A readable stream.
+ * 
+ * @note This function does not reset the start condition to @c INITIAL .
+ */
+    void prsarestart  (FILE * input_file )
+{
+    
+	if ( ! YY_CURRENT_BUFFER ){
+        prsaensure_buffer_stack ();
+		YY_CURRENT_BUFFER_LVALUE =
+            prsa_create_buffer(prsain,YY_BUF_SIZE );
+	}
+
+	prsa_init_buffer(YY_CURRENT_BUFFER,input_file );
+	prsa_load_buffer_state( );
+}
+
+/** Switch to a different input buffer.
+ * @param new_buffer The new input buffer.
+ * 
+ */
+    void prsa_switch_to_buffer  (YY_BUFFER_STATE  new_buffer )
+{
+    
+	/* TODO. We should be able to replace this entire function body
+	 * with
+	 *		prsapop_buffer_state();
+	 *		prsapush_buffer_state(new_buffer);
+     */
+	prsaensure_buffer_stack ();
+	if ( YY_CURRENT_BUFFER == new_buffer )
+		return;
+
+	if ( YY_CURRENT_BUFFER )
+		{
+		/* Flush out information for old buffer. */
+		*(yy_c_buf_p) = (yy_hold_char);
+		YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p);
+		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
+		}
+
+	YY_CURRENT_BUFFER_LVALUE = new_buffer;
+	prsa_load_buffer_state( );
+
+	/* We don't actually know whether we did this switch during
+	 * EOF (prsawrap()) processing, but the only time this flag
+	 * is looked at is after prsawrap() is called, so it's safe
+	 * to go ahead and always set it.
+	 */
+	(yy_did_buffer_switch_on_eof) = 1;
+}
+
+static void prsa_load_buffer_state  (void)
+{
+    	(yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
+	(yytext_ptr) = (yy_c_buf_p) = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos;
+	prsain = YY_CURRENT_BUFFER_LVALUE->yy_input_file;
+	(yy_hold_char) = *(yy_c_buf_p);
+}
+
+/** Allocate and initialize an input buffer state.
+ * @param file A readable stream.
+ * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE.
+ * 
+ * @return the allocated buffer state.
+ */
+    YY_BUFFER_STATE prsa_create_buffer  (FILE * file, int  size )
+{
+	YY_BUFFER_STATE b;
+    
+	b = (YY_BUFFER_STATE) prsaalloc(sizeof( struct yy_buffer_state )  );
+	if ( ! b )
+		YY_FATAL_ERROR( "out of dynamic memory in prsa_create_buffer()" );
+
+	b->yy_buf_size = size;
+
+	/* yy_ch_buf has to be 2 characters longer than the size given because
+	 * we need to put in 2 end-of-buffer characters.
+	 */
+	b->yy_ch_buf = (char *) prsaalloc(b->yy_buf_size + 2  );
+	if ( ! b->yy_ch_buf )
+		YY_FATAL_ERROR( "out of dynamic memory in prsa_create_buffer()" );
+
+	b->yy_is_our_buffer = 1;
+
+	prsa_init_buffer(b,file );
+
+	return b;
+}
+
+/** Destroy the buffer.
+ * @param b a buffer created with prsa_create_buffer()
+ * 
+ */
+    void prsa_delete_buffer (YY_BUFFER_STATE  b )
+{
+    
+	if ( ! b )
+		return;
+
+	if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */
+		YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0;
+
+	if ( b->yy_is_our_buffer )
+		prsafree((void *) b->yy_ch_buf  );
+
+	prsafree((void *) b  );
+}
+
+#ifndef __cplusplus
+extern int isatty (int );
+#endif /* __cplusplus */
+    
+/* Initializes or reinitializes a buffer.
+ * This function is sometimes called more than once on the same buffer,
+ * such as during a prsarestart() or at EOF.
+ */
+    static void prsa_init_buffer  (YY_BUFFER_STATE  b, FILE * file )
+
+{
+	int oerrno = errno;
+    
+	prsa_flush_buffer(b );
+
+	b->yy_input_file = file;
+	b->yy_fill_buffer = 1;
+
+    /* If b is the current buffer, then prsa_init_buffer was _probably_
+     * called from prsarestart() or through yy_get_next_buffer.
+     * In that case, we don't want to reset the lineno or column.
+     */
+    if (b != YY_CURRENT_BUFFER){
+        b->yy_bs_lineno = 1;
+        b->yy_bs_column = 0;
+    }
+
+        b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0;
+    
+	errno = oerrno;
+}
+
+/** Discard all buffered characters. On the next scan, YY_INPUT will be called.
+ * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER.
+ * 
+ */
+    void prsa_flush_buffer (YY_BUFFER_STATE  b )
+{
+    	if ( ! b )
+		return;
+
+	b->yy_n_chars = 0;
+
+	/* We always need two end-of-buffer characters.  The first causes
+	 * a transition to the end-of-buffer state.  The second causes
+	 * a jam in that state.
+	 */
+	b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR;
+	b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR;
+
+	b->yy_buf_pos = &b->yy_ch_buf[0];
+
+	b->yy_at_bol = 1;
+	b->yy_buffer_status = YY_BUFFER_NEW;
+
+	if ( b == YY_CURRENT_BUFFER )
+		prsa_load_buffer_state( );
+}
+
+/** Pushes the new state onto the stack. The new state becomes
+ *  the current state. This function will allocate the stack
+ *  if necessary.
+ *  @param new_buffer The new state.
+ *  
+ */
+void prsapush_buffer_state (YY_BUFFER_STATE new_buffer )
+{
+    	if (new_buffer == NULL)
+		return;
+
+	prsaensure_buffer_stack();
+
+	/* This block is copied from prsa_switch_to_buffer. */
+	if ( YY_CURRENT_BUFFER )
+		{
+		/* Flush out information for old buffer. */
+		*(yy_c_buf_p) = (yy_hold_char);
+		YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p);
+		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
+		}
+
+	/* Only push if top exists. Otherwise, replace top. */
+	if (YY_CURRENT_BUFFER)
+		(yy_buffer_stack_top)++;
+	YY_CURRENT_BUFFER_LVALUE = new_buffer;
+
+	/* copied from prsa_switch_to_buffer. */
+	prsa_load_buffer_state( );
+	(yy_did_buffer_switch_on_eof) = 1;
+}
+
+/** Removes and deletes the top of the stack, if present.
+ *  The next element becomes the new top.
+ *  
+ */
+void prsapop_buffer_state (void)
+{
+    	if (!YY_CURRENT_BUFFER)
+		return;
+
+	prsa_delete_buffer(YY_CURRENT_BUFFER );
+	YY_CURRENT_BUFFER_LVALUE = NULL;
+	if ((yy_buffer_stack_top) > 0)
+		--(yy_buffer_stack_top);
+
+	if (YY_CURRENT_BUFFER) {
+		prsa_load_buffer_state( );
+		(yy_did_buffer_switch_on_eof) = 1;
+	}
+}
+
+/* Allocates the stack if it does not exist.
+ *  Guarantees space for at least one push.
+ */
+static void prsaensure_buffer_stack (void)
+{
+	int num_to_alloc;
+    
+	if (!(yy_buffer_stack)) {
+
+		/* First allocation is just for 2 elements, since we don't know if this
+		 * scanner will even need a stack. We use 2 instead of 1 to avoid an
+		 * immediate realloc on the next call.
+         */
+		num_to_alloc = 1;
+		(yy_buffer_stack) = (struct yy_buffer_state**)prsaalloc
+								(num_to_alloc * sizeof(struct yy_buffer_state*)
+								);
+		if ( ! (yy_buffer_stack) )
+			YY_FATAL_ERROR( "out of dynamic memory in prsaensure_buffer_stack()" );
+								  
+		memset((yy_buffer_stack), 0, num_to_alloc * sizeof(struct yy_buffer_state*));
+				
+		(yy_buffer_stack_max) = num_to_alloc;
+		(yy_buffer_stack_top) = 0;
+		return;
+	}
+
+	if ((yy_buffer_stack_top) >= ((yy_buffer_stack_max)) - 1){
+
+		/* Increase the buffer to prepare for a possible push. */
+		int grow_size = 8 /* arbitrary grow size */;
+
+		num_to_alloc = (yy_buffer_stack_max) + grow_size;
+		(yy_buffer_stack) = (struct yy_buffer_state**)prsarealloc
+								((yy_buffer_stack),
+								num_to_alloc * sizeof(struct yy_buffer_state*)
+								);
+		if ( ! (yy_buffer_stack) )
+			YY_FATAL_ERROR( "out of dynamic memory in prsaensure_buffer_stack()" );
+
+		/* zero only the new slots.*/
+		memset((yy_buffer_stack) + (yy_buffer_stack_max), 0, grow_size * sizeof(struct yy_buffer_state*));
+		(yy_buffer_stack_max) = num_to_alloc;
+	}
+}
+
+/** Setup the input buffer state to scan directly from a user-specified character buffer.
+ * @param base the character buffer
+ * @param size the size in bytes of the character buffer
+ * 
+ * @return the newly allocated buffer state object. 
+ */
+YY_BUFFER_STATE prsa_scan_buffer  (char * base, yy_size_t  size )
+{
+	YY_BUFFER_STATE b;
+    
+	if ( size < 2 ||
+	     base[size-2] != YY_END_OF_BUFFER_CHAR ||
+	     base[size-1] != YY_END_OF_BUFFER_CHAR )
+		/* They forgot to leave room for the EOB's. */
+		return 0;
+
+	b = (YY_BUFFER_STATE) prsaalloc(sizeof( struct yy_buffer_state )  );
+	if ( ! b )
+		YY_FATAL_ERROR( "out of dynamic memory in prsa_scan_buffer()" );
+
+	b->yy_buf_size = size - 2;	/* "- 2" to take care of EOB's */
+	b->yy_buf_pos = b->yy_ch_buf = base;
+	b->yy_is_our_buffer = 0;
+	b->yy_input_file = 0;
+	b->yy_n_chars = b->yy_buf_size;
+	b->yy_is_interactive = 0;
+	b->yy_at_bol = 1;
+	b->yy_fill_buffer = 0;
+	b->yy_buffer_status = YY_BUFFER_NEW;
+
+	prsa_switch_to_buffer(b  );
+
+	return b;
+}
+
+/** Setup the input buffer state to scan a string. The next call to prsalex() will
+ * scan from a @e copy of @a str.
+ * @param yystr a NUL-terminated string to scan
+ * 
+ * @return the newly allocated buffer state object.
+ * @note If you want to scan bytes that may contain NUL values, then use
+ *       prsa_scan_bytes() instead.
+ */
+YY_BUFFER_STATE prsa_scan_string (yyconst char * yystr )
+{
+    
+	return prsa_scan_bytes(yystr,strlen(yystr) );
+}
+
+/** Setup the input buffer state to scan the given bytes. The next call to prsalex() will
+ * scan from a @e copy of @a bytes.
+ * @param bytes the byte buffer to scan
+ * @param len the number of bytes in the buffer pointed to by @a bytes.
+ * 
+ * @return the newly allocated buffer state object.
+ */
+YY_BUFFER_STATE prsa_scan_bytes  (yyconst char * yybytes, int  _yybytes_len )
+{
+	YY_BUFFER_STATE b;
+	char *buf;
+	yy_size_t n;
+	int i;
+    
+	/* Get memory for full buffer, including space for trailing EOB's. */
+	n = _yybytes_len + 2;
+	buf = (char *) prsaalloc(n  );
+	if ( ! buf )
+		YY_FATAL_ERROR( "out of dynamic memory in prsa_scan_bytes()" );
+
+	for ( i = 0; i < _yybytes_len; ++i )
+		buf[i] = yybytes[i];
+
+	buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR;
+
+	b = prsa_scan_buffer(buf,n );
+	if ( ! b )
+		YY_FATAL_ERROR( "bad buffer in prsa_scan_bytes()" );
+
+	/* It's okay to grow etc. this buffer, and we should throw it
+	 * away when we're done.
+	 */
+	b->yy_is_our_buffer = 1;
+
+	return b;
+}
+
+#ifndef YY_EXIT_FAILURE
+#define YY_EXIT_FAILURE 2
+#endif
+
+static void yy_fatal_error (yyconst char* msg )
+{
+    	(void) fprintf( stderr, "%s\n", msg );
+	exit( YY_EXIT_FAILURE );
+}
+
+/* Redefine yyless() so it works in section 3 code. */
+
+#undef yyless
+#define yyless(n) \
+	do \
+		{ \
+		/* Undo effects of setting up prsatext. */ \
+        int yyless_macro_arg = (n); \
+        YY_LESS_LINENO(yyless_macro_arg);\
+		prsatext[prsaleng] = (yy_hold_char); \
+		(yy_c_buf_p) = prsatext + yyless_macro_arg; \
+		(yy_hold_char) = *(yy_c_buf_p); \
+		*(yy_c_buf_p) = '\0'; \
+		prsaleng = yyless_macro_arg; \
+		} \
+	while ( 0 )
+
+/* Accessor  methods (get/set functions) to struct members. */
+
+/** Get the current line number.
+ * 
+ */
+int prsaget_lineno  (void)
+{
+        
+    return prsalineno;
+}
+
+/** Get the input stream.
+ * 
+ */
+FILE *prsaget_in  (void)
+{
+        return prsain;
+}
+
+/** Get the output stream.
+ * 
+ */
+FILE *prsaget_out  (void)
+{
+        return prsaout;
+}
+
+/** Get the length of the current token.
+ * 
+ */
+int prsaget_leng  (void)
+{
+        return prsaleng;
+}
+
+/** Get the current token.
+ * 
+ */
+
+char *prsaget_text  (void)
+{
+        return prsatext;
+}
+
+/** Set the current line number.
+ * @param line_number
+ * 
+ */
+void prsaset_lineno (int  line_number )
+{
+    
+    prsalineno = line_number;
+}
+
+/** Set the input stream. This does not discard the current
+ * input buffer.
+ * @param in_str A readable stream.
+ * 
+ * @see prsa_switch_to_buffer
+ */
+void prsaset_in (FILE *  in_str )
+{
+        prsain = in_str ;
+}
+
+void prsaset_out (FILE *  out_str )
+{
+        prsaout = out_str ;
+}
+
+int prsaget_debug  (void)
+{
+        return prsa_flex_debug;
+}
+
+void prsaset_debug (int  bdebug )
+{
+        prsa_flex_debug = bdebug ;
+}
+
+static int yy_init_globals (void)
+{
+        /* Initialization is the same as for the non-reentrant scanner.
+     * This function is called from prsalex_destroy(), so don't allocate here.
+     */
+
+    (yy_buffer_stack) = 0;
+    (yy_buffer_stack_top) = 0;
+    (yy_buffer_stack_max) = 0;
+    (yy_c_buf_p) = (char *) 0;
+    (yy_init) = 0;
+    (yy_start) = 0;
+
+/* Defined in main.c */
+#ifdef YY_STDINIT
+    prsain = stdin;
+    prsaout = stdout;
+#else
+    prsain = (FILE *) 0;
+    prsaout = (FILE *) 0;
+#endif
+
+    /* For future reference: Set errno on error, since we are called by
+     * prsalex_init()
+     */
+    return 0;
+}
+
+/* prsalex_destroy is for both reentrant and non-reentrant scanners. */
+int prsalex_destroy  (void)
+{
+    
+    /* Pop the buffer stack, destroying each element. */
+	while(YY_CURRENT_BUFFER){
+		prsa_delete_buffer(YY_CURRENT_BUFFER  );
+		YY_CURRENT_BUFFER_LVALUE = NULL;
+		prsapop_buffer_state();
+	}
+
+	/* Destroy the stack itself. */
+	prsafree((yy_buffer_stack) );
+	(yy_buffer_stack) = NULL;
+
+    /* Reset the globals. This is important in a non-reentrant scanner so the next time
+     * prsalex() is called, initialization will occur. */
+    yy_init_globals( );
+
+    return 0;
+}
+
+/*
+ * Internal utility routines.
+ */
+
+#ifndef yytext_ptr
+static void yy_flex_strncpy (char* s1, yyconst char * s2, int n )
+{
+	register int i;
+	for ( i = 0; i < n; ++i )
+		s1[i] = s2[i];
+}
+#endif
+
+#ifdef YY_NEED_STRLEN
+static int yy_flex_strlen (yyconst char * s )
+{
+	register int n;
+	for ( n = 0; s[n]; ++n )
+		;
+
+	return n;
+}
+#endif
+
+void *prsaalloc (yy_size_t  size )
+{
+	return (void *) malloc( size );
+}
+
+void *prsarealloc  (void * ptr, yy_size_t  size )
+{
+	/* The cast to (char *) in the following accommodates both
+	 * implementations that use char* generic pointers, and those
+	 * that use void* generic pointers.  It works with the latter
+	 * because both ANSI C and C++ allow castless assignment from
+	 * any pointer type to void*, and deal with argument conversions
+	 * as though doing an assignment.
+	 */
+	return (void *) realloc( (char *) ptr, size );
+}
+
+void prsafree (void * ptr )
+{
+	free( (char *) ptr );	/* see prsarealloc() for (char *) cast */
+}
+
+#define YYTABLES_NAME "yytables"
+
+#line 89 "prsa_tok.l"
+
+
+
diff --git a/src/racoon/prsa_tok.l b/src/racoon/prsa_tok.l
new file mode 100644
index 0000000..83e3d14
--- /dev/null
+++ b/src/racoon/prsa_tok.l
@@ -0,0 +1,89 @@
+/*	$NetBSD: prsa_tok.l,v 1.4 2006/09/09 16:22:10 manu Exp $	*/
+
+/* Id: prsa_tok.l,v 1.2 2004/07/12 20:43:51 ludvigm Exp */
+
+%{
+/*
+ * Copyright (C) 2004 SuSE Linux AG, Nuernberg, Germany.
+ * Contributed by: Michal Ludvig <mludvig@suse.cz>, SUSE Labs
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* This file contains a tokeniser for FreeS/WAN-style ipsec.secrets RSA keys. */
+
+#include <string.h>
+#include <openssl/bn.h>
+#include <openssl/rsa.h>
+#include "prsa_par.h"
+
+extern int prsalex (void);
+extern int prsa_cur_lineno;
+
+%}
+
+comment		\#.*
+digit		[0-9]
+octet		(([01]?{digit}?{digit})|((2([0-4]{digit}))|(25[0-5])))
+addr4		{octet}\.{octet}\.{octet}\.{octet}
+hex		[0-9a-fA-F]
+word6		{hex}{0,4}
+base64		[A-Za-z0-9+/=]
+addr6		(::({word6}|{addr4})?|({word6}:)+:?({word6}|{addr4})?)
+%%
+\{		{ return OBRACE; }
+\}		{ return EBRACE; }
+:		{ return COLON; }
+RSA		{ return TAG_RSA; }
+PSK		{ return TAG_PSK; }
+PUB		{ return TAG_PUB; }
+0x[0-9a-fA-F]+	{ 
+			BIGNUM *bn = BN_new();
+			BN_hex2bn(&bn, prsatext+2);
+			prsalval.bn = bn;
+			return HEX;
+		}
+0s{base64}+	{
+			prsalval.chr = strdup(prsatext);
+			return BASE64;
+		}
+Modulus		{ return MODULUS; }
+PublicExponent	{ return PUBLIC_EXPONENT; }
+PrivateExponent	{ return PRIVATE_EXPONENT; }
+Prime1		{ return PRIME1; }
+Prime2		{ return PRIME2; }
+Exponent1	{ return EXPONENT1; }
+Exponent2	{ return EXPONENT2; }
+Coefficient	{ return COEFFICIENT; }
+\/		{ return SLASH; }
+{digit}+	{ prsalval.num = atol(prsatext); return NUMBER; }
+any		{ return ADDRANY; }
+{addr4}		{ prsalval.chr = strdup(prsatext); return ADDR4; }
+{addr6}		{ prsalval.chr = strdup(prsatext); return ADDR6; }
+[ \t]*		;
+\n		{ prsa_cur_lineno++; }
+\#.*		;
+%%
diff --git a/src/racoon/racoon.8 b/src/racoon/racoon.8
new file mode 100644
index 0000000..a6d39d7
--- /dev/null
+++ b/src/racoon/racoon.8
@@ -0,0 +1,155 @@
+.\"	$NetBSD: racoon.8,v 1.10 2006/09/09 16:22:10 manu Exp $
+.\"
+.\" Id: racoon.8,v 1.4 2005/04/18 11:07:55 manubsd Exp
+.\"
+.\" Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\" 3. Neither the name of the project nor the names of its contributors
+.\"    may be used to endorse or promote products derived from this software
+.\"    without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.Dd November 20, 2000
+.Dt RACOON 8
+.Os
+.\"
+.Sh NAME
+.Nm racoon
+.Nd IKE (ISAKMP/Oakley) key management daemon
+.\"
+.Sh SYNOPSIS
+.Nm racoon
+.Bk -words
+.Op Fl 46BdFLv
+.Ek
+.Bk -words
+.Op Fl f Ar configfile
+.Ek
+.Bk -words
+.Op Fl l Ar logfile
+.Ek
+.Bk -words
+.Op Fl P Ar isakmp-natt-port
+.Ek
+.Bk -words
+.Op Fl p Ar isakmp-port
+.Ek
+.\"
+.Sh DESCRIPTION
+.Nm
+speaks the IKE
+.Pq ISAKMP/Oakley
+key management protocol,
+to establish security associations with other hosts.
+The SPD
+.Pq Security Policy Database
+in the kernel usually triggers
+.Nm .
+.Nm
+usually sends all informational messages, warnings and error messages to
+.Xr syslogd 8
+with the facility
+.Dv LOG_DAEMON
+and the priority
+.Dv LOG_INFO .
+Debugging messages are sent with the priority
+.Dv LOG_DEBUG .
+You should configure
+.Xr syslog.conf 5
+appropriately to see these messages.
+.Bl -tag -width Ds
+.It Fl 4
+.It Fl 6
+Specify the default address family for the sockets.
+.It Fl B
+Install SA(s) from the file which is specified in
+.Xr racoon.conf 5 .
+.It Fl d
+Increase the debug level.
+Multiple
+.Fl d
+arguments will increase the debug level even more.
+.It Fl F
+Run
+.Nm
+in the foreground.
+.It Fl f Ar configfile
+Use
+.Ar configfile
+as the configuration file instead of the default.
+.It Fl L
+Include
+.Ar file_name:line_number:function_name
+in all messages.
+.It Fl l Ar logfile
+Use
+.Ar logfile
+as the logging file instead of
+.Xr syslogd 8 .
+.It Fl P Ar isakmp-natt-port
+Use
+.Ar isakmp-natt-port
+for NAT-Traversal port-floating.
+The default is 4500.
+.It Fl p Ar isakmp-port
+Listen to the ISAKMP key exchange on port
+.Ar isakmp-port
+instead of the default port number, 500.
+.It Fl v
+This flag causes the packet dump be more verbose, with higher
+debugging level.
+.El
+.Pp
+.Nm
+assumes the presence of the kernel random number device
+.Xr rnd 4
+at
+.Pa /dev/urandom .
+.\"
+.Sh RETURN VALUES
+The command exits with 0 on success, and non-zero on errors.
+.\"
+.Sh FILES
+.Bl -tag -width /etc/racoon.conf -compact
+.It Pa /etc/racoon.conf
+default configuration file.
+.El
+.\"
+.Sh SEE ALSO
+.Xr ipsec 4 ,
+.Xr racoon.conf 5 ,
+.Xr syslog.conf 5 ,
+.Xr setkey 8 ,
+.Xr syslogd 8
+.\"
+.Sh HISTORY
+The
+.Nm
+command first appeared in the
+.Dq YIPS
+Yokogawa IPsec implementation.
+.\"
+.Sh SECURITY CONSIDERATIONS
+The use of IKE phase 1 aggressive mode is not recommended,
+as described in
+.Pa http://www.kb.cert.org/vuls/id/886601 .
diff --git a/src/racoon/racoon.conf.5 b/src/racoon/racoon.conf.5
new file mode 100644
index 0000000..9ddee80
--- /dev/null
+++ b/src/racoon/racoon.conf.5
@@ -0,0 +1,1420 @@
+.\"	$NetBSD: racoon.conf.5,v 1.34.4.3 2007/09/03 18:07:29 mgrooms Exp $
+.\"
+.\"	Id: racoon.conf.5,v 1.54 2006/08/22 18:17:17 manubsd Exp
+.\"
+.\" Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\" 3. Neither the name of the project nor the names of its contributors
+.\"    may be used to endorse or promote products derived from this software
+.\"    without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.Dd September 19, 2006
+.Dt RACOON.CONF 5
+.Os
+.\"
+.Sh NAME
+.Nm racoon.conf
+.Nd configuration file for racoon
+.\"
+.\" .Sh SYNOPSIS
+.\"
+.Sh DESCRIPTION
+.Nm
+is the configuration file for the
+.Xr racoon 8
+ISAKMP daemon.
+.Xr racoon 8
+negotiates security associations for itself (ISAKMP SA, or phase 1 SA)
+and for kernel IPsec (IPsec SA, or phase 2 SA).
+The file consists of a sequence of directives and statements.
+Each directive is composed by a tag and statements, enclosed by
+.Ql {
+and
+.Ql } .
+Lines beginning with
+.Ql #
+are comments.
+.\"
+.Ss Meta Syntax
+Keywords and special characters that the parser expects exactly are
+displayed using
+.Ic this
+font.
+Parameters are specified with
+.Ar this
+font.
+Square brackets
+.Po
+.Ql \&[
+and
+.Ql \&]
+.Pc
+are used to show optional keywords and parameters.
+Note that
+you have to pay attention when this manual is describing
+.Ar port
+numbers.
+The
+.Ar port
+number is always enclosed by
+.Ql \&[
+and
+.Ql \&] .
+In this case, the port number is not an optional keyword.
+If it is possible to omit the
+.Ar port
+number,
+the expression becomes
+.Bq Bq Ar port .
+The vertical bar
+.Pq Ql \&|
+is used to indicate
+a choice between optional parameters.
+Parentheses
+.Po
+.Ql \&(
+and
+.Ql \&)
+.Pc
+are used to group keywords and parameters when necessary.
+Major parameters are listed below.
+.Pp
+.Bl -tag -width addressx -compact
+.It Ar number
+means a hexadecimal or a decimal number.
+The former must be prefixed with
+.Ql Li 0x .
+.It Ar string
+.It Ar path
+.It Ar file
+means any string enclosed in
+.Ql \&"
+.Pq double quotes .
+.It Ar address
+means IPv6 and/or IPv4 address.
+.It Ar port
+means a TCP/UDP port number.
+The port number is always enclosed by
+.Ql \&[
+and
+.Ql \&] .
+.It Ar timeunit
+is one of following:
+.Ic sec , secs , second , seconds ,
+.Ic min , mins , minute , minutes ,
+.Ic hour , hours .
+.El
+.\"
+.Ss Privilege separation
+.Bl -tag -width Ds -compact
+.It Ic privsep { Ar statements Ic }
+Specifies privilege separation parameters.
+When enabled, these enable
+.Xr racoon 8
+to operate with an unprivileged instance doing most of the work, while
+a privileged instance takes care of performing the following operations
+as root: reading PSK and private keys, launching hook scripts, and
+validating passwords against system databases or against PAM.
+Please note that using privilege separation makes changes to the
+.Ar listen
+and
+.Ar paths
+sections ignored upon configuration reloads.
+A
+.Xr racoon 8
+restart is required if you want such changes to be taken into account.
+.Pp
+.Bl -tag -width Ds -compact
+.It Ic user Ar user ;
+The user to which the unprivileged instance of
+.Xr racoon 8 ,
+should switch.
+This can be a quoted user name or a numeric UID.
+.It Ic group Ar group ;
+The group the unprivilegied instance of
+.Xr racoon 8 ,
+should switch.
+This can be a quoted group name or a numeric GID.
+.It Ic chroot Ar path ;
+A directory to which the unprivileged instance of
+.Xr racoon 8
+should
+.Xr chroot 2 .
+This directory should hold a tree where the following files must be
+reachable:
+.Bl -tag -width Ds -compact
+.It Pa /dev/random
+.It Pa /dev/urandom
+.It The certificates
+.It The file containing the Xauth banner
+.El
+.Pp
+The PSK file, the private keys, and the hook scripts are accessed through the
+privileged instance of
+.Xr racoon 8
+and do not need to be reachable in the
+.Xr chroot 2 Ap ed
+tree.
+.El
+.El
+.Ss Path Specification
+This section specifies various paths used by racoon.
+When running in privilege separation mode,
+.Ic certificate
+and
+.Ic script
+paths are mandatory. A
+.Xr racoon 8
+restart is required if you want path changes to be taken into account.
+.Bl -tag -width Ds -compact
+.It Ic path include Ar path ;
+Specifies a path to include a file.
+See
+.Sx File Inclusion .
+.It Ic path pre_shared_key Ar file ;
+Specifies a file containing pre-shared key(s) for various ID(s).
+See
+.Sx Pre-shared key File .
+.It Ic path certificate Ar path ;
+.Xr racoon 8
+will search this directory if a certificate or certificate request is received.
+If you run with privilege separation,
+.Xr racoon 8
+will refuse to use a certificate stored outside of this directory.
+.It Ic path backupsa Ar file ;
+Specifies a file to which SA information negotiated by
+racoon should be stored.
+.Xr racoon 8
+will install SA(s) from the file when started with the
+.Fl B
+flag.
+The file is growing because
+.Xr racoon 8
+simply adds SAs to it.
+You should maintain the file manually.
+.It Ic path script Ar path ;
+.Xr racoon 8
+will search this directory for scripts hooks.
+If you run with privilege separation,
+.Xr racoon 8
+will refuse to execute a script stored outside of this directory.
+.It Ic path pidfile Ar file ;
+Specifies file where to store PID of process.
+If path starts with
+.Pa /
+it is treated as an absolute path. Otherwise, it is treated as a relative 
+path to the VARRUN directory specified at compilation time.
+Default is
+.Pa racoon.pid .
+.El
+.\"
+.Ss File Inclusion
+.Bl -tag -width Ds -compact
+.It Ic include Ar file
+Specifies other configuration files to be included.
+.El
+.\"
+.Ss Identifier Specification
+is obsolete.
+It must be defined at each
+.Ic remote
+directive.
+.\"
+.Ss Timer Specification
+.Bl -tag -width Ds -compact
+.It Ic timer { Ar statements Ic }
+This section specifies various timer values used by racoon.
+.Pp
+.Bl -tag -width Ds -compact
+.It Ic counter Ar number ;
+The maximum number of retries to send.
+The default is 5.
+.It Ic interval Ar number Ar timeunit ;
+The interval to resend, in seconds.
+The default time is 10 seconds.
+.It Ic persend Ar number ;
+The number of packets per send.
+The default is 1.
+.It Ic phase1 Ar number Ar timeunit ;
+The maximum time it should take to complete phase 1.
+The default time is 15 seconds.
+.It Ic phase2 Ar number Ar timeunit ;
+The maximum time it should take to complete phase 2.
+The default time is 10 seconds.
+.It Ic natt_keepalive Ar number Ar timeunit ;
+The interval between sending NAT-Traversal keep-alive packets.
+The default time is 20 seconds.
+Set to 0s to disable keep-alive packets.
+.El
+.El
+.\"
+.Ss Listening Port Specification
+.Bl -tag -width Ds -compact
+.It Ic listen { Ar statements Ic }
+If no
+.Ar listen
+directive is specified,
+.Xr racoon 8
+will listen on all available interface addresses.
+The following is the list of valid statements:
+.Pp
+.Bl -tag -width Ds -compact
+.\" How do I express bold brackets; `[' and `]' .
+.\" Answer: For bold brackets, do "Ic \&[ foo \&]".
+.\" Is the "Bq Ic [ Ar port ] ;" buggy ?
+.It Ic isakmp Ar address Bq Bq Ar port ;
+If this is specified,
+.Xr racoon 8
+will only listen on the defined
+.Ar address .
+The default port is 500, which is specified by IANA.
+You can provide more than one address definition.
+.It Ic isakmp_natt Ar address Bq Ar port ;
+Same as
+.Ic isakmp
+but also sets the socket options to accept UDP-encapsulated ESP traffic for
+NAT-Traversal.
+If you plan to use NAT-T, you should provide at least one address
+with port 4500, which is specified by IANA.
+There is no default.
+.It Ic strict_address ;
+Requires that all addresses for ISAKMP be bound.
+This statement will be ignored if you do not specify address definitions.
+.El
+When running in privilege separation mode, you need to restart
+.Xr racoon 8
+to have changes to the
+.Ar listen
+section taken into account.
+.Pp
+The
+.Ar listen
+section can also be used to specify the admin socket mode and ownership
+if racoon was built with support for admin port.
+.Bl -tag -width Ds -compact
+.It Ic adminsock Ar path Op Ar owner\ group\ mode ;
+The
+.Ar path ,
+.Ar owner ,
+and
+.Ar group
+values specify the socket path, owner, and group. They must be quoted.
+The defaults are
+.Pa /var/racoon/racoon.sock ,
+UID 0, and GID 0.
+.Ar mode
+is the access mode in octal. The default is 0600.
+.It Ic adminsock disabled ;
+This directive tells racoon to not listen on the admin socket.
+.El
+.El
+.\"
+.Ss Miscellaneous Global Parameters
+.Bl -tag -width Ds -compact
+.It Ic gss_id_enc Ar enctype ;
+Older versions of
+.Xr racoon 8
+used ISO-Latin-1 as the encoding of the GSS-API identifier attribute.
+For interoperability with Microsoft Windows' GSS-API authentication
+scheme, the default encoding has been changed to UTF-16LE.
+The
+.Ic gss_id_enc
+parameter allows
+.Xr racoon 8
+to be configured to use the old encoding for compatibility with existing
+.Xr racoon 8
+installations.
+The following are valid values for
+.Ar enctype :
+.Pp
+.Bl -tag -width Ds -compact
+.It Ic utf-16le
+Use UTF-16LE to encode the GSS-API identifier attribute.
+This is the default encoding.
+This encoding is compatible with Microsoft Windows.
+.It Ic latin1
+Use ISO-Latin-1 to encode the GSS-API identifier attribute.
+This is the encoding used by older versions of
+.Xr racoon 8 .
+.El
+.El
+.\"
+.Ss Remote Nodes Specifications
+.Bl -tag -width Ds -compact
+.It Xo
+.Ic remote ( Ar address | Ic anonymous )
+.Bq Bq Ar port
+.Bq Ic inherit Ar parent
+.Ic { Ar statements Ic }
+.Xc
+Specifies the IKE phase 1 parameters for each remote node.
+The default port is 500.
+If
+.Ic anonymous
+is specified, the statements will apply to any peer that does not match a
+more specific
+.Ic remote
+directive.
+.Pp
+Sections with
+.Ic inherit Ar parent
+statements (where
+.Ar parent
+is either
+.Ar address
+or a keyword
+.Ic anonymous )
+that have all values predefined to those of a given
+.Ar parent .
+In these sections it is enough to redefine only the changed parameters.
+.Pp
+The following are valid statements.
+.Pp
+.Bl -tag -width Ds -compact
+.\"
+.It Ic exchange_mode ( main | aggressive | base ) ;
+Defines the exchange mode for phase 1 when racoon is the initiator.
+It also means the acceptable exchange mode when racoon is the responder.
+More than one mode can be specified by separating them with a comma.
+All of the modes are acceptable.
+The first exchange mode is what racoon uses when it is the initiator.
+.\"
+.It Ic doi Ic ipsec_doi ;
+Means to use IPsec DOI as specified in RFC 2407.
+You can omit this statement.
+.\"
+.It Ic situation Ic identity_only ;
+Means to use SIT_IDENTITY_ONLY as specified in RFC 2407.
+You can omit this statement.
+.\"
+.It Ic identifier Ar idtype ;
+This statment is obsolete. Instead, use
+.Ic my_identifier .
+.\"
+.It Xo
+.Ic my_identifier Bq Ar qualifier
+.Ar idtype ... ;
+.Xc
+Specifies the identifier sent to the remote host
+and the type to use in the phase 1 negotiation.
+.Ic address, fqdn , user_fqdn , keyid ,
+and
+.Ic asn1dn
+can be used as an
+.Ar idtype .
+The
+.Ar qualifier
+is currently only used for
+.Ic keyid ,
+and can be either
+.Ic file
+or
+.Ic tag .
+The possible values are :
+.Bl -tag -width Ds -compact
+.It Ic my_identifier Ic address Bq Ar address ;
+The type is the IP address.
+This is the default type if you do not specify an identifier to use.
+.It Ic my_identifier Ic user_fqdn Ar string ;
+The type is a USER_FQDN (user fully-qualified domain name).
+.It Ic my_identifier Ic fqdn Ar string ;
+The type is a FQDN (fully-qualified domain name).
+.It Xo
+.Ic my_identifier Ic keyid Bq Ic file
+.Ar file ;
+.Xc
+The type is a KEY_ID, read from the file.
+.It Ic my_identifier Ic keyid Ic tag Ar string ;
+The type is a KEY_ID, specified in the quoted string.
+.It Ic my_identifier Ic asn1dn Bq Ar string ;
+The type is an ASN.1 distinguished name.
+If
+.Ar string
+is omitted,
+.Xr racoon 8
+will get the DN from the Subject field in the certificate.
+.El
+.\"
+.It Ic xauth_login Bq Ar string ;
+Specifies the login to use in client-side Hybrid authentication.
+It is available only if
+.Xr racoon 8
+has been built with this option.
+The associated password is looked up in the pre-shared key files,
+using the login
+.Ic string
+as the key id.
+.\"
+.It Ic peers_identifier Ar idtype ... ;
+Specifies the peer's identifier to be received.
+If it is not defined then
+.Xr racoon 8
+will not verify the peer's identifier in ID payload transmitted from the peer.
+If it is defined, the behavior of the verification depends on the flag of
+.Ic verify_identifier .
+The usage of
+.Ar idtype
+is the same as
+.Ic my_identifier
+except that the individual component values of an
+.Ic asn1dn
+identifier may specified as
+.Ic *
+to match any value (e.g. "C=XX, O=MyOrg, OU=*, CN=Mine").
+Alternative acceptable peer identifiers may be specified by repeating the
+.Ic peers_identifier
+statement.
+.\"
+.It Ic verify_identifier (on | off) ;
+If you want to verify the peer's identifier,
+set this to on.
+In this case, if the value defined by
+.Ic peers_identifier
+is not the same as the peer's identifier in the ID payload,
+the negotiation will fail.
+The default is off.
+.\"
+.It Ic certificate_type Ar certspec ;
+Specifies a certificate specification.
+.Ar certspec
+is one of followings:
+.Bl -tag -width Ds -compact
+.It Ic x509 Ar certfile Ar privkeyfile ;
+.Ar certfile
+means a file name of a certificate.
+.Ar privkeyfile
+means a file name of a secret key.
+.El
+.Bl -tag -width Ds -compact
+.It Ic plain_rsa Ar privkeyfile ;
+.Ar privkeyfile
+means a file name of a private key generated by plainrsa-gen(8).  Required
+for RSA authentication.
+.El
+.It Ic ca_type Ar cacertspec ;
+Specifies a root certificate authority specification.
+.Ar cacertspec
+is one of followings:
+.Bl -tag -width Ds -compact
+.It Ic x509 Ar cacertfile ;
+.Ar cacertfile
+means a file name of the root certificate authority.
+Default is
+.Pa /etc/openssl/cert.pem
+.El
+.\"
+.It Ic mode_cfg (on | off) ;
+Gather network information through ISAKMP mode configuration.
+Default is off.
+.\"
+.It Ic weak_phase1_check (on | off) ;
+Tells racoon to act on unencrypted deletion messages during phase 1.
+This is a small security risk, so the default is off, meaning that
+racoon will keep on trying to establish a connection even if the
+user credentials are wrong, for instance.
+.\"
+.It Ic peers_certfile ( dnssec | Ar certfile | Ic plain_rsa Ar pubkeyfile ) ;
+If
+.Ic dnssec
+is defined,
+.Xr racoon 8
+will ignore the CERT payload from the peer,
+and try to get the peer's certificate from DNS instead.
+If
+.Ar certfile
+is defined,
+.Xr racoon 8
+will ignore the CERT payload from the peer,
+and will use this certificate as the peer's certificate.
+If
+.Ic plain_rsa
+is defined,
+.Xr racoon 8
+will expect
+.Ar pubkeyfile
+to be the peer's public key that was generated
+by plainrsa-gen(8).
+.\"
+.It Ic script Ar script Ic phase1_up
+.It Ic script Ar script Ic phase1_down
+Shell scripts that get executed when a phase 1 SA goes up or down.
+Both scripts get either
+.Ic phase1_up
+or
+.Ic phase1_down
+as first argument, and the following
+variables are set in their environment:
+.Bl -tag -width Ds -compact
+.It Ev LOCAL_ADDR
+The local address of the phase 1 SA.
+.It Ev LOCAL_PORT
+The local port used for IKE for the phase 1 SA.
+.It Ev REMOTE_ADDR
+The remote address of the phase 1 SA.
+.It Ev REMOTE_PORT
+The remote port used for IKE for the phase 1 SA.
+.El
+The following variables are only set if
+.Ic mode_cfg
+was enabled:
+.Bl -tag -width Ds -compact
+.It INTERNAL_ADDR4
+An IPv4 internal address obtained by ISAKMP mode config.
+.It INTERNAL_NETMASK4
+An IPv4 internal netmask obtained by ISAKMP mode config.
+.It INTERNAL_CIDR4
+An IPv4 internal netmask obtained by ISAKMP mode config, in CIDR notation.
+.It INTERNAL_DNS4
+The first internal DNS server IPv4 address obtained by ISAKMP mode config.
+.It INTERNAL_DNS4_LIST
+A list of internal DNS servers IPv4 address obtained by ISAKMP mode config,
+separated by spaces.
+.It INTERNAL_WINS4
+The first internal WINS server IPv4 address obtained by ISAKMP mode config.
+.It INTERNAL_WINS4_LIST
+A list of internal WINS servers IPv4 address obtained by ISAKMP mode config,
+separated by spaces.
+.It SPLIT_INCLUDE
+The space separated list of IPv4 addresses and masks (address slash mask)
+that define the networks to be encrypted (as opposed to the default where
+all the traffic should be encrypted) ; obtained by ISAKMP mode config ;
+SPLIT_INCLUDE and SPLIT_LOCAL are mutually exclusive.
+.It SPLIT_LOCAL
+The space separated list of IPv4 addresses and masks (address slash mask)
+that define the networks to be considered local, and thus excluded from the
+tunnels ; obtained by ISAKMP mode config.
+.It DEFAULT_DOMAIN
+The DNS default domain name obtained by ISAKMP mode config.
+.El
+.\"
+.\"
+.It Ic send_cert (on | off) ;
+If you do not want to send a certificate, set this to off.
+The default is on.
+.\"
+.It Ic send_cr (on | off) ;
+If you do not want to send a certificate request, set this to off.
+The default is on.
+.\"
+.It Ic verify_cert (on | off) ;
+By default, the identifier sent by the remote host (as specified in its
+.Ic my_identifier
+statement) is compared with the credentials in the certificate
+used to authenticate the remote host as follows:
+.Bl -tag -width Ds -compact
+.It Type Ic asn1dn:
+The entire certificate subject name is compared with the identifier,
+e.g. "C=XX, O=YY, ...".
+.It Type Ic address, fqdn, or user_fqdn:
+The certificate's subjectAltName is compared with the identifier.
+.El
+If the two do not match the negotiation will fail.
+If you do not want to verify the identifier using the peer's certificate,
+set this to off.
+.\"
+.It Ic lifetime time Ar number Ar timeunit ;
+Define a lifetime of a certain time
+which will be proposed in the phase 1 negotiations.
+Any proposal will be accepted, and the attribute(s) will not be proposed to
+the peer if you do not specify it (them).
+They can be individually specified in each proposal.
+.\"
+.It Ic ike_frag (on | off | force) ;
+Enable receiver-side IKE fragmentation if
+.Xr racoon 8
+has been built with this feature.
+If set to on, racoon will advertise
+itself as being capable of receiving packets split by IKE fragmentation.
+This extension is there to work around broken firewalls that do not
+work with fragmented UDP packets.
+IKE fragmentation is always enabled on the sender-side, and it is
+used if the peer advertises itself as IKE fragmentation capable.
+By selecting force, IKE Fragmentation will
+be used when racoon is acting as the initiator even before the remote
+peer has advertised itself as IKE fragmentation capable.
+.\"
+.It Ic esp_frag Ar fraglen ;
+This option is only relevant if you use NAT traversal in tunnel mode.
+Its purpose is to work around broken DSL routers that reject UDP
+fragments, by fragmenting the IP packets before ESP encapsulation.
+The result is ESP over UDP of fragmented packets instead of fragmented
+ESP over UDP packets (i.e., IP:UDP:ESP:frag(IP) instead of
+frag(IP:UDP:ESP:IP)).
+.Ar fraglen
+is the maximum size of the fragments.
+552 should work anywhere,
+but the higher
+.Ar fraglen
+is, the better the performance.
+.Pp
+Note that because PMTU discovery is broken on many sites, you will
+have to use MSS clamping if you want TCP to work correctly.
+.\"
+.It Ic initial_contact (on | off) ;
+Enable this to send an INITIAL-CONTACT message.
+The default value is
+.Ic on .
+This message is useful only when the responder implementation chooses an
+old SA when there are multiple SAs with different established time and the
+initiator reboots.
+If racoon did not send the message,
+the responder would use an old SA even when a new SA was established.
+For systems that use a KAME derived IPSEC stack, the
+.Xr sysctl 8
+variable net.key.preferred_oldsa can be used to control this preference.
+When the value is zero, the stack always uses a new SA.
+.\"
+.It Ic passive (on | off) ;
+If you do not want to initiate the negotiation, set this to on.
+The default value is
+.Ic off .
+It is useful for a server.
+.\"
+.It Ic proposal_check Ar level ;
+Specifies the action of lifetime length, key length and PFS of the phase 2
+selection on the responder side, and the action of lifetime check in
+phase 1.
+The default level is
+.Ic strict .
+If the
+.Ar level
+is:
+.Bl -tag -width Ds -compact
+.It Ic obey
+The responder will obey the initiator anytime.
+.It Ic strict
+If the responder's lifetime length is longer than the initiator's or
+the responder's key length is shorter than the initiator's,
+the responder will use the initiator's value.
+Otherwise, the proposal will be rejected.
+If PFS is not required by the responder, the responder will obey the proposal.
+If PFS is required by both sides and the responder's group is not equal to
+the initiator's, then the responder will reject the proposal.
+.It Ic claim
+If the responder's lifetime length is longer than the initiator's or
+the responder's key length is shorter than the initiator's,
+the responder will use the initiator's value.
+If the responder's lifetime length is shorter than the initiator's,
+the responder uses its own length AND sends a RESPONDER-LIFETIME notify
+message to an initiator in the case of lifetime (phase 2 only).
+For PFS, this directive behaves the same as
+.Ic strict .
+.It Ic exact
+If the initiator's lifetime or key length is not equal to the responder's,
+the responder will reject the proposal.
+If PFS is required by both sides and the responder's group is not equal to
+the initiator's, then the responder will reject the proposal.
+.El
+.\"
+.It Ic support_proxy (on | off) ;
+If this value is set to on, then both values of ID payloads in the
+phase 2 exchange are always used as the addresses of end-point of
+IPsec-SAs.
+The default is off.
+.\"
+.It Ic generate_policy (on | off | require | unique) ;
+This directive is for the responder.
+Therefore you should set
+.Ic passive
+to on in order that
+.Xr racoon 8
+only becomes a responder.
+If the responder does not have any policy in SPD during phase 2
+negotiation, and the directive is set to on, then
+.Xr racoon 8
+will choose the first proposal in the
+SA payload from the initiator, and generate policy entries from the proposal.
+It is useful to negotiate with clients whose IP address is allocated
+dynamically.
+Note that an inappropriate policy might be installed into the responder's SPD
+by the initiator,
+so other communications might fail if such policies are installed
+due to a policy mismatch between the initiator and the responder.
+.Ic on
+and
+.Ic require
+values mean the same thing (generate a require policy).
+.Ic unique
+tells racoon to set up unique policies, with a monotoning increasing
+reqid number (between 1 and IPSEC_MANUAL_REQID_MAX).
+This directive is ignored in the initiator case.
+The default value is
+.Ic off .
+.\"
+.\"
+.It Ic nat_traversal (on | off | force) ;
+This directive enables use of the NAT-Traversal IPsec extension
+(NAT-T).
+NAT-T allows one or both peers to reside behind a NAT gateway (i.e.,
+doing address- or port-translation).
+If a NAT gateway is detected during the phase 1 handshake, racoon will
+attempt to negotiate the use of NAT-T with the remote peer.
+If the negotiation succeeds, all ESP and AH packets for the given connection
+will be encapsulated into UDP datagrams (port 4500, by default).
+Possible values are:
+.Bl -tag -width Ds -compact
+.It Ic on
+NAT-T is used when a NAT gateway is detected between the peers.
+.It Ic off
+NAT-T is not proposed/accepted.
+This is the default.
+.It Ic force
+NAT-T is used regardless of whether a NAT gateway is detected between the
+peers or not.
+.El
+Please note that NAT-T support is a compile-time option.
+Although it is enabled in the source distribution by default, it
+may not be available in your particular build.
+In that case you will get a
+warning when using any NAT-T related config options.
+.\"
+.It Ic dpd_delay Ar delay ;
+This option activates the DPD and sets the time (in seconds) allowed
+between 2 proof of liveliness requests.
+The default value is
+.Ic 0 ,
+which disables DPD monitoring, but still negotiates DPD support.
+.\"
+.It Ic dpd_retry Ar delay ;
+If
+.Ic dpd_delay
+is set, this sets the delay (in seconds) to wait for a proof of
+liveliness before considering it as failed and send another request.
+The default value is
+.Ic 5 .
+.\"
+.It Ic dpd_maxfail Ar number ;
+If
+.Ic dpd_delay
+is set, this sets the maximum number of liveliness proofs to request
+(without reply) before considering the peer is dead.
+The default value is
+.Ic 5 .
+.\"
+.It Ic nonce_size Ar number ;
+define the byte size of nonce value.
+Racoon can send any value although
+RFC2409 specifies that the value MUST be between 8 and 256 bytes.
+The default size is 16 bytes.
+.\"
+.It Ic ph1id Ar number ;
+An optionnal number to identify the remote proposal and to link it
+only with sainfos who have the same number.
+Defaults to 0.
+.\"
+.It Xo
+.Ic proposal { Ar sub-substatements Ic }
+.Xc
+.Bl -tag -width Ds -compact
+.\"
+.It Ic encryption_algorithm Ar algorithm ;
+Specifies the encryption algorithm used for the phase 1 negotiation.
+This directive must be defined.
+.Ar algorithm
+is one of following:
+.Ic des, 3des, blowfish, cast128, aes, camellia
+.\".Ic rc5 , idea
+for Oakley.
+For other transforms, this statement should not be used.
+.\"
+.It Ic hash_algorithm Ar algorithm ;
+Defines the hash algorithm used for the phase 1 negotiation.
+This directive must be defined.
+.Ar algorithm
+is one of following:
+.Ic md5, sha1, sha256, sha384, sha512
+for Oakley.
+.\"
+.It Ic authentication_method Ar type ;
+Defines the authentication method used for the phase 1 negotiation.
+This directive must be defined.
+.Ar type
+is one of:
+.Ic pre_shared_key , rsasig
+(for plain RSA authentication),
+.Ic gssapi_krb , hybrid_rsa_server ,
+.Ic hybrid_rsa_client , xauth_rsa_server , xauth_rsa_client , xauth_psk_server
+or
+.Ic xauth_psk_client .
+.\"
+.It Ic dh_group Ar group ;
+Defines the group used for the Diffie-Hellman exponentiations.
+This directive must be defined.
+.Ar group
+is one of following:
+.Ic modp768 , modp1024 , modp1536 ,
+.Ic modp2048 , modp3072 , modp4096 ,
+.Ic modp6144 , modp8192 .
+Or you can define 1, 2, 5, 14, 15, 16, 17, or 18 as the DH group number.
+When you want to use aggressive mode,
+you must define the same DH group in each proposal.
+.It Ic lifetime time Ar number Ar timeunit ;
+Defines the lifetime of the phase 1 SA proposal.
+Refer to the description of the
+.Ic lifetime
+directive defined in the
+.Ic remote
+directive.
+.It Ic gss_id Ar string ;
+Defines the GSS-API endpoint name, to be included as an attribute in the SA,
+if the
+.Ic gssapi_krb
+authentication method is used.
+If this is not defined, the default value of
+.Ql host/hostname
+is used, where hostname is the value returned by the
+.Xr hostname 1
+command.
+.El
+.El
+.El
+.\"
+.Ss Policy Specifications
+The policy directive is obsolete, policies are now in the SPD.
+.Xr racoon 8
+will obey the policy configured into the kernel by
+.Xr setkey 8 ,
+and will construct phase 2 proposals by combining
+.Ic sainfo
+specifications in
+.Nm ,
+and policies in the kernel.
+.\"
+.Ss Sainfo Specifications
+.Bl -tag -width Ds -compact
+.It Xo
+.Ic sainfo ( Ar source_id destination_id | Ar source_id Ic anonymous | Ic anonymous Ar destination_id | Ic anonymous ) [ from Ar idtype [ Ar string ] ] [ Ic group Ar string ]
+.Ic { Ar statements Ic }
+.Xc
+defines the parameters of the IKE phase 2 (IPsec-SA establishment).
+.Ar source_id
+and
+.Ar destination_id
+are constructed like:
+.Pp
+.Ic address Ar address
+.Bq Ic / Ar prefix
+.Bq Ic [ Ar port ]
+.Ar ul_proto
+.Pp
+or
+.Pp
+.Ic subnet Ar address
+.Bq Ic / Ar prefix
+.Bq Ic [ Ar port ]
+.Ar ul_proto
+.Pp
+or
+.Pp
+.Ar idtype Ar string
+.Pp
+An id string should be expressed to match the exact value of an ID payload
+(source is the local end, destination is the remote end).
+This is not like a filter rule.
+For example, if you define 3ffe:501:4819::/48 as
+.Ar source_id .
+3ffe:501:4819:1000:/64 will not match.
+.Pp
+In the case of a longest prefix (selecting a single host),
+.Ar address
+instructs to send ID type of ADDRESS while
+.Ar subnet
+instructs to send ID type of SUBNET.
+Otherwise, these instructions are identical.
+.Pp
+The group keyword allows an XAuth group membership check to be performed
+for this sainfo section.
+When the mode_cfg auth source is set to
+.Ic system
+or
+.Ic ldap ,
+the XAuth user is verified to be a member of the specified group
+before allowing a matching SA to be negotiated.
+.Pp
+.Bl -tag -width Ds -compact
+.\"
+.It Ic pfs_group Ar group ;
+define the group of Diffie-Hellman exponentiations.
+If you do not require PFS then you can omit this directive.
+Any proposal will be accepted if you do not specify one.
+.Ar group
+is one of following:
+.Ic modp768 , modp1024 , modp1536 ,
+.Ic modp2048 , modp3072 , modp4096 ,
+.Ic modp6144 , modp8192 .
+Or you can define 1, 2, 5, 14, 15, 16, 17, or 18 as the DH group number.
+.\"
+.It Ic lifetime time Ar number Ar timeunit ;
+define how long an IPsec-SA will be used, in timeunits.
+Any proposal will be accepted, and no attribute(s) will be proposed to
+the peer if you do not specify it(them).
+See the
+.Ic proposal_check
+directive.
+.\"
+.It Ic remoteid Ar number ;
+Sainfos will only be used if their remoteid matches the ph1id of the
+remote section used for phase 1.
+Defaults to 0, which is also the default for ph1id.
+.\"
+.It Ic my_identifier Ar idtype ... ;
+is obsolete.
+It does not make sense to specify an identifier in the phase 2.
+.El
+.\"
+.Pp
+.Xr racoon 8
+does not have a list of security protocols to be negotiated.
+The list of security protocols are passed by SPD in the kernel.
+Therefore you have to define all of the potential algorithms
+in the phase 2 proposals even if there are algorithms which will not be used.
+These algorithms are define by using the following three directives,
+with a single comma as the separator.
+For algorithms that can take variable-length keys, algorithm names
+can be followed by a key length, like
+.Dq Li blowfish 448 .
+.Xr racoon 8
+will compute the actual phase 2 proposals by computing
+the permutation of the specified algorithms,
+and then combining them with the security protocol specified by the SPD.
+For example, if
+.Ic des , 3des , hmac_md5 ,
+and
+.Ic hmac_sha1
+are specified as algorithms, we have four combinations for use with ESP,
+and two for AH.
+Then, based on the SPD settings,
+.Xr racoon 8
+will construct the actual proposals.
+If the SPD entry asks for ESP only, there will be 4 proposals.
+If it asks for both AH and ESP, there will be 8 proposals.
+Note that the kernel may not support the algorithm you have specified.
+.\"
+.Bl -tag -width Ds -compact
+.It Ic encryption_algorithm Ar algorithms ;
+.Ic des , 3des , des_iv64 , des_iv32 ,
+.Ic rc5 , rc4 , idea , 3idea ,
+.Ic cast128 , blowfish , null_enc ,
+.Ic twofish , rijndael , aes , camellia
+.Pq used with ESP
+.\"
+.It Ic authentication_algorithm Ar algorithms ;
+.Ic des , 3des , des_iv64 , des_iv32 ,
+.Ic hmac_md5 , hmac_sha1 , hmac_sha256, hmac_sha384, hmac_sha512, non_auth
+.Pq used with ESP authentication and AH
+.\"
+.It Ic compression_algorithm Ar algorithms ;
+.Ic deflate
+.Pq used with IPComp
+.El
+.El
+.\"
+.Ss Logging level
+.Bl -tag -width Ds -compact
+.It Ic log Ar level ;
+Defines the logging level.
+.Ar level
+is one of following:
+.Ic error , warning , notify , info , debug
+and
+.Ic debug2 .
+The default is
+.Ic info .
+If you set the logging level too high on slower machines,
+IKE negotiation can fail due to timing constraint changes.
+.El
+.\"
+.Ss Specifies the way to pad
+.Bl -tag -width Ds -compact
+.It Ic padding { Ar statements Ic }
+specifies the padding format.
+The following are valid statements:
+.Bl -tag -width Ds -compact
+.It Ic randomize (on | off) ;
+Enables the use of a randomized value for padding.
+The default is on.
+.It Ic randomize_length (on | off) ;
+The pad length will be random.
+The default is off.
+.It Ic maximum_length Ar number ;
+Defines a maximum padding length.
+If
+.Ic randomize_length
+is off, this is ignored.
+The default is 20 bytes.
+.It Ic exclusive_tail (on | off) ;
+Means to put the number of pad bytes minus one into the last part
+of the padding.
+The default is on.
+.It Ic strict_check (on | off) ;
+Means to constrain the peer to set the number of pad bytes.
+The default is off.
+.El
+.El
+.Ss ISAKMP mode configuration settings
+.Bl -tag -width Ds -compact
+.It Ic mode_cfg { Ar statements Ic }
+Defines the information to return for remote hosts' ISAKMP mode config
+requests.
+Also defines the authentication source for remote peers
+authenticating through Xauth.
+.Pp
+The following are valid statements:
+.Bl -tag -width Ds -compact
+.It Ic auth_source (system | radius | pam | ldap) ;
+Specifies the source for authentication of users through Xauth.
+.Ar system
+means to use the Unix user database.
+This is the default.
+.Ar radius
+means to use a RADIUS server.
+It works only if
+.Xr racoon 8
+was built with libradius support. Radius configuration is hanlded by
+.Xr radius.conf 5 .
+.Ar pam
+means to use PAM.
+It works only if
+.Xr racoon 8
+was built with libpam support.
+.Ar ldap
+means to use LDAP.
+It works only if
+.Xr racoon 8
+was built with libldap support. LDAP configuration is handled by
+statements in the
+.Ic ldapcfg
+section.
+.It Ic auth_groups Ar "group1", ... ;
+Specifies the group memberships for Xauth in quoted group name strings.
+When defined, the authenticating user must be a member of at least one
+group for Xauth to succeed.
+.It Ic group_source (system | ldap) ;
+Specifies the source for group validataion of users through Xauth.
+.Ar system
+means to use the Unix user database.
+This is the default.
+.Ar ldap
+means to use LDAP.
+It works only if
+.Xr racoon 8
+was built with libldap support and requires LDAP authentication.
+LDAP configuration is handled by statements in the
+.Ic ldapcfg
+section.
+.It Ic conf_source (local | radius | ldap) ;
+Specifies the source for IP addresses and netmask allocated through ISAKMP
+mode config.
+.Ar local
+means to use the local IP pool defined by the
+.Ic network4
+and
+.Ic pool_size
+statements.
+This is the default.
+.Ar radius
+means to use a RADIUS server.
+It works only if
+.Xr racoon 8
+was built with libradius support and requires RADIUS authentiation.
+RADIUS configuration is handled by
+.Xr radius.conf 5 .
+.Ar ldap
+means to use an LDAP server.
+It works only if
+.Xr racoon 8
+was built with libldap support and requires LDAP authentication.
+LDAP configuration is handled by
+statements in the
+.Ic ldapcfg
+section.
+.It Ic accounting (none | system | radius | pam) ;
+Enables or disables accounting for Xauth logins and logouts.
+The default is
+.Ar none
+which disable accounting.
+Specifying
+.Ar system
+enables system accounting through
+.Xr utmp 5 .
+Specifying
+.Ar radius
+enables RADIUS accounting.
+It works only if
+.Xr racoon 8
+was built with libradius support and requires RADIUS authentication.
+RADIUS configuration is handled by
+.Xr radius.conf 5 .
+Specifying
+.Ar pam
+enables PAM accounting.
+It works only if
+.Xr racoon 8
+was build with libpam support and requires PAM authentication.
+.It Ic pool_size Ar size
+Specify the size of the IP address pool, either local or allocated
+through RADIUS.
+.Ic conf_source
+selects the local pool or the RADIUS configuration, but in both
+configurations, you cannot have more than
+.Ar size
+users connected at the same time.
+The default is 255.
+.It Ic network4 Ar address ;
+.It Ic netmask4 Ar address ;
+The local IP pool base address and network mask from which dynamically
+allocated IPv4 addresses should be taken.
+This is used if
+.Ic conf_source
+is set to
+.Ar local
+or if the RADIUS server returned
+.Ar 255.255.255.254 .
+Default is
+.Ar 0.0.0.0/0.0.0.0 .
+.It Ic dns4 Ar addresses ;
+A list of IPv4 addresses for DNS servers, separated by commas, or on multiple
+.Ic dns4
+lines.
+.It Ic wins4 Ar addresses ;
+A list of IPv4 address for WINS servers. The keyword
+.It nbns4
+can also be used as an alias for
+.It wins4 .
+.It Ic split_network (include | local_lan) Ar network/mask, ...
+The network configuration to send, in cidr notation (e.g. 192.168.1.0/24).
+If
+.Ic include
+is specified, the tunnel should be only used to encrypt the indicated
+destinations ; otherwise, if
+.Ic local_lan
+is used, everything will pass through the tunnel but those destinations.
+.It Ic default_domain Ar domain ;
+The default DNS domain to send.
+.It Ic split_dns Ar "domain", ...
+The split dns configuration to send, in quoted domain name strings.
+This list can be used to describe a list of domain names for which
+a peer should query a modecfg assigned dns server.
+DNS queries for all other domains would be handled locally.
+(Cisco VPN client only).
+.It Ic banner Ar path ;
+The path of a file displayed on the client at connection time.
+Default is
+.Ar /etc/motd .
+.It Ic auth_throttle Ar delay ;
+On each failed Xauth authentication attempt, refuse new attempts for a set
+.Ar delay
+of seconds.
+This is to avoid dictionary attacks on Xauth passwords.
+Default is one second.
+Set to zero to disable authentication delay.
+.It Ic pfs_group Ar group ;
+Sets the PFS group used in the client proposal (Cisco VPN client only).
+Default is 0.
+.It Ic save_passwd (on | off) ;
+Allow the client to save the Xauth password (Cisco VPN client only).
+Default is off.
+.El
+.El
+.Ss Ldap configuration settings
+.Bl -tag -width Ds -compact
+.It Ic ldapcfg { Ar statements Ic }
+Defines the parameters that will be used to communicate with an ldap
+server for
+.Ic xauth
+authentication.
+.Pp
+The following are valid statements:
+.Bl -tag -width Ds -compact
+.It Ic version (2 | 3) ;
+The ldap protocol version used to communicate with the server.
+The default is
+.Ic 3 .
+.It Ic host Ar (hostname | address) ;
+The host name or ip address of the ldap server.
+The default is
+.Ic localhost .
+.It Ic port Ar number;
+The port that the ldap server is configured to listen on.
+The default is
+.Ic 389 .
+.It Ic base Ar distinguished name;
+The ldap search base.
+This option has no default value.
+.It Ic subtree (on | off) ;
+Use the subtree ldap search scope.
+Otherwise, use the one level search scope.
+The default is
+.Ic off .
+.It Ic bind_dn Ar distinguised name;
+The user dn used to optionaly bind as before performing ldap search operations.
+If this option is not specified, anonymous binds are used.
+.It Ic bind_pw Ar string;
+The password used when binding as
+.Ic bind_dn .
+.It Ic attr_user Ar attribute name;
+The attribute used to specify a users name in an ldap directory.
+For example,
+if a user dn is "cn=jdoe,dc=my,dc=net" then the attribute would be "cn".
+The default value is
+.Ic cn .
+.It Ic attr_addr Ar attribute name;
+.It Ic attr_mask Ar attribute name;
+The attributes used to specify a users network address and subnet mask in an
+ldap directory.
+These values are forwarded during mode_cfg negotiation when
+the conf_source is set to ldap.
+The default values are
+.Ic racoon-address
+and
+.Ic racoon-netmask .
+.It Ic attr_group Ar attribute name;
+The attribute used to specify a group name in an ldap directory.
+For example,
+if a group dn is "cn=users,dc=my,dc=net" then the attribute would be "cn".
+The default value is
+.Ic cn .
+.It Ic attr_member Ar attribute name;
+The attribute used to specify group membership in an ldap directory.
+The default value is
+.Ic member .
+.El
+.El
+.Ss Special directives
+.Bl -tag -width Ds -compact
+.It Ic complex_bundle (on | off) ;
+defines the interpretation of proposal in the case of SA bundle.
+Normally
+.Dq IP AH ESP IP payload
+is proposed as
+.Dq AH tunnel and ESP tunnel .
+The interpretation is more common to other IKE implementations, however,
+it allows very limited set of combinations for proposals.
+With the option enabled, it will be proposed as
+.Dq AH transport and ESP tunnel .
+The default value is
+.Ic off .
+.El
+.\"
+.Ss Pre-shared key File
+The pre-shared key file defines pairs of identifiers and corresponding
+shared secret keys which are used in the pre-shared key authentication
+method in phase 1.
+The pair in each line is separated by some number of blanks and/or tab
+characters like in the
+.Xr hosts 5
+file.
+Key can include blanks because everything after the first blanks
+is interpreted as the secret key.
+Lines starting with
+.Ql #
+are ignored.
+Keys which start with
+.Ql 0x
+are interpreted as hexadecimal strings.
+Note that the file must be owned by the user ID running
+.Xr racoon 8
+.Pq usually the privileged user ,
+and must not be accessible by others.
+.\"
+.Sh EXAMPLES
+The following shows how the remote directive should be configured.
+.Bd -literal -offset
+path pre_shared_key "/usr/local/v6/etc/psk.txt" ;
+remote anonymous
+{
+	exchange_mode aggressive,main,base;
+	lifetime time 24 hour;
+	proposal {
+		encryption_algorithm 3des;
+		hash_algorithm sha1;
+		authentication_method pre_shared_key;
+		dh_group 2;
+	}
+}
+
+sainfo anonymous
+{
+	pfs_group 2;
+	lifetime time 12 hour ;
+	encryption_algorithm 3des, blowfish 448, twofish, rijndael ;
+	authentication_algorithm hmac_sha1, hmac_md5 ;
+	compression_algorithm deflate ;
+}
+.Ed
+.Pp
+If you are configuring plain RSA authentication, the remote directive
+should look like the following:
+.Bd -literal -offset
+path certificate "/usr/local/v6/etc" ;
+remote anonymous
+{
+        exchange_mode main,base ;
+        lifetime time 12 hour ;
+        certificate_type plain_rsa "/usr/local/v6/etc/myrsakey.priv";
+        peers_certfile plain_rsa "/usr/local/v6/etc/yourrsakey.pub";
+        proposal {
+                        encryption_algorithm aes ;
+                        hash_algorithm sha1 ;
+                        authentication_method rsasig ;
+                        dh_group 2 ;
+        }
+}
+.Ed
+.Pp
+The following is a sample for the pre-shared key file.
+.Bd -literal -offset
+10.160.94.3     mekmitasdigoat
+172.16.1.133    0x12345678
+194.100.55.1    whatcertificatereally
+3ffe:501:410:ffff:200:86ff:fe05:80fa    mekmitasdigoat
+3ffe:501:410:ffff:210:4bff:fea2:8baa    mekmitasdigoat
+foo@kame.net    mekmitasdigoat
+foo.kame.net    hoge
+.Ed
+.\"
+.Sh SEE ALSO
+.Xr racoon 8 ,
+.Xr racoonctl 8 ,
+.Xr setkey 8
+.\"
+.Sh HISTORY
+The
+.Nm
+configuration file first appeared in the
+.Dq YIPS
+Yokogawa IPsec implementation.
+.\"
+.Sh BUGS
+Some statements may not be handled by
+.Xr racoon 8
+yet.
+.Pp
+Diffie-Hellman computation can take a very long time, and may cause
+unwanted timeouts, specifically when a large D-H group is used.
+.\"
+.Sh SECURITY CONSIDERATIONS
+The use of IKE phase 1 aggressive mode is not recommended,
+as described in
+.Li http://www.kb.cert.org/vuls/id/886601 .
diff --git a/src/racoon/racoonctl.8 b/src/racoon/racoonctl.8
new file mode 100644
index 0000000..b27b188
--- /dev/null
+++ b/src/racoon/racoonctl.8
@@ -0,0 +1,199 @@
+.\"	$NetBSD: racoonctl.8,v 1.13 2006/09/09 16:22:10 manu Exp $
+.\"
+.\" Id: racoonctl.8,v 1.6 2006/05/07 21:32:59 manubsd Exp
+.\"
+.\" Copyright (C) 2004 Emmanuel Dreyfus
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\" 3. Neither the name of the project nor the names of its contributors
+.\"    may be used to endorse or promote products derived from this software
+.\"    without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.Dd November 16, 2004
+.Dt RACOONCTL 8
+.Os
+.\"
+.Sh NAME
+.Nm racoonctl
+.Nd racoon administrative control tool
+.\"
+.Sh SYNOPSIS
+.Nm
+reload-config
+.Nm
+show-schedule
+.Nm
+.Op Fl l Op Fl l
+show-sa
+.Op isakmp|esp|ah|ipsec
+.Nm
+flush-sa
+.Op isakmp|esp|ah|ipsec
+.Nm
+delete-sa
+.Ar saopts
+.Nm
+establish-sa
+.Op Fl u Ar identity
+.Ar saopts
+.Nm
+vpn-connect
+.Op Fl u identity
+.Ar vpn_gateway
+.Nm
+vpn-disconnect
+.Ar vpn_gateway
+.Nm
+show-event
+.Op Fl l
+.Nm
+logout-user
+.Ar login
+.\"
+.Sh DESCRIPTION
+.Nm
+is used to control
+.Xr racoon 8
+operation, if ipsec-tools was configured with adminport support.
+Communication between
+.Nm
+and
+.Xr racoon 8
+is done through a UNIX socket.
+By changing the default mode and ownership
+of the socket, you can allow non-root users to alter
+.Xr racoon 8
+behavior, so do that with caution.
+.Pp
+The following commands are available:
+.Bl -tag -width Ds
+.It reload-config
+This should cause
+.Xr racoon 8
+to reload its configuration file.
+.It show-schedule
+Unknown command.
+.It show-sa Op isakmp|esp|ah|ipsec
+Dump the SA: All the SAs if no SA class is provided, or either ISAKMP SAs,
+IPsec ESP SAs, IPsec AH SAs, or all IPsec SAs.
+Use
+.Fl l
+to increase verbosity.
+.It flush-sa Op isakmp|esp|ah|ipsec
+is used to flush all SAs if no SA class is provided, or a class of SAs,
+either ISAKMP SAs, IPsec ESP SAs, IPsec AH SAs, or all IPsec SAs.
+.It Xo establish-sa
+.Oo Fl u Ar username
+.Oc Ar saopts
+.Xc
+Establish an SA, either an ISAKMP SA, IPsec ESP SA, or IPsec AH SA.
+The optional
+.Fl u Ar username
+can be used when establishing an ISAKMP SA while hybrid auth is in use.
+.Nm
+will prompt you for the password associated with
+.Ar username
+and these credentials will be used in the Xauth exchange.
+.Pp
+.Ar saopts
+has the following format:
+.Bl -tag -width Bl
+.It isakmp {inet|inet6} Ar src Ar dst
+.It {esp|ah} {inet|inet6} Ar src/prefixlen/port Ar dst/prefixlen/port
+{icmp|tcp|udp|any}
+.El
+.It Xo vpn-connect
+.Oo Fl u Ar username
+.Oc Ar vpn_gateway
+.Xc
+This is a particular case of the previous command.
+It will establish an ISAKMP SA with
+.Ar vpn_gateway .
+.It delete-sa Ar saopts
+Delete an SA, either an ISAKMP SA, IPsec ESP SA, or IPsec AH SA.
+.It vpn-disconnect Ar vpn_gateway
+This is a particular case of the previous command.
+It will kill all SAs associated with
+.Ar vpn_gateway .
+.It show-event Op Fl l
+Dump all events reported by
+.Xr racoon 8 ,
+then quit.
+The
+.Fl l
+flag causes
+.Nm
+to not stop once all the events have been read, but rather to loop
+awaiting and reporting new events.
+.It logout-user Ar login
+Delete all SA established on behalf of the Xauth user
+.Ar login .
+.El
+.Pp
+Command shortcuts are available:
+.Bl -tag -width XXX -compact -offset indent
+.It rc
+reload-config
+.It ss
+show-sa
+.It sc
+show-schedule
+.It fs
+flush-sa
+.It ds
+delete-sa
+.It es
+establish-sa
+.It vc
+vpn-connect
+.It vd
+vpn-disconnect
+.It se
+show-event
+.It lu
+logout-user
+.El
+.\"
+.Sh RETURN VALUES
+The command should exit with 0 on success, and non-zero on errors.
+.\"
+.Sh FILES
+.Bl -tag -width 30n -compact
+.It Pa /var/racoon/racoon.sock No or
+.It Pa /var/run/racoon.sock
+.Xr racoon 8
+control socket.
+.El
+.\"
+.Sh SEE ALSO
+.Xr ipsec 4 ,
+.Xr racoon 8
+.Sh HISTORY
+Once was
+.Ic kmpstat
+in the KAME project.
+It turned into
+.Nm
+but remained undocumented for a while.
+.An Emmanuel Dreyfus Aq manu@NetBSD.org
+wrote this man page.
diff --git a/src/racoon/racoonctl.c b/src/racoon/racoonctl.c
new file mode 100644
index 0000000..afe954c
--- /dev/null
+++ b/src/racoon/racoonctl.c
@@ -0,0 +1,1652 @@
+/*	$NetBSD: racoonctl.c,v 1.7.6.1 2008/07/15 00:55:48 mgrooms Exp $	*/
+
+/*	Id: racoonctl.c,v 1.11 2006/04/06 17:06:25 manubsd Exp */
+
+/*
+ * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <net/pfkeyv2.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#if TIME_WITH_SYS_TIME
+# include <sys/time.h>
+# include <time.h>
+#else
+# if HAVE_SYS_TIME_H
+#  include <sys/time.h>
+# else
+#  include <time.h>
+# endif
+#endif
+#include <netdb.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <err.h>
+#include <sys/ioctl.h> 
+#include <resolv.h>
+
+#include "var.h"
+#include "vmbuf.h"
+#include "misc.h"
+#include "gcmalloc.h"
+
+#include "racoonctl.h"
+#include "admin.h"
+#include "schedule.h"
+#include "handler.h"
+#include "sockmisc.h"
+#include "vmbuf.h"
+#include "plog.h"
+#include "isakmp_var.h"
+#include "isakmp.h"
+#include "isakmp_xauth.h"
+#include "isakmp_cfg.h"
+#include "isakmp_unity.h"
+#include "ipsec_doi.h"
+#include "evt.h"
+
+char *adminsock_path = ADMINSOCK_PATH;
+
+static void usage __P((void));
+static vchar_t *get_combuf __P((int, char **));
+static int handle_recv __P((vchar_t *));
+static vchar_t *f_reload __P((int, char **));
+static vchar_t *f_getsched __P((int, char **));
+static vchar_t *f_getsa __P((int, char **));
+static vchar_t *f_flushsa __P((int, char **));
+static vchar_t *f_deletesa __P((int, char **));
+static vchar_t *f_exchangesa __P((int, char **));
+static vchar_t *f_vpnc __P((int, char **));
+static vchar_t *f_vpnd __P((int, char **));
+static vchar_t *f_getevt __P((int, char **));
+#ifdef ENABLE_HYBRID
+static vchar_t *f_logoutusr __P((int, char **));
+#endif
+
+struct cmd_tag {
+	vchar_t *(*func) __P((int, char **));
+	int cmd;
+	char *str;
+} cmdtab[] = {
+	{ f_reload,	ADMIN_RELOAD_CONF,	"reload-config" },
+	{ f_reload,	ADMIN_RELOAD_CONF,	"rc" },
+	{ f_getsched,	ADMIN_SHOW_SCHED,	"show-schedule" },
+	{ f_getsched,	ADMIN_SHOW_SCHED,	"sc" },
+	{ f_getsa,	ADMIN_SHOW_SA,		"show-sa" },
+	{ f_getsa,	ADMIN_SHOW_SA,		"ss" },
+	{ f_flushsa,	ADMIN_FLUSH_SA,		"flush-sa" },
+	{ f_flushsa,	ADMIN_FLUSH_SA,		"fs" },
+	{ f_deletesa,	ADMIN_DELETE_SA,	"delete-sa" },
+	{ f_deletesa,	ADMIN_DELETE_SA,	"ds" },
+	{ f_exchangesa,	ADMIN_ESTABLISH_SA,	"establish-sa" },
+	{ f_exchangesa,	ADMIN_ESTABLISH_SA,	"es" },
+	{ f_vpnc,	ADMIN_ESTABLISH_SA,	"vpn-connect" },
+	{ f_vpnc,	ADMIN_ESTABLISH_SA,	"vc" },
+	{ f_vpnd,	ADMIN_DELETE_ALL_SA_DST,"vpn-disconnect" },
+	{ f_vpnd,	ADMIN_DELETE_ALL_SA_DST,"vd" },
+	{ f_getevt,	ADMIN_SHOW_EVT,		"show-event" },
+	{ f_getevt,	ADMIN_SHOW_EVT,		"se" },
+#ifdef ENABLE_HYBRID
+	{ f_logoutusr,	ADMIN_LOGOUT_USER,	"logout-user" },
+	{ f_logoutusr,	ADMIN_LOGOUT_USER,	"lu" },
+#endif
+	{ NULL, 0, NULL },
+};
+
+struct evtmsg {
+	int type;
+	char *msg;
+	enum { UNSPEC, ERROR, INFO } level;
+} evtmsg[] = {
+	{ EVTT_PHASE1_UP, "Phase 1 established", INFO },
+	{ EVTT_PHASE1_DOWN, "Phase 1 deleted", INFO },
+	{ EVTT_XAUTH_SUCCESS, "Xauth exchange passed", INFO },
+	{ EVTT_ISAKMP_CFG_DONE, "ISAKMP mode config done", INFO },
+	{ EVTT_PHASE2_UP, "Phase 2 established", INFO },
+	{ EVTT_PHASE2_DOWN, "Phase 2 deleted", INFO },
+	{ EVTT_DPD_TIMEOUT, "Peer not reachable anymore", ERROR },
+	{ EVTT_PEER_NO_RESPONSE, "Peer not responding", ERROR },
+	{ EVTT_PEER_DELETE, "Peer terminated security association", ERROR },
+	{ EVTT_RACOON_QUIT, "Raccon terminated", ERROR },
+	{ EVTT_OVERFLOW, "Event queue overflow", ERROR },
+	{ EVTT_XAUTH_FAILED, "Xauth exchange failed", ERROR },
+	{ EVTT_PEERPH1AUTH_FAILED, "Peer failed phase 1 authentication "
+	    "(certificate problem?)", ERROR },
+	{ EVTT_PEERPH1_NOPROP, "Peer failed phase 1 initiation "
+	    "(proposal problem?)", ERROR },
+	{ 0, NULL, UNSPEC },
+	{ EVTT_NO_ISAKMP_CFG, "No need for ISAKMP mode config ", INFO },
+};
+
+static int get_proto __P((char *));
+static vchar_t *get_index __P((int, char **));
+static int get_family __P((char *));
+static vchar_t *get_comindexes __P((int, int, char **));
+static int get_comindex __P((char *, char **, char **, char **));
+static int get_ulproto __P((char *));
+
+struct proto_tag {
+	int proto;
+	char *str;
+} prototab[] = {
+	{ ADMIN_PROTO_ISAKMP,	"isakmp" },
+	{ ADMIN_PROTO_IPSEC,	"ipsec" },
+	{ ADMIN_PROTO_AH,	"ah" },
+	{ ADMIN_PROTO_ESP,	"esp" },
+	{ ADMIN_PROTO_INTERNAL,	"internal" },
+	{ 0, NULL },
+};
+
+struct ulproto_tag {
+	int ul_proto;
+	char *str;
+} ulprototab[] = {
+	{ 0,		"any" },
+	{ IPPROTO_ICMP,	"icmp" },
+	{ IPPROTO_TCP,	"tcp" },
+	{ IPPROTO_UDP,	"udp" },
+	{ 0, NULL },
+};
+
+int so;
+
+static char _addr1_[NI_MAXHOST], _addr2_[NI_MAXHOST];
+
+char *pname;
+int long_format = 0;
+
+#define EVTF_NONE		0x0000	/* Ignore any events */
+#define EVTF_LOOP		0x0001	/* Loop awaiting for new events */
+#define EVTF_CFG_STOP		0x0002	/* Stop after ISAKMP mode config */
+#define EVTF_CFG		0x0004	/* Print ISAKMP mode config info */
+#define EVTF_ALL		0x0008	/* Print any events */
+#define EVTF_PURGE		0x0010	/* Print all available events */
+#define EVTF_PH1DOWN_STOP	0x0020	/* Stop when phase 1 SA gets down */
+#define EVTF_PH1DOWN		0x0040	/* Print that phase 1 SA got down */
+#define EVTF_ERR		0x0080	/* Print any error */
+#define EVTF_ERR_STOP		0x0100	/* Stop on any error */
+
+int evt_filter = EVTF_NONE;
+time_t evt_start;
+
+void dump_isakmp_sa __P((char *, int));
+void dump_internal __P((char *, int));
+char *pindex_isakmp __P((isakmp_index *));
+void print_schedule __P((caddr_t, int));
+void print_evt __P((caddr_t, int));
+void print_cfg __P((caddr_t, int));
+void print_err __P((caddr_t, int));
+void print_ph1down __P((caddr_t, int));
+void print_ph1up __P((caddr_t, int));
+int evt_poll __P((void));
+char * fixed_addr __P((char *, char *, int));
+
+static void
+usage()
+{
+	printf(
+"Usage:\n"
+"  %s reload-config\n"
+"  %s [-l [-l]] show-sa [protocol]\n"
+"  %s flush-sa [protocol]\n"
+"  %s delete-sa <saopts>\n"
+"  %s establish-sa [-u identity] <saopts>\n"
+"  %s vpn-connect [-u identity] vpn_gateway\n"
+"  %s vpn-disconnect vpn_gateway\n"
+"\n"
+"    <protocol>: \"isakmp\", \"esp\" or \"ah\".\n"
+"        In the case of \"show-sa\" or \"flush-sa\", you can use \"ipsec\".\n"
+"\n"
+"    <saopts>: \"isakmp\" <family> <src> <dst>\n"
+"            : {\"esp\",\"ah\"} <family> <src/prefixlen/port> <dst/prefixlen/port>\n"
+"                              <ul_proto>\n"
+"    <family>: \"inet\" or \"inet6\"\n"
+"    <ul_proto>: \"icmp\", \"tcp\", \"udp\" or \"any\"\n",
+	pname, pname, pname, pname, pname, pname, pname);
+}
+
+/*
+ * Check for proper racoonctl interface
+ */
+#if ((RACOONCTL_INTERFACE_MAJOR != 1) || (RACOONCTL_INTERFACE < 20041230))
+#error	"Incompatible racoonctl interface"
+#endif
+
+int
+main(ac, av)
+	int ac;
+	char **av;
+{
+	vchar_t *combuf;
+	int c;
+
+	pname = *av;
+
+	/*
+	 * Check for proper racoonctl interface
+	 */
+	if ((racoonctl_interface_major != RACOONCTL_INTERFACE_MAJOR) ||
+	    (racoonctl_interface < RACOONCTL_INTERFACE))
+		errx(1, "Incompatible racoonctl interface");
+
+#ifdef __linux__
+	/*
+	 * Disable GNU extensions that will prevent racoonct vc -u login
+	 * from working (GNU getopt(3) does not like options after vc)
+	 */
+	setenv("POSIXLY_CORRECT", "1", 0);
+#endif
+	while ((c = getopt(ac, av, "lds:")) != -1) {
+		switch(c) {
+		case 'l':
+			long_format++;
+			break;
+
+		case 'd':
+			loglevel++;
+			break;
+
+		case 's':
+			adminsock_path = optarg;
+			break;
+
+		default:
+			usage();
+			exit(0);
+		}
+	}
+
+	ac -= optind;
+	av += optind;
+
+	combuf = get_combuf(ac, av);
+	if (!combuf)
+		err(1, "kmpstat");
+
+	if (loglevel)
+		racoon_hexdump(combuf, ((struct admin_com *)combuf)->ac_len);
+
+	com_init();
+
+	if (com_send(combuf) != 0)
+		goto bad;
+
+	vfree(combuf);
+
+	if (com_recv(&combuf) != 0)
+		goto bad;
+	if (handle_recv(combuf) != 0)
+		goto bad;
+
+	vfree(combuf);
+
+	if (evt_filter != EVTF_NONE)
+		if (evt_poll() != 0)
+			goto bad;	
+	
+	exit(0);
+
+    bad:
+	exit(1);
+}
+
+int
+evt_poll(void) {
+	struct timeval tv;
+	vchar_t *recvbuf;
+	vchar_t *sendbuf;
+
+	if ((sendbuf = f_getevt(0, NULL)) == NULL)
+		errx(1, "Cannot make combuf");
+
+
+	while (evt_filter & (EVTF_LOOP|EVTF_PURGE)) {
+		/* handle_recv closes the socket time, so open it each time */
+		com_init();
+
+		if (com_send(sendbuf) != 0)
+			errx(1, "Cannot send combuf");
+
+		if (com_recv(&recvbuf) == 0) {
+			handle_recv(recvbuf);
+			vfree(recvbuf);
+		}
+
+		tv.tv_sec = 0;
+		tv.tv_usec = 10;
+		(void)select(0, NULL, NULL, NULL, &tv);
+	}
+
+	vfree(sendbuf);
+	return 0;
+}
+
+/* %%% */
+/*
+ * return command buffer.
+ */
+static vchar_t *
+get_combuf(ac, av)
+	int ac;
+	char **av;
+{
+	struct cmd_tag *cp;
+
+	if (ac == 0) {
+		usage();
+		exit(0);
+	}
+
+	/* checking the string of command. */
+	for (cp = &cmdtab[0]; cp->str; cp++) {
+		if (strcmp(*av, cp->str) == 0) {
+			break;
+		}
+	}
+	if (!cp->str) {
+		printf("Invalid command [%s]\n", *av);
+		errno = EINVAL;
+		return NULL;
+	}
+
+	ac--;
+	av++;
+	return (cp->func)(ac, av);
+}
+
+static vchar_t *
+f_reload(ac, av)
+	int ac;
+	char **av;
+{
+	vchar_t *buf;
+	struct admin_com *head;
+
+	buf = vmalloc(sizeof(*head));
+	if (buf == NULL)
+		errx(1, "not enough core");
+
+	head = (struct admin_com *)buf->v;
+	head->ac_len = buf->l;
+	head->ac_cmd = ADMIN_RELOAD_CONF;
+	head->ac_errno = 0;
+	head->ac_proto = 0;
+
+	return buf;
+}
+
+static vchar_t *
+f_getevt(ac, av)
+	int ac;
+	char **av;
+{
+	vchar_t *buf;
+	struct admin_com *head;
+
+	/*
+	 * There are 3 ways of getting here
+	 * 1) racoonctl vc => evt_filter = (EVTF_LOOP|EVTF_CFG| ... )
+	 * 2) racoonctl es => evt_filter = EVTF_NONE
+	 * 3) racoonctl es -l => evt_filter = EVTF_LOOP
+	 * Catch the second case: show-event is here to purge all
+	 */
+	if (evt_filter == EVTF_NONE)
+		evt_filter = (EVTF_ALL|EVTF_PURGE);
+
+	if ((ac >= 1) && (strcmp(av[0], "-l") == 0))
+		evt_filter |= EVTF_LOOP;
+
+	if (ac >= 2)
+		errx(1, "too many arguments");
+
+	buf = vmalloc(sizeof(*head));
+	if (buf == NULL)
+		errx(1, "not enough core");
+
+	head = (struct admin_com *)buf->v;
+	head->ac_len = buf->l;
+	head->ac_cmd = ADMIN_SHOW_EVT;
+	head->ac_errno = 0;
+	head->ac_proto = 0;
+
+	return buf;
+}
+
+static vchar_t *
+f_getsched(ac, av)
+	int ac;
+	char **av;
+{
+	vchar_t *buf;
+	struct admin_com *head;
+
+	buf = vmalloc(sizeof(*head));
+	if (buf == NULL)
+		errx(1, "not enough core");
+
+	head = (struct admin_com *)buf->v;
+	head->ac_len = buf->l;
+	head->ac_cmd = ADMIN_SHOW_SCHED;
+	head->ac_errno = 0;
+	head->ac_proto = 0;
+
+	return buf;
+}
+
+static vchar_t *
+f_getsa(ac, av)
+	int ac;
+	char **av;
+{
+	vchar_t *buf;
+	struct admin_com *head;
+	int proto;
+
+	/* need protocol */
+	if (ac != 1)
+		errx(1, "insufficient arguments");
+	proto = get_proto(*av);
+	if (proto == -1)
+		errx(1, "unknown protocol %s", *av);
+
+	buf = vmalloc(sizeof(*head));
+	if (buf == NULL)
+		errx(1, "not enough core");
+
+	head = (struct admin_com *)buf->v;
+	head->ac_len = buf->l;
+	head->ac_cmd = ADMIN_SHOW_SA;
+	head->ac_errno = 0;
+	head->ac_proto = proto;
+
+	return buf;
+}
+
+static vchar_t *
+f_flushsa(ac, av)
+	int ac;
+	char **av;
+{
+	vchar_t *buf;
+	struct admin_com *head;
+	int proto;
+
+	/* need protocol */
+	if (ac != 1)
+		errx(1, "insufficient arguments");
+	proto = get_proto(*av);
+	if (proto == -1)
+		errx(1, "unknown protocol %s", *av);
+
+	buf = vmalloc(sizeof(*head));
+	if (buf == NULL)
+		errx(1, "not enough core");
+
+	head = (struct admin_com *)buf->v;
+	head->ac_len = buf->l;
+	head->ac_cmd = ADMIN_FLUSH_SA;
+	head->ac_errno = 0;
+	head->ac_proto = proto;
+
+	return buf;
+}
+
+static vchar_t *
+f_deletesa(ac, av)
+	int ac;
+	char **av;
+{
+	vchar_t *buf, *index;
+	struct admin_com *head;
+	int proto;
+
+	/* need protocol */
+	if (ac < 1)
+		errx(1, "insufficient arguments");
+	proto = get_proto(*av);
+	if (proto == -1)
+		errx(1, "unknown protocol %s", *av);
+
+	/* get index(es) */
+	av++;
+	ac--;
+	switch (proto) {
+	case ADMIN_PROTO_ISAKMP:
+		index = get_index(ac, av);
+		if (index == NULL)
+			return NULL;
+		break;
+	case ADMIN_PROTO_AH:
+	case ADMIN_PROTO_ESP:
+		index = get_index(ac, av);
+		if (index == NULL)
+			return NULL;
+		break;
+	default:
+		errno = EPROTONOSUPPORT;
+		return NULL;
+	}
+
+	buf = vmalloc(sizeof(*head) + index->l);
+	if (buf == NULL)
+		goto out;
+
+	head = (struct admin_com *)buf->v;
+	head->ac_len = buf->l + index->l;
+	head->ac_cmd = ADMIN_DELETE_SA;
+	head->ac_errno = 0;
+	head->ac_proto = proto;
+
+	memcpy(buf->v+sizeof(*head), index->v, index->l);
+
+out:
+	if (index != NULL)
+		vfree(index);
+
+	return buf;
+}
+
+static vchar_t *
+f_deleteallsadst(ac, av)
+	int ac;
+	char **av;
+{
+	vchar_t *buf, *index;
+	struct admin_com *head;
+	int proto;
+
+	/* need protocol */
+	if (ac < 1)
+		errx(1, "insufficient arguments");
+	proto = get_proto(*av);
+	if (proto == -1)
+		errx(1, "unknown protocol %s", *av);
+
+	/* get index(es) */
+	av++;
+	ac--;
+	switch (proto) {
+	case ADMIN_PROTO_ISAKMP:
+		index = get_index(ac, av);
+		if (index == NULL)
+			return NULL;
+		break;
+	case ADMIN_PROTO_AH:
+	case ADMIN_PROTO_ESP:
+		index = get_index(ac, av);
+		if (index == NULL)
+			return NULL;
+		break;
+	default:
+		errno = EPROTONOSUPPORT;
+		return NULL;
+	}
+
+	buf = vmalloc(sizeof(*head) + index->l);
+	if (buf == NULL)
+		goto out;
+
+	head = (struct admin_com *)buf->v;
+	head->ac_len = buf->l + index->l;
+	head->ac_cmd = ADMIN_DELETE_ALL_SA_DST;
+	head->ac_errno = 0;
+	head->ac_proto = proto;
+
+	memcpy(buf->v+sizeof(*head), index->v, index->l);
+
+out:
+	if (index != NULL)
+		vfree(index);
+
+	return buf;
+}
+
+static vchar_t *
+f_exchangesa(ac, av)
+	int ac;
+	char **av;
+{
+	vchar_t *buf, *index;
+	struct admin_com *head;
+	int proto;
+	int cmd = ADMIN_ESTABLISH_SA;
+	size_t com_len = 0;
+	char *id = NULL;
+	char *key = NULL;
+	struct admin_com_psk *acp;
+
+	if (ac < 1)
+		errx(1, "insufficient arguments");
+
+	/* Optional -u identity */
+	if (strcmp(av[0], "-u") == 0) {
+		if (ac < 2)
+			errx(1, "-u require an argument");
+
+		id = av[1];
+		if ((key = getpass("Password: ")) == NULL)
+			errx(1, "getpass() failed: %s", strerror(errno));
+		
+		com_len += sizeof(*acp) + strlen(id) + 1 + strlen(key) + 1;
+		cmd = ADMIN_ESTABLISH_SA_PSK;
+
+		av += 2;
+		ac -= 2;
+	}
+
+	/* need protocol */
+	if (ac < 1)
+		errx(1, "insufficient arguments");
+	if ((proto = get_proto(*av)) == -1)
+		errx(1, "unknown protocol %s", *av);
+
+	/* get index(es) */
+	av++;
+	ac--;
+	switch (proto) {
+	case ADMIN_PROTO_ISAKMP:
+		index = get_index(ac, av);
+		if (index == NULL)
+			return NULL;
+		break;
+	case ADMIN_PROTO_AH:
+	case ADMIN_PROTO_ESP:
+		index = get_index(ac, av);
+		if (index == NULL)
+			return NULL;
+		break;
+	default:
+		errno = EPROTONOSUPPORT;
+		return NULL;
+	}
+
+	com_len += sizeof(*head) + index->l;
+	if ((buf = vmalloc(com_len)) == NULL)
+		errx(1, "Cannot allocate buffer");
+
+	head = (struct admin_com *)buf->v;
+	head->ac_len = buf->l;
+	head->ac_cmd = cmd;
+	head->ac_errno = 0;
+	head->ac_proto = proto;
+
+	memcpy(buf->v+sizeof(*head), index->v, index->l);
+
+	if (id && key) {
+		char *data;
+		acp = (struct admin_com_psk *)
+		    (buf->v + sizeof(*head) + index->l);
+
+		acp->id_type = IDTYPE_USERFQDN;
+		acp->id_len = strlen(id) + 1;
+		acp->key_len = strlen(key) + 1;
+
+		data = (char *)(acp + 1);
+		strcpy(data, id);
+
+		data = (char *)(data + acp->id_len);
+		strcpy(data, key);
+	}
+
+	vfree(index);
+
+	return buf;
+}
+
+static vchar_t *
+f_vpnc(ac, av)
+	int ac;
+	char **av;
+{
+	char *nav[] = {NULL, NULL, NULL, NULL, NULL, NULL};
+	int nac = 0;
+	char *isakmp = "isakmp";
+	char *inet = "inet";
+	char *srcaddr;
+	struct addrinfo hints, *res;
+	struct sockaddr *src;
+	char *idx;
+
+	if (ac < 1)
+		errx(1, "insufficient arguments");
+
+	evt_filter = (EVTF_LOOP|EVTF_CFG|EVTF_CFG_STOP|EVTF_ERR|EVTF_ERR_STOP);
+	time(&evt_start);
+	
+	/* Optional -u identity */
+	if (strcmp(av[0], "-u") == 0) {
+		if (ac < 2)
+			errx(1, "-u require an argument");
+
+		nav[nac++] = av[0];
+		nav[nac++] = av[1];
+
+		ac -= 2;
+		av += 2;
+	}
+
+	if (ac < 1)
+		errx(1, "VPN gateway required");	
+	if (ac > 1)
+		warnx("Extra arguments");
+
+	/*
+	 * Find the source address
+	 */
+	memset(&hints, 0, sizeof(hints));
+	hints.ai_family = PF_UNSPEC;
+	hints.ai_socktype = SOCK_DGRAM;
+	if (getaddrinfo(av[0], "4500", &hints, &res) != 0)
+		errx(1, "Cannot resolve destination address");
+
+	if ((src = getlocaladdr(res->ai_addr)) == NULL)
+		errx(1, "cannot find source address");
+
+	if ((srcaddr = saddr2str(src)) == NULL)
+		errx(1, "cannot read source address");
+
+	/* We get "ip[port]" strip the port */
+	if ((idx = index(srcaddr, '[')) == NULL) 
+		errx(1, "unexpected source address format");
+	*idx = '\0';
+
+	nav[nac++] = isakmp;
+	nav[nac++] = inet;
+	nav[nac++] = srcaddr;
+	nav[nac++] = av[0];
+
+	return f_exchangesa(nac, nav);
+}
+
+static vchar_t *
+f_vpnd(ac, av)
+	int ac;
+	char **av;
+{
+	char *nav[] = {NULL, NULL, NULL, NULL};
+	int nac = 0;
+	char *isakmp = "isakmp";
+	char *inet = "inet";
+	char *anyaddr = "0.0.0.0";
+	char *idx;
+
+	if (ac < 1)
+		errx(1, "VPN gateway required");	
+	if (ac > 1)
+		warnx("Extra arguments");
+
+	evt_filter = 
+	    (EVTF_PH1DOWN|EVTF_PH1DOWN_STOP|EVTF_LOOP|EVTF_ERR|EVTF_ERR_STOP);
+
+	nav[nac++] = isakmp;
+	nav[nac++] = inet;
+	nav[nac++] = anyaddr;
+	nav[nac++] = av[0];
+
+	return f_deleteallsadst(nac, nav);
+}
+
+#ifdef ENABLE_HYBRID
+static vchar_t *
+f_logoutusr(ac, av)
+	int ac;
+	char **av;
+{
+	vchar_t *buf;
+	struct admin_com *head;
+	char *user;
+
+	/* need username */
+	if (ac < 1)
+		errx(1, "insufficient arguments");
+	user = av[0];
+	if ((user == NULL) || (strlen(user) > LOGINLEN))
+		errx(1, "bad login (too long?)");
+
+	buf = vmalloc(sizeof(*head) + strlen(user) + 1);
+	if (buf == NULL)
+		return NULL;
+
+	head = (struct admin_com *)buf->v;
+	head->ac_len = buf->l;
+	head->ac_cmd = ADMIN_LOGOUT_USER;
+	head->ac_errno = 0;
+	head->ac_proto = 0;
+
+	strncpy((char *)(head + 1), user, LOGINLEN);
+
+	return buf;
+}
+#endif /* ENABLE_HYBRID */
+
+
+static int
+get_proto(str)
+	char *str;
+{
+	struct proto_tag *cp;
+
+	if (str == NULL) {
+		errno = EINVAL;
+		return -1;
+	}
+
+	/* checking the string of command. */
+	for (cp = &prototab[0]; cp->str; cp++) {
+		if (strcmp(str, cp->str) == 0)
+			return cp->proto;
+	}
+
+	errno = EINVAL;
+	return -1;
+}
+
+static vchar_t *
+get_index(ac, av)
+	int ac;
+	char **av;
+{
+	int family;
+
+	if (ac != 3 && ac != 4) {
+		errno = EINVAL;
+		return NULL;
+	}
+
+	/* checking the string of family */
+	family = get_family(*av);
+	if (family == -1)
+		return NULL;
+	av++;
+	ac--;
+
+	return get_comindexes(family, ac, av);
+}
+
+static int
+get_family(str)
+	char *str;
+{
+	if (strcmp("inet", str) == 0)
+		return AF_INET;
+#ifdef INET6
+	else if (strcmp("inet6", str) == 0)
+		return AF_INET6;
+#endif
+	errno = EAFNOSUPPORT;
+	return -1;
+}
+
+static vchar_t *
+get_comindexes(family, ac, av)
+	int family;
+	int ac;
+	char **av;
+{
+	vchar_t *buf;
+	struct admin_com_indexes *ci;
+	char *p_name = NULL, *p_port = NULL;
+	char *p_prefs = NULL, *p_prefd = NULL;
+	struct sockaddr *src = NULL, *dst = NULL;
+	int ulproto;
+
+	if (ac != 2 && ac != 3) {
+		errno = EINVAL;
+		return NULL;
+	}
+
+	if (get_comindex(*av, &p_name, &p_port, &p_prefs) == -1)
+		goto bad;
+	src = get_sockaddr(family, p_name, p_port);
+	if (p_name) {
+		racoon_free(p_name);
+		p_name = NULL;
+	}
+	if (p_port) {
+		racoon_free(p_port);
+		p_port = NULL;
+	}
+	if (src == NULL)
+		goto bad;
+	av++;
+	ac--;
+	if (get_comindex(*av, &p_name, &p_port, &p_prefd) == -1)
+		goto bad;
+	dst = get_sockaddr(family, p_name, p_port);
+	if (p_name) {
+		racoon_free(p_name);
+		p_name = NULL;
+	}
+	if (p_port) {
+		racoon_free(p_port);
+		p_port = NULL;
+	}
+	if (dst == NULL)
+		goto bad;
+
+	buf = vmalloc(sizeof(*ci));
+	if (buf == NULL)
+		goto bad;
+
+	av++;
+	ac--;
+	if(ac){
+		ulproto = get_ulproto(*av);
+		if (ulproto == -1)
+			goto bad;
+	}else
+		ulproto=0;
+
+	ci = (struct admin_com_indexes *)buf->v;
+	if(p_prefs)
+		ci->prefs = (u_int8_t)atoi(p_prefs); /* XXX should be handled error. */
+	else
+		ci->prefs = 32;
+	if(p_prefd)
+		ci->prefd = (u_int8_t)atoi(p_prefd); /* XXX should be handled error. */
+	else
+		ci->prefd = 32;
+	ci->ul_proto = ulproto;
+	memcpy(&ci->src, src, sysdep_sa_len(src));
+	memcpy(&ci->dst, dst, sysdep_sa_len(dst));
+
+	if (p_name)
+		racoon_free(p_name);
+
+	return buf;
+
+   bad:
+	if (p_name)
+		racoon_free(p_name);
+	if (p_port)
+		racoon_free(p_port);
+	if (p_prefs)
+		racoon_free(p_prefs);
+	if (p_prefd)
+		racoon_free(p_prefd);
+	return NULL;
+}
+
+static int
+get_comindex(str, name, port, pref)
+	char *str, **name, **port, **pref;
+{
+	char *p;
+
+	*name = *port = *pref = NULL;
+
+	*name = racoon_strdup(str);
+	STRDUP_FATAL(*name);
+	p = strpbrk(*name, "/[");
+	if (p != NULL) {
+		if (*(p + 1) == '\0')
+			goto bad;
+		if (*p == '/') {
+			*p = '\0';
+			*pref = racoon_strdup(p + 1);
+			STRDUP_FATAL(*pref);
+			p = strchr(*pref, '[');
+			if (p != NULL) {
+				if (*(p + 1) == '\0')
+					goto bad;
+				*p = '\0';
+				*port = racoon_strdup(p + 1);
+				STRDUP_FATAL(*port);
+				p = strchr(*pref, ']');
+				if (p == NULL)
+					goto bad;
+				*p = '\0';
+			}
+		} else if (*p == '[') {
+			if (*pref == NULL)
+				goto bad;
+			*p = '\0';
+			*port = racoon_strdup(p + 1);
+			STRDUP_FATAL(*port);
+			p = strchr(*pref, ']');
+			if (p == NULL)
+				goto bad;
+			*p = '\0';
+		} else {
+			/* XXX */
+		}
+	}
+
+	return 0;
+
+    bad:
+
+	if (*name)
+		racoon_free(*name);
+	if (*port)
+		racoon_free(*port);
+	if (*pref)
+		racoon_free(*pref);
+	*name = *port = *pref = NULL;
+	return -1;
+}
+
+static int
+get_ulproto(str)
+	char *str;
+{
+	struct ulproto_tag *cp;
+
+	if(str == NULL){
+		errno = EINVAL;
+		return -1;
+	}
+
+	/* checking the string of upper layer protocol. */
+	for (cp = &ulprototab[0]; cp->str; cp++) {
+		if (strcmp(str, cp->str) == 0)
+			return cp->ul_proto;
+	}
+
+	errno = EINVAL;
+	return -1;
+}
+
+/* %%% */
+void
+dump_isakmp_sa(buf, len)
+	char *buf;
+	int len;
+{
+	struct ph1dump *pd;
+	struct tm *tm;
+	char tbuf[56];
+	caddr_t p = NULL;
+
+/* isakmp status header */
+/* short header;
+ 1234567890123456789012 0000000000000000:0000000000000000 000000000000
+*/
+char *header1 = 
+"Destination            Cookies                           Created";
+
+/* semi long header;
+ 1234567890123456789012 0000000000000000:0000000000000000 00 X 00 X 0000-00-00 00:00:00 000000
+*/
+char *header2 = 
+"Destination            Cookies                           ST S  V E Created             Phase2";
+
+/* long header;
+ 0000:0000:0000:0000:0000:0000:0000:0000.00000 0000:0000:0000:0000:0000:0000:0000:0000.00000 0000000000000000:0000000000000000 00 X 00 X 0000-00-00 00:00:00 000000
+*/
+char *header3 =
+"Source                                        Destination                                   Cookies                           ST S  V E Created             Phase2";
+
+/* phase status header */
+/* short format;
+   side stats source address         destination address   
+   xxx  xxxxx 1234567890123456789012 1234567890123456789012
+*/
+
+	static char *estr[] = { "", "B", "M", "U", "A", "I", };
+
+	switch (long_format) {
+	case 0:
+		printf("%s\n", header1);
+		break;
+	case 1:
+		printf("%s\n", header2);
+		break;
+	case 2:
+	default:
+		printf("%s\n", header3);
+		break;
+	}
+
+	if (len % sizeof(*pd))
+		printf("invalid length %d\n", len);
+	len /= sizeof(*pd);
+
+	pd = (struct ph1dump *)buf;
+
+	while (len-- > 0) {
+		/* source address */
+		if (long_format >= 2) {
+			GETNAMEINFO((struct sockaddr *)&pd->local, _addr1_, _addr2_);
+			switch (long_format) {
+			case 0:
+				break;
+			case 1:
+				p = fixed_addr(_addr1_, _addr2_, 22);
+				break;
+			case 2:
+			default:
+				p = fixed_addr(_addr1_, _addr2_, 45);
+				break;
+			}
+			printf("%s ", p);
+		}
+
+		/* destination address */
+		GETNAMEINFO((struct sockaddr *)&pd->remote, _addr1_, _addr2_);
+		switch (long_format) {
+		case 0:
+		case 1:
+			p = fixed_addr(_addr1_, _addr2_, 22);
+			break;
+		case 2:
+		default:
+			p = fixed_addr(_addr1_, _addr2_, 45);
+			break;
+		}
+		printf("%s ", p);
+
+		printf("%s ", pindex_isakmp(&pd->index));
+
+		/* statuc, side and version */
+		if (long_format >= 1) {
+			printf("%2d %c %2x ",
+				pd->status,
+				pd->side == INITIATOR ? 'I' : 'R',
+				pd->version);
+			if (ARRAYLEN(estr) > pd->etype)
+				printf("%s ", estr[pd->etype]);
+		}
+
+		/* created date */
+		if (pd->created) {
+			tm = localtime(&pd->created);
+			strftime(tbuf, sizeof(tbuf), "%Y-%m-%d %T", tm);
+		} else
+			snprintf(tbuf, sizeof(tbuf), "                   ");
+		printf("%s ", tbuf);
+
+		/* counter of phase 2 */
+		if (long_format >= 1)
+			printf("%6d ", pd->ph2cnt);
+
+		printf("\n");
+
+		pd++;
+	}
+
+	return;
+}
+
+/* %%% */
+void
+dump_internal(buf, tlen)
+	char *buf;
+	int tlen;
+{
+	struct ph2handle *iph2;
+	struct sockaddr *addr;
+
+/*
+short header;
+ source address         destination address    
+ 1234567890123456789012 1234567890123456789012 
+*/
+char *short_h1 = 
+"Source                 Destination            ";
+
+/*
+long header;
+ source address                                destination address                           
+ 123456789012345678901234567890123456789012345 123456789012345678901234567890123456789012345 
+ 0000:0000:0000:0000:0000:0000:0000:0000.00000 0000:0000:0000:0000:0000:0000:0000:0000.00000 0000:0000:0000:0000:0000:0000:0000:0000.00000
+*/
+char *long_h1 = 
+"Source                                        Destination                                  ";
+
+	printf("%s\n", long_format ? long_h1 : short_h1);
+
+	while (tlen > 0) {
+		iph2 = (struct ph2handle *)buf;
+		addr = (struct sockaddr *)(++iph2);
+
+		GETNAMEINFO(addr, _addr1_, _addr2_);
+		printf("%s ", long_format ?
+			  fixed_addr(_addr1_, _addr2_, 45)
+			: fixed_addr(_addr1_, _addr2_, 22));
+		addr++;
+		tlen -= sysdep_sa_len(addr);
+
+		GETNAMEINFO(addr, _addr1_, _addr2_);
+		printf("%s ", long_format ?
+			  fixed_addr(_addr1_, _addr2_, 45)
+			: fixed_addr(_addr1_, _addr2_, 22));
+		addr++;
+		tlen -= sysdep_sa_len(addr);
+
+		printf("\n");
+	}
+
+	return;
+}
+
+/* %%% */
+char *
+pindex_isakmp(index)
+	isakmp_index *index;
+{
+	static char buf[64];
+	u_char *p;
+	int i, j;
+
+	memset(buf, 0, sizeof(buf));
+
+	/* copy index */
+	p = (u_char *)index;
+	for (j = 0, i = 0; i < sizeof(isakmp_index); i++) {
+		snprintf((char *)&buf[j], sizeof(buf) - j, "%02x", p[i]);
+		j += 2;
+		switch (i) {
+		case 7:
+#if 0
+		case 15:
+#endif
+			buf[j++] = ':';
+		}
+	}
+
+	return buf;
+}
+
+/* print schedule */
+char *str_sched_stat[] = {
+"off",
+"on",
+"dead",
+};
+
+char *str_sched_id[] = {
+"PH1resend",
+"PH1lifetime",
+"PH2resend",
+"PSTacquire",
+"PSTlifetime",
+};
+
+void
+print_schedule(buf, len)
+	caddr_t buf;
+	int len;
+{
+	struct scheddump *sc = (struct scheddump *)buf;
+	struct tm *tm;
+	char tbuf[56];
+
+	if (len % sizeof(*sc))
+		printf("invalid length %d\n", len);
+	len /= sizeof(*sc);
+
+	/*      00000000 00000000 00000000 xxx........*/
+	printf("index    tick     xtime    created\n");
+
+	while (len-- > 0) {
+		tm = localtime(&sc->created);
+		strftime(tbuf, sizeof(tbuf), "%Y-%m-%d %T", tm);
+
+		printf("%-8ld %-8ld %-8ld %s\n",
+			sc->id,
+			(long)sc->tick,
+			(long)sc->xtime,
+			tbuf);
+		sc++;
+	}
+
+	return;
+}
+
+
+void
+print_evt(buf, len)
+	caddr_t buf;
+	int len;
+{
+	struct evtdump *evtdump = (struct evtdump *)buf;
+	int i;
+	char *srcstr;
+	char *dststr;
+	
+	for (i = 0; evtmsg[i].msg; i++)
+		if (evtmsg[i].type == evtdump->type)
+			break;				
+	
+	if (evtmsg[i].msg == NULL) 
+		printf("Event %d: ", evtdump->type);
+	else
+		printf("%s : ", evtmsg[i].msg);
+
+	if ((srcstr = saddr2str((struct sockaddr *)&evtdump->src)) == NULL)
+		printf("unknown");
+	else 
+		printf("%s", srcstr);
+	printf(" -> ");
+	if ((dststr = saddr2str((struct sockaddr *)&evtdump->dst)) == NULL)
+		printf("unknown");
+	else 
+		printf("%s", dststr);
+	printf("\n");
+
+	return;
+}
+
+void
+print_err(buf, len)
+	caddr_t buf;
+	int len;
+{
+	struct evtdump *evtdump = (struct evtdump *)buf;
+	int i;
+	
+	
+	for (i = 0; evtmsg[i].msg; i++)
+		if (evtmsg[i].type == evtdump->type)
+			break;				
+
+	if (evtmsg[i].level != ERROR)
+		return;
+	
+	if (evtmsg[i].msg == NULL) 
+		printf("Error: Event %d\n", evtdump->type);
+	else
+		printf("Error: %s\n", evtmsg[i].msg);
+
+	if (evt_filter & EVTF_ERR_STOP)
+		evt_filter &= ~EVTF_LOOP;
+
+	return;
+}
+
+/*
+ * Print a message when phase 1 SA goes down
+ */
+void
+print_ph1down(buf, len)
+	caddr_t buf;
+	int len;
+{
+	struct evtdump *evtdump = (struct evtdump *)buf;
+	
+	if (evtdump->type != EVTT_PHASE1_DOWN)
+		return;
+
+	printf("VPN connexion terminated\n");
+
+	if (evt_filter & EVTF_PH1DOWN_STOP)
+		evt_filter &= ~EVTF_LOOP;
+	
+	return;
+}
+
+/*
+ * Print ISAKMP mode config info (IP and banner)
+ */
+void
+print_cfg(buf, len)
+	caddr_t buf;
+	int len;
+{
+	struct evtdump *evtdump = (struct evtdump *)buf;
+	struct isakmp_data *attr;
+	char *banner = NULL;
+	struct in_addr addr4;
+	
+	memset(&addr4, 0, sizeof(addr4));
+
+	if (evtdump->type != EVTT_ISAKMP_CFG_DONE && 
+	    evtdump->type != EVTT_NO_ISAKMP_CFG)
+		return;
+
+	len -= sizeof(*evtdump);
+	attr = (struct isakmp_data *)(evtdump + 1);
+
+	while (len > 0) {
+		if (len < sizeof(*attr)) {
+			printf("short attribute too short\n");
+			break;
+		}
+
+		if ((ntohs(attr->type) & ISAKMP_GEN_MASK) == ISAKMP_GEN_TV) {
+			/* Short attribute, skip */
+			len -= sizeof(*attr);
+			attr++;
+		} else { /* Long attribute */
+			char *n;
+
+			if (len < (sizeof(*attr) + ntohs(attr->lorv))) {
+				printf("long attribute too long\n");
+				break;
+			}
+
+			switch (ntohs(attr->type) & ~ISAKMP_GEN_MASK) {
+			case INTERNAL_IP4_ADDRESS:
+				if (ntohs(attr->lorv) < sizeof(addr4)) {
+					printf("addr4 attribute too short\n");
+					break;
+				}
+				memcpy(&addr4, attr + 1, sizeof(addr4));
+				break;
+
+			case UNITY_BANNER:
+				banner = racoon_malloc(ntohs(attr->lorv) + 1);
+				if (banner == NULL) {
+					printf("malloc failed\n");
+					break;
+				}
+				memcpy(banner, attr + 1, ntohs(attr->lorv));
+				banner[ntohs(attr->lorv)] = '\0';
+				break;
+
+			default:
+				break;
+			}
+
+			len -= (sizeof(*attr) + ntohs(attr->lorv));
+			n = (char *)attr;
+			attr = (struct isakmp_data *)
+			    (n + sizeof(*attr) + ntohs(attr->lorv));
+		}
+	}
+	
+	if (evtdump->type == EVTT_ISAKMP_CFG_DONE)
+		printf("Bound to address %s\n", inet_ntoa(addr4));
+	else
+		printf("VPN connexion established\n");
+	
+	if (banner) {
+		struct winsize win;
+		int col = 0;
+		int i;
+
+		if (ioctl(1, TIOCGWINSZ, &win) != 1) 
+			col = win.ws_col;
+			
+		for (i = 0; i < col; i++)
+			printf("%c", '=');
+		printf("\n%s\n", banner);
+		for (i = 0; i < col; i++)
+			printf("%c", '=');
+		printf("\n");
+		racoon_free(banner);
+	}
+	
+	if (evt_filter & EVTF_CFG_STOP)
+		evt_filter &= ~EVTF_LOOP;
+	
+	return;
+}
+	
+
+char *
+fixed_addr(addr, port, len)
+	char *addr, *port;
+	int len;
+{
+	static char _addr_buf_[BUFSIZ];
+	char *p;
+	int plen, i;
+
+	/* initialize */
+	memset(_addr_buf_, ' ', sizeof(_addr_buf_));
+
+	plen = strlen(port);
+	if (len < plen + 1)
+		return NULL;
+
+	p = _addr_buf_;
+	for (i = 0; i < len - plen - 1 && addr[i] != '\0'; /*noting*/)
+		*p++ = addr[i++];
+	*p++ = '.';
+
+	for (i = 0; i < plen && port[i] != '\0'; /*noting*/)
+		*p++ = port[i++];
+
+	_addr_buf_[len] = '\0';
+
+	return _addr_buf_;
+}
+
+static int
+handle_recv(combuf)
+	vchar_t *combuf;
+{
+        struct admin_com h, *com;
+        caddr_t buf;
+        int len;
+
+	com = (struct admin_com *)combuf->v;
+	len = com->ac_len - sizeof(*com);
+	buf = combuf->v + sizeof(*com);
+
+	switch (com->ac_cmd) {
+	case ADMIN_SHOW_SCHED:
+		print_schedule(buf, len);
+		break;
+
+	case ADMIN_SHOW_EVT: {
+		struct evtdump *evtdump;
+
+		/* We got no event */
+		if (len == 0) {
+			/* If we were purging the queue, it is now done */
+			if (evt_filter & EVTF_PURGE)
+				evt_filter &= ~EVTF_PURGE;
+			break;
+		}
+
+		if (len < sizeof(struct evtdump))
+			errx(1, "Short buffer\n");		
+
+		/* Toss outdated events */
+		evtdump = (struct evtdump *)buf;
+		if (evtdump->timestamp < evt_start)
+			break;
+
+		if (evt_filter & EVTF_ALL)
+			print_evt(buf, len);
+		if (evt_filter & EVTF_ERR)
+			print_err(buf, len);
+		if (evt_filter & EVTF_CFG)
+			print_cfg(buf, len);
+		if (evt_filter & EVTF_PH1DOWN)
+			print_ph1down(buf, len);
+		break;
+	}
+
+	case ADMIN_SHOW_SA:
+	   {
+		switch (com->ac_proto) {
+		case ADMIN_PROTO_ISAKMP:
+			dump_isakmp_sa(buf, len);
+			break;
+		case ADMIN_PROTO_IPSEC:
+		case ADMIN_PROTO_AH:
+		case ADMIN_PROTO_ESP:
+		    {
+			struct sadb_msg *msg = (struct sadb_msg *)buf;
+
+			switch (msg->sadb_msg_errno) {
+			case ENOENT:
+				switch (msg->sadb_msg_type) {
+				case SADB_DELETE:
+				case SADB_GET:
+					printf("No entry.\n");
+					break;
+				case SADB_DUMP:
+					printf("No SAD entries.\n");
+					break;
+				}
+				break;
+			case 0:
+				while (1) {
+					pfkey_sadump(msg);
+					if (msg->sadb_msg_seq == 0)
+						break;
+					msg = (struct sadb_msg *)((caddr_t)msg +
+						     PFKEY_UNUNIT64(msg->sadb_msg_len));
+				}
+				break;
+			default:
+				printf("%s.\n", strerror(msg->sadb_msg_errno));
+			}
+		    }
+			break;
+		case ADMIN_PROTO_INTERNAL:
+			dump_internal(buf, len);
+			break;
+		default:
+			printf("Invalid proto [%d]\n", com->ac_proto);
+		}
+
+	    }
+		break;
+
+	default:
+		/* IGNORE */
+		break;
+	}
+
+	close(so);
+	return 0;
+
+    bad:
+	close(so);
+	return -1;
+}
diff --git a/src/racoon/racoonctl.h b/src/racoon/racoonctl.h
new file mode 100644
index 0000000..d507213
--- /dev/null
+++ b/src/racoon/racoonctl.h
@@ -0,0 +1,53 @@
+/*	$NetBSD: racoonctl.h,v 1.4 2006/09/09 16:22:10 manu Exp $	*/
+
+/* Id: racoonctl.h,v 1.3 2005/06/19 22:37:47 manubsd Exp */
+
+/*
+ * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _RACOONCTL_H
+#define _RACOONCTL_H
+
+/* bumped on any change to the interface */
+#define RACOONCTL_INTERFACE	20050619
+extern u_int32_t racoonctl_interface;
+
+/* bumped when introducing changes that break backward compatibility */
+#define RACOONCTL_INTERFACE_MAJOR	1	
+extern u_int32_t racoonctl_interface_major;
+
+extern u_int32_t loglevel;
+
+int com_init(void);
+int com_send(vchar_t *);
+int com_recv(vchar_t **);
+struct sockaddr *get_sockaddr(int, char *, char *);
+
+#endif /* _RACOONCTL_H */
+
diff --git a/src/racoon/remoteconf.c b/src/racoon/remoteconf.c
new file mode 100644
index 0000000..c9c803f
--- /dev/null
+++ b/src/racoon/remoteconf.c
@@ -0,0 +1,695 @@
+/*	$NetBSD: remoteconf.c,v 1.9.4.2 2008/06/18 07:30:19 mgrooms Exp $	*/
+
+/* Id: remoteconf.c,v 1.38 2006/05/06 15:52:44 manubsd Exp */
+
+/*
+ * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <sys/queue.h>
+
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+
+#include PATH_IPSEC_H
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+
+#include "var.h"
+#include "misc.h"
+#include "vmbuf.h"
+#include "plog.h"
+#include "sockmisc.h"
+#include "genlist.h"
+#include "debug.h"
+
+#include "isakmp_var.h"
+#ifdef ENABLE_HYBRID
+#include "isakmp_xauth.h"
+#endif
+#include "isakmp.h"
+#include "ipsec_doi.h"
+#include "oakley.h"
+#include "remoteconf.h"
+#include "localconf.h"
+#include "grabmyaddr.h"
+#include "policy.h"
+#include "proposal.h"
+#include "vendorid.h"
+#include "gcmalloc.h"
+#include "strnames.h"
+#include "algorithm.h"
+#include "nattraversal.h"
+#include "isakmp_frag.h"
+#include "genlist.h"
+
+static TAILQ_HEAD(_rmtree, remoteconf) rmtree, rmtree_save, rmtree_tmp;
+
+/* 
+ * Script hook names and script hook paths
+ */
+char *script_names[SCRIPT_MAX + 1] = { "phase1_up", "phase1_down" };
+
+/*%%%*/
+/*
+ * search remote configuration.
+ * don't use port number to search if its value is either IPSEC_PORT_ANY.
+ * If matching anonymous entry, then new entry is copied from anonymous entry.
+ * If no anonymous entry found, then return NULL.
+ * OUT:	NULL:	NG
+ *	Other:	remote configuration entry.
+ */
+struct remoteconf *
+getrmconf_strict(remote, allow_anon)
+	struct sockaddr *remote;
+	int allow_anon;
+{
+	struct remoteconf *p;
+	struct remoteconf *anon = NULL;
+	int withport;
+	char buf[NI_MAXHOST + NI_MAXSERV + 10];
+	char addr[NI_MAXHOST], port[NI_MAXSERV];
+
+	withport = 0;
+
+#ifndef ENABLE_NATT
+	/* 
+	 * We never have ports set in our remote configurations, but when
+	 * NAT-T is enabled, the kernel can have policies with ports and
+	 * send us an acquire message for a destination that has a port set.
+	 * If we do this port check here, we don't find the remote config.
+	 *
+	 * In an ideal world, we would be able to have remote conf with
+	 * port, and the port could be a wildcard. That test could be used.
+	 */
+	if (remote->sa_family != AF_UNSPEC &&
+	    extract_port(remote) != IPSEC_PORT_ANY)
+		withport = 1;
+#endif /* ENABLE_NATT */
+
+	if (remote->sa_family == AF_UNSPEC)
+		snprintf (buf, sizeof(buf), "%s", "anonymous");
+	else {
+		GETNAMEINFO(remote, addr, port);
+		snprintf(buf, sizeof(buf), "%s%s%s%s", addr,
+			withport ? "[" : "",
+			withport ? port : "",
+			withport ? "]" : "");
+	}
+
+	TAILQ_FOREACH(p, &rmtree, chain) {
+		if ((remote->sa_family == AF_UNSPEC
+		     && remote->sa_family == p->remote->sa_family)
+		 || (!withport && cmpsaddrwop(remote, p->remote) == 0)
+		 || (withport && cmpsaddrstrict(remote, p->remote) == 0)) {
+			plog(LLV_DEBUG, LOCATION, NULL,
+				"configuration found for %s.\n", buf);
+			return p;
+		}
+
+		/* save the pointer to the anonymous configuration */
+		if (p->remote->sa_family == AF_UNSPEC)
+			anon = p;
+	}
+
+	if (allow_anon && anon != NULL) {
+		plog(LLV_DEBUG, LOCATION, NULL,
+			"anonymous configuration selected for %s.\n", buf);
+		return anon;
+	}
+
+	plog(LLV_DEBUG, LOCATION, NULL,
+		"no remote configuration found.\n");
+
+	return NULL;
+}
+
+struct remoteconf *
+getrmconf(remote)
+	struct sockaddr *remote;
+{
+	return getrmconf_strict(remote, 1);
+}
+
+struct remoteconf *
+newrmconf()
+{
+	struct remoteconf *new;
+	int i;
+
+	new = racoon_calloc(1, sizeof(*new));
+	if (new == NULL)
+		return NULL;
+
+	new->proposal = NULL;
+
+	/* set default */
+	new->doitype = IPSEC_DOI;
+	new->sittype = IPSECDOI_SIT_IDENTITY_ONLY;
+	new->idvtype = IDTYPE_UNDEFINED;
+	new->idvl_p = genlist_init();
+	new->nonce_size = DEFAULT_NONCE_SIZE;
+	new->passive = FALSE;
+	new->ike_frag = FALSE;
+	new->esp_frag = IP_MAXPACKET;
+	new->ini_contact = TRUE;
+	new->mode_cfg = FALSE;
+	new->pcheck_level = PROP_CHECK_STRICT;
+	new->verify_identifier = FALSE;
+	new->verify_cert = TRUE;
+	new->getcert_method = ISAKMP_GETCERT_PAYLOAD;
+	new->getcacert_method = ISAKMP_GETCERT_LOCALFILE;
+	new->cacerttype = ISAKMP_CERT_X509SIGN;
+	new->certtype = ISAKMP_CERT_NONE;
+	new->cacertfile = NULL;
+	new->send_cert = TRUE;
+	new->send_cr = TRUE;
+	new->support_proxy = FALSE;
+	for (i = 0; i <= SCRIPT_MAX; i++)
+		new->script[i] = NULL;
+	new->gen_policy = FALSE;
+	new->retry_counter = lcconf->retry_counter;
+	new->retry_interval = lcconf->retry_interval;
+	new->nat_traversal = FALSE;
+	new->rsa_private = genlist_init();
+	new->rsa_public = genlist_init();
+	new->idv = NULL;
+	new->key = NULL;
+
+	new->dpd = TRUE; /* Enable DPD support by default */
+	new->dpd_interval = 0; /* Disable DPD checks by default */
+	new->dpd_retry = 5;
+	new->dpd_maxfails = 5;
+
+	new->weak_phase1_check = 0;
+
+#ifdef ENABLE_HYBRID
+	new->xauth = NULL;
+#endif
+
+	return new;
+}
+
+struct remoteconf *
+copyrmconf(remote)
+	struct sockaddr *remote;
+{
+	struct remoteconf *new, *old;
+
+	old = getrmconf_strict (remote, 0);
+	if (old == NULL) {
+		plog (LLV_ERROR, LOCATION, NULL,
+		      "Remote configuration for '%s' not found!\n",
+		      saddr2str (remote));
+		return NULL;
+	}
+
+	new = duprmconf (old);
+
+	return new;
+}
+
+void *
+dupidvl(entry, arg)
+	void *entry;
+	void *arg;
+{
+	struct idspec *id;
+	struct idspec *old = (struct idspec *) entry;
+	id = newidspec();
+	if (!id) return (void *) -1;
+
+	if (set_identifier(&id->id, old->idtype, old->id) != 0) {
+		racoon_free(id);
+		return (void *) -1;
+	}
+
+	id->idtype = old->idtype;
+
+	genlist_append(arg, id);
+	return NULL;
+}
+
+struct remoteconf *
+duprmconf (rmconf)
+	struct remoteconf *rmconf;
+{
+	struct remoteconf *new;
+
+	new = racoon_calloc(1, sizeof(*new));
+	if (new == NULL)
+		return NULL;
+	memcpy (new, rmconf, sizeof (*new));
+	// FIXME: We should duplicate the proposal as well.
+	// This is now handled in the cfparse.y
+	// new->proposal = ...;
+	
+	/* duplicate dynamic structures */
+	if (new->etypes)
+		new->etypes=dupetypes(new->etypes);
+	new->idvl_p = genlist_init();
+	genlist_foreach(rmconf->idvl_p, dupidvl, new->idvl_p);
+
+	return new;
+}
+
+static void
+idspec_free(void *data)
+{
+	vfree (((struct idspec *)data)->id);
+	free (data);
+}
+
+void
+delrmconf(rmconf)
+	struct remoteconf *rmconf;
+{
+#ifdef ENABLE_HYBRID
+	if (rmconf->xauth)
+		xauth_rmconf_delete(&rmconf->xauth);
+#endif
+	if (rmconf->etypes){
+		deletypes(rmconf->etypes);
+		rmconf->etypes=NULL;
+	}
+	if (rmconf->idvl_p)
+		genlist_free(rmconf->idvl_p, idspec_free);
+	if (rmconf->dhgrp)
+		oakley_dhgrp_free(rmconf->dhgrp);
+	if (rmconf->proposal)
+		delisakmpsa(rmconf->proposal);
+	racoon_free(rmconf);
+}
+
+void
+delisakmpsa(sa)
+	struct isakmpsa *sa;
+{
+	if (sa->dhgrp)
+		oakley_dhgrp_free(sa->dhgrp);
+	if (sa->next)
+		delisakmpsa(sa->next);
+#ifdef HAVE_GSSAPI
+	if (sa->gssid)
+		vfree(sa->gssid);
+#endif
+	racoon_free(sa);
+}
+
+struct etypes *
+dupetypes(orig)
+	struct etypes *orig;
+{
+	struct etypes *new;
+
+	if (!orig) 
+		return NULL;
+
+	new = racoon_malloc(sizeof(struct etypes));
+	if (new == NULL) 
+		return NULL;
+
+	new->type = orig->type;
+	new->next = NULL;
+
+	if (orig->next)
+		new->next=dupetypes(orig->next);
+
+	return new;
+}
+
+void
+deletypes(e)
+	struct etypes *e;
+{
+	if (e->next)
+		deletypes(e->next);
+	racoon_free(e);
+}
+
+/*
+ * insert into head of list.
+ */
+void
+insrmconf(new)
+	struct remoteconf *new;
+{
+	TAILQ_INSERT_HEAD(&rmtree, new, chain);
+}
+
+void
+remrmconf(rmconf)
+	struct remoteconf *rmconf;
+{
+	TAILQ_REMOVE(&rmtree, rmconf, chain);
+}
+
+void
+flushrmconf()
+{
+	struct remoteconf *p, *next;
+
+	for (p = TAILQ_FIRST(&rmtree); p; p = next) {
+		next = TAILQ_NEXT(p, chain);
+		remrmconf(p);
+		delrmconf(p);
+	}
+}
+
+void
+initrmconf()
+{
+	TAILQ_INIT(&rmtree);
+}
+
+void
+save_rmconf()
+{
+	rmtree_save=rmtree;
+	initrmconf();
+}
+
+void
+save_rmconf_flush()
+{
+	rmtree_tmp=rmtree;
+	rmtree=rmtree_save;
+	flushrmconf();
+	initrmconf();
+	rmtree=rmtree_tmp;
+}
+
+
+
+/* check exchange type to be acceptable */
+struct etypes *
+check_etypeok(rmconf, etype)
+	struct remoteconf *rmconf;
+	u_int8_t etype;
+{
+	struct etypes *e;
+
+	for (e = rmconf->etypes; e != NULL; e = e->next) {
+		if (e->type == etype)
+			break;
+	}
+
+	return e;
+}
+
+/*%%%*/
+struct isakmpsa *
+newisakmpsa()
+{
+	struct isakmpsa *new;
+
+	new = racoon_calloc(1, sizeof(*new));
+	if (new == NULL)
+		return NULL;
+
+	/*
+	 * Just for sanity, make sure this is initialized.  This is
+	 * filled in for real when the ISAKMP proposal is configured.
+	 */
+	new->vendorid = VENDORID_UNKNOWN;
+
+	new->next = NULL;
+	new->rmconf = NULL;
+#ifdef HAVE_GSSAPI
+	new->gssid = NULL;
+#endif
+
+	return new;
+}
+
+/*
+ * insert into tail of list.
+ */
+void
+insisakmpsa(new, rmconf)
+	struct isakmpsa *new;
+	struct remoteconf *rmconf;
+{
+	struct isakmpsa *p;
+
+	new->rmconf = rmconf;
+
+	if (rmconf->proposal == NULL) {
+		rmconf->proposal = new;
+		return;
+	}
+
+	for (p = rmconf->proposal; p->next != NULL; p = p->next)
+		;
+	p->next = new;
+
+	return;
+}
+
+struct remoteconf *
+foreachrmconf(rmconf_func_t rmconf_func, void *data)
+{
+  struct remoteconf *p, *ret = NULL;
+  RACOON_TAILQ_FOREACH_REVERSE(p, &rmtree, _rmtree, chain) {
+    ret = (*rmconf_func)(p, data);
+    if (ret)
+      break;
+  }
+
+  return ret;
+}
+
+static void *
+dump_peers_identifiers (void *entry, void *arg)
+{
+	struct idspec *id = (struct idspec*) entry;
+	char buf[1024], *pbuf;
+	pbuf = buf;
+	pbuf += sprintf (pbuf, "\tpeers_identifier %s",
+			 s_idtype (id->idtype));
+	if (id->id)
+		pbuf += sprintf (pbuf, " \"%s\"", id->id->v);
+	plog(LLV_INFO, LOCATION, NULL, "%s;\n", buf);
+	return NULL;
+}
+
+static struct remoteconf *
+dump_rmconf_single (struct remoteconf *p, void *data)
+{
+	struct etypes *etype = p->etypes;
+	struct isakmpsa *prop = p->proposal;
+	char buf[1024], *pbuf;
+
+	pbuf = buf;
+	pbuf += sprintf(pbuf, "remote %s", saddr2str(p->remote));
+	if (p->inherited_from)
+		pbuf += sprintf(pbuf, " inherit %s",
+				saddr2str(p->inherited_from->remote));
+	plog(LLV_INFO, LOCATION, NULL, "%s {\n", buf);
+	pbuf = buf;
+	pbuf += sprintf(pbuf, "\texchange_type ");
+	while (etype) {
+		pbuf += sprintf (pbuf, "%s%s", s_etype(etype->type),
+				 etype->next != NULL ? ", " : ";\n");
+		etype = etype->next;
+	}
+	plog(LLV_INFO, LOCATION, NULL, "%s", buf);
+	plog(LLV_INFO, LOCATION, NULL, "\tdoi %s;\n", s_doi(p->doitype));
+	pbuf = buf;
+	pbuf += sprintf(pbuf, "\tmy_identifier %s", s_idtype (p->idvtype));
+	if (p->idvtype == IDTYPE_ASN1DN) {
+		plog(LLV_INFO, LOCATION, NULL, "%s;\n", buf);
+		plog(LLV_INFO, LOCATION, NULL, "\tcertificate_type %s \"%s\" \"%s\";\n",
+			p->certtype == ISAKMP_CERT_X509SIGN ? "x509" : "*UNKNOWN*",
+			p->mycertfile, p->myprivfile);
+		switch (p->getcert_method) {
+		  case 0:
+		  	break;
+		  case ISAKMP_GETCERT_PAYLOAD:
+			plog(LLV_INFO, LOCATION, NULL, "\t/* peers certificate from payload */\n");
+			break;
+		  case ISAKMP_GETCERT_LOCALFILE:
+			plog(LLV_INFO, LOCATION, NULL, "\tpeers_certfile \"%s\";\n", p->peerscertfile);
+			break;
+		  case ISAKMP_GETCERT_DNS:
+			plog(LLV_INFO, LOCATION, NULL, "\tpeer_certfile dnssec;\n");
+			break;
+		  default:
+			plog(LLV_INFO, LOCATION, NULL, "\tpeers_certfile *UNKNOWN* (%d)\n", p->getcert_method);
+		}
+	}
+	else {
+		if (p->idv)
+			pbuf += sprintf (pbuf, " \"%s\"", p->idv->v);
+		plog(LLV_INFO, LOCATION, NULL, "%s;\n", buf);
+		genlist_foreach(p->idvl_p, &dump_peers_identifiers, NULL);
+	}
+
+	plog(LLV_INFO, LOCATION, NULL, "\tsend_cert %s;\n",
+		s_switch (p->send_cert));
+	plog(LLV_INFO, LOCATION, NULL, "\tsend_cr %s;\n",
+		s_switch (p->send_cr));
+	plog(LLV_INFO, LOCATION, NULL, "\tverify_cert %s;\n",
+		s_switch (p->verify_cert));
+	plog(LLV_INFO, LOCATION, NULL, "\tverify_identifier %s;\n",
+		s_switch (p->verify_identifier));
+	plog(LLV_INFO, LOCATION, NULL, "\tnat_traversal %s;\n",
+		p->nat_traversal == NATT_FORCE ?
+			"force" : s_switch (p->nat_traversal));
+	plog(LLV_INFO, LOCATION, NULL, "\tnonce_size %d;\n",
+		p->nonce_size);
+	plog(LLV_INFO, LOCATION, NULL, "\tpassive %s;\n",
+		s_switch (p->passive));
+	plog(LLV_INFO, LOCATION, NULL, "\tike_frag %s;\n",
+		p->ike_frag == ISAKMP_FRAG_FORCE ?
+			"force" : s_switch (p->ike_frag));
+	plog(LLV_INFO, LOCATION, NULL, "\tesp_frag %d;\n", p->esp_frag);
+	plog(LLV_INFO, LOCATION, NULL, "\tinitial_contact %s;\n",
+		s_switch (p->ini_contact));
+	plog(LLV_INFO, LOCATION, NULL, "\tgenerate_policy %s;\n",
+		s_switch (p->gen_policy));
+	plog(LLV_INFO, LOCATION, NULL, "\tsupport_proxy %s;\n",
+		s_switch (p->support_proxy));
+
+	while (prop) {
+		plog(LLV_INFO, LOCATION, NULL, "\n");
+		plog(LLV_INFO, LOCATION, NULL,
+			"\t/* prop_no=%d, trns_no=%d, rmconf=%s */\n",
+			prop->prop_no, prop->trns_no,
+			saddr2str(prop->rmconf->remote));
+		plog(LLV_INFO, LOCATION, NULL, "\tproposal {\n");
+		plog(LLV_INFO, LOCATION, NULL, "\t\tlifetime time %lu sec;\n",
+			(long)prop->lifetime);
+		plog(LLV_INFO, LOCATION, NULL, "\t\tlifetime bytes %zd;\n",
+			prop->lifebyte);
+		plog(LLV_INFO, LOCATION, NULL, "\t\tdh_group %s;\n",
+			alg_oakley_dhdef_name(prop->dh_group));
+		plog(LLV_INFO, LOCATION, NULL, "\t\tencryption_algorithm %s;\n", 
+			alg_oakley_encdef_name(prop->enctype));
+		plog(LLV_INFO, LOCATION, NULL, "\t\thash_algorithm %s;\n", 
+			alg_oakley_hashdef_name(prop->hashtype));
+		plog(LLV_INFO, LOCATION, NULL, "\t\tauthentication_method %s;\n", 
+			alg_oakley_authdef_name(prop->authmethod));
+		plog(LLV_INFO, LOCATION, NULL, "\t}\n");
+		prop = prop->next;
+	}
+	plog(LLV_INFO, LOCATION, NULL, "}\n");
+	plog(LLV_INFO, LOCATION, NULL, "\n");
+
+	return NULL;
+}
+
+void
+dumprmconf()
+{
+	foreachrmconf (dump_rmconf_single, NULL);
+}
+
+struct idspec *
+newidspec()
+{
+	struct idspec *new;
+
+	new = racoon_calloc(1, sizeof(*new));
+	if (new == NULL)
+		return NULL;
+	new->idtype = IDTYPE_ADDRESS;
+
+	return new;
+}
+
+vchar_t *
+script_path_add(path)
+	vchar_t *path;
+{
+	char *script_dir;
+	vchar_t *new_path;
+	vchar_t *new_storage;
+	vchar_t **sp;
+	size_t len;
+	size_t size;
+
+	script_dir = lcconf->pathinfo[LC_PATHTYPE_SCRIPT];
+
+	/* Try to find the script in the script directory */
+	if ((path->v[0] != '/') && (script_dir != NULL)) {
+		len = strlen(script_dir) + sizeof("/") + path->l + 1;
+
+		if ((new_path = vmalloc(len)) == NULL) {
+			plog(LLV_ERROR, LOCATION, NULL,
+			    "Cannot allocate memory: %s\n", strerror(errno));
+			return NULL;
+		}
+
+		new_path->v[0] = '\0';
+		(void)strlcat(new_path->v, script_dir, len);
+		(void)strlcat(new_path->v, "/", len);
+		(void)strlcat(new_path->v, path->v, len);
+
+		vfree(path);
+		path = new_path;
+	}
+
+	return path;
+}
+
+
+struct isakmpsa *
+dupisakmpsa(struct isakmpsa *sa)
+{
+	struct isakmpsa *res=NULL;
+
+	if(sa == NULL)
+		return NULL;
+
+	res=newisakmpsa();
+	if(res == NULL)
+		return NULL;
+
+	*res=*sa;
+#ifdef HAVE_GSSAPI
+	/* XXX gssid
+	 */
+#endif
+	res->next=NULL;
+
+	if(sa->dhgrp != NULL)
+		oakley_setdhgroup (sa->dh_group, &(res->dhgrp));
+
+	return res;
+
+}
diff --git a/src/racoon/remoteconf.h b/src/racoon/remoteconf.h
new file mode 100644
index 0000000..ca5945e
--- /dev/null
+++ b/src/racoon/remoteconf.h
@@ -0,0 +1,196 @@
+/*	$NetBSD: remoteconf.h,v 1.7 2006/10/03 08:01:56 vanhu Exp $	*/
+
+/* Id: remoteconf.h,v 1.26 2006/05/06 15:52:44 manubsd Exp */
+
+/*
+ * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _REMOTECONF_H
+#define _REMOTECONF_H
+
+/* remote configuration */
+
+#include <sys/queue.h>
+#include "genlist.h"
+#ifdef ENABLE_HYBRID
+#include "isakmp_var.h"
+#include "isakmp_xauth.h"
+#endif
+
+struct proposalspec;
+
+struct etypes {
+	int type;
+	struct etypes *next;
+};
+
+/* Script hooks */
+#define SCRIPT_PHASE1_UP	0
+#define SCRIPT_PHASE1_DOWN	1
+#define SCRIPT_MAX		1
+extern char *script_names[SCRIPT_MAX + 1];
+
+struct remoteconf {
+	struct sockaddr *remote;	/* remote IP address */
+					/* if family is AF_UNSPEC, that is
+					 * for anonymous configuration. */
+
+	struct etypes *etypes;		/* exchange type list. the head
+					 * is a type to be sent first. */
+	int doitype;			/* doi type */
+	int sittype;			/* situation type */
+
+	int idvtype;			/* my identifier type */
+	vchar_t *idv;			/* my identifier */
+	vchar_t *key;			/* my pre-shared key */
+	struct genlist *idvl_p;         /* peer's identifiers list */
+
+	int certtype;			/* certificate type if need */
+	char *mycertfile;		/* file name of my certificate */
+	char *myprivfile;		/* file name of my private key file */
+	char *peerscertfile;		/* file name of peer's certifcate */
+	int getcert_method;		/* the way to get peer's certificate */
+	int cacerttype;			/* CA type is needed */
+	char *cacertfile;		/* file name of CA */
+	int getcacert_method;		/* the way to get the CA */
+	int send_cert;			/* send to CERT or not */
+	int send_cr;			/* send to CR or not */
+	int verify_cert;		/* verify a CERT strictly */
+	int verify_identifier;		/* vefify the peer's identifier */
+	int nonce_size;			/* the number of bytes of nonce */
+	int passive;			/* never initiate */
+	int ike_frag;			/* IKE fragmentation */
+	int esp_frag;			/* ESP fragmentation */
+	int mode_cfg;			/* Gets config through mode config */
+	int support_proxy;		/* support mip6/proxy */
+#define GENERATE_POLICY_NONE   0
+#define GENERATE_POLICY_REQUIRE        1
+#define GENERATE_POLICY_UNIQUE 2
+	int gen_policy;			/* generate policy if no policy found */
+	int ini_contact;		/* initial contact */
+	int pcheck_level;		/* level of propocl checking */
+	int nat_traversal;		/* NAT-Traversal */
+	vchar_t *script[SCRIPT_MAX + 1];/* script hooks paths */
+	int dh_group;			/* use it when only aggressive mode */
+	struct dhgroup *dhgrp;		/* use it when only aggressive mode */
+					/* above two can't be defined by user*/
+
+	int retry_counter;		/* times to retry. */
+	int retry_interval;		/* interval each retry. */
+				/* above 2 values are copied from localconf. */
+
+	int dpd;				/* Negociate DPD support ? */
+	int dpd_retry;			/* in seconds */
+	int dpd_interval;		/* in seconds */
+	int dpd_maxfails; 
+
+	int ph1id; /* ph1id to be matched with sainfo sections */
+
+	int weak_phase1_check;		/* act on unencrypted deletions ? */
+
+	struct isakmpsa *proposal;	/* proposal list */
+	struct remoteconf *inherited_from;	/* the original rmconf 
+						   from which this one 
+						   was inherited */
+	struct proposalspec *prhead;
+
+	struct genlist	*rsa_private,	/* lists of PlainRSA keys to use */
+			*rsa_public;
+
+#ifdef ENABLE_HYBRID
+	struct xauth_rmconf *xauth;
+#endif
+
+	TAILQ_ENTRY(remoteconf) chain;	/* next remote conf */
+};
+
+struct dhgroup;
+
+/* ISAKMP SA specification */
+struct isakmpsa {
+	int prop_no;
+	int trns_no;
+	time_t lifetime;
+	size_t lifebyte;
+	int enctype;
+	int encklen;
+	int authmethod;
+	int hashtype;
+	int vendorid;
+#ifdef HAVE_GSSAPI
+	vchar_t *gssid;
+#endif
+	int dh_group;			/* don't use it if aggressive mode */
+	struct dhgroup *dhgrp;		/* don't use it if aggressive mode */
+
+	struct isakmpsa *next;		/* next transform */
+	struct remoteconf *rmconf;	/* backpointer to remoteconf */
+};
+
+struct idspec {
+	int idtype;                     /* identifier type */
+	vchar_t *id;                    /* identifier */
+};
+
+typedef struct remoteconf * (rmconf_func_t)(struct remoteconf *rmconf, void *data);
+
+extern struct remoteconf *getrmconf __P((struct sockaddr *));
+extern struct remoteconf *getrmconf_strict
+	__P((struct sockaddr *remote, int allow_anon));
+extern struct remoteconf *copyrmconf __P((struct sockaddr *));
+extern struct remoteconf *newrmconf __P((void));
+extern struct remoteconf *duprmconf __P((struct remoteconf *));
+extern void delrmconf __P((struct remoteconf *));
+extern void delisakmpsa __P((struct isakmpsa *));
+extern void deletypes __P((struct etypes *));
+extern struct etypes * dupetypes __P((struct etypes *));
+extern void insrmconf __P((struct remoteconf *));
+extern void remrmconf __P((struct remoteconf *));
+extern void flushrmconf __P((void));
+extern void initrmconf __P((void));
+extern void save_rmconf __P((void));
+extern void save_rmconf_flush __P((void));
+
+extern struct etypes *check_etypeok
+	__P((struct remoteconf *, u_int8_t));
+extern struct remoteconf *foreachrmconf __P((rmconf_func_t rmconf_func,
+					     void *data));
+
+extern struct isakmpsa *newisakmpsa __P((void));
+extern struct isakmpsa *dupisakmpsa __P((struct isakmpsa *));
+
+extern void insisakmpsa __P((struct isakmpsa *, struct remoteconf *));
+
+extern void dumprmconf __P((void));
+
+extern struct idspec *newidspec __P((void));
+
+extern vchar_t *script_path_add __P((vchar_t *));
+
+#endif /* _REMOTECONF_H */
diff --git a/src/racoon/rsalist.c b/src/racoon/rsalist.c
new file mode 100644
index 0000000..850aa4c
--- /dev/null
+++ b/src/racoon/rsalist.c
@@ -0,0 +1,216 @@
+/*	$NetBSD: rsalist.c,v 1.4 2006/09/09 16:22:10 manu Exp $	*/
+
+/* Id: rsalist.c,v 1.3 2004/11/08 12:04:23 ludvigm Exp */
+
+/*
+ * Copyright (C) 2004 SuSE Linux AG, Nuernberg, Germany.
+ * Contributed by: Michal Ludvig <mludvig@suse.cz>, SUSE Labs
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include <stdio.h>
+#include <string.h>
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/socket.h>
+#include <netdb.h>
+
+#include <openssl/bn.h>
+#include <openssl/rsa.h>
+
+#include "misc.h"
+#include "plog.h"
+#include "sockmisc.h"
+#include "rsalist.h"
+#include "genlist.h"
+#include "remoteconf.h"
+#include "crypto_openssl.h"
+
+#ifndef LIST_FIRST
+#define LIST_FIRST(head)        ((head)->lh_first)
+#endif
+
+#ifndef LIST_NEXT
+#define LIST_NEXT(elm, field)   ((elm)->field.le_next)
+#endif
+
+/* from prsa_tok.l */
+int prsa_parse_file(struct genlist *list, const char *fname, enum rsa_key_type type);
+
+int
+rsa_key_insert(struct genlist *list, struct netaddr *src,
+	       struct netaddr *dst, RSA *rsa)
+{
+	struct rsa_key *rsa_key;
+
+	rsa_key = calloc(sizeof(struct rsa_key), 1);
+	rsa_key->rsa = rsa;
+
+	if (src)
+		rsa_key->src = src;
+	else
+		rsa_key->src = calloc(sizeof(*rsa_key->src), 1);
+
+	if (dst)
+		rsa_key->dst = dst;
+	else
+		rsa_key->dst = calloc(sizeof(*rsa_key->dst), 1);
+
+	genlist_append(list, rsa_key);
+
+	return 0;
+}
+
+static void *
+rsa_key_dump_one(void *entry, void *arg)
+{
+	struct rsa_key *key = entry;
+
+	plog(LLV_DEBUG, LOCATION, NULL, "Entry %s\n",
+	     naddrwop2str_fromto("%s -> %s", key->src,
+				 key->dst));
+	if (loglevel > LLV_DEBUG)
+		RSA_print_fp(stdout, key->rsa, 4);
+
+	return NULL;
+}
+
+void
+rsa_key_dump(struct genlist *list)
+{
+	genlist_foreach(list, rsa_key_dump_one, NULL);
+}
+
+static void *
+rsa_list_count_one(void *entry, void *arg)
+{
+	if (arg)
+		(*(unsigned long *)arg)++;
+	return NULL;
+}
+
+unsigned long
+rsa_list_count(struct genlist *list)
+{
+	unsigned long count = 0;
+	genlist_foreach(list, rsa_list_count_one, &count);
+	return count;
+}
+
+struct lookup_result {
+	struct ph1handle *iph1;
+	int max_score;
+	struct genlist *winners;
+};
+	
+static void *
+rsa_lookup_key_one(void *entry, void *data)
+{
+	int local_score, remote_score;
+	struct lookup_result *req = data;
+	struct rsa_key *key = entry;
+
+	local_score = naddr_score(key->src, req->iph1->local);
+	remote_score = naddr_score(key->dst, req->iph1->remote);
+
+	plog(LLV_DEBUG, LOCATION, NULL, "Entry %s scored %d/%d\n",
+		naddrwop2str_fromto("%s -> %s", key->src, key->dst),
+		local_score, remote_score);
+
+	if (local_score >= 0 && remote_score >= 0) {
+		if (local_score + remote_score > req->max_score) {
+			req->max_score = local_score + remote_score;
+//			genlist_free(req->winners, NULL);
+		}
+
+		if (local_score + remote_score >= req->max_score) {
+			genlist_append(req->winners, key);
+		}
+	}
+
+	/* Always traverse the whole list */
+	return NULL;
+}
+
+struct genlist *
+rsa_lookup_keys(struct ph1handle *iph1, int my)
+{
+	struct genlist *list;
+	struct lookup_result r;
+
+	plog(LLV_DEBUG, LOCATION, NULL, "Looking up RSA key for %s\n",
+	     saddr2str_fromto("%s <-> %s", iph1->local, iph1->remote));
+
+	r.iph1 = iph1;
+	r.max_score = -1;
+	r.winners = genlist_init();
+
+	if (my)
+		list = iph1->rmconf->rsa_private;
+	else
+		list = iph1->rmconf->rsa_public;
+
+	genlist_foreach(list, rsa_lookup_key_one, &r);
+
+	if (loglevel >= LLV_DEBUG)
+		rsa_key_dump(r.winners);
+
+	return r.winners;
+}
+
+int
+rsa_parse_file(struct genlist *list, const char *fname, enum rsa_key_type type)
+{
+	int ret;
+	
+	plog(LLV_DEBUG, LOCATION, NULL, "Parsing %s\n", fname);
+	ret = prsa_parse_file(list, fname, type);
+	if (loglevel >= LLV_DEBUG)
+		rsa_key_dump(list);
+	return ret;
+}
+
+RSA *
+rsa_try_check_rsasign(vchar_t *source, vchar_t *sig, struct genlist *list)
+{
+	struct rsa_key *key;
+	struct genlist_entry *gp;
+
+	for(key = genlist_next(list, &gp); key; key = genlist_next(NULL, &gp)) {
+		plog(LLV_DEBUG, LOCATION, NULL, "Checking key %s...\n",
+			naddrwop2str_fromto("%s -> %s", key->src, key->dst));
+		if (eay_check_rsasign(source, sig, key->rsa) == 0) {
+			plog(LLV_DEBUG, LOCATION, NULL, " ... YEAH!\n");
+			return key->rsa;
+		}
+		plog(LLV_DEBUG, LOCATION, NULL, " ... nope.\n");
+	}
+	return NULL;
+}
diff --git a/src/racoon/rsalist.h b/src/racoon/rsalist.h
new file mode 100644
index 0000000..911670f
--- /dev/null
+++ b/src/racoon/rsalist.h
@@ -0,0 +1,65 @@
+/*	$NetBSD: rsalist.h,v 1.4 2006/09/09 16:22:10 manu Exp $	*/
+
+/* Id: rsalist.h,v 1.2 2004/07/12 20:43:51 ludvigm Exp */
+/*
+ * Copyright (C) 2004 SuSE Linux AG, Nuernberg, Germany.
+ * Contributed by: Michal Ludvig <mludvig@suse.cz>, SUSE Labs
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _RSALIST_H
+#define _RSALIST_H
+
+#include <netinet/in.h>
+#include <openssl/rsa.h>
+
+#include "handler.h"
+#include "genlist.h"
+
+enum rsa_key_type {
+	RSA_TYPE_ANY = 0,
+	RSA_TYPE_PUBLIC,
+	RSA_TYPE_PRIVATE
+};
+
+struct rsa_key {
+	struct netaddr *src;
+	struct netaddr *dst;
+	RSA *rsa;
+};
+
+int rsa_key_insert(struct genlist *list, struct netaddr *src, struct netaddr *dst, RSA *rsa);
+void rsa_key_dump(struct genlist *list);
+
+struct genlist *rsa_lookup_keys(struct ph1handle *iph1, int my);
+RSA *rsa_try_check_rsasign(vchar_t *source, vchar_t *sig, struct genlist *list);
+
+unsigned long rsa_list_count(struct genlist *list);
+
+int rsa_parse_file(struct genlist *list, const char *fname, enum rsa_key_type type);
+
+#endif /* _RSALIST_H */
diff --git a/src/racoon/safefile.c b/src/racoon/safefile.c
new file mode 100644
index 0000000..5241092
--- /dev/null
+++ b/src/racoon/safefile.c
@@ -0,0 +1,93 @@
+/*	$NetBSD: safefile.c,v 1.4 2006/09/09 16:22:10 manu Exp $	*/
+
+/*	$KAME: safefile.c,v 1.5 2001/03/05 19:54:06 thorpej Exp $	*/
+
+/*
+ * Copyright (C) 2000 WIDE Project.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <unistd.h>
+
+#include "plog.h"
+#include "debug.h"
+#include "misc.h"
+#include "safefile.h"
+
+int
+safefile(path, secret)
+	const char *path;
+	int secret;
+{
+	struct stat s;
+	uid_t me;
+
+	/* no setuid */
+	if (getuid() != geteuid()) {
+		plog(LLV_ERROR, LOCATION, NULL,
+		    "setuid'ed execution not allowed\n");
+		return -1;
+	}
+
+	if (stat(path, &s) != 0)
+		return -1;
+
+	/* the file must be owned by the running uid */
+	me = getuid();
+	if (s.st_uid != me) {
+		plog(LLV_ERROR, LOCATION, NULL,
+		    "%s has invalid owner uid\n", path);
+		return -1;
+	}
+
+	switch (s.st_mode & S_IFMT) {
+	case S_IFREG:
+		break;
+	default:
+		plog(LLV_ERROR, LOCATION, NULL,
+		    "%s is an invalid file type 0x%x\n", path,
+		    (s.st_mode & S_IFMT));
+		return -1;
+	}
+
+	/* secret file should not be read by others */
+	if (secret) {
+		if ((s.st_mode & S_IRWXG) != 0 || (s.st_mode & S_IRWXO) != 0) {
+			plog(LLV_ERROR, LOCATION, NULL,
+			    "%s has weak file permission\n", path);
+			return -1;
+		}
+	}
+
+	return 0;
+}
diff --git a/src/racoon/safefile.h b/src/racoon/safefile.h
new file mode 100644
index 0000000..c8d6a6c
--- /dev/null
+++ b/src/racoon/safefile.h
@@ -0,0 +1,39 @@
+/*	$NetBSD: safefile.h,v 1.4 2006/09/09 16:22:10 manu Exp $	*/
+
+/* Id: safefile.h,v 1.4 2004/07/12 18:32:12 ludvigm Exp */
+
+/*
+ * Copyright (C) 2000 WIDE Project.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _SAFEFILE_H
+#define _SAFEFILE_H
+
+extern int safefile __P((const char *, int));
+
+#endif /* _SAFEFILE_H */
diff --git a/src/racoon/sainfo.c b/src/racoon/sainfo.c
new file mode 100644
index 0000000..afa0aac
--- /dev/null
+++ b/src/racoon/sainfo.c
@@ -0,0 +1,319 @@
+/*	$NetBSD: sainfo.c,v 1.7.6.1 2007/08/01 11:52:22 vanhu Exp $	*/
+
+/*	$KAME: sainfo.c,v 1.16 2003/06/27 07:32:39 sakane Exp $	*/
+
+/*
+ * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/queue.h>
+
+#include <netinet/in.h>
+#include <netinet/in.h> 
+#include PATH_IPSEC_H
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+
+#include "var.h"
+#include "misc.h"
+#include "vmbuf.h"
+#include "plog.h"
+#include "sockmisc.h"
+#include "debug.h"
+
+#include "localconf.h"
+#include "isakmp_var.h"
+#include "isakmp.h"
+#include "ipsec_doi.h"
+#include "oakley.h"
+#include "handler.h"
+#include "algorithm.h"
+#include "sainfo.h"
+#include "gcmalloc.h"
+
+static LIST_HEAD(_sitree, sainfo) sitree, sitree_save, sitree_tmp;
+
+/* %%%
+ * modules for ipsec sa info
+ */
+/*
+ * return matching entry.
+ * no matching entry found and if there is anonymous entry, return it.
+ * else return NULL.
+ * First pass is for sainfo from a specified peer, second for others.
+ */
+struct sainfo *
+getsainfo(loc, rmt, peer, remoteid)
+	const vchar_t *loc, *rmt, *peer;
+	int remoteid;
+{
+	struct sainfo *s = NULL;
+	struct sainfo *anonymous = NULL;
+	int pass = 1;
+
+	if (peer == NULL)
+		pass = 2;
+
+	/* debug level output */
+	if(loglevel >= LLV_DEBUG) {
+		char *dloc, *drmt, *dpeer, *dclient;
+ 
+		if (loc == NULL)
+			dloc = strdup("ANONYMOUS");
+		else
+			dloc = ipsecdoi_id2str(loc);
+ 
+		if (rmt == NULL)
+			drmt = strdup("ANONYMOUS");
+		else
+			drmt = ipsecdoi_id2str(rmt);
+ 
+		if (peer == NULL)
+			dpeer = strdup("NULL");
+		else
+			dpeer = ipsecdoi_id2str(peer);
+ 
+		plog(LLV_DEBUG, LOCATION, NULL,
+			"getsainfo params: loc=\'%s\', rmt=\'%s\', peer=\'%s\', id=%i\n",
+			dloc, drmt, dpeer, remoteid );
+ 
+                racoon_free(dloc);
+                racoon_free(drmt);
+                racoon_free(dpeer);
+	}
+
+    again:
+	plog(LLV_DEBUG, LOCATION, NULL,
+		"getsainfo pass #%i\n", pass);
+ 
+	LIST_FOREACH(s, &sitree, chain) {
+		const char *sainfostr = sainfo2str(s);
+		plog(LLV_DEBUG, LOCATION, NULL,
+			"evaluating sainfo: %s\n", sainfostr);
+
+		if(s->remoteid != remoteid)
+			continue;
+
+		if (s->id_i != NULL) {
+			if (pass == 2)
+				continue;
+			if (ipsecdoi_chkcmpids(peer, s->id_i, 0))
+				continue;
+		} else if (pass == 1)
+			continue;
+		if (s->idsrc == NULL && s->iddst == NULL) {
+			anonymous = s;
+			continue;
+		}
+
+		/* anonymous ? */
+		if (loc == NULL) {
+			if (anonymous != NULL)
+				break;
+			continue;
+		}
+
+		/* compare the ids */
+		if (!ipsecdoi_chkcmpids(loc, s->idsrc, 0) &&
+		    !ipsecdoi_chkcmpids(rmt, s->iddst, 0))
+			return s;
+	}
+
+	if ((anonymous == NULL) && (pass == 1)) {
+		pass++;
+		goto again;
+	}
+
+	return anonymous;
+}
+
+struct sainfo *
+newsainfo()
+{
+	struct sainfo *new;
+
+	new = racoon_calloc(1, sizeof(*new));
+	if (new == NULL)
+		return NULL;
+
+	new->lifetime = IPSECDOI_ATTR_SA_LD_SEC_DEFAULT;
+	new->lifebyte = IPSECDOI_ATTR_SA_LD_KB_MAX;
+
+	return new;
+}
+
+void
+delsainfo(si)
+	struct sainfo *si;
+{
+	int i;
+
+	for (i = 0; i < MAXALGCLASS; i++)
+		delsainfoalg(si->algs[i]);
+
+	if (si->idsrc)
+		vfree(si->idsrc);
+	if (si->iddst)
+		vfree(si->iddst);
+
+#ifdef ENABLE_HYBRID
+	if (si->group)
+		vfree(si->group);
+#endif
+
+	racoon_free(si);
+}
+
+void
+inssainfo(new)
+	struct sainfo *new;
+{
+	LIST_INSERT_HEAD(&sitree, new, chain);
+}
+
+void
+remsainfo(si)
+	struct sainfo *si;
+{
+	LIST_REMOVE(si, chain);
+}
+
+void
+flushsainfo()
+{
+	struct sainfo *s, *next;
+
+	for (s = LIST_FIRST(&sitree); s; s = next) {
+		next = LIST_NEXT(s, chain);
+		remsainfo(s);
+		delsainfo(s);
+	}
+}
+
+void
+initsainfo()
+{
+	LIST_INIT(&sitree);
+}
+
+struct sainfoalg *
+newsainfoalg()
+{
+	struct sainfoalg *new;
+
+	new = racoon_calloc(1, sizeof(*new));
+	if (new == NULL)
+		return NULL;
+
+	return new;
+}
+
+void
+delsainfoalg(alg)
+	struct sainfoalg *alg;
+{
+	struct sainfoalg *a, *next;
+
+	for (a = alg; a; a = next) {
+		next = a->next;
+		racoon_free(a);
+	}
+}
+
+void
+inssainfoalg(head, new)
+	struct sainfoalg **head;
+	struct sainfoalg *new;
+{
+	struct sainfoalg *a;
+
+	for (a = *head; a && a->next; a = a->next)
+		;
+	if (a)
+		a->next = new;
+	else
+		*head = new;
+}
+
+const char *
+sainfo2str(si)
+	const struct sainfo *si;
+{
+        static char buf[256];
+
+        char *idloc = NULL, *idrmt = NULL, *id_i;
+ 
+        if (si->idsrc == NULL)
+                idloc = strdup("ANONYMOUS");
+        else
+                idloc = ipsecdoi_id2str(si->idsrc);
+ 
+        if (si->iddst == NULL)
+                idrmt = strdup("ANONYMOUS");
+        else
+                idrmt = ipsecdoi_id2str(si->iddst);
+ 
+        if (si->id_i == NULL)
+                id_i = strdup("ANY");
+        else
+                id_i = ipsecdoi_id2str(si->id_i);
+ 
+        snprintf(buf, 255, "loc=\'%s\', rmt=\'%s\', peer=\'%s\', id=%i",
+		idloc, idrmt, id_i, si->remoteid);
+ 
+        racoon_free(idloc);
+        racoon_free(idrmt);
+        racoon_free(id_i);
+ 
+        return buf;
+}
+
+void save_sainfotree(void){
+	sitree_save=sitree;
+	initsainfo();
+}
+
+void save_sainfotree_flush(void){
+	sitree_tmp=sitree;
+	sitree=sitree_save;
+	flushsainfo();
+	sitree=sitree_tmp;
+}
+
+void save_sainfotree_restore(void){
+	flushsainfo();
+	sitree=sitree_save;
+}
diff --git a/src/racoon/sainfo.h b/src/racoon/sainfo.h
new file mode 100644
index 0000000..357da3f
--- /dev/null
+++ b/src/racoon/sainfo.h
@@ -0,0 +1,88 @@
+/*	$NetBSD: sainfo.h,v 1.5 2006/10/03 08:01:56 vanhu Exp $	*/
+
+/* Id: sainfo.h,v 1.5 2006/07/09 17:19:38 manubsd Exp */
+
+/*
+ * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _SAINFO_H
+#define _SAINFO_H
+
+#include <sys/queue.h>
+
+/* SA info */
+struct sainfo {
+	vchar_t *idsrc;
+	vchar_t *iddst;
+		/*
+		 * idsrc and iddst are constructed body of ID payload.
+		 * that is (struct ipsecdoi_id_b) + ID value.
+		 * If idsrc == NULL, that is anonymous entry.
+		 */
+
+#ifdef ENABLE_HYBRID
+	vchar_t *group;
+#endif
+
+	time_t lifetime;
+	int lifebyte;
+	int pfs_group;		/* only use when pfs is required. */
+	vchar_t *id_i;		/* identifier of the authorized initiator */
+	struct sainfoalg *algs[MAXALGCLASS];
+
+	int remoteid;
+
+	LIST_ENTRY(sainfo) chain;
+};
+
+/* algorithm type */
+struct sainfoalg {
+	int alg;
+	int encklen;			/* key length if encryption algorithm */
+	struct sainfoalg *next;
+};
+
+extern struct sainfo *getsainfo __P((const vchar_t *,
+	const vchar_t *, const vchar_t *, int));
+extern struct sainfo *newsainfo __P((void));
+extern void delsainfo __P((struct sainfo *));
+extern void inssainfo __P((struct sainfo *));
+extern void remsainfo __P((struct sainfo *));
+extern void flushsainfo __P((void));
+extern void initsainfo __P((void));
+extern struct sainfoalg *newsainfoalg __P((void));
+extern void delsainfoalg __P((struct sainfoalg *));
+extern void inssainfoalg __P((struct sainfoalg **, struct sainfoalg *));
+extern const char * sainfo2str __P((const struct sainfo *));
+
+extern void save_sainfotree __P((void));
+extern void save_sainfotree_flush __P((void));
+extern void save_sainfotree_restore __P((void));
+
+#endif /* _SAINFO_H */
diff --git a/src/racoon/samples/psk.txt.in b/src/racoon/samples/psk.txt.in
new file mode 100644
index 0000000..52f1a55
--- /dev/null
+++ b/src/racoon/samples/psk.txt.in
@@ -0,0 +1,21 @@
+# IPv4/v6 addresses
+10.160.94.3	mekmitasdigoat
+172.16.1.133	mekmitasdigoat
+194.100.55.1	whatcertificatereally
+203.178.141.208	mekmitasdigoat
+206.175.160.18	mekmitasdigoat
+206.175.160.20	mekmitasdigoat
+206.175.160.21	mekmitasdigoat
+206.175.160.22	mekmitasdigoat
+206.175.160.23	mekmitasdigoat
+206.175.160.36	mekmitasdigoat
+206.175.161.125	mekmitasdigoat
+206.175.161.154	mekmitasdigoat
+206.175.161.156	mekmitasdigoat
+206.175.161.182	mekmitasdigoat
+3ffe:501:410:ffff:200:86ff:fe05:80fa	mekmitasdigoat
+3ffe:501:410:ffff:210:4bff:fea2:8baa	mekmitasdigoat
+# USER_FQDN
+sakane@kame.net	mekmitasdigoat
+# FQDN
+kame		hoge
diff --git a/src/racoon/samples/psk.txt.sample b/src/racoon/samples/psk.txt.sample
new file mode 100644
index 0000000..2ad1d0b
--- /dev/null
+++ b/src/racoon/samples/psk.txt.sample
@@ -0,0 +1,10 @@
+# IPv4/v6 addresses
+10.160.94.3	mekmitasdigoat
+172.16.1.133	0x12345678
+194.100.55.1	whatcertificatereally
+3ffe:501:410:ffff:200:86ff:fe05:80fa	mekmitasdigoat
+3ffe:501:410:ffff:210:4bff:fea2:8baa	mekmitasdigoat
+# USER_FQDN
+foo@kame.net	mekmitasdigoat
+# FQDN
+foo.kame.net	hoge
diff --git a/src/racoon/samples/racoon.conf.in b/src/racoon/samples/racoon.conf.in
new file mode 100644
index 0000000..29b7951
--- /dev/null
+++ b/src/racoon/samples/racoon.conf.in
@@ -0,0 +1,121 @@
+# $KAME: racoon.conf.in,v 1.18 2001/08/16 06:33:40 itojun Exp $
+
+# "path" affects "include" directives.  "path" must be specified before any
+# "include" directive with relative file path.
+# you can overwrite "path" directive afterwards, however, doing so may add
+# more confusion.
+path include "@sysconfdir_x@/racoon";
+#include "remote.conf";
+
+# the file should contain key ID/key pairs, for pre-shared key authentication.
+path pre_shared_key "@sysconfdir_x@/racoon/psk.txt";
+
+# racoon will look for certificate file in the directory,
+# if the certificate/certificate request payload is received.
+path certificate "@sysconfdir_x@/cert";
+
+# "log" specifies logging level.  It is followed by either "notify", "debug"
+# or "debug2".
+#log debug;
+
+# "padding" defines some padding parameters.  You should not touch these.
+padding
+{
+	maximum_length 20;	# maximum padding length.
+	randomize off;		# enable randomize length.
+	strict_check off;	# enable strict check.
+	exclusive_tail off;	# extract last one octet.
+}
+
+# if no listen directive is specified, racoon will listen on all
+# available interface addresses.
+listen
+{
+	#isakmp ::1 [7000];
+	#isakmp 202.249.11.124 [500];
+	#admin [7002];		# administrative port for racoonctl.
+	#strict_address; 	# requires that all addresses must be bound.
+}
+
+# Specify various default timers.
+timer
+{
+	# These value can be changed per remote node.
+	counter 5;		# maximum trying count to send.
+	interval 20 sec;	# maximum interval to resend.
+	persend 1;		# the number of packets per send.
+
+	# maximum time to wait for completing each phase.
+	phase1 30 sec;
+	phase2 15 sec;
+}
+
+remote anonymous
+{
+	exchange_mode main,aggressive;
+	doi ipsec_doi;
+	situation identity_only;
+
+	my_identifier asn1dn;
+	certificate_type x509 "my.cert.pem" "my.key.pem";
+
+	nonce_size 16;
+	initial_contact on;
+	proposal_check strict;	# obey, strict, or claim
+
+	proposal {
+		encryption_algorithm 3des;
+		hash_algorithm sha1;
+		authentication_method rsasig;
+		dh_group 2;
+	}
+}
+
+remote ::1 [8000]
+{
+	#exchange_mode main,aggressive;
+	exchange_mode aggressive,main;
+	doi ipsec_doi;
+	situation identity_only;
+
+	my_identifier user_fqdn "sakane@kame.net";
+	peers_identifier user_fqdn "sakane@kame.net";
+	#certificate_type x509 "mycert" "mypriv";
+
+	nonce_size 16;
+	lifetime time 1 min;	# sec,min,hour
+
+	proposal {
+		encryption_algorithm 3des;
+		hash_algorithm sha1;
+		authentication_method pre_shared_key;
+		dh_group 2;
+	}
+}
+
+sainfo anonymous
+{
+	pfs_group 2;
+	encryption_algorithm 3des;
+	authentication_algorithm hmac_sha1;
+	compression_algorithm deflate;
+}
+
+sainfo address 203.178.141.209 any address 203.178.141.218 any
+{
+	pfs_group 2;
+	lifetime time 30 sec;
+	encryption_algorithm des;
+	authentication_algorithm hmac_md5;
+	compression_algorithm deflate;
+}
+
+sainfo address ::1 icmp6 address ::1 icmp6
+{
+	pfs_group 3;
+	lifetime time 60 sec;
+	encryption_algorithm 3des, blowfish, aes;
+	authentication_algorithm hmac_sha1, hmac_md5;
+	compression_algorithm deflate;
+}
+
diff --git a/src/racoon/samples/racoon.conf.sample b/src/racoon/samples/racoon.conf.sample
new file mode 100644
index 0000000..631910f
--- /dev/null
+++ b/src/racoon/samples/racoon.conf.sample
@@ -0,0 +1,61 @@
+# $KAME: racoon.conf.sample,v 1.28 2002/10/18 14:33:28 itojun Exp $
+
+# "path" affects "include" directives.  "path" must be specified before any
+# "include" directive with relative file path.
+# you can overwrite "path" directive afterwards, however, doing so may add
+# more confusion.
+#path include "/usr/local/v6/etc" ;
+#include "remote.conf" ;
+
+# the file should contain key ID/key pairs, for pre-shared key authentication.
+path pre_shared_key "/usr/local/v6/etc/psk.txt" ;
+
+# racoon will look for certificate file in the directory,
+# if the certificate/certificate request payload is received.
+#path certificate "/usr/local/openssl/certs" ;
+
+# "log" specifies logging level.  It is followed by either "notify", "debug"
+# or "debug2".
+#log debug;
+
+remote anonymous
+{
+	#exchange_mode main,aggressive,base;
+	exchange_mode main,base;
+
+	#my_identifier fqdn "server.kame.net";
+	#certificate_type x509 "foo@kame.net.cert" "foo@kame.net.priv" ;
+
+	lifetime time 24 hour ;	# sec,min,hour
+
+	#initial_contact off ;
+	#passive on ;
+
+	# phase 1 proposal (for ISAKMP SA)
+	proposal {
+		encryption_algorithm 3des;
+		hash_algorithm sha1;
+		authentication_method pre_shared_key ;
+		dh_group 2 ;
+	}
+
+	# the configuration could makes racoon (as a responder)
+	# to obey the initiator's lifetime and PFS group proposal,
+	# by setting proposal_check to obey.
+	# this would makes testing "so much easier", but is really
+	# *not* secure !!!
+	proposal_check strict;
+}
+
+# phase 2 proposal (for IPsec SA).
+# actual phase 2 proposal will obey the following items:
+# - kernel IPsec policy configuration (like "esp/transport//use)
+# - permutation of the crypto/hash/compression algorithms presented below
+sainfo anonymous
+{
+	pfs_group 2;
+	lifetime time 12 hour ;
+	encryption_algorithm 3des, cast128, blowfish 448, des, rijndael ;
+	authentication_algorithm hmac_sha1, hmac_md5 ;
+	compression_algorithm deflate ;
+}
diff --git a/src/racoon/samples/racoon.conf.sample-gssapi b/src/racoon/samples/racoon.conf.sample-gssapi
new file mode 100644
index 0000000..09c4df1
--- /dev/null
+++ b/src/racoon/samples/racoon.conf.sample-gssapi
@@ -0,0 +1,43 @@
+# $KAME: racoon.conf.sample-gssapi,v 1.5 2001/08/16 06:33:40 itojun Exp $
+
+# sample configuration for GSSAPI authentication (basically, Kerberos).
+# doc/README.gssapi gives some idea on how to configure it.
+# TODO: more documentation.
+
+#listen {
+#	strict_address;
+#}
+
+# Uncomment the following for GSS-API to work with older versions of
+# racoon that (incorrectly) used ISO-Latin-1 encoding for the GSS-API
+# identifier attribute.
+#gss_id_enc latin1;
+
+remote anonymous {
+	exchange_mode main;
+
+	lifetime time 24 hour;
+
+	proposal {
+		encryption_algorithm 3des;
+		hash_algorithm sha1;
+		authentication_method gssapi_krb;
+		# The default GSS-API ID is "host/hostname", where
+		# hostname is the output of the hostname(1) command.
+		# You probably want this to match your system's host
+		# principal.  ktutil(8)'s "list" command will list the
+		# principals in your system's keytab.  If you need to,
+		# you can change the GSS-API ID here.
+		#gss_id "host/some.host.name";
+
+		dh_group 1;
+	}
+}
+
+sainfo anonymous {
+	lifetime time 2 hour;
+
+	encryption_algorithm rijndael, 3des;
+	authentication_algorithm hmac_sha1, hmac_md5;
+	compression_algorithm deflate;
+}
diff --git a/src/racoon/samples/racoon.conf.sample-inherit b/src/racoon/samples/racoon.conf.sample-inherit
new file mode 100644
index 0000000..9e1185f
--- /dev/null
+++ b/src/racoon/samples/racoon.conf.sample-inherit
@@ -0,0 +1,55 @@
+# Id: racoon.conf.sample-inherit,v 1.3 2005/12/13 16:41:07 vanhu Exp
+# Contributed by: Michal Ludvig <mludvig@suse.cz>, SUSE Labs
+
+# This file shows the basic inheritance usage in 'remote' statements.
+
+path pre_shared_key "/etc/racoon/psk.txt";
+path certificate "/etc/racoon";
+
+remote anonymous
+{
+	exchange_mode main,aggressive;
+	doi ipsec_doi;
+	situation identity_only;
+
+	my_identifier asn1dn;
+	certificate_type x509 "my.cert.pem" "my.key.pem";
+
+	nonce_size 16;
+	initial_contact on;
+	proposal_check strict;	# obey, strict or claim
+
+	proposal {
+		encryption_algorithm 3des;
+		hash_algorithm sha1;
+		authentication_method rsasig;
+		dh_group 2;
+	}
+}
+
+remote 3ffe:ffff::1 inherit anonymous
+{
+	exchange_mode aggressive;
+	nat_traversal force;
+}
+
+remote 3ffe:ffff::1 [8000] inherit 3ffe:ffff::1
+{
+	lifetime time 1 min;	# sec,min,hour
+
+	proposal {
+		encryption_algorithm 3des;
+		hash_algorithm sha1;
+		authentication_method pre_shared_key;
+		dh_group 2;
+	}
+}
+
+sainfo anonymous
+{
+	pfs_group 2;
+	lifetime time 12 hour;
+	encryption_algorithm aes, 3des;
+	authentication_algorithm hmac_sha1, hmac_md5;
+	compression_algorithm deflate;
+}
diff --git a/src/racoon/samples/racoon.conf.sample-natt b/src/racoon/samples/racoon.conf.sample-natt
new file mode 100644
index 0000000..645b4de
--- /dev/null
+++ b/src/racoon/samples/racoon.conf.sample-natt
@@ -0,0 +1,97 @@
+# Id: racoon.conf.sample-natt,v 1.5 2005/12/13 16:41:07 vanhu Exp
+# Contributed by: Michal Ludvig <mludvig@suse.cz>, SUSE Labs
+
+# This file can be used as a template for NAT-Traversal setups.
+# Only NAT-T related options are explained here, refer to other 
+# sample files and manual pages for details about the rest.
+
+path include "/etc/racoon";
+path certificate "/etc/racoon/cert";
+
+# Define addresses and ports where racoon will listen for an incoming
+# traffic. Don't forget to open these ports on your firewall!
+listen
+{
+	# First define an address where racoon will listen 
+	# for "normal" IKE traffic. IANA allocated port 500.
+	isakmp 172.16.0.1[500];
+
+	# To use NAT-T you must also open port 4500 of 
+	# the same address so that peers can do 'Port floating'.
+	# The same port will also be used for the UDP-Encapsulated 
+	# ESP traffic.
+	isakmp_natt 172.16.0.1[4500];
+}
+
+
+timer
+{
+	# To keep the NAT-mappings on your NAT gateway, there must be
+	# traffic between the peers. Normally the UDP-Encap traffic
+	# (i.e. the real data transported over the tunnel) would be
+	# enough, but to be safe racoon will send a short
+	# "Keep-alive packet" every few seconds to every peer with
+	# whom it does NAT-Traversal.
+	# The default is 20s. Set it to 0s to disable sending completely.
+	natt_keepalive 10 sec;
+}
+
+# To trigger the SA negotiation there must be an appropriate 
+# policy in the kernel SPD. For example for traffic between 
+# networks 192.168.0.0/24 and 192.168.1.0/24 with gateways 
+# 172.16.0.1 and 172.16.1.1, where the first gateway is behind 
+# a NAT which translates its address to 172.16.1.3, you need the 
+# following rules:
+# On 172.16.0.1 (e.g. behind the NAT):
+#     spdadd 192.168.0.0/24 192.168.1.0/24 any -P out ipsec \
+#            esp/tunnel/172.16.0.1-172.16.1.1/require;
+#     spdadd 192.168.1.0/24 192.168.0.0/24 any -P in ipsec \
+#            esp/tunnel/172.16.1.1-172.16.0.1/require;
+# On the other side (172.16.1.1) either use a "generate_policy on"
+# statement in the remote block, or in case that you know 
+# the translated address, use the following policy:
+#     spdadd 192.168.1.0/24 192.168.0.0/24 any -P out ipsec \
+#            esp/tunnel/172.16.1.1-172.16.1.3/require;
+#     spdadd 192.168.0.0/24 192.168.1.0/24 any -P in ipsec \
+#            esp/tunnel/172.16.1.3-172.16.1.1/require;
+
+# Phase 1 configuration (for ISAKMP SA)
+remote anonymous
+{
+	# NAT-T is supported with all exchange_modes.
+	exchange_mode main,base,aggressive;
+
+	# With NAT-T you shouldn't use PSK. Let's go on with certs.
+	my_identifier asn1dn;
+	certificate_type x509 "your-host.cert.pem" "your-host.key.pem";
+
+	# This is the main switch that enables NAT-T.
+	# Possible values are:
+	#   off - NAT-T support is disabled, i.e. neither offered,
+	#         nor accepted. This is the default.
+	#    on - normal NAT-T support, i.e. if NAT is detected 
+	#         along the way, NAT-T is used.
+	# force - if NAT-T is supported by both peers, it is used
+	#         regardless of whether there is a NAT gateway between them
+	#         or not. This is useful for traversing some firewalls.
+	nat_traversal on;
+	
+	proposal {
+		authentication_method rsasig;
+		encryption_algorithm 3des;
+		hash_algorithm sha1;
+		dh_group 2;
+	}
+
+	proposal_check strict;
+}
+
+# Phase 2 proposal (for IPsec SA)
+sainfo anonymous
+{
+	pfs_group 2;
+	lifetime time 12 hour;
+	encryption_algorithm 3des, rijndael;
+	authentication_algorithm hmac_sha1;
+	compression_algorithm deflate;
+}
diff --git a/src/racoon/samples/racoon.conf.sample-plainrsa b/src/racoon/samples/racoon.conf.sample-plainrsa
new file mode 100644
index 0000000..8447eb3
--- /dev/null
+++ b/src/racoon/samples/racoon.conf.sample-plainrsa
@@ -0,0 +1,46 @@
+# Id: racoon.conf.sample-plainrsa,v 1.4 2005/12/13 16:41:07 vanhu Exp
+# Contributed by: Michal Ludvig <mludvig@suse.cz>, SUSE Labs
+#                 http://www.logix.cz/michal
+
+# This file shows the usage of PlainRSA keys, which are widely used
+# by FreeSWAN/OpenSwan/StrongSwan/*Swan users. This functionality is 
+# here mainly for those who are moving from the *Swan world to Racoon.
+
+# Racoon will look for a keyfile in this directory.
+path certificate "samples" ;
+
+remote anonymous
+{
+	# *Swan supports only 'main' mode.
+	exchange_mode main;
+
+	# *Swan doesn't send identifiers by default.
+	my_identifier address;
+	peers_identifier address;
+
+	# This is the trick - use PlainRSA certificates.
+	certificate_type plain_rsa "privatekey.rsa";
+
+	# Multiple certfiles are supported.
+	peers_certfile plain_rsa "pubkey1.rsa";
+	peers_certfile plain_rsa "pubkey2.rsa";
+
+	# Standard setup follows...
+	proposal_check strict;
+
+	proposal {
+		encryption_algorithm 3des;
+		hash_algorithm sha1;
+		authentication_method rsasig;
+		dh_group 2;
+	}
+}
+
+sainfo anonymous
+{
+	pfs_group 2;
+	lifetime time 12 hour;
+	encryption_algorithm 3des, aes;
+	authentication_algorithm hmac_sha1, hmac_md5;
+	compression_algorithm deflate;
+}
diff --git a/src/racoon/samples/roadwarrior/README b/src/racoon/samples/roadwarrior/README
new file mode 100644
index 0000000..aac9d43
--- /dev/null
+++ b/src/racoon/samples/roadwarrior/README
@@ -0,0 +1,67 @@
+This directory contains sample configurations files used for roadwarrior
+remote access using hybrid authentication. In this setup, the VPN 
+gateway authenticates to the client using a certificate, and the client
+authenticates to the VPN gateway using a login and a password.
+
+Moreover, this setup makes use of ISAKMP mode config to autoconfigure 
+the client. After a successful login, the client will receive an 
+internal address, netmask and DNS from the VPN gateway.
+
+
+Server setups
+=============
+The server setups need racoon built with the following options:
+configure --enable-natt --enable-frag --enable-hybrid --enable-dpd \
+	  --with-libradius --sysconfdir=/etc/racoon
+
+The first server setup, in server/racoon.conf, is for a VPN gateway 
+using authentication against the system password database, and using 
+a locally configured pool of addresses. 
+
+The second setup, server/racoon.conf-radius, uses a RADIUS server for 
+authentication, IP allocation and accounting. The address and secret
+to be used for the RADIUS server are configured in /etc/radius.conf, 
+see radius.conf(5).
+
+Both configurations can be used with the Cisco VPN client if it
+is set up to use hybrid authentication (aka mutual group authentication,
+available in Cisco VPN client version 4.0.5 and above). The group 
+password configured in the Cisco VPN client is not used by racoon.
+
+After you have installed /etc/racoon/racoon.conf, you will also have 
+to install a server certificate and key in /etc/openssl/certs/server.crt
+and /etc/openssl/certs/server.key
+
+
+Client setup
+============
+The client setup needs racoon built with the following options:
+configure --enable-natt --enable-frag --enable-hybrid --enable-dpd \
+	  --enable-adminport --sysconfdir=/etc/racoon --localstatedir=/var
+
+You need to copy client/racoon.conf, client/phase1-up.sh and
+client/phase1-down.sh to /etc/racoon, and you need to copy the 
+certificate authority that signed the VPN gateway certificate in
+/etc/openssl/certs/root-ca.crt
+
+Once this is done, you can run racoon, and then you can start
+the VPN using racoonctl:
+racoonctl vc -u username vpn-gateway.example.net
+
+Where username is your login, and vpn-gateway.example.net is
+the DNS or IP address of the VPN gateway. racoonctl will prompt 
+you for the password.
+
+The password can be stored in the psk.txt file. In that situation, 
+add this directive to the remote section of racoon.conf:
+	 xauth_login "username";
+where username is your login.
+
+Note that for now there is no feedback in racoonctl if the authentication
+fails. Peek at the racoon logs to discover what goes wrong.
+
+In order to disconnect from the VPN, do this:
+racoonctl vd vpn-gateway.example.net
+
+This configuration should be compatible with the Cisco VPN 3000 using 
+hybrid authentication, though this has not been tested.
diff --git a/src/racoon/samples/roadwarrior/client/phase1-down.sh b/src/racoon/samples/roadwarrior/client/phase1-down.sh
new file mode 100755
index 0000000..8edc187
--- /dev/null
+++ b/src/racoon/samples/roadwarrior/client/phase1-down.sh
@@ -0,0 +1,73 @@
+#!/bin/sh
+
+#
+# sa-down.sh local configuration for a new SA
+#
+
+PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin
+
+case `uname -s` in
+NetBSD)
+	DEFAULT_GW=`netstat -rn | awk '($1 == "default"){print $2}'`
+	;;
+Linux)
+	DEFAULT_GW=`netstat -rn | awk '($1 == "0.0.0.0"){print $2}'`
+	;;
+esac
+
+echo $@
+echo "LOCAL_ADDR = ${LOCAL_ADDR}"
+echo "LOCAL_PORT = ${LOCAL_PORT}"
+echo "REMOTE_ADDR = ${REMOTE_ADDR}"
+echo "REMOTE_PORT = ${REMOTE_PORT}"
+echo "DEFAULT_GW = ${DEFAULT_GW}"
+echo "INTERNAL_ADDR4 = ${INTERNAL_ADDR4}"
+echo "INTERNAL_DNS4 = ${INTERNAL_DNS4}"
+
+echo ${INTERNAL_ADDR4} | grep '[0-9]' > /dev/null || exit 0
+echo ${DEFAULT_GW} | grep '[0-9]' > /dev/null || exit 0
+
+test -f /etc/resolv.conf.bak && cp /etc/resolv.conf.bak /etc/resolv.conf
+
+case `uname -s` in
+NetBSD)
+	if=`netstat -rn|awk '($1 == "default"){print $7}'`
+	ifconfig ${if} delete ${INTERNAL_ADDR4}
+	route delete default
+	route delete ${REMOTE_ADDR}
+	route add default ${DEFAULT_GW} -ifa ${LOCAL_ADDR}
+	;;
+Linux)
+	if=`netstat -rn|awk '($1 == "0.0.0.0"){print $8}'`
+	route delete default
+	route delete ${REMOTE_ADDR}
+	ifconfig ${if}:1 del ${INTERNAL_ADDR4}
+	route add default gw ${DEFAULT_GW}
+
+	#
+	# XXX This is a workaround because Linux seems to ignore
+	# the deleteall commands below. This is bad because it flushes
+	# any SAD instead of flushing what needs to be flushed.
+	# Someone using Linux please fix it
+	#
+	setkey -F
+	;;
+esac
+
+# Use this for a NAT-T setup
+LOCAL="${LOCAL_ADDR}[${LOCAL_PORT}]"
+REMOTE="${REMOTE_ADDR}[${REMOTE_PORT}]"
+
+# Use this for a non NAT-T setup
+#LOCAL="${LOCAL_ADDR}"
+#REMOTE="${REMOTE_ADDR}"
+
+echo "
+deleteall ${REMOTE_ADDR} ${LOCAL_ADDR} esp;
+deleteall ${LOCAL_ADDR} ${REMOTE_ADDR} esp; 
+spddelete ${INTERNAL_ADDR4}/32[any] 0.0.0.0/0[any] any
+	-P out ipsec esp/tunnel/${LOCAL}-${REMOTE}/require;
+spddelete 0.0.0.0/0[any] ${INTERNAL_ADDR4}[any] any
+	-P in ipsec esp/tunnel/${REMOTE}-${LOCAL}/require;
+" | setkey -c
+
diff --git a/src/racoon/samples/roadwarrior/client/phase1-up.sh b/src/racoon/samples/roadwarrior/client/phase1-up.sh
new file mode 100755
index 0000000..e45b648
--- /dev/null
+++ b/src/racoon/samples/roadwarrior/client/phase1-up.sh
@@ -0,0 +1,77 @@
+#!/bin/sh
+
+#
+# sa-up.sh local configuration for a new SA
+#
+PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin
+
+case `uname -s` in
+NetBSD)
+	DEFAULT_GW=`netstat -rn | awk '($1 == "default"){print $2}'`
+	;;
+Linux)
+	DEFAULT_GW=`netstat -rn | awk '($1 == "0.0.0.0"){print $2}'`
+	;;
+esac
+
+echo $@
+echo "LOCAL_ADDR = ${LOCAL_ADDR}"
+echo "LOCAL_PORT = ${LOCAL_PORT}"
+echo "REMOTE_ADDR = ${REMOTE_ADDR}"
+echo "REMOTE_PORT = ${REMOTE_PORT}"
+echo "DEFAULT_GW = ${DEFAULT_GW}"
+echo "INTERNAL_ADDR4 = ${INTERNAL_ADDR4}"
+echo "INTERNAL_DNS4 = ${INTERNAL_DNS4}"
+
+echo ${INTERNAL_ADDR4} | grep '[0-9]' > /dev/null || exit 0
+echo ${DEFAULT_GW} | grep '[0-9]' > /dev/null || exit 0
+
+test -f /etc/resolv.conf.bak || cp /etc/resolv.conf /etc/resolv.conf.bak
+echo "# Generated by racoon on `date`" > /etc/resolv.conf
+echo "nameserver ${INTERNAL_DNS4}" >> /etc/resolv.conf
+
+case `uname -s` in
+NetBSD)
+	if=`netstat -rn|awk '($1 == "default"){print $7}'`
+	ifconfig ${if} alias ${INTERNAL_ADDR4} netmask ${INTERNAL_NETMASK4}
+	route delete default
+	route add default ${DEFAULT_GW} -ifa ${INTERNAL_ADDR4}
+	route add ${REMOTE_ADDR} ${DEFAULT_GW}
+	;;
+Linux)
+	if=`netstat -rn|awk '($1 == "0.0.0.0"){print $8}'`
+	ifconfig ${if}:1 ${INTERNAL_ADDR4}      
+	route delete default
+	route add ${REMOTE_ADDR} gw ${DEFAULT_GW} dev ${if}
+	route add default gw ${DEFAULT_GW} dev ${if}:1
+	;;
+esac
+
+# Use this for a NAT-T setup
+LOCAL="${LOCAL_ADDR}[${LOCAL_PORT}]"
+REMOTE="${REMOTE_ADDR}[${REMOTE_PORT}]"
+
+# Use this for a non NAT-T setup
+#LOCAL="${LOCAL_ADDR}"
+#REMOTE="${REMOTE_ADDR}"
+
+
+echo "
+spdadd ${INTERNAL_ADDR4}/32[any] 0.0.0.0/0[any] any
+       -P out ipsec esp/tunnel/${LOCAL}-${REMOTE}/require;
+spdadd 0.0.0.0/0[any] ${INTERNAL_ADDR4}[any] any
+       -P in ipsec esp/tunnel/${REMOTE}-${LOCAL}/require;
+" | setkey -c
+
+#
+# XXX This is a workaround for Linux forward policies problem. 
+# Someone familiar with forward policies please fix this properly.
+#
+case `uname -s` in
+Linux)
+	echo "
+	spddelete 0.0.0.0/0[any] ${INTERNAL_ADDR4}[any] any
+		-P fwd ipsec esp/tunnel/${REMOTE}-${LOCAL}/require;
+	" | setkey -c
+	;;
+esac
diff --git a/src/racoon/samples/roadwarrior/client/racoon.conf b/src/racoon/samples/roadwarrior/client/racoon.conf
new file mode 100644
index 0000000..669be36
--- /dev/null
+++ b/src/racoon/samples/roadwarrior/client/racoon.conf
@@ -0,0 +1,33 @@
+path certificate "/etc/openssl/certs";
+path pre_shared_key "/etc/racoon/psk.txt";
+
+listen {
+	adminsock "/var/racoon/racoon.sock" "root" "operator" 0660;
+}
+
+remote 192.0.2.50 {
+        exchange_mode aggressive;
+	ca_type x509 "root-ca.crt";
+        proposal_check strict;
+	nat_traversal on;
+	ike_frag on;
+	mode_cfg on;
+	script "/etc/racoon/phase1-up.sh" phase1_up;
+	script "/etc/racoon/phase1-down.sh" phase1_down;
+	passive off;
+        proposal {
+                encryption_algorithm aes;
+                hash_algorithm sha1;
+                authentication_method hybrid_rsa_client;
+                dh_group 2;
+        }
+}
+
+
+sainfo anonymous {
+        pfs_group 2;
+        lifetime time 1 hour;
+        encryption_algorithm aes;
+        authentication_algorithm hmac_sha1;
+        compression_algorithm deflate ;
+}
diff --git a/src/racoon/samples/roadwarrior/server/racoon.conf b/src/racoon/samples/roadwarrior/server/racoon.conf
new file mode 100644
index 0000000..ae7d603
--- /dev/null
+++ b/src/racoon/samples/roadwarrior/server/racoon.conf
@@ -0,0 +1,42 @@
+path certificate "/etc/openssl/certs";
+
+listen {
+	adminsock disabled;
+}
+
+remote anonymous {
+	exchange_mode aggressive;
+	certificate_type x509 "server.crt" "server.key";
+	my_identifier asn1dn;
+	proposal_check strict;
+	generate_policy on;
+	nat_traversal on;
+	dpd_delay 20;
+	ike_frag on;
+	proposal {
+		encryption_algorithm aes;
+		hash_algorithm sha1;
+		authentication_method hybrid_rsa_server;
+		dh_group 2;
+	}
+}
+
+mode_cfg {
+	network4 10.99.99.0;
+	pool_size 255;
+	netmask4 255.255.255.0;  
+	auth_source system;
+	dns4 10.0.12.1;
+	wins4 10.0.12.1;
+	banner "/etc/racoon/motd";
+	pfs_group 2;
+}	       
+		
+sainfo anonymous {
+	pfs_group 2;
+	lifetime time 1 hour;
+	encryption_algorithm aes;
+	authentication_algorithm hmac_sha1;
+	compression_algorithm deflate;
+}   
+
diff --git a/src/racoon/samples/roadwarrior/server/racoon.conf-radius b/src/racoon/samples/roadwarrior/server/racoon.conf-radius
new file mode 100644
index 0000000..24e8d4e
--- /dev/null
+++ b/src/racoon/samples/roadwarrior/server/racoon.conf-radius
@@ -0,0 +1,42 @@
+path certificate "/etc/openssl/certs";
+
+listen {
+	adminsock disabled;
+}
+
+remote anonymous {
+	exchange_mode aggressive;
+	certificate_type x509 "server.crt" "server.key";
+	my_identifier asn1dn;
+	proposal_check strict;
+	generate_policy on;
+	nat_traversal on;
+	dpd_delay 20;
+	ike_frag on;
+	proposal {
+		encryption_algorithm aes;
+		hash_algorithm sha1;
+		authentication_method hybrid_rsa_server;
+		dh_group 2;
+	}
+}
+
+mode_cfg {
+	pool_size 255;
+	auth_source radius;
+	conf_source radius;
+	accounting radius;
+	dns4 10.0.12.1;
+	wins4 10.0.12.1;
+	banner "/etc/racoon/motd";
+	pfs_group 2;
+}	       
+		
+sainfo anonymous {
+	pfs_group 2;
+	lifetime time 1 hour;
+	encryption_algorithm aes;
+	authentication_algorithm hmac_sha1;
+	compression_algorithm deflate;
+}   
+
diff --git a/src/racoon/schedule.c b/src/racoon/schedule.c
new file mode 100644
index 0000000..04723c5
--- /dev/null
+++ b/src/racoon/schedule.c
@@ -0,0 +1,364 @@
+/*	$NetBSD: schedule.c,v 1.4 2006/09/09 16:22:10 manu Exp $	*/
+
+/*	$KAME: schedule.c,v 1.19 2001/11/05 10:53:19 sakane Exp $	*/
+
+/*
+ * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/time.h>
+#include <sys/queue.h>
+#include <sys/socket.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <time.h>
+
+#include "misc.h"
+#include "plog.h"
+#include "schedule.h"
+#include "var.h"
+#include "gcmalloc.h"
+
+#define FIXY2038PROBLEM
+
+#ifndef TAILQ_FOREACH
+#define TAILQ_FOREACH(elm, head, field) \
+        for (elm = TAILQ_FIRST(head); elm; elm = TAILQ_NEXT(elm, field))
+#endif
+
+static struct timeval timeout;
+
+#ifdef FIXY2038PROBLEM
+#define Y2038TIME_T	0x7fffffff
+static time_t launched;		/* time when the program launched. */
+static time_t deltaY2038;
+#endif
+
+static TAILQ_HEAD(_schedtree, sched) sctree;
+
+static void sched_add __P((struct sched *));
+static time_t current_time __P((void));
+
+/*
+ * schedule handler
+ * OUT:
+ *	time to block until next event.
+ *	if no entry, NULL returned.
+ */
+struct timeval *
+schedular()
+{
+	time_t now, delta;
+	struct sched *p, *next = NULL;
+
+	now = current_time();
+
+        for (p = TAILQ_FIRST(&sctree); p; p = next) {
+		/* if the entry has been daed, remove it */
+		if (p->dead)
+			goto next_schedule;
+
+		/* if the time hasn't come, proceed to the next entry */
+		if (now < p->xtime) {
+			next = TAILQ_NEXT(p, chain);
+			continue;
+		}
+
+		/* mark it with dead. and call the function. */
+		p->dead = 1;
+		if (p->func != NULL)
+			(p->func)(p->param);
+
+	   next_schedule:
+		next = TAILQ_NEXT(p, chain);
+		TAILQ_REMOVE(&sctree, p, chain);
+		racoon_free(p);
+	}
+
+	p = TAILQ_FIRST(&sctree);
+	if (p == NULL)
+		return NULL;
+
+	now = current_time();
+
+	delta = p->xtime - now;
+	timeout.tv_sec = delta < 0 ? 0 : delta;
+	timeout.tv_usec = 0;
+
+	return &timeout;
+}
+
+/*
+ * add new schedule to schedule table.
+ */
+struct sched *
+sched_new(tick, func, param)
+	time_t tick;
+	void (*func) __P((void *));
+	void *param;
+{
+	static long id = 1;
+	struct sched *new;
+
+	new = (struct sched *)racoon_malloc(sizeof(*new));
+	if (new == NULL)
+		return NULL;
+
+	memset(new, 0, sizeof(*new));
+	new->func = func;
+	new->param = param;
+
+	new->id = id++;
+	time(&new->created);
+	new->tick = tick;
+
+	new->xtime = current_time() + tick;
+	new->dead = 0;
+
+	/* add to schedule table */
+	sched_add(new);
+
+	return(new);
+}
+
+/* add new schedule to schedule table */
+static void
+sched_add(sc)
+	struct sched *sc;
+{
+	struct sched *p;
+
+	TAILQ_FOREACH(p, &sctree, chain) {
+		if (sc->xtime < p->xtime) {
+			TAILQ_INSERT_BEFORE(p, sc, chain);
+			return;
+		}
+	}
+	if (p == NULL)
+		TAILQ_INSERT_TAIL(&sctree, sc, chain);
+
+	return;
+}
+
+/* get current time.
+ * if defined FIXY2038PROBLEM, base time is the time when called sched_init().
+ * Otherwise, conform to time(3).
+ */
+static time_t
+current_time()
+{
+	time_t n;
+#ifdef FIXY2038PROBLEM
+	time_t t;
+
+	time(&n);
+	t = n - launched;
+	if (t < 0)
+		t += deltaY2038;
+
+	return t;
+#else
+	return time(&n);
+#endif
+}
+
+void
+sched_kill(sc)
+	struct sched *sc;
+{
+	sc->dead = 1;
+
+	return;
+}
+
+/* XXX this function is probably unnecessary. */
+void
+sched_scrub_param(param)
+	void *param;
+{
+	struct sched *sc;
+
+	TAILQ_FOREACH(sc, &sctree, chain) {
+		if (sc->param == param) {
+			if (!sc->dead) {
+				plog(LLV_DEBUG, LOCATION, NULL,
+				    "an undead schedule has been deleted.\n");
+			}
+			sched_kill(sc);
+		}
+	}
+}
+
+/*
+ * for debug
+ */
+int
+sched_dump(buf, len)
+	caddr_t *buf;
+	int *len;
+{
+	caddr_t new;
+	struct sched *p;
+	struct scheddump *dst;
+	int cnt = 0;
+
+	/* initialize */
+	*len = 0;
+	*buf = NULL;
+
+	TAILQ_FOREACH(p, &sctree, chain)
+		cnt++;
+
+	/* no entry */
+	if (cnt == 0)
+		return -1;
+
+	*len = cnt * sizeof(*dst);
+
+	new = racoon_malloc(*len);
+	if (new == NULL)
+		return -1;
+	dst = (struct scheddump *)new;
+
+        p = TAILQ_FIRST(&sctree);
+	while (p) {
+		dst->xtime = p->xtime;
+		dst->id = p->id;
+		dst->created = p->created;
+		dst->tick = p->tick;
+
+		p = TAILQ_NEXT(p, chain);
+		if (p == NULL)
+			break;
+		dst++;
+	}
+
+	*buf = new;
+
+	return 0;
+}
+
+/* initialize schedule table */
+void
+sched_init()
+{
+#ifdef FIXY2038PROBLEM
+	time(&launched);
+
+	deltaY2038 = Y2038TIME_T - launched;
+#endif
+
+	TAILQ_INIT(&sctree);
+
+	return;
+}
+
+#ifdef STEST
+#include <sys/types.h>
+#include <sys/time.h>
+#include <unistd.h>
+#include <err.h>
+
+void
+test(tick)
+	int *tick;
+{
+	printf("execute %d\n", *tick);
+	racoon_free(tick);
+}
+
+void
+getstdin()
+{
+	int *tick;
+	char buf[16];
+
+	read(0, buf, sizeof(buf));
+	if (buf[0] == 'd') {
+		struct scheddump *scbuf, *p;
+		int len;
+		sched_dump((caddr_t *)&scbuf, &len);
+		if (scbuf == NULL)
+			return;
+		for (p = scbuf; len; p++) {
+			printf("xtime=%ld\n", p->xtime);
+			len -= sizeof(*p);
+		}
+		racoon_free(scbuf);
+		return;
+	}
+
+	tick = (int *)racoon_malloc(sizeof(*tick));
+	*tick = atoi(buf);
+	printf("new queue tick = %d\n", *tick);
+	sched_new(*tick, test, tick);
+}
+
+int
+main()
+{
+	static fd_set mask0;
+	int nfds = 0;
+	fd_set rfds;
+	struct timeval *timeout;
+	int error;
+
+	FD_ZERO(&mask0);
+	FD_SET(0, &mask0);
+	nfds = 1;
+
+	/* initialize */
+	sched_init();
+
+	while (1) {
+		rfds = mask0;
+
+		timeout = schedular();
+
+		error = select(nfds, &rfds, (fd_set *)0, (fd_set *)0, timeout);
+		if (error < 0) {
+			switch (errno) {
+			case EINTR: continue;
+			default:
+				err(1, "select");
+			}
+			/*NOTREACHED*/
+		}
+
+		if (FD_ISSET(0, &rfds))
+			getstdin();
+	}
+}
+#endif
diff --git a/src/racoon/schedule.h b/src/racoon/schedule.h
new file mode 100644
index 0000000..bd66593
--- /dev/null
+++ b/src/racoon/schedule.h
@@ -0,0 +1,85 @@
+/*	$NetBSD: schedule.h,v 1.4.6.1 2007/03/21 14:29:48 vanhu Exp $	*/
+
+/* Id: schedule.h,v 1.5 2006/05/03 21:53:42 vanhu Exp */
+
+/*
+ * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _SCHEDULE_H
+#define _SCHEDULE_H
+
+#include <sys/queue.h>
+#include "gnuc.h"
+
+/* scheduling table */
+/* the head is the nearest event. */
+struct sched {
+	time_t xtime;		/* event time which is as time(3). */
+				/*
+				 * if defined FIXY2038PROBLEM, this time
+				 * is from the time when called sched_init().
+				 */
+	void (*func) __P((void *)); /* call this function when timeout. */
+	void *param;		/* pointer to parameter */
+
+	int dead;		/* dead or alive */
+	long id;		/* for debug */
+	time_t created;		/* for debug */
+	time_t tick;		/* for debug */
+
+	TAILQ_ENTRY(sched) chain;
+};
+
+/* cancel schedule */
+#define SCHED_KILL(s)                                                          \
+do {                                                                           \
+	if(s != NULL){	   														\
+		sched_kill(s);                                                         \
+		s = NULL;                                                              \
+	}\
+} while(0)
+
+/* must be called after it's called from scheduler. */
+#define SCHED_INIT(s)	(s) = NULL
+
+struct scheddump {
+	time_t xtime;
+	long id;
+	time_t created;
+	time_t tick;
+};
+
+struct timeval *schedular __P((void));
+struct sched *sched_new __P((time_t, void (*func) __P((void *)), void *));
+void sched_kill __P((struct sched *));
+int sched_dump __P((caddr_t *, int *));
+void sched_init __P((void));
+void sched_scrub_param __P((void *));
+
+#endif /* _SCHEDULE_H */
diff --git a/src/racoon/security.c b/src/racoon/security.c
new file mode 100644
index 0000000..e4b5a0d
--- /dev/null
+++ b/src/racoon/security.c
@@ -0,0 +1,265 @@
+/*
+ * Copyright (C) 2005 International Business Machines Corporation
+ * Copyright (c) 2005 by Trusted Computer Solutions, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+
+#include "config.h"
+
+#include <sys/types.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <selinux/selinux.h>
+#include <selinux/flask.h>
+#include <selinux/av_permissions.h>
+#include <selinux/avc.h>
+#include <selinux/context.h>
+
+#include "var.h"
+#include "vmbuf.h"
+#include "misc.h"
+#include "plog.h"
+
+#include "isakmp_var.h"
+#include "isakmp.h"
+#include "ipsec_doi.h"
+#include "policy.h"
+#include "proposal.h"
+#include "strnames.h"
+#include "handler.h"
+
+/* 
+ * Get the security context information from SA.
+ */
+int
+get_security_context(sa, p)
+	vchar_t *sa;
+	struct policyindex *p;
+{
+	int len = 0;
+	int flag, type = 0;
+	u_int16_t lorv;
+	caddr_t bp;
+	vchar_t *pbuf = NULL;
+	vchar_t *tbuf = NULL;
+	struct isakmp_parse_t *pa;
+	struct isakmp_parse_t *ta;
+	struct isakmp_pl_p *prop;
+	struct isakmp_pl_t *trns;
+	struct isakmp_data *d;
+	struct ipsecdoi_sa_b *sab = (struct ipsecdoi_sa_b *)sa->v;
+	
+	/* check SA payload size */
+	if (sa->l < sizeof(*sab)) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"Invalid SA length = %zu.\n", sa->l);
+		return -1;
+	}
+
+	bp = (caddr_t)(sab + 1); /* here bp points to first proposal payload */
+	len = sa->l - sizeof(*sab);
+
+	pbuf = isakmp_parsewoh(ISAKMP_NPTYPE_P, (struct isakmp_gen *)bp, len);
+	if (pbuf == NULL)
+		return -1;
+
+	pa = (struct isakmp_parse_t *)pbuf->v; 
+        /* check the value of next payload */
+	if (pa->type != ISAKMP_NPTYPE_P) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"Invalid payload type=%u\n", pa->type);
+		vfree(pbuf);
+		return -1;
+	}
+
+	if (pa->len == 0) {
+		plog(LLV_ERROR, LOCATION, NULL,
+		"invalid proposal with length %d\n", pa->len);
+		vfree(pbuf);
+		return -1;
+	}
+
+	/* our first proposal */
+	prop = (struct isakmp_pl_p *)pa->ptr;
+
+	/* now get transform */
+	bp = (caddr_t)prop + sizeof(struct isakmp_pl_p) + prop->spi_size;
+	len = ntohs(prop->h.len) - 
+		(sizeof(struct isakmp_pl_p) + prop->spi_size);
+	tbuf = isakmp_parsewoh(ISAKMP_NPTYPE_T, (struct isakmp_gen *)bp, len);
+	if (tbuf == NULL)
+		return -1;
+
+	ta = (struct isakmp_parse_t *)tbuf->v;
+	if (ta->type != ISAKMP_NPTYPE_T) {
+		plog(LLV_ERROR, LOCATION, NULL,
+		     "Invalid payload type=%u\n", ta->type);
+		return -1;
+	}
+	
+	trns = (struct isakmp_pl_t *)ta->ptr;
+
+	len = ntohs(trns->h.len) - sizeof(struct isakmp_pl_t);
+	d = (struct isakmp_data *)((caddr_t)trns + sizeof(struct isakmp_pl_t));
+
+	while (len > 0) {
+		type = ntohs(d->type) & ~ISAKMP_GEN_MASK;
+		flag = ntohs(d->type) & ISAKMP_GEN_MASK;
+		lorv = ntohs(d->lorv);
+
+		if (type != IPSECDOI_ATTR_SECCTX) {
+			if (flag) {
+				len -= sizeof(*d);
+				d = (struct isakmp_data *)((char *)d 
+				     + sizeof(*d));
+			} else {
+				len -= (sizeof(*d) + lorv);
+				d = (struct isakmp_data *)((caddr_t)d
+				     + sizeof(*d) + lorv);
+			}
+		} else {
+			flag = ntohs(d->type & ISAKMP_GEN_MASK);
+			if (flag) {
+				plog(LLV_ERROR, LOCATION, NULL,
+				     "SECCTX must be in TLV.\n");
+				return -1;
+			}
+			memcpy(&p->sec_ctx, d + 1, lorv);
+			p->sec_ctx.ctx_strlen = ntohs(p->sec_ctx.ctx_strlen);
+			return 0;
+		}
+	}
+	return 0;
+}
+
+void
+set_secctx_in_proposal(iph2, spidx)
+	struct ph2handle *iph2;
+	struct policyindex spidx;
+{
+	iph2->proposal->sctx.ctx_doi = spidx.sec_ctx.ctx_doi;
+	iph2->proposal->sctx.ctx_alg = spidx.sec_ctx.ctx_alg;
+	iph2->proposal->sctx.ctx_strlen = spidx.sec_ctx.ctx_strlen;
+		memcpy(iph2->proposal->sctx.ctx_str, spidx.sec_ctx.ctx_str,
+			spidx.sec_ctx.ctx_strlen);
+}
+
+
+/*
+ * function: 	init_avc
+ * description:	function performs the steps necessary to initialize the
+ *		userspace avc.
+ * input:	void
+ * return:	0	if avc was successfully initialized
+ * 		1	if the avc could not be initialized
+ */
+
+static int mls_ready = 0;
+
+void
+init_avc(void)
+{
+	if (!is_selinux_mls_enabled()) {
+		plog(LLV_ERROR, LOCATION, NULL, "racoon: MLS support is not"
+				" enabled.\n");
+		return;
+	}
+
+	if (avc_init("racoon", NULL, NULL, NULL, NULL) == 0)
+		mls_ready = 1;
+	else
+		plog(LLV_ERROR, LOCATION, NULL, 
+		     "racoon: could not initialize avc.\n");
+}
+
+/*
+ * function: 	within_range
+ * description:	function determines if the specified sl is within the
+ * 		configured range for a policy rule.
+ * input:	security_context *sl		SL
+ * 		char *range		Range
+ * return:	1	if the sl is within the range
+ * 		0	if the sl is not within the range or an error
+ * 			occurred which prevented the determination
+ */
+
+int
+within_range(security_context_t sl, security_context_t range)
+{
+	int rtn = 1;
+	security_id_t slsid;
+	security_id_t rangesid;
+	struct av_decision avd;
+	security_class_t tclass;
+	access_vector_t av;
+
+	if (!*range)	/* This policy doesn't have security context */
+		return 1;
+
+	if (!mls_ready)  /* mls may not be enabled */
+		return 0;
+
+	/*
+	 * Get the sids for the sl and range contexts
+	 */
+	rtn = avc_context_to_sid(sl, &slsid);
+	if (rtn != 0) {
+		plog(LLV_ERROR, LOCATION, NULL, 
+				"within_range: Unable to retrieve "
+				"sid for sl context (%s).\n", sl);
+		return 0;
+	}
+	rtn = avc_context_to_sid(range, &rangesid);
+	if (rtn != 0) {
+		plog(LLV_ERROR, LOCATION, NULL, 
+				"within_range: Unable to retrieve "
+				"sid for range context (%s).\n", range);
+		sidput(slsid);
+		return 0;
+	}
+
+	/* 
+	 * Straight up test between sl and range
+	 */
+	tclass = SECCLASS_ASSOCIATION;
+	av = ASSOCIATION__POLMATCH;
+	rtn = avc_has_perm(slsid, rangesid, tclass, av, NULL, &avd);
+	if (rtn != 0) {
+		plog(LLV_INFO, LOCATION, NULL, 
+			"within_range: The sl is not within range\n");
+		sidput(slsid);
+		sidput(rangesid);
+		return 0;
+	}
+	plog(LLV_DEBUG, LOCATION, NULL, 
+		"within_range: The sl (%s) is within range (%s)\n", sl, range);
+		return 1;
+}
diff --git a/src/racoon/session.c b/src/racoon/session.c
new file mode 100644
index 0000000..10463c9
--- /dev/null
+++ b/src/racoon/session.c
@@ -0,0 +1,596 @@
+/*	$NetBSD: session.c,v 1.7.6.2 2007/08/01 11:52:22 vanhu Exp $	*/
+
+/*	$KAME: session.c,v 1.32 2003/09/24 02:01:17 jinmei Exp $	*/
+
+/*
+ * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/time.h>
+#include <sys/socket.h>
+#if HAVE_SYS_WAIT_H
+# include <sys/wait.h>
+#endif
+#ifndef WEXITSTATUS
+# define WEXITSTATUS(s)	((unsigned)(s) >> 8)
+#endif
+#ifndef WIFEXITED
+# define WIFEXITED(s)	(((s) & 255) == 0)
+#endif
+
+#include PATH_IPSEC_H
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <signal.h>
+#include <sys/stat.h>
+#include <paths.h>
+
+#include <netinet/in.h>
+#include <resolv.h>
+#ifdef ANDROID_CHANGES
+#include <arpa/inet.h>
+#include <arpa_nameser.h>
+#endif
+
+#include "libpfkey.h"
+
+#include "var.h"
+#include "misc.h"
+#include "vmbuf.h"
+#include "plog.h"
+#include "debug.h"
+
+#include "schedule.h"
+#include "session.h"
+#include "grabmyaddr.h"
+#include "evt.h"
+#include "cfparse_proto.h"
+#include "isakmp_var.h"
+#include "isakmp_xauth.h"
+#include "isakmp_cfg.h"
+#include "admin_var.h"
+#include "admin.h"
+#include "privsep.h"
+#include "oakley.h"
+#include "pfkey.h"
+#include "handler.h"
+#include "localconf.h"
+#include "remoteconf.h"
+#include "backupsa.h"
+#ifdef ENABLE_NATT
+#include "nattraversal.h"
+#endif
+
+
+#include "algorithm.h" /* XXX ??? */
+
+#include "sainfo.h"
+
+static void close_session __P((void));
+static void check_rtsock __P((void *));
+static void initfds __P((void));
+static void init_signal __P((void));
+static int set_signal __P((int sig, RETSIGTYPE (*func) __P((int))));
+static void check_sigreq __P((void));
+static void check_flushsa_stub __P((void *));
+static void check_flushsa __P((void));
+static int close_sockets __P((void));
+
+static fd_set mask0;
+static fd_set maskdying;
+static int nfds = 0;
+static volatile sig_atomic_t sigreq[NSIG + 1];
+static int dying = 0;
+
+int
+session(void)
+{
+	fd_set rfds;
+	struct timeval *timeout;
+	int error;
+	struct myaddrs *p;
+	char pid_file[MAXPATHLEN];
+	FILE *fp;
+	pid_t racoon_pid = 0;
+	int i;
+
+	/* initialize schedular */
+	sched_init();
+
+	init_signal();
+
+#ifdef ENABLE_ADMINPORT
+	if (admin_init() < 0)
+		exit(1);
+#endif
+
+	initmyaddr();
+
+	if (isakmp_init() < 0)
+		exit(1);
+
+	initfds();
+
+#ifdef ENABLE_NATT
+	natt_keepalive_init ();
+#endif
+
+	if (privsep_init() != 0)
+		exit(1);
+
+	for (i = 0; i <= NSIG; i++)
+		sigreq[i] = 0;
+
+	/* write .pid file */
+	racoon_pid = getpid();
+	if (lcconf->pathinfo[LC_PATHTYPE_PIDFILE] == NULL) 
+		strlcpy(pid_file, _PATH_VARRUN "racoon.pid", MAXPATHLEN);
+	else if (lcconf->pathinfo[LC_PATHTYPE_PIDFILE][0] == '/') 
+		strlcpy(pid_file, lcconf->pathinfo[LC_PATHTYPE_PIDFILE], MAXPATHLEN);
+	else {
+		strlcat(pid_file, _PATH_VARRUN, MAXPATHLEN);
+		strlcat(pid_file, lcconf->pathinfo[LC_PATHTYPE_PIDFILE], MAXPATHLEN);
+	} 
+	fp = fopen(pid_file, "w");
+	if (fp) {
+		if (fchmod(fileno(fp),
+			S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) == -1) {
+			syslog(LOG_ERR, "%s", strerror(errno));
+			fclose(fp);
+			exit(1);
+		}
+		fprintf(fp, "%ld\n", (long)racoon_pid);
+		fclose(fp);
+	} else {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"cannot open %s", pid_file);
+	}
+
+	while (1) {
+		if (dying)
+			rfds = maskdying;
+		else
+			rfds = mask0;
+
+		/*
+		 * asynchronous requests via signal.
+		 * make sure to reset sigreq to 0.
+		 */
+		check_sigreq();
+
+		/* scheduling */
+		timeout = schedular();
+
+		error = select(nfds, &rfds, (fd_set *)0, (fd_set *)0, timeout);
+		if (error < 0) {
+			switch (errno) {
+			case EINTR:
+				continue;
+			default:
+				plog(LLV_ERROR, LOCATION, NULL,
+					"failed to select (%s)\n",
+					strerror(errno));
+				return -1;
+			}
+			/*NOTREACHED*/
+		}
+
+#ifdef ENABLE_ADMINPORT
+		if ((lcconf->sock_admin != -1) &&
+		    (FD_ISSET(lcconf->sock_admin, &rfds)))
+			admin_handler();
+#endif
+
+		for (p = lcconf->myaddrs; p; p = p->next) {
+			if (!p->addr)
+				continue;
+			if (FD_ISSET(p->sock, &rfds))
+				isakmp_handler(p->sock);
+		}
+
+		if (FD_ISSET(lcconf->sock_pfkey, &rfds))
+			pfkey_handler();
+
+		if (lcconf->rtsock >= 0 && FD_ISSET(lcconf->rtsock, &rfds)) {
+			if (update_myaddrs() && lcconf->autograbaddr)
+				check_rtsock(NULL);
+			else
+				initfds();
+		}
+	}
+}
+
+/* clear all status and exit program. */
+static void
+close_session()
+{
+#ifdef ENABLE_FASTQUIT
+	flushph2();
+#endif
+	flushph1();
+	close_sockets();
+	backupsa_clean();
+
+	plog(LLV_INFO, LOCATION, NULL, "racoon shutdown\n");
+	exit(0);
+}
+
+static void
+check_rtsock(unused)
+	void *unused;
+{
+	isakmp_close();
+	grab_myaddrs();
+	autoconf_myaddrsport();
+	isakmp_open();
+
+	/* initialize socket list again */
+	initfds();
+}
+
+static void
+initfds()
+{
+	struct myaddrs *p;
+
+	nfds = 0;
+
+	FD_ZERO(&mask0);
+	FD_ZERO(&maskdying);
+
+#ifdef ENABLE_ADMINPORT
+	if (lcconf->sock_admin != -1) {
+		if (lcconf->sock_admin >= FD_SETSIZE) {
+			plog(LLV_ERROR, LOCATION, NULL, "fd_set overrun\n");
+			exit(1);
+		}
+		FD_SET(lcconf->sock_admin, &mask0);
+		/* XXX should we listen on admin socket when dying ?
+		 */
+#if 0
+		FD_SET(lcconf->sock_admin, &maskdying);
+#endif
+		nfds = (nfds > lcconf->sock_admin ? nfds : lcconf->sock_admin);
+	}
+#endif
+	if (lcconf->sock_pfkey >= FD_SETSIZE) {
+		plog(LLV_ERROR, LOCATION, NULL, "fd_set overrun\n");
+		exit(1);
+	}
+	FD_SET(lcconf->sock_pfkey, &mask0);
+	FD_SET(lcconf->sock_pfkey, &maskdying);
+	nfds = (nfds > lcconf->sock_pfkey ? nfds : lcconf->sock_pfkey);
+	if (lcconf->rtsock >= 0) {
+		if (lcconf->rtsock >= FD_SETSIZE) {
+			plog(LLV_ERROR, LOCATION, NULL, "fd_set overrun\n");
+			exit(1);
+		}
+		FD_SET(lcconf->rtsock, &mask0);
+		nfds = (nfds > lcconf->rtsock ? nfds : lcconf->rtsock);
+	}
+
+	for (p = lcconf->myaddrs; p; p = p->next) {
+		if (!p->addr)
+			continue;
+		if (p->sock >= FD_SETSIZE) {
+			plog(LLV_ERROR, LOCATION, NULL, "fd_set overrun\n");
+			exit(1);
+		}
+		FD_SET(p->sock, &mask0);
+		nfds = (nfds > p->sock ? nfds : p->sock);
+	}
+	nfds++;
+}
+
+static int signals[] = {
+	SIGHUP,
+	SIGINT,
+	SIGTERM,
+	SIGUSR1,
+	SIGUSR2,
+	SIGCHLD,
+	0
+};
+
+/*
+ * asynchronous requests will actually dispatched in the
+ * main loop in session().
+ */
+RETSIGTYPE
+signal_handler(sig)
+	int sig;
+{
+	/* Do not just set it to 1, because we may miss some signals by just setting
+	 * values to 0/1
+	 */
+	sigreq[sig]++;
+}
+
+
+/* XXX possible mem leaks and no way to go back for now !!!
+ */
+static void reload_conf(){
+	int error;
+
+#ifdef ENABLE_HYBRID
+	if ((isakmp_cfg_init(ISAKMP_CFG_INIT_WARM)) != 0) {
+		plog(LLV_ERROR, LOCATION, NULL, 
+		    "ISAKMP mode config structure reset failed, "
+		    "not reloading\n");
+		return;
+	}
+#endif
+
+	save_sainfotree();
+
+	/* TODO: save / restore / flush old lcconf (?) / rmtree
+	 */
+/*	initlcconf();*/ /* racoon_conf ? ! */
+
+	save_rmconf();
+	initrmconf();
+
+	/* Do a part of pfkey_init() ?
+	 * SPD reload ?
+	 */
+	
+	save_params();
+	error = cfparse();
+	if (error != 0){
+		plog(LLV_ERROR, LOCATION, NULL, "config reload failed\n");
+		/* We are probably in an inconsistant state... */
+		return;
+	}
+	restore_params();
+
+#if 0	
+	if (dump_config)
+		dumprmconf ();
+#endif
+
+	/* 
+	 * init_myaddr() ?
+	 * If running in privilege separation, do not reinitialize
+	 * the IKE listener, as we will not have the right to 
+	 * setsockopt(IP_IPSEC_POLICY). 
+	 */
+	if (geteuid() == 0)
+		check_rtsock(NULL);
+
+	/* Revalidate ph1 / ph2tree !!!
+	 * update ctdtree if removing some ph1 !
+	 */
+	revalidate_ph12();
+	/* Update ctdtree ?
+	 */
+
+	save_sainfotree_flush();
+	save_rmconf_flush();
+}
+
+static void
+check_sigreq()
+{
+	int sig;
+
+	/* 
+	 * XXX We are not able to tell if we got 
+	 * several time the same signal. This is
+	 * not a problem for the current code, 
+	 * but we shall remember this limitation.
+	 */
+	for (sig = 0; sig <= NSIG; sig++) {
+		if (sigreq[sig] == 0)
+			continue;
+
+		sigreq[sig]--;
+		switch(sig) {
+		case 0:
+			return;
+			
+			/* Catch up childs, mainly scripts.
+			 */
+		case SIGCHLD:
+	    {
+			pid_t pid;
+			int s;
+			
+			pid = wait(&s);
+	    }
+		break;
+
+#ifdef DEBUG_RECORD_MALLOCATION
+		/* 
+		 * XXX This operation is signal handler unsafe and may lead to 
+		 * crashes and security breaches: See Henning Brauer talk at
+		 * EuroBSDCon 2005. Do not run in production with this option
+		 * enabled.
+		 */
+		case SIGUSR2:
+			DRM_dump();
+			break;
+#endif
+
+		case SIGHUP:
+			/* Save old configuration, load new one...  */
+			reload_conf();
+			break;
+
+		case SIGINT:
+		case SIGTERM:			
+			plog(LLV_INFO, LOCATION, NULL, 
+			    "caught signal %d\n", sig);
+			EVT_PUSH(NULL, NULL, EVTT_RACOON_QUIT, NULL);
+			pfkey_send_flush(lcconf->sock_pfkey, 
+			    SADB_SATYPE_UNSPEC);
+#ifdef ENABLE_FASTQUIT
+			close_session();
+#else
+			sched_new(1, check_flushsa_stub, NULL);
+#endif
+			dying = 1;
+			break;
+
+		default:
+			plog(LLV_INFO, LOCATION, NULL, 
+			    "caught signal %d\n", sig);
+			break;
+		}
+	}
+}
+
+/*
+ * waiting the termination of processing until sending DELETE message
+ * for all inbound SA will complete.
+ */
+static void
+check_flushsa_stub(p)
+	void *p;
+{
+
+	check_flushsa();
+}
+
+static void
+check_flushsa()
+{
+	vchar_t *buf;
+	struct sadb_msg *msg, *end, *next;
+	struct sadb_sa *sa;
+	caddr_t mhp[SADB_EXT_MAX + 1];
+	int n;
+
+	buf = pfkey_dump_sadb(SADB_SATYPE_UNSPEC);
+	if (buf == NULL) {
+		plog(LLV_DEBUG, LOCATION, NULL,
+		    "pfkey_dump_sadb: returned nothing.\n");
+		return;
+	}
+
+	msg = (struct sadb_msg *)buf->v;
+	end = (struct sadb_msg *)(buf->v + buf->l);
+
+	/* counting SA except of dead one. */
+	n = 0;
+	while (msg < end) {
+		if (PFKEY_UNUNIT64(msg->sadb_msg_len) < sizeof(*msg))
+			break;
+		next = (struct sadb_msg *)((caddr_t)msg + PFKEY_UNUNIT64(msg->sadb_msg_len));
+		if (msg->sadb_msg_type != SADB_DUMP) {
+			msg = next;
+			continue;
+		}
+
+		if (pfkey_align(msg, mhp) || pfkey_check(mhp)) {
+			plog(LLV_ERROR, LOCATION, NULL,
+				"pfkey_check (%s)\n", ipsec_strerror());
+			msg = next;
+			continue;
+		}
+
+		sa = (struct sadb_sa *)(mhp[SADB_EXT_SA]);
+		if (!sa) {
+			msg = next;
+			continue;
+		}
+
+		if (sa->sadb_sa_state != SADB_SASTATE_DEAD) {
+			n++;
+			msg = next;
+			continue;
+		}
+
+		msg = next;
+	}
+
+	if (buf != NULL)
+		vfree(buf);
+
+	if (n) {
+		sched_new(1, check_flushsa_stub, NULL);
+		return;
+	}
+
+	close_session();
+}
+
+static void
+init_signal()
+{
+	int i;
+
+	for (i = 0; signals[i] != 0; i++)
+		if (set_signal(signals[i], signal_handler) < 0) {
+			plog(LLV_ERROR, LOCATION, NULL,
+				"failed to set_signal (%s)\n",
+				strerror(errno));
+			exit(1);
+		}
+}
+
+static int
+set_signal(sig, func)
+	int sig;
+	RETSIGTYPE (*func) __P((int));
+{
+	struct sigaction sa;
+
+	memset((caddr_t)&sa, 0, sizeof(sa));
+	sa.sa_handler = func;
+	sa.sa_flags = SA_RESTART;
+
+	if (sigemptyset(&sa.sa_mask) < 0)
+		return -1;
+
+	if (sigaction(sig, &sa, (struct sigaction *)0) < 0)
+		return(-1);
+
+	return 0;
+}
+
+static int
+close_sockets()
+{
+	isakmp_close();
+	pfkey_close(lcconf->sock_pfkey);
+#ifdef ENABLE_ADMINPORT
+	(void)admin_close();
+#endif
+	return 0;
+}
+
diff --git a/src/racoon/session.h b/src/racoon/session.h
new file mode 100644
index 0000000..58799ee
--- /dev/null
+++ b/src/racoon/session.h
@@ -0,0 +1,40 @@
+/*	$NetBSD: session.h,v 1.4 2006/09/09 16:22:10 manu Exp $	*/
+
+/* Id: session.h,v 1.3 2004/06/11 16:00:17 ludvigm Exp */
+
+/*
+ * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _SESSION_H
+#define _SESSION_H
+
+extern int session __P((void));
+extern RETSIGTYPE signal_handler __P((int));
+
+#endif /* _SESSION_H */
diff --git a/src/racoon/sockmisc.c b/src/racoon/sockmisc.c
new file mode 100644
index 0000000..781e6d6
--- /dev/null
+++ b/src/racoon/sockmisc.c
@@ -0,0 +1,1115 @@
+/*	$NetBSD: sockmisc.c,v 1.8.6.1 2007/08/01 11:52:22 vanhu Exp $	*/
+
+/* Id: sockmisc.c,v 1.24 2006/05/07 21:32:59 manubsd Exp */
+
+/*
+ * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <sys/uio.h>
+
+#include <netinet/in.h>
+#include PATH_IPSEC_H
+
+#if defined(INET6) && !defined(INET6_ADVAPI) && \
+	defined(IP_RECVDSTADDR) && !defined(IPV6_RECVDSTADDR)
+#define IPV6_RECVDSTADDR IP_RECVDSTADDR
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include "var.h"
+#include "misc.h"
+#include "plog.h"
+#include "sockmisc.h"
+#include "debug.h"
+#include "gcmalloc.h"
+#include "debugrm.h"
+#include "libpfkey.h"
+
+#ifndef IP_IPSEC_POLICY
+#define IP_IPSEC_POLICY 16	/* XXX: from linux/in.h */
+#endif
+
+#ifndef IPV6_IPSEC_POLICY
+#define IPV6_IPSEC_POLICY 34	/* XXX: from linux/???.h per
+				   "Tom Lendacky" <toml@us.ibm.com> */
+#endif
+
+const int niflags = 0;
+
+/*
+ * compare two sockaddr without port number.
+ * OUT:	0: equal.
+ *	1: not equal.
+ */
+int
+cmpsaddrwop(addr1, addr2)
+	const struct sockaddr *addr1;
+	const struct sockaddr *addr2;
+{
+	caddr_t sa1, sa2;
+
+	if (addr1 == 0 && addr2 == 0)
+		return 0;
+	if (addr1 == 0 || addr2 == 0)
+		return 1;
+
+#ifdef __linux__
+	if (addr1->sa_family != addr2->sa_family)
+		return 1;
+#else
+	if (addr1->sa_len != addr2->sa_len
+	 || addr1->sa_family != addr2->sa_family)
+		return 1;
+
+#endif /* __linux__ */
+
+	switch (addr1->sa_family) {
+	case AF_INET:
+		sa1 = (caddr_t)&((struct sockaddr_in *)addr1)->sin_addr;
+		sa2 = (caddr_t)&((struct sockaddr_in *)addr2)->sin_addr;
+		if (memcmp(sa1, sa2, sizeof(struct in_addr)) != 0)
+			return 1;
+		break;
+#ifdef INET6
+	case AF_INET6:
+		sa1 = (caddr_t)&((struct sockaddr_in6 *)addr1)->sin6_addr;
+		sa2 = (caddr_t)&((struct sockaddr_in6 *)addr2)->sin6_addr;
+		if (memcmp(sa1, sa2, sizeof(struct in6_addr)) != 0)
+			return 1;
+		if (((struct sockaddr_in6 *)addr1)->sin6_scope_id !=
+		    ((struct sockaddr_in6 *)addr2)->sin6_scope_id)
+			return 1;
+		break;
+#endif
+	default:
+		return 1;
+	}
+
+	return 0;
+}
+
+/*
+ * compare two sockaddr with port, taking care wildcard.
+ * addr1 is a subject address, addr2 is in a database entry.
+ * OUT:	0: equal.
+ *	1: not equal.
+ */
+int
+cmpsaddrwild(addr1, addr2)
+	const struct sockaddr *addr1;
+	const struct sockaddr *addr2;
+{
+	caddr_t sa1, sa2;
+	u_short port1, port2;
+
+	if (addr1 == 0 && addr2 == 0)
+		return 0;
+	if (addr1 == 0 || addr2 == 0)
+		return 1;
+
+#ifdef __linux__
+	if (addr1->sa_family != addr2->sa_family)
+		return 1;
+#else
+	if (addr1->sa_len != addr2->sa_len
+	 || addr1->sa_family != addr2->sa_family)
+		return 1;
+
+#endif /* __linux__ */
+
+	switch (addr1->sa_family) {
+	case AF_INET:
+		sa1 = (caddr_t)&((struct sockaddr_in *)addr1)->sin_addr;
+		sa2 = (caddr_t)&((struct sockaddr_in *)addr2)->sin_addr;
+		port1 = ((struct sockaddr_in *)addr1)->sin_port;
+		port2 = ((struct sockaddr_in *)addr2)->sin_port;
+		if (!(port1 == IPSEC_PORT_ANY ||
+		      port2 == IPSEC_PORT_ANY ||
+		      port1 == port2))
+			return 1;
+		if (memcmp(sa1, sa2, sizeof(struct in_addr)) != 0)
+			return 1;
+		break;
+#ifdef INET6
+	case AF_INET6:
+		sa1 = (caddr_t)&((struct sockaddr_in6 *)addr1)->sin6_addr;
+		sa2 = (caddr_t)&((struct sockaddr_in6 *)addr2)->sin6_addr;
+		port1 = ((struct sockaddr_in6 *)addr1)->sin6_port;
+		port2 = ((struct sockaddr_in6 *)addr2)->sin6_port;
+		if (!(port1 == IPSEC_PORT_ANY ||
+		      port2 == IPSEC_PORT_ANY ||
+		      port1 == port2))
+			return 1;
+		if (memcmp(sa1, sa2, sizeof(struct in6_addr)) != 0)
+			return 1;
+		if (((struct sockaddr_in6 *)addr1)->sin6_scope_id !=
+		    ((struct sockaddr_in6 *)addr2)->sin6_scope_id)
+			return 1;
+		break;
+#endif
+	default:
+		return 1;
+	}
+
+	return 0;
+}
+
+/*
+ * compare two sockaddr with strict match on port.
+ * OUT:	0: equal.
+ *	1: not equal.
+ */
+int
+cmpsaddrstrict(addr1, addr2)
+	const struct sockaddr *addr1;
+	const struct sockaddr *addr2;
+{
+	caddr_t sa1, sa2;
+	u_short port1, port2;
+
+	if (addr1 == 0 && addr2 == 0)
+		return 0;
+	if (addr1 == 0 || addr2 == 0)
+		return 1;
+
+#ifdef __linux__
+	if (addr1->sa_family != addr2->sa_family)
+		return 1;
+#else
+	if (addr1->sa_len != addr2->sa_len
+	 || addr1->sa_family != addr2->sa_family)
+		return 1;
+
+#endif /* __linux__ */
+
+	switch (addr1->sa_family) {
+	case AF_INET:
+		sa1 = (caddr_t)&((struct sockaddr_in *)addr1)->sin_addr;
+		sa2 = (caddr_t)&((struct sockaddr_in *)addr2)->sin_addr;
+		port1 = ((struct sockaddr_in *)addr1)->sin_port;
+		port2 = ((struct sockaddr_in *)addr2)->sin_port;
+		if (port1 != port2)
+			return 1;
+		if (memcmp(sa1, sa2, sizeof(struct in_addr)) != 0)
+			return 1;
+		break;
+#ifdef INET6
+	case AF_INET6:
+		sa1 = (caddr_t)&((struct sockaddr_in6 *)addr1)->sin6_addr;
+		sa2 = (caddr_t)&((struct sockaddr_in6 *)addr2)->sin6_addr;
+		port1 = ((struct sockaddr_in6 *)addr1)->sin6_port;
+		port2 = ((struct sockaddr_in6 *)addr2)->sin6_port;
+		if (port1 != port2)
+			return 1;
+		if (memcmp(sa1, sa2, sizeof(struct in6_addr)) != 0)
+			return 1;
+		if (((struct sockaddr_in6 *)addr1)->sin6_scope_id !=
+		    ((struct sockaddr_in6 *)addr2)->sin6_scope_id)
+			return 1;
+		break;
+#endif
+	default:
+		return 1;
+	}
+
+	return 0;
+}
+
+/* get local address against the destination. */
+struct sockaddr *
+getlocaladdr(remote)
+	struct sockaddr *remote;
+{
+	struct sockaddr *local;
+	u_int local_len = sizeof(struct sockaddr_storage);
+	int s;	/* for dummy connection */
+
+	/* allocate buffer */
+	if ((local = racoon_calloc(1, local_len)) == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"failed to get address buffer.\n");
+		goto err;
+	}
+	
+	/* get real interface received packet */
+	if ((s = socket(remote->sa_family, SOCK_DGRAM, 0)) < 0) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"socket (%s)\n", strerror(errno));
+		goto err;
+	}
+
+	setsockopt_bypass(s, remote->sa_family);
+	
+	if (connect(s, remote, sysdep_sa_len(remote)) < 0) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"connect (%s)\n", strerror(errno));
+		close(s);
+		goto err;
+	}
+
+	if (getsockname(s, local, &local_len) < 0) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"getsockname (%s)\n", strerror(errno));
+		close(s);
+		return NULL;
+	}
+
+	close(s);
+	return local;
+
+    err:
+	if (local != NULL)
+		racoon_free(local);
+	return NULL;
+}
+
+/*
+ * Receive packet, with src/dst information.  It is assumed that necessary
+ * setsockopt() have already performed on socket.
+ */
+int
+recvfromto(s, buf, buflen, flags, from, fromlen, to, tolen)
+	int s;
+	void *buf;
+	size_t buflen;
+	int flags;
+	struct sockaddr *from;
+	socklen_t *fromlen;
+	struct sockaddr *to;
+	u_int *tolen;
+{
+	int otolen;
+	u_int len;
+	struct sockaddr_storage ss;
+	struct msghdr m;
+	struct cmsghdr *cm;
+	struct iovec iov[2];
+	u_char cmsgbuf[256];
+#if defined(INET6) && defined(INET6_ADVAPI)
+	struct in6_pktinfo *pi;
+#endif /*INET6_ADVAPI*/
+	struct sockaddr_in *sin;
+#ifdef INET6
+	struct sockaddr_in6 *sin6;
+#endif
+
+	len = sizeof(ss);
+	if (getsockname(s, (struct sockaddr *)&ss, &len) < 0) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"getsockname (%s)\n", strerror(errno));
+		return -1;
+	}
+
+	m.msg_name = (caddr_t)from;
+	m.msg_namelen = *fromlen;
+	iov[0].iov_base = (caddr_t)buf;
+	iov[0].iov_len = buflen;
+	m.msg_iov = iov;
+	m.msg_iovlen = 1;
+	memset(cmsgbuf, 0, sizeof(cmsgbuf));
+	cm = (struct cmsghdr *)cmsgbuf;
+	m.msg_control = (caddr_t)cm;
+	m.msg_controllen = sizeof(cmsgbuf);
+	if ((len = recvmsg(s, &m, flags)) < 0) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"recvmsg (%s)\n", strerror(errno));
+		return -1;
+	}
+	*fromlen = m.msg_namelen;
+
+	otolen = *tolen;
+	*tolen = 0;
+	for (cm = (struct cmsghdr *)CMSG_FIRSTHDR(&m);
+	     m.msg_controllen != 0 && cm;
+	     cm = (struct cmsghdr *)CMSG_NXTHDR(&m, cm)) {
+#if 0
+		plog(LLV_ERROR, LOCATION, NULL,
+			"cmsg %d %d\n", cm->cmsg_level, cm->cmsg_type);)
+#endif
+#if defined(INET6) && defined(INET6_ADVAPI)
+		if (ss.ss_family == AF_INET6
+		 && cm->cmsg_level == IPPROTO_IPV6
+		 && cm->cmsg_type == IPV6_PKTINFO
+		 && otolen >= sizeof(*sin6)) {
+			pi = (struct in6_pktinfo *)(CMSG_DATA(cm));
+			*tolen = sizeof(*sin6);
+			sin6 = (struct sockaddr_in6 *)to;
+			memset(sin6, 0, sizeof(*sin6));
+			sin6->sin6_family = AF_INET6;
+#ifndef __linux__
+			sin6->sin6_len = sizeof(*sin6);
+#endif
+			memcpy(&sin6->sin6_addr, &pi->ipi6_addr,
+				sizeof(sin6->sin6_addr));
+			/* XXX other cases, such as site-local? */
+			if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr))
+				sin6->sin6_scope_id = pi->ipi6_ifindex;
+			else
+				sin6->sin6_scope_id = 0;
+			sin6->sin6_port =
+				((struct sockaddr_in6 *)&ss)->sin6_port;
+			otolen = -1;	/* "to" already set */
+			continue;
+		}
+#endif
+#ifdef __linux__
+		if (ss.ss_family == AF_INET
+		 && cm->cmsg_level == IPPROTO_IP
+		 && cm->cmsg_type == IP_PKTINFO
+		 && otolen >= sizeof(sin)) {
+			struct in_pktinfo *pi = (struct in_pktinfo *)(CMSG_DATA(cm));
+			*tolen = sizeof(*sin);
+			sin = (struct sockaddr_in *)to;
+			memset(sin, 0, sizeof(*sin));
+			sin->sin_family = AF_INET;
+			memcpy(&sin->sin_addr, &pi->ipi_addr,
+				sizeof(sin->sin_addr));
+			sin->sin_port =
+				((struct sockaddr_in *)&ss)->sin_port;
+			otolen = -1;	/* "to" already set */
+			continue;
+		}
+#endif
+#if defined(INET6) && defined(IPV6_RECVDSTADDR)
+		if (ss.ss_family == AF_INET6
+		      && cm->cmsg_level == IPPROTO_IPV6
+		      && cm->cmsg_type == IPV6_RECVDSTADDR
+		      && otolen >= sizeof(*sin6)) {
+			*tolen = sizeof(*sin6);
+			sin6 = (struct sockaddr_in6 *)to;
+			memset(sin6, 0, sizeof(*sin6));
+			sin6->sin6_family = AF_INET6;
+			sin6->sin6_len = sizeof(*sin6);
+			memcpy(&sin6->sin6_addr, CMSG_DATA(cm),
+				sizeof(sin6->sin6_addr));
+			sin6->sin6_port =
+				((struct sockaddr_in6 *)&ss)->sin6_port;
+			otolen = -1;	/* "to" already set */
+			continue;
+		}
+#endif
+#ifndef __linux__
+		if (ss.ss_family == AF_INET
+		 && cm->cmsg_level == IPPROTO_IP
+		 && cm->cmsg_type == IP_RECVDSTADDR
+		 && otolen >= sizeof(*sin)) {
+			*tolen = sizeof(*sin);
+			sin = (struct sockaddr_in *)to;
+			memset(sin, 0, sizeof(*sin));
+			sin->sin_family = AF_INET;
+			sin->sin_len = sizeof(*sin);
+			memcpy(&sin->sin_addr, CMSG_DATA(cm),
+				sizeof(sin->sin_addr));
+			sin->sin_port = ((struct sockaddr_in *)&ss)->sin_port;
+			otolen = -1;	/* "to" already set */
+			continue;
+		}
+#endif
+	}
+
+	return len;
+}
+
+/* send packet, with fixing src/dst address pair. */
+int
+sendfromto(s, buf, buflen, src, dst, cnt)
+	int s, cnt;
+	const void *buf;
+	size_t buflen;
+	struct sockaddr *src;
+	struct sockaddr *dst;
+{
+	struct sockaddr_storage ss;
+	u_int len;
+	int i;
+
+	if (src->sa_family != dst->sa_family) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"address family mismatch\n");
+		return -1;
+	}
+
+	len = sizeof(ss);
+	if (getsockname(s, (struct sockaddr *)&ss, &len) < 0) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"getsockname (%s)\n", strerror(errno));
+		return -1;
+	}
+
+	plog(LLV_DEBUG, LOCATION, NULL,
+		"sockname %s\n", saddr2str((struct sockaddr *)&ss));
+	plog(LLV_DEBUG, LOCATION, NULL,
+		"send packet from %s\n", saddr2str(src));
+	plog(LLV_DEBUG, LOCATION, NULL,
+		"send packet to %s\n", saddr2str(dst));
+
+	if (src->sa_family != ss.ss_family) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"address family mismatch\n");
+		return -1;
+	}
+
+	switch (src->sa_family) {
+#if defined(INET6) && defined(INET6_ADVAPI)
+// XXX: This block wasn't compiled on Linux - does it work?
+	case AF_INET6:
+	    {
+		struct msghdr m;
+		struct cmsghdr *cm;
+		struct iovec iov[2];
+		u_char cmsgbuf[256];
+		struct in6_pktinfo *pi;
+		int ifindex;
+		struct sockaddr_in6 src6, dst6;
+
+		memcpy(&src6, src, sizeof(src6));
+		memcpy(&dst6, dst, sizeof(dst6));
+
+		/* XXX take care of other cases, such as site-local */
+		ifindex = 0;
+		if (IN6_IS_ADDR_LINKLOCAL(&src6.sin6_addr)
+		 || IN6_IS_ADDR_MULTICAST(&src6.sin6_addr)) {
+			ifindex = src6.sin6_scope_id;	/*???*/
+		}
+
+		/* XXX some sanity check on dst6.sin6_scope_id */
+
+		/* flowinfo for IKE?  mmm, maybe useful but for now make it 0 */
+		src6.sin6_flowinfo = dst6.sin6_flowinfo = 0;
+
+		memset(&m, 0, sizeof(m));
+		m.msg_name = (caddr_t)&dst6;
+		m.msg_namelen = sizeof(dst6);
+		iov[0].iov_base = (char *)buf;
+		iov[0].iov_len = buflen;
+		m.msg_iov = iov;
+		m.msg_iovlen = 1;
+
+		memset(cmsgbuf, 0, sizeof(cmsgbuf));
+		cm = (struct cmsghdr *)cmsgbuf;
+		m.msg_control = (caddr_t)cm;
+		m.msg_controllen = CMSG_SPACE(sizeof(struct in6_pktinfo));
+
+		cm->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
+		cm->cmsg_level = IPPROTO_IPV6;
+		cm->cmsg_type = IPV6_PKTINFO;
+		pi = (struct in6_pktinfo *)CMSG_DATA(cm);
+		memcpy(&pi->ipi6_addr, &src6.sin6_addr, sizeof(src6.sin6_addr));
+		pi->ipi6_ifindex = ifindex;
+
+		plog(LLV_DEBUG, LOCATION, NULL,
+			"src6 %s %d\n",
+			saddr2str((struct sockaddr *)&src6),
+			src6.sin6_scope_id);
+		plog(LLV_DEBUG, LOCATION, NULL,
+			"dst6 %s %d\n",
+			saddr2str((struct sockaddr *)&dst6),
+			dst6.sin6_scope_id);
+
+		for (i = 0; i < cnt; i++) {
+			len = sendmsg(s, &m, 0 /*MSG_DONTROUTE*/);
+			if (len < 0) {
+				plog(LLV_ERROR, LOCATION, NULL,
+					"sendmsg (%s)\n", strerror(errno));
+				return -1;
+			}
+			plog(LLV_DEBUG, LOCATION, NULL,
+				"%d times of %d bytes message will be sent "
+				"to %s\n",
+				i + 1, len, saddr2str(dst));
+		}
+		plogdump(LLV_DEBUG, (char *)buf, buflen);
+
+		return len;
+	    }
+#endif
+#ifdef __linux__
+	case AF_INET:
+	    {
+		struct msghdr m;
+		struct cmsghdr *cm;
+		struct iovec iov[2];
+		u_char cmsgbuf[256];
+		struct in_pktinfo *pi;
+		int ifindex = 0;
+		struct sockaddr_in src6, dst6;
+
+		memcpy(&src6, src, sizeof(src6));
+		memcpy(&dst6, dst, sizeof(dst6));
+
+		memset(&m, 0, sizeof(m));
+		m.msg_name = (caddr_t)&dst6;
+		m.msg_namelen = sizeof(dst6);
+		iov[0].iov_base = (char *)buf;
+		iov[0].iov_len = buflen;
+		m.msg_iov = iov;
+		m.msg_iovlen = 1;
+
+		memset(cmsgbuf, 0, sizeof(cmsgbuf));
+		cm = (struct cmsghdr *)cmsgbuf;
+		m.msg_control = (caddr_t)cm;
+		m.msg_controllen = CMSG_SPACE(sizeof(struct in_pktinfo));
+
+		cm->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo));
+		cm->cmsg_level = IPPROTO_IP;
+		cm->cmsg_type = IP_PKTINFO;
+		pi = (struct in_pktinfo *)CMSG_DATA(cm);
+		memcpy(&pi->ipi_spec_dst, &src6.sin_addr, sizeof(src6.sin_addr));
+		pi->ipi_ifindex = ifindex;
+
+		plog(LLV_DEBUG, LOCATION, NULL,
+			"src4 %s\n",
+			saddr2str((struct sockaddr *)&src6));
+		plog(LLV_DEBUG, LOCATION, NULL,
+			"dst4 %s\n",
+			saddr2str((struct sockaddr *)&dst6));
+
+		for (i = 0; i < cnt; i++) {
+			len = sendmsg(s, &m, 0 /*MSG_DONTROUTE*/);
+			if (len < 0) {
+				plog(LLV_ERROR, LOCATION, NULL,
+					"sendmsg (%s)\n", strerror(errno));
+				return -1;
+			}
+			plog(LLV_DEBUG, LOCATION, NULL,
+				"%d times of %d bytes message will be sent "
+				"to %s\n",
+				i + 1, len, saddr2str(dst));
+		}
+		plogdump(LLV_DEBUG, (char *)buf, buflen);
+
+		return len;
+	    }
+#endif /* __linux__ */
+	default:
+	    {
+		int needclose = 0;
+		int sendsock;
+
+		if (ss.ss_family == src->sa_family && memcmp(&ss, src, sysdep_sa_len(src)) == 0) {
+			sendsock = s;
+			needclose = 0;
+		} else {
+			int yes = 1;
+			/*
+			 * Use newly opened socket for sending packets.
+			 * NOTE: this is unsafe, because if the peer is quick enough
+			 * the packet from the peer may be queued into sendsock.
+			 * Better approach is to prepare bind'ed udp sockets for
+			 * each of the interface addresses.
+			 */
+			sendsock = socket(src->sa_family, SOCK_DGRAM, 0);
+			if (sendsock < 0) {
+				plog(LLV_ERROR, LOCATION, NULL,
+					"socket (%s)\n", strerror(errno));
+				return -1;
+			}
+			if (setsockopt(sendsock, SOL_SOCKET,
+#ifdef __linux__
+				       SO_REUSEADDR,
+#else
+				       SO_REUSEPORT,
+#endif
+				       (void *)&yes, sizeof(yes)) < 0) {
+				plog(LLV_ERROR, LOCATION, NULL,
+					"setsockopt SO_REUSEPORT (%s)\n", 
+					strerror(errno));
+				close(sendsock);
+				return -1;
+			}
+#ifdef IPV6_USE_MIN_MTU
+			if (src->sa_family == AF_INET6 &&
+			    setsockopt(sendsock, IPPROTO_IPV6, IPV6_USE_MIN_MTU,
+			    (void *)&yes, sizeof(yes)) < 0) {
+				plog(LLV_ERROR, LOCATION, NULL,
+					"setsockopt IPV6_USE_MIN_MTU (%s)\n", 
+					strerror(errno));
+				close(sendsock);
+				return -1;
+			}
+#endif
+			if (setsockopt_bypass(sendsock, src->sa_family) < 0) {
+				close(sendsock);
+				return -1;
+			}
+
+			if (bind(sendsock, (struct sockaddr *)src, sysdep_sa_len(src)) < 0) {
+				plog(LLV_ERROR, LOCATION, NULL,
+					"bind 1 (%s)\n", strerror(errno));
+				close(sendsock);
+				return -1;
+			}
+			needclose = 1;
+		}
+
+		for (i = 0; i < cnt; i++) {
+			len = sendto(sendsock, buf, buflen, 0, dst, sysdep_sa_len(dst));
+			if (len < 0) {
+				plog(LLV_ERROR, LOCATION, NULL,
+					"sendto (%s)\n", strerror(errno));
+				if (needclose)
+					close(sendsock);
+				return len;
+			}
+			plog(LLV_DEBUG, LOCATION, NULL,
+				"%d times of %d bytes message will be sent "
+				"to %s\n",
+				i + 1, len, saddr2str(dst));
+		}
+		plogdump(LLV_DEBUG, (char *)buf, buflen);
+
+		if (needclose)
+			close(sendsock);
+
+		return len;
+	    }
+	}
+}
+
+int
+setsockopt_bypass(so, family)
+	int so, family;
+{
+	int level;
+	char *buf;
+	char *policy;
+
+	switch (family) {
+	case AF_INET:
+		level = IPPROTO_IP;
+		break;
+#ifdef INET6
+	case AF_INET6:
+		level = IPPROTO_IPV6;
+		break;
+#endif
+	default:
+		plog(LLV_ERROR, LOCATION, NULL,
+			"unsupported address family %d\n", family);
+		return -1;
+	}
+
+	policy = "in bypass";
+	buf = ipsec_set_policy(policy, strlen(policy));
+	if (buf == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"ipsec_set_policy (%s)\n",
+			ipsec_strerror());
+		return -1;
+	}
+	if (setsockopt(so, level,
+	               (level == IPPROTO_IP ?
+	                         IP_IPSEC_POLICY : IPV6_IPSEC_POLICY),
+	               buf, ipsec_get_policylen(buf)) < 0) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"setsockopt IP_IPSEC_POLICY (%s)\n",
+			strerror(errno));
+		return -1;
+	}
+	racoon_free(buf);
+
+	policy = "out bypass";
+	buf = ipsec_set_policy(policy, strlen(policy));
+	if (buf == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"ipsec_set_policy (%s)\n",
+			ipsec_strerror());
+		return -1;
+	}
+	if (setsockopt(so, level,
+	               (level == IPPROTO_IP ?
+	                         IP_IPSEC_POLICY : IPV6_IPSEC_POLICY),
+	               buf, ipsec_get_policylen(buf)) < 0) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"setsockopt IP_IPSEC_POLICY (%s)\n",
+			strerror(errno));
+		return -1;
+	}
+	racoon_free(buf);
+
+	return 0;
+}
+
+struct sockaddr *
+newsaddr(len)
+	int len;
+{
+	struct sockaddr *new;
+
+	if ((new = racoon_calloc(1, len)) == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"%s\n", strerror(errno)); 
+		goto out;
+	}
+
+#ifdef __linux__
+	if (len == sizeof (struct sockaddr_in6))
+		new->sa_family = AF_INET6;
+	else
+		new->sa_family = AF_INET;
+#else
+	/* initial */
+	new->sa_len = len;
+#endif
+out:
+	return new;
+}
+
+struct sockaddr *
+dupsaddr(src)
+	struct sockaddr *src;
+{
+	struct sockaddr *dst;
+
+	dst = racoon_calloc(1, sysdep_sa_len(src));
+	if (dst == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"%s\n", strerror(errno)); 
+		return NULL;
+	}
+
+	memcpy(dst, src, sysdep_sa_len(src));
+
+	return dst;
+}
+
+char *
+saddr2str(saddr)
+	const struct sockaddr *saddr;
+{
+	static char buf[NI_MAXHOST + NI_MAXSERV + 10];
+	char addr[NI_MAXHOST], port[NI_MAXSERV];
+
+	if (saddr == NULL)
+		return NULL;
+
+	if (saddr->sa_family == AF_UNSPEC)
+		snprintf (buf, sizeof(buf), "%s", "anonymous");
+	else {
+		GETNAMEINFO(saddr, addr, port);
+		snprintf(buf, sizeof(buf), "%s[%s]", addr, port);
+	}
+
+	return buf;
+}
+
+char *
+saddrwop2str(saddr)
+	const struct sockaddr *saddr;
+{
+	static char buf[NI_MAXHOST + NI_MAXSERV + 10];
+	char addr[NI_MAXHOST];
+
+	if (saddr == NULL)
+		return NULL;
+
+	GETNAMEINFO_NULL(saddr, addr);
+	snprintf(buf, sizeof(buf), "%s", addr);
+
+	return buf;
+}
+
+char *
+naddrwop2str(const struct netaddr *naddr)
+{
+	static char buf[NI_MAXHOST + 10];
+	static const struct sockaddr sa_any;	/* this is initialized to all zeros */
+	
+	if (naddr == NULL)
+		return NULL;
+
+	if (memcmp(&naddr->sa, &sa_any, sizeof(sa_any)) == 0)
+		snprintf(buf, sizeof(buf), "%s", "any");
+	else {
+		snprintf(buf, sizeof(buf), "%s", saddrwop2str(&naddr->sa.sa));
+		snprintf(&buf[strlen(buf)], sizeof(buf) - strlen(buf), "/%ld", naddr->prefix);
+	}
+	return buf;
+}
+
+char *
+naddrwop2str_fromto(const char *format, const struct netaddr *saddr,
+		    const struct netaddr *daddr)
+{
+	static char buf[2*(NI_MAXHOST + NI_MAXSERV + 10) + 100];
+	char *src, *dst;
+
+	src = racoon_strdup(naddrwop2str(saddr));
+	dst = racoon_strdup(naddrwop2str(daddr));
+	STRDUP_FATAL(src);
+	STRDUP_FATAL(dst);
+	/* WARNING: Be careful about the format string! Don't 
+	   ever pass in something that a user can modify!!! */
+	snprintf (buf, sizeof(buf), format, src, dst);
+	racoon_free (src);
+	racoon_free (dst);
+
+	return buf;
+}
+
+char *
+saddr2str_fromto(format, saddr, daddr)
+	const char *format;
+	const struct sockaddr *saddr;
+	const struct sockaddr *daddr;
+{
+	static char buf[2*(NI_MAXHOST + NI_MAXSERV + 10) + 100];
+	char *src, *dst;
+
+	src = racoon_strdup(saddr2str(saddr));
+	dst = racoon_strdup(saddr2str(daddr));
+	STRDUP_FATAL(src);
+	STRDUP_FATAL(dst);
+	/* WARNING: Be careful about the format string! Don't 
+	   ever pass in something that a user can modify!!! */
+	snprintf (buf, sizeof(buf), format, src, dst);
+	racoon_free (src);
+	racoon_free (dst);
+
+	return buf;
+}
+
+struct sockaddr *
+str2saddr(host, port)
+	char *host;
+	char *port;
+{
+	struct addrinfo hints, *res;
+	struct sockaddr *saddr;
+	int error;
+
+	memset(&hints, 0, sizeof(hints));
+	hints.ai_family = PF_UNSPEC;
+	hints.ai_socktype = SOCK_DGRAM;
+	hints.ai_flags = AI_NUMERICHOST;
+	error = getaddrinfo(host, port, &hints, &res);
+	if (error != 0) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"getaddrinfo(%s%s%s): %s\n",
+			host, port ? "," : "", port ? port : "",
+			gai_strerror(error));
+		return NULL;
+	}
+	if (res->ai_next != NULL) {
+		plog(LLV_WARNING, LOCATION, NULL,
+			"getaddrinfo(%s%s%s): "
+			"resolved to multiple address, "
+			"taking the first one\n",
+			host, port ? "," : "", port ? port : "");
+	}
+	saddr = racoon_malloc(res->ai_addrlen);
+	if (saddr == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"failed to allocate buffer.\n");
+		freeaddrinfo(res);
+		return NULL;
+	}
+	memcpy(saddr, res->ai_addr, res->ai_addrlen);
+	freeaddrinfo(res);
+
+	return saddr;
+}
+
+void
+mask_sockaddr(a, b, l)
+	struct sockaddr *a;
+	const struct sockaddr *b;
+	size_t l;
+{
+	size_t i;
+	u_int8_t *p, alen;
+
+	switch (b->sa_family) {
+	case AF_INET:
+		alen = sizeof(struct in_addr);
+		p = (u_int8_t *)&((struct sockaddr_in *)a)->sin_addr;
+		break;
+#ifdef INET6
+	case AF_INET6:
+		alen = sizeof(struct in6_addr);
+		p = (u_int8_t *)&((struct sockaddr_in6 *)a)->sin6_addr;
+		break;
+#endif
+	default:
+		plog(LLV_ERROR, LOCATION, NULL,
+			"invalid family: %d\n", b->sa_family);
+		exit(1);
+	}
+
+	if ((alen << 3) < l) {
+		plog(LLV_ERROR, LOCATION, NULL,
+			"unexpected inconsistency: %d %zu\n", b->sa_family, l);
+		exit(1);
+	}
+
+	memcpy(a, b, sysdep_sa_len(b));
+	p[l / 8] &= (0xff00 >> (l % 8)) & 0xff;
+	for (i = l / 8 + 1; i < alen; i++)
+		p[i] = 0x00;
+}
+
+/* Compute a score describing how "accurate" a netaddr is for a given sockaddr.
+ * Examples:
+ * 	Return values for address 10.20.30.40 [port 500] and given netaddresses...
+ * 		10.10.0.0/16	=> -1	... doesn't match
+ * 		0.0.0.0/0	=> 0	... matches, but only 0 bits.
+ * 		10.20.0.0/16	=> 16	... 16 bits match
+ * 		10.20.30.0/24	=> 24	... guess what ;-)
+ * 		10.20.30.40/32	=> 32	... whole address match
+ * 		10.20.30.40:500	=> 33	... both address and port match
+ * 		10.20.30.40:501	=> -1	... port doesn't match and isn't 0 (=any)
+ */
+int
+naddr_score(const struct netaddr *naddr, const struct sockaddr *saddr)
+{
+	static const struct netaddr naddr_any;	/* initialized to all-zeros */
+	struct sockaddr sa;
+	u_int16_t naddr_port, saddr_port;
+	int port_score;
+
+	if (!naddr || !saddr) {
+		plog(LLV_ERROR, LOCATION, NULL,
+		     "Call with null args: naddr=%p, saddr=%p\n",
+		     naddr, saddr);
+		return -1;
+	}
+
+	/* Wildcard address matches, but only 0 bits. */
+	if (memcmp(naddr, &naddr_any, sizeof(naddr_any)) == 0)
+		return 0;
+
+	/* If families don't match we really can't do much... */
+	if (naddr->sa.sa.sa_family != saddr->sa_family)
+		return -1;
+	
+	/* If port check fail don't bother to check addresses. */
+	naddr_port = extract_port(&naddr->sa.sa);
+	saddr_port = extract_port(saddr);
+	if (naddr_port == 0 || saddr_port == 0)	/* wildcard match */
+		port_score = 0;
+	else if (naddr_port == saddr_port)	/* exact match */
+		port_score = 1;
+	else					/* mismatch :-) */
+		return -1;
+
+	/* Here it comes - compare network addresses. */
+	mask_sockaddr(&sa, saddr, naddr->prefix);
+	if (loglevel >= LLV_DEBUG) {	/* debug only */
+		char *a1, *a2, *a3;
+		a1 = racoon_strdup(naddrwop2str(naddr));
+		a2 = racoon_strdup(saddrwop2str(saddr));
+		a3 = racoon_strdup(saddrwop2str(&sa));
+		STRDUP_FATAL(a1);
+		STRDUP_FATAL(a2);
+		STRDUP_FATAL(a3);
+		plog(LLV_DEBUG, LOCATION, NULL,
+		     "naddr=%s, saddr=%s (masked=%s)\n",
+		     a1, a2, a3);
+		free(a1);
+		free(a2);
+		free(a3);
+	}
+	if (cmpsaddrwop(&sa, &naddr->sa.sa) == 0)
+		return naddr->prefix + port_score;
+
+	return -1;
+}
+
+/* Some usefull functions for sockaddr port manipulations. */
+u_int16_t
+extract_port (const struct sockaddr *addr)
+{
+  u_int16_t port = 0;
+  
+  if (!addr)
+    return port;
+
+  switch (addr->sa_family) {
+    case AF_INET:
+      port = ((struct sockaddr_in *)addr)->sin_port;
+      break;
+    case AF_INET6:
+      port = ((struct sockaddr_in6 *)addr)->sin6_port;
+      break;
+    default:
+      plog(LLV_ERROR, LOCATION, NULL, "unknown AF: %u\n", addr->sa_family);
+      break;
+  }
+
+  return ntohs(port);
+}
+
+u_int16_t *
+get_port_ptr (struct sockaddr *addr)
+{
+  u_int16_t *port_ptr;
+
+  if (!addr)
+    return NULL;
+
+  switch (addr->sa_family) {
+    case AF_INET:
+      port_ptr = &(((struct sockaddr_in *)addr)->sin_port);
+      break;
+    case AF_INET6:
+      port_ptr = &(((struct sockaddr_in6 *)addr)->sin6_port);
+      break;
+    default:
+      plog(LLV_ERROR, LOCATION, NULL, "unknown AF: %u\n", addr->sa_family);
+      return NULL;
+      break;
+  }
+
+  return port_ptr;
+}
+
+u_int16_t *
+set_port (struct sockaddr *addr, u_int16_t new_port)
+{
+  u_int16_t *port_ptr;
+
+  port_ptr = get_port_ptr (addr);
+
+  if (port_ptr)
+    *port_ptr = htons(new_port);
+
+  return port_ptr;
+}
diff --git a/src/racoon/sockmisc.h b/src/racoon/sockmisc.h
new file mode 100644
index 0000000..a035dec
--- /dev/null
+++ b/src/racoon/sockmisc.h
@@ -0,0 +1,89 @@
+/*	$NetBSD: sockmisc.h,v 1.7 2006/09/09 16:22:10 manu Exp $	*/
+
+/* Id: sockmisc.h,v 1.9 2005/10/05 16:55:41 manubsd Exp */
+
+/*
+ * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _SOCKMISC_H
+#define _SOCKMISC_H
+
+struct netaddr {
+	union {
+		struct sockaddr sa;
+		struct sockaddr_in sin;
+		struct sockaddr_in6 sin6;
+	} sa;
+	unsigned long prefix;
+};
+
+extern const int niflags;
+
+extern int cmpsaddrwop __P((const struct sockaddr *, const struct sockaddr *));
+extern int cmpsaddrwild __P((const struct sockaddr *, const struct sockaddr *));
+extern int cmpsaddrstrict __P((const struct sockaddr *, const struct sockaddr *));
+
+#ifdef ENABLE_NATT 
+#define CMPSADDR(saddr1, saddr2) cmpsaddrstrict((saddr1), (saddr2))
+#else 
+#define CMPSADDR(saddr1, saddr2) cmpsaddrwop((saddr1), (saddr2))
+#endif
+
+extern struct sockaddr *getlocaladdr __P((struct sockaddr *));
+
+extern int recvfromto __P((int, void *, size_t, int,
+	struct sockaddr *, socklen_t *, struct sockaddr *, unsigned int *));
+extern int sendfromto __P((int, const void *, size_t,
+	struct sockaddr *, struct sockaddr *, int));
+
+extern int setsockopt_bypass __P((int, int));
+
+extern struct sockaddr *newsaddr __P((int));
+extern struct sockaddr *dupsaddr __P((struct sockaddr *));
+extern char *saddr2str __P((const struct sockaddr *));
+extern char *saddrwop2str __P((const struct sockaddr *));
+extern char *saddr2str_fromto __P((const char *format, 
+				   const struct sockaddr *saddr, 
+				   const struct sockaddr *daddr));
+extern struct sockaddr *str2saddr __P((char *, char *));
+extern void mask_sockaddr __P((struct sockaddr *, const struct sockaddr *,
+	size_t));
+
+/* struct netaddr functions */
+extern char *naddrwop2str __P((const struct netaddr *naddr));
+extern char *naddrwop2str_fromto __P((const char *format, const struct netaddr *saddr,
+				      const struct netaddr *daddr));
+extern int naddr_score(const struct netaddr *naddr, const struct sockaddr *saddr);
+
+/* Some usefull functions for sockaddr port manipulations. */
+extern u_int16_t extract_port __P((const struct sockaddr *addr));
+extern u_int16_t *set_port __P((struct sockaddr *addr, u_int16_t new_port));
+extern u_int16_t *get_port_ptr __P((struct sockaddr *addr));
+
+#endif /* _SOCKMISC_H */
diff --git a/src/racoon/stats.pl b/src/racoon/stats.pl
new file mode 100644
index 0000000..f509512
--- /dev/null
+++ b/src/racoon/stats.pl
@@ -0,0 +1,15 @@
+#!/usr/bin/perl
+# usage:
+# % cat /var/log/racoon-stats.log | perl stats.pl
+
+while(<STDIN>) {
+	chomp;
+	($a, $a, $a, $a, $a, $b) = split(/\s+/, $_, 6);
+	($a, $c) = split(/:/, $b, 2);
+	$r{$a} += $c;
+	$t{$a}++;
+}
+
+foreach (sort keys %t) {
+	printf "%s: total=%d avg=%8.6f\n", $_, $t{$_}, $r{$_}/$t{$_};
+}
diff --git a/src/racoon/str2val.c b/src/racoon/str2val.c
new file mode 100644
index 0000000..62d38a6
--- /dev/null
+++ b/src/racoon/str2val.c
@@ -0,0 +1,126 @@
+/*	$NetBSD: str2val.c,v 1.4 2006/09/09 16:22:10 manu Exp $	*/
+
+/*	$KAME: str2val.c,v 1.11 2001/08/16 14:37:29 itojun Exp $	*/
+
+/*
+ * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <ctype.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "str2val.h"
+#include "gcmalloc.h"
+
+/*
+ * exchange a value to a hex string.
+ * must free buffer allocated later.
+ */
+caddr_t
+val2str(buf, mlen)
+	const char *buf;
+	size_t mlen;
+{
+	caddr_t new;
+	size_t len = (mlen * 2) + mlen / 8 + 10;
+	size_t i, j;
+
+	if ((new = racoon_malloc(len)) == 0) return(0);
+
+	for (i = 0, j = 0; i < mlen; i++) {
+		snprintf(&new[j], len - j, "%02x", (u_char)buf[i]);
+		j += 2;
+		if (i % 8 == 7) {
+			new[j++] = ' ';
+			new[j] = '\0';
+		}
+	}
+	new[j] = '\0';
+
+	return(new);
+}
+
+/*
+ * exchange a string based "base" to a value.
+ */
+char *
+str2val(str, base, len)
+	const char *str;
+	int base;
+	size_t *len;
+{
+	int f;
+	size_t i;
+	char *dst;
+	char *rp;
+	const char *p;
+	char b[3];
+
+	i = 0;
+	for (p = str; *p != '\0'; p++) {
+		if (isxdigit((int)*p))
+			i++;
+		else if (isspace((int)*p))
+			;
+		else
+			return NULL;
+	}
+	if (i == 0 || (i % 2) != 0)
+		return NULL;
+	i /= 2;
+
+	if ((dst = racoon_malloc(i)) == NULL)
+		return NULL;
+
+	i = 0;
+	f = 0;
+	for (rp = dst, p = str; *p != '\0'; p++) {
+		if (isxdigit((int)*p)) {
+			if (!f) {
+				b[0] = *p;
+				f = 1;
+			} else {
+				b[1] = *p;
+				b[2] = '\0';
+				*rp++ = (char)strtol(b, NULL, base);
+				i++;
+				f = 0;
+			}
+		}
+	}
+
+	*len = i;
+
+	return(dst);
+}
diff --git a/src/racoon/str2val.h b/src/racoon/str2val.h
new file mode 100644
index 0000000..4a7cec1
--- /dev/null
+++ b/src/racoon/str2val.h
@@ -0,0 +1,40 @@
+/*	$NetBSD: str2val.h,v 1.4 2006/09/09 16:22:10 manu Exp $	*/
+
+/* Id: str2val.h,v 1.3 2004/06/11 16:00:17 ludvigm Exp */
+
+/*
+ * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _STR2VAL_H
+#define _STR2VAL_H
+
+extern caddr_t val2str __P((const char *, size_t));
+extern char *str2val __P((const char *, int, size_t *));
+
+#endif /* _STR2VAL_H */
diff --git a/src/racoon/strnames.c b/src/racoon/strnames.c
new file mode 100644
index 0000000..fa5df0f
--- /dev/null
+++ b/src/racoon/strnames.c
@@ -0,0 +1,1034 @@
+/*	$NetBSD: strnames.c,v 1.7.6.1 2007/08/01 11:52:22 vanhu Exp $	*/
+
+/*	$KAME: strnames.c,v 1.25 2003/11/13 10:53:26 itojun Exp $	*/
+
+/*
+ * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+
+#include <netinet/in.h> 
+#include PATH_IPSEC_H
+#include <netinet/in.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#ifdef ENABLE_HYBRID
+#include <resolv.h>
+#endif
+
+#include "var.h"
+#include "misc.h"
+#include "vmbuf.h"
+#include "plog.h"
+
+#include "isakmp_var.h"
+#include "isakmp.h"
+#ifdef ENABLE_HYBRID
+#  include "isakmp_xauth.h"
+#  include "isakmp_unity.h"
+#  include "isakmp_cfg.h"
+#endif
+#include "ipsec_doi.h"
+#include "oakley.h"
+#include "handler.h"
+#include "pfkey.h"
+#include "strnames.h"
+#include "algorithm.h"
+
+struct ksmap {
+	int key;
+	char *str;
+	char *(*f) __P((int));
+};
+
+char *
+num2str(n)
+	int n;
+{
+	static char buf[20];
+
+	snprintf(buf, sizeof(buf), "%d", n);
+
+	return buf;
+}
+
+/* isakmp.h */
+char *
+s_isakmp_state(t, d, s)
+	int t, d, s;
+{
+	switch (t) {
+	case ISAKMP_ETYPE_AGG:
+		switch (d) {
+		case INITIATOR:
+			switch (s) {
+			case PHASE1ST_MSG1SENT:
+				return "agg I msg1";
+			case PHASE1ST_ESTABLISHED:
+				return "agg I msg2";
+			default:
+				break;
+			}
+		case RESPONDER:
+			switch (s) {
+			case PHASE1ST_MSG1SENT:
+				return "agg R msg1";
+			default:
+				break;
+			}
+		}
+		break;
+	case ISAKMP_ETYPE_BASE:
+		switch (d) {
+		case INITIATOR:
+			switch (s) {
+			case PHASE1ST_MSG1SENT:
+				return "base I msg1";
+			case PHASE1ST_MSG2SENT:
+				return "base I msg2";
+			default:
+				break;
+			}
+		case RESPONDER:
+			switch (s) {
+			case PHASE1ST_MSG1SENT:
+				return "base R msg1";
+			case PHASE1ST_ESTABLISHED:
+				return "base R msg2";
+			default:
+				break;
+			}
+		}
+		break;
+	case ISAKMP_ETYPE_IDENT:
+		switch (d) {
+		case INITIATOR:
+			switch (s) {
+			case PHASE1ST_MSG1SENT:
+				return "ident I msg1";
+			case PHASE1ST_MSG2SENT:
+				return "ident I msg2";
+			case PHASE1ST_MSG3SENT:
+				return "ident I msg3";
+			default:
+				break;
+			}
+		case RESPONDER:
+			switch (s) {
+			case PHASE1ST_MSG1SENT:
+				return "ident R msg1";
+			case PHASE1ST_MSG2SENT:
+				return "ident R msg2";
+			case PHASE1ST_ESTABLISHED:
+				return "ident R msg3";
+			default:
+				break;
+			}
+		}
+		break;
+	case ISAKMP_ETYPE_QUICK:
+		switch (d) {
+		case INITIATOR:
+			switch (s) {
+			case PHASE2ST_MSG1SENT:
+				return "quick I msg1";
+			case PHASE2ST_ADDSA:
+				return "quick I msg2";
+			default:
+				break;
+			}
+		case RESPONDER:
+			switch (s) {
+			case PHASE2ST_MSG1SENT:
+				return "quick R msg1";
+			case PHASE2ST_COMMIT:
+				return "quick R msg2";
+			default:
+				break;
+			}
+		}
+		break;
+	default:
+	case ISAKMP_ETYPE_NONE:
+	case ISAKMP_ETYPE_AUTH:
+	case ISAKMP_ETYPE_INFO:
+	case ISAKMP_ETYPE_NEWGRP:
+	case ISAKMP_ETYPE_ACKINFO:
+		break;
+	}
+	/*NOTREACHED*/
+
+	return "???";
+}
+
+static struct ksmap name_isakmp_certtype[] = {
+{ ISAKMP_CERT_NONE,	"NONE",					NULL },
+{ ISAKMP_CERT_PKCS7,	"PKCS #7 wrapped X.509 certificate",	NULL },
+{ ISAKMP_CERT_PGP,	"PGP Certificate",			NULL },
+{ ISAKMP_CERT_DNS,	"DNS Signed Key",			NULL },
+{ ISAKMP_CERT_X509SIGN,	"X.509 Certificate Signature",		NULL },
+{ ISAKMP_CERT_X509KE,	"X.509 Certificate Key Exchange",	NULL },
+{ ISAKMP_CERT_KERBEROS,	"Kerberos Tokens",			NULL },
+{ ISAKMP_CERT_CRL,	"Certificate Revocation List (CRL)",	NULL },
+{ ISAKMP_CERT_ARL,	"Authority Revocation List (ARL)",	NULL },
+{ ISAKMP_CERT_SPKI,	"SPKI Certificate",			NULL },
+{ ISAKMP_CERT_X509ATTR,	"X.509 Certificate Attribute",		NULL },
+};
+
+char *
+s_isakmp_certtype(k)
+	int k;
+{
+	int i;
+	for (i = 0; i < ARRAYLEN(name_isakmp_certtype); i++)
+		if (name_isakmp_certtype[i].key == k)
+			return name_isakmp_certtype[i].str;
+	return num2str(k);
+}
+
+static struct ksmap name_isakmp_etype[] = {
+{ ISAKMP_ETYPE_NONE,	"None",			NULL },
+{ ISAKMP_ETYPE_BASE,	"Base",			NULL },
+{ ISAKMP_ETYPE_IDENT,	"Identity Protection",	NULL },
+{ ISAKMP_ETYPE_AUTH,	"Authentication Only",	NULL },
+{ ISAKMP_ETYPE_AGG,	"Aggressive",		NULL },
+{ ISAKMP_ETYPE_INFO,	"Informational",	NULL },
+{ ISAKMP_ETYPE_CFG,	"Mode config",		NULL },
+{ ISAKMP_ETYPE_QUICK,	"Quick",		NULL },
+{ ISAKMP_ETYPE_NEWGRP,	"New Group",		NULL },
+{ ISAKMP_ETYPE_ACKINFO,	"Acknowledged Informational",	NULL },
+};
+
+char *
+s_isakmp_etype(k)
+	int k;
+{
+	int i;
+	for (i = 0; i < ARRAYLEN(name_isakmp_etype); i++)
+		if (name_isakmp_etype[i].key == k)
+			return name_isakmp_etype[i].str;
+	return num2str(k);
+}
+
+static struct ksmap name_isakmp_notify_msg[] = {
+{ ISAKMP_NTYPE_INVALID_PAYLOAD_TYPE,	"INVALID-PAYLOAD-TYPE",		NULL },
+{ ISAKMP_NTYPE_DOI_NOT_SUPPORTED,	"DOI-NOT-SUPPORTED",		NULL },
+{ ISAKMP_NTYPE_SITUATION_NOT_SUPPORTED,	"SITUATION-NOT-SUPPORTED",	NULL },
+{ ISAKMP_NTYPE_INVALID_COOKIE,		"INVALID-COOKIE",		NULL },
+{ ISAKMP_NTYPE_INVALID_MAJOR_VERSION,	"INVALID-MAJOR-VERSION",	NULL },
+{ ISAKMP_NTYPE_INVALID_MINOR_VERSION,	"INVALID-MINOR-VERSION",	NULL },
+{ ISAKMP_NTYPE_INVALID_EXCHANGE_TYPE,	"INVALID-EXCHANGE-TYPE",	NULL },
+{ ISAKMP_NTYPE_INVALID_FLAGS,		"INVALID-FLAGS",		NULL },
+{ ISAKMP_NTYPE_INVALID_MESSAGE_ID,	"INVALID-MESSAGE-ID",		NULL },
+{ ISAKMP_NTYPE_INVALID_PROTOCOL_ID,	"INVALID-PROTOCOL-ID",		NULL },
+{ ISAKMP_NTYPE_INVALID_SPI,		"INVALID-SPI",			NULL },
+{ ISAKMP_NTYPE_INVALID_TRANSFORM_ID,	"INVALID-TRANSFORM-ID",		NULL },
+{ ISAKMP_NTYPE_ATTRIBUTES_NOT_SUPPORTED, "ATTRIBUTES-NOT-SUPPORTED",	NULL },
+{ ISAKMP_NTYPE_NO_PROPOSAL_CHOSEN,	"NO-PROPOSAL-CHOSEN",		NULL },
+{ ISAKMP_NTYPE_BAD_PROPOSAL_SYNTAX,	"BAD-PROPOSAL-SYNTAX",		NULL },
+{ ISAKMP_NTYPE_PAYLOAD_MALFORMED,	"PAYLOAD-MALFORMED",		NULL },
+{ ISAKMP_NTYPE_INVALID_KEY_INFORMATION,	"INVALID-KEY-INFORMATION",	NULL },
+{ ISAKMP_NTYPE_INVALID_ID_INFORMATION,	"INVALID-ID-INFORMATION",	NULL },
+{ ISAKMP_NTYPE_INVALID_CERT_ENCODING,	"INVALID-CERT-ENCODING",	NULL },
+{ ISAKMP_NTYPE_INVALID_CERTIFICATE,	"INVALID-CERTIFICATE",		NULL },
+{ ISAKMP_NTYPE_BAD_CERT_REQUEST_SYNTAX,	"BAD-CERT-REQUEST-SYNTAX",	NULL },
+{ ISAKMP_NTYPE_INVALID_CERT_AUTHORITY,	"INVALID-CERT-AUTHORITY",	NULL },
+{ ISAKMP_NTYPE_INVALID_HASH_INFORMATION, "INVALID-HASH-INFORMATION",	NULL },
+{ ISAKMP_NTYPE_AUTHENTICATION_FAILED,	"AUTHENTICATION-FAILED",	NULL },
+{ ISAKMP_NTYPE_INVALID_SIGNATURE,	"INVALID-SIGNATURE",		NULL },
+{ ISAKMP_NTYPE_ADDRESS_NOTIFICATION,	"ADDRESS-NOTIFICATION",		NULL },
+{ ISAKMP_NTYPE_NOTIFY_SA_LIFETIME,	"NOTIFY-SA-LIFETIME",		NULL },
+{ ISAKMP_NTYPE_CERTIFICATE_UNAVAILABLE,	"CERTIFICATE-UNAVAILABLE",	NULL },
+{ ISAKMP_NTYPE_UNSUPPORTED_EXCHANGE_TYPE, "UNSUPPORTED-EXCHANGE-TYPE",	NULL },
+{ ISAKMP_NTYPE_UNEQUAL_PAYLOAD_LENGTHS,	"UNEQUAL-PAYLOAD-LENGTHS",	NULL },
+{ ISAKMP_NTYPE_CONNECTED,		"CONNECTED",			NULL },
+{ ISAKMP_NTYPE_RESPONDER_LIFETIME,	"RESPONDER-LIFETIME",		NULL },
+{ ISAKMP_NTYPE_REPLAY_STATUS,		"REPLAY-STATUS",		NULL },
+{ ISAKMP_NTYPE_INITIAL_CONTACT,		"INITIAL-CONTACT",		NULL },
+#ifdef ENABLE_HYBRID
+{ ISAKMP_NTYPE_UNITY_HEARTBEAT,		"HEARTBEAT (Unity)",		NULL },
+#endif
+{ ISAKMP_LOG_RETRY_LIMIT_REACHED,	"RETRY-LIMIT-REACHED",		NULL },
+};
+
+char *
+s_isakmp_notify_msg(k)
+	int k;
+{
+	int i;
+	for (i = 0; i < ARRAYLEN(name_isakmp_notify_msg); i++)
+		if (name_isakmp_notify_msg[i].key == k)
+			return name_isakmp_notify_msg[i].str;
+
+	return num2str(k);
+}
+
+static struct ksmap name_isakmp_nptype[] = {
+{ ISAKMP_NPTYPE_NONE,		"none",		NULL },
+{ ISAKMP_NPTYPE_SA,		"sa",		NULL },
+{ ISAKMP_NPTYPE_P,		"prop",		NULL },
+{ ISAKMP_NPTYPE_T,		"trns",		NULL },
+{ ISAKMP_NPTYPE_KE,		"ke",		NULL },
+{ ISAKMP_NPTYPE_ID,		"id",		NULL },
+{ ISAKMP_NPTYPE_CERT,		"cert",		NULL },
+{ ISAKMP_NPTYPE_CR,		"cr",		NULL },
+{ ISAKMP_NPTYPE_HASH,		"hash",		NULL },
+{ ISAKMP_NPTYPE_SIG,		"sig",		NULL },
+{ ISAKMP_NPTYPE_NONCE,		"nonce",	NULL },
+{ ISAKMP_NPTYPE_N,		"notify",	NULL },
+{ ISAKMP_NPTYPE_D,		"delete",	NULL },
+{ ISAKMP_NPTYPE_VID,		"vid",		NULL },
+{ ISAKMP_NPTYPE_ATTR,		"attr",		NULL },
+{ ISAKMP_NPTYPE_GSS,		"gss id",	NULL },
+{ ISAKMP_NPTYPE_NATD_RFC,	"nat-d",	NULL },
+{ ISAKMP_NPTYPE_NATOA_RFC,	"nat-oa",	NULL },
+{ ISAKMP_NPTYPE_NATD_DRAFT,	"nat-d",	NULL },
+{ ISAKMP_NPTYPE_NATOA_DRAFT,	"nat-oa",	NULL },
+{ ISAKMP_NPTYPE_FRAG,		"ike frag",	NULL },
+};
+
+char *
+s_isakmp_nptype(k)
+	int k;
+{
+	int i;
+	for (i = 0; i < ARRAYLEN(name_isakmp_nptype); i++)
+		if (name_isakmp_nptype[i].key == k)
+			return name_isakmp_nptype[i].str;
+	return num2str(k);
+}
+
+#ifdef ENABLE_HYBRID
+/* isakmp_cfg.h / isakmp_unity.h / isakmp_xauth.h */
+static struct ksmap name_isakmp_cfg_type[] = {
+{ INTERNAL_IP4_ADDRESS,		"INTERNAL_IP4_ADDRESS",		NULL },
+{ INTERNAL_IP4_NETMASK,		"INTERNAL_IP4_NETMASK",		NULL },
+{ INTERNAL_IP4_DNS,		"INTERNAL_IP4_DNS",		NULL },
+{ INTERNAL_IP4_NBNS,		"INTERNAL_IP4_NBNS",		NULL },
+{ INTERNAL_ADDRESS_EXPIRY,	"INTERNAL_ADDRESS_EXPIRY",	NULL },
+{ INTERNAL_IP4_DHCP,		"INTERNAL_IP4_DHCP",		NULL },
+{ APPLICATION_VERSION,		"APPLICATION_VERSION",		NULL },
+{ INTERNAL_IP6_ADDRESS,		"INTERNAL_IP6_ADDRESS",		NULL },
+{ INTERNAL_IP6_NETMASK,		"INTERNAL_IP6_NETMASK",		NULL },
+{ INTERNAL_IP6_DNS,		"INTERNAL_IP6_DNS",		NULL },
+{ INTERNAL_IP6_NBNS,		"INTERNAL_IP6_NBNS",		NULL },
+{ INTERNAL_IP6_DHCP,		"INTERNAL_IP6_DHCP",		NULL },
+{ INTERNAL_IP4_SUBNET,		"INTERNAL_IP4_SUBNET",		NULL },
+{ SUPPORTED_ATTRIBUTES,		"SUPPORTED_ATTRIBUTES",		NULL },
+{ INTERNAL_IP6_SUBNET,		"INTERNAL_IP6_SUBNET",		NULL },
+{ XAUTH_TYPE,			"XAUTH_TYPE",			NULL },
+{ XAUTH_USER_NAME,		"XAUTH_USER_NAME",		NULL },
+{ XAUTH_USER_PASSWORD,		"XAUTH_USER_PASSWORD",		NULL },
+{ XAUTH_PASSCODE,		"XAUTH_PASSCODE",		NULL },
+{ XAUTH_MESSAGE,		"XAUTH_MESSAGE",		NULL },
+{ XAUTH_CHALLENGE,		"XAUTH_CHALLENGE",		NULL },
+{ XAUTH_DOMAIN,			"XAUTH_DOMAIN",			NULL },
+{ XAUTH_STATUS,			"XAUTH_STATUS",			NULL },
+{ XAUTH_NEXT_PIN,		"XAUTH_NEXT_PIN",		NULL },
+{ XAUTH_ANSWER,			"XAUTH_ANSWER",			NULL },
+{ UNITY_BANNER,			"UNITY_BANNER",			NULL },
+{ UNITY_SAVE_PASSWD,		"UNITY_SAVE_PASSWD",		NULL },
+{ UNITY_DEF_DOMAIN,		"UNITY_DEF_DOMAIN",		NULL },
+{ UNITY_SPLITDNS_NAME,		"UNITY_SPLITDNS_NAME",		NULL },
+{ UNITY_SPLIT_INCLUDE,		"UNITY_SPLIT_INCLUDE",		NULL },
+{ UNITY_NATT_PORT,		"UNITY_NATT_PORT",		NULL },
+{ UNITY_LOCAL_LAN,		"UNITY_LOCAL_LAN",		NULL },
+{ UNITY_PFS,			"UNITY_PFS",			NULL },
+{ UNITY_FW_TYPE,		"UNITY_FW_TYPE",		NULL },
+{ UNITY_BACKUP_SERVERS,		"UNITY_BACKUP_SERVERS",		NULL },
+{ UNITY_DDNS_HOSTNAME,		"UNITY_DDNS_HOSTNAME",		NULL },
+};
+
+char *
+s_isakmp_cfg_type(k)
+	int k;
+{
+	int i;
+	for (i = 0; i < ARRAYLEN(name_isakmp_cfg_type); i++)
+		if (name_isakmp_cfg_type[i].key == k)
+			return name_isakmp_cfg_type[i].str;
+	return num2str(k);
+}
+
+/* isakmp_cfg.h / isakmp_unity.h / isakmp_xauth.h */
+static struct ksmap name_isakmp_cfg_ptype[] = {
+{ ISAKMP_CFG_ACK,		"mode config ACK",		NULL },
+{ ISAKMP_CFG_SET,		"mode config SET",		NULL },
+{ ISAKMP_CFG_REQUEST,		"mode config REQUEST",		NULL },
+{ ISAKMP_CFG_REPLY,		"mode config REPLY",		NULL },
+};
+
+char *
+s_isakmp_cfg_ptype(k)
+	int k;
+{
+	int i;
+	for (i = 0; i < ARRAYLEN(name_isakmp_cfg_ptype); i++)
+		if (name_isakmp_cfg_ptype[i].key == k)
+			return name_isakmp_cfg_ptype[i].str;
+	return num2str(k);
+}
+
+#endif
+
+/* ipsec_doi.h */
+static struct ksmap name_ipsecdoi_proto[] = {
+{ IPSECDOI_PROTO_ISAKMP,	"ISAKMP",	s_ipsecdoi_trns_isakmp },
+{ IPSECDOI_PROTO_IPSEC_AH,	"AH",		s_ipsecdoi_trns_ah },
+{ IPSECDOI_PROTO_IPSEC_ESP,	"ESP",		s_ipsecdoi_trns_esp },
+{ IPSECDOI_PROTO_IPCOMP,	"IPCOMP",	s_ipsecdoi_trns_ipcomp },
+};
+
+char *
+s_ipsecdoi_proto(k)
+	int k;
+{
+	int i;
+	for (i = 0; i < ARRAYLEN(name_ipsecdoi_proto); i++)
+		if (name_ipsecdoi_proto[i].key == k)
+			return name_ipsecdoi_proto[i].str;
+	return num2str(k);
+}
+
+static struct ksmap name_ipsecdoi_trns_isakmp[] = {
+{ IPSECDOI_KEY_IKE,	"IKE", NULL },
+};
+
+char *
+s_ipsecdoi_trns_isakmp(k)
+	int k;
+{
+	int i;
+	for (i = 0; i < ARRAYLEN(name_ipsecdoi_trns_isakmp); i++)
+		if (name_ipsecdoi_trns_isakmp[i].key == k)
+			return name_ipsecdoi_trns_isakmp[i].str;
+	return num2str(k);
+}
+
+static struct ksmap name_ipsecdoi_trns_ah[] = {
+{ IPSECDOI_AH_MD5,	"MD5", NULL },
+{ IPSECDOI_AH_SHA,	"SHA", NULL },
+{ IPSECDOI_AH_DES,	"DES", NULL },
+{ IPSECDOI_AH_SHA256,	"SHA256", NULL },
+{ IPSECDOI_AH_SHA384,	"SHA384", NULL },
+{ IPSECDOI_AH_SHA512,	"SHA512", NULL },
+};
+
+char *
+s_ipsecdoi_trns_ah(k)
+	int k;
+{
+	int i;
+	for (i = 0; i < ARRAYLEN(name_ipsecdoi_trns_ah); i++)
+		if (name_ipsecdoi_trns_ah[i].key == k)
+			return name_ipsecdoi_trns_ah[i].str;
+	return num2str(k);
+}
+
+static struct ksmap name_ipsecdoi_trns_esp[] = {
+{ IPSECDOI_ESP_DES_IV64,	"DES_IV64",	NULL },
+{ IPSECDOI_ESP_DES,		"DES",		NULL },
+{ IPSECDOI_ESP_3DES,		"3DES",		NULL },
+{ IPSECDOI_ESP_RC5,		"RC5",		NULL },
+{ IPSECDOI_ESP_IDEA,		"IDEA",		NULL },
+{ IPSECDOI_ESP_CAST,		"CAST",		NULL },
+{ IPSECDOI_ESP_BLOWFISH,	"BLOWFISH",	NULL },
+{ IPSECDOI_ESP_3IDEA,		"3IDEA",	NULL },
+{ IPSECDOI_ESP_DES_IV32,	"DES_IV32",	NULL },
+{ IPSECDOI_ESP_RC4,		"RC4",		NULL },
+{ IPSECDOI_ESP_NULL,		"NULL",		NULL },
+{ IPSECDOI_ESP_AES,		"AES",		NULL },
+{ IPSECDOI_ESP_TWOFISH,		"TWOFISH",	NULL },
+{ IPSECDOI_ESP_CAMELLIA,	"CAMELLIA",	NULL },
+};
+
+char *
+s_ipsecdoi_trns_esp(k)
+	int k;
+{
+	int i;
+	for (i = 0; i < ARRAYLEN(name_ipsecdoi_trns_esp); i++)
+		if (name_ipsecdoi_trns_esp[i].key == k)
+			return name_ipsecdoi_trns_esp[i].str;
+	return num2str(k);
+}
+
+static struct ksmap name_ipsecdoi_trns_ipcomp[] = {
+{ IPSECDOI_IPCOMP_OUI,		"OUI",		NULL},
+{ IPSECDOI_IPCOMP_DEFLATE,	"DEFLATE",	NULL},
+{ IPSECDOI_IPCOMP_LZS,		"LZS",		NULL},
+};
+
+char *
+s_ipsecdoi_trns_ipcomp(k)
+	int k;
+{
+	int i;
+	for (i = 0; i < ARRAYLEN(name_ipsecdoi_trns_ipcomp); i++)
+		if (name_ipsecdoi_trns_ipcomp[i].key == k)
+			return name_ipsecdoi_trns_ipcomp[i].str;
+	return num2str(k);
+}
+
+char *
+s_ipsecdoi_trns(proto, trns)
+	int proto, trns;
+{
+	int i;
+	for (i = 0; i < ARRAYLEN(name_ipsecdoi_proto); i++)
+		if (name_ipsecdoi_proto[i].key == proto
+		 && name_ipsecdoi_proto[i].f)
+			return (name_ipsecdoi_proto[i].f)(trns);
+	return num2str(trns);
+}
+
+static struct ksmap name_attr_ipsec[] = {
+{ IPSECDOI_ATTR_SA_LD_TYPE,	"SA Life Type",		s_ipsecdoi_ltype },
+{ IPSECDOI_ATTR_SA_LD,		"SA Life Duration",	NULL },
+{ IPSECDOI_ATTR_GRP_DESC,	"Group Description",	NULL },
+{ IPSECDOI_ATTR_ENC_MODE,	"Encryption Mode",	s_ipsecdoi_encmode },
+{ IPSECDOI_ATTR_AUTH,		"Authentication Algorithm", s_ipsecdoi_auth },
+{ IPSECDOI_ATTR_KEY_LENGTH,	"Key Length",		NULL },
+{ IPSECDOI_ATTR_KEY_ROUNDS,	"Key Rounds",		NULL },
+{ IPSECDOI_ATTR_COMP_DICT_SIZE,	"Compression Dictionary Size",	NULL },
+{ IPSECDOI_ATTR_COMP_PRIVALG,	"Compression Private Algorithm", NULL },
+};
+
+char *
+s_ipsecdoi_attr(k)
+	int k;
+{
+	int i;
+	for (i = 0; i < ARRAYLEN(name_attr_ipsec); i++)
+		if (name_attr_ipsec[i].key == k)
+			return name_attr_ipsec[i].str;
+	return num2str(k);
+}
+
+static struct ksmap name_attr_ipsec_ltype[] = {
+{ IPSECDOI_ATTR_SA_LD_TYPE_SEC,	"seconds",	NULL },
+{ IPSECDOI_ATTR_SA_LD_TYPE_KB,	"kilobytes",	NULL },
+};
+
+char *
+s_ipsecdoi_ltype(k)
+	int k;
+{
+	int i;
+	for (i = 0; i < ARRAYLEN(name_attr_ipsec_ltype); i++)
+		if (name_attr_ipsec_ltype[i].key == k)
+			return name_attr_ipsec_ltype[i].str;
+	return num2str(k);
+}
+
+static struct ksmap name_attr_ipsec_encmode[] = {
+{ IPSECDOI_ATTR_ENC_MODE_ANY,		"Any",		NULL },
+{ IPSECDOI_ATTR_ENC_MODE_TUNNEL,	"Tunnel",	NULL },
+{ IPSECDOI_ATTR_ENC_MODE_TRNS,		"Transport",	NULL },
+{ IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_RFC,	"UDP-Tunnel",	NULL },
+{ IPSECDOI_ATTR_ENC_MODE_UDPTRNS_RFC,	"UDP-Transport",	NULL },
+{ IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_DRAFT,	"UDP-Tunnel",	NULL },
+{ IPSECDOI_ATTR_ENC_MODE_UDPTRNS_DRAFT,	"UDP-Transport",	NULL },
+};
+
+char *
+s_ipsecdoi_encmode(k)
+	int k;
+{
+	int i;
+	for (i = 0; i < ARRAYLEN(name_attr_ipsec_encmode); i++)
+		if (name_attr_ipsec_encmode[i].key == k)
+			return name_attr_ipsec_encmode[i].str;
+	return num2str(k);
+}
+
+static struct ksmap name_attr_ipsec_auth[] = {
+{ IPSECDOI_ATTR_AUTH_HMAC_MD5,		"hmac-md5",	NULL },
+{ IPSECDOI_ATTR_AUTH_HMAC_SHA1,		"hmac-sha",	NULL },
+{ IPSECDOI_ATTR_AUTH_HMAC_SHA2_256,	"hmac-sha256",	NULL },
+{ IPSECDOI_ATTR_AUTH_HMAC_SHA2_384,	"hmac-sha384",	NULL },
+{ IPSECDOI_ATTR_AUTH_HMAC_SHA2_512,	"hmac-sha512",	NULL },
+{ IPSECDOI_ATTR_AUTH_DES_MAC,		"des-mac",	NULL },
+{ IPSECDOI_ATTR_AUTH_KPDK,		"kpdk",		NULL },
+};
+
+char *
+s_ipsecdoi_auth(k)
+	int k;
+{
+	int i;
+	for (i = 0; i < ARRAYLEN(name_attr_ipsec_auth); i++)
+		if (name_attr_ipsec_auth[i].key == k)
+			return name_attr_ipsec_auth[i].str;
+	return num2str(k);
+}
+
+char *
+s_ipsecdoi_attr_v(type, val)
+	int type, val;
+{
+	int i;
+	for (i = 0; i < ARRAYLEN(name_attr_ipsec); i++)
+		if (name_attr_ipsec[i].key == type
+		 && name_attr_ipsec[i].f)
+			return (name_attr_ipsec[i].f)(val);
+	return num2str(val);
+}
+
+static struct ksmap name_ipsecdoi_ident[] = {
+{ IPSECDOI_ID_IPV4_ADDR,	"IPv4_address",	NULL },
+{ IPSECDOI_ID_FQDN,		"FQDN",		NULL },
+{ IPSECDOI_ID_USER_FQDN,	"User_FQDN",	NULL },
+{ IPSECDOI_ID_IPV4_ADDR_SUBNET,	"IPv4_subnet",	NULL },
+{ IPSECDOI_ID_IPV6_ADDR,	"IPv6_address",	NULL },
+{ IPSECDOI_ID_IPV6_ADDR_SUBNET,	"IPv6_subnet",	NULL },
+{ IPSECDOI_ID_IPV4_ADDR_RANGE,	"IPv4_address_range",	NULL },
+{ IPSECDOI_ID_IPV6_ADDR_RANGE,	"IPv6_address_range",	NULL },
+{ IPSECDOI_ID_DER_ASN1_DN,	"DER_ASN1_DN",	NULL },
+{ IPSECDOI_ID_DER_ASN1_GN,	"DER_ASN1_GN",	NULL },
+{ IPSECDOI_ID_KEY_ID,		"KEY_ID",	NULL },
+};
+
+char *
+s_ipsecdoi_ident(k)
+	int k;
+{
+	int i;
+	for (i = 0; i < ARRAYLEN(name_ipsecdoi_ident); i++)
+		if (name_ipsecdoi_ident[i].key == k)
+			return name_ipsecdoi_ident[i].str;
+	return num2str(k);
+}
+
+/* oakley.h */
+static struct ksmap name_oakley_attr[] = {
+{ OAKLEY_ATTR_ENC_ALG,		"Encryption Algorithm",	s_attr_isakmp_enc },
+{ OAKLEY_ATTR_HASH_ALG,		"Hash Algorithm",	s_attr_isakmp_hash },
+{ OAKLEY_ATTR_AUTH_METHOD,	"Authentication Method", s_oakley_attr_method },
+{ OAKLEY_ATTR_GRP_DESC,		"Group Description",	s_attr_isakmp_desc },
+{ OAKLEY_ATTR_GRP_TYPE,		"Group Type",		s_attr_isakmp_group },
+{ OAKLEY_ATTR_GRP_PI,		"Group Prime/Irreducible Polynomial",	NULL },
+{ OAKLEY_ATTR_GRP_GEN_ONE,	"Group Generator One",	NULL },
+{ OAKLEY_ATTR_GRP_GEN_TWO,	"Group Generator Two",	NULL },
+{ OAKLEY_ATTR_GRP_CURVE_A,	"Group Curve A",	NULL },
+{ OAKLEY_ATTR_GRP_CURVE_B,	"Group Curve B",	NULL },
+{ OAKLEY_ATTR_SA_LD_TYPE,	"Life Type",		s_attr_isakmp_ltype },
+{ OAKLEY_ATTR_SA_LD,		"Life Duration",	NULL },
+{ OAKLEY_ATTR_PRF,		"PRF",			NULL },
+{ OAKLEY_ATTR_KEY_LEN,		"Key Length",		NULL },
+{ OAKLEY_ATTR_FIELD_SIZE,	"Field Size",		NULL },
+{ OAKLEY_ATTR_GRP_ORDER,	"Group Order",		NULL },
+{ OAKLEY_ATTR_BLOCK_SIZE,	"Block Size",		NULL },
+{ OAKLEY_ATTR_GSS_ID,		"GSS-API endpoint name",NULL },
+};
+
+char *
+s_oakley_attr(k)
+	int k;
+{
+	int i;
+	for (i = 0; i < ARRAYLEN(name_oakley_attr); i++)
+		if (name_oakley_attr[i].key == k)
+			return name_oakley_attr[i].str;
+	return num2str(k);
+}
+
+static struct ksmap name_attr_isakmp_enc[] = {
+{ OAKLEY_ATTR_ENC_ALG_DES,	"DES-CBC",		NULL },
+{ OAKLEY_ATTR_ENC_ALG_IDEA,	"IDEA-CBC",		NULL },
+{ OAKLEY_ATTR_ENC_ALG_BLOWFISH,	"Blowfish-CBC",		NULL },
+{ OAKLEY_ATTR_ENC_ALG_RC5,	"RC5-R16-B64-CBC",	NULL },
+{ OAKLEY_ATTR_ENC_ALG_3DES,	"3DES-CBC",		NULL },
+{ OAKLEY_ATTR_ENC_ALG_CAST,	"CAST-CBC",		NULL },
+{ OAKLEY_ATTR_ENC_ALG_AES,	"AES-CBC",		NULL },
+};
+
+char *
+s_attr_isakmp_enc(k)
+	int k;
+{
+	int i;
+	for (i = 0; i < ARRAYLEN(name_attr_isakmp_enc); i++)
+		if (name_attr_isakmp_enc[i].key == k)
+			return name_attr_isakmp_enc[i].str;
+	return num2str(k);
+}
+
+static struct ksmap name_attr_isakmp_hash[] = {
+{ OAKLEY_ATTR_HASH_ALG_MD5,	"MD5",		NULL },
+{ OAKLEY_ATTR_HASH_ALG_SHA,	"SHA",		NULL },
+{ OAKLEY_ATTR_HASH_ALG_TIGER,	"Tiger",	NULL },
+{ OAKLEY_ATTR_HASH_ALG_SHA2_256,"SHA256",	NULL },
+{ OAKLEY_ATTR_HASH_ALG_SHA2_384,"SHA384",	NULL },
+{ OAKLEY_ATTR_HASH_ALG_SHA2_512,"SHA512",	NULL },
+};
+
+char *
+s_attr_isakmp_hash(k)
+	int k;
+{
+	int i;
+	for (i = 0; i < ARRAYLEN(name_attr_isakmp_hash); i++)
+		if (name_attr_isakmp_hash[i].key == k)
+			return name_attr_isakmp_hash[i].str;
+	return num2str(k);
+}
+
+static struct ksmap name_attr_isakmp_method[] = {
+{ OAKLEY_ATTR_AUTH_METHOD_PSKEY,		"pre-shared key",	NULL },
+{ OAKLEY_ATTR_AUTH_METHOD_DSSSIG,		"DSS signatures",	NULL },
+{ OAKLEY_ATTR_AUTH_METHOD_RSASIG,		"RSA signatures",	NULL },
+{ OAKLEY_ATTR_AUTH_METHOD_RSAENC,		"Encryption with RSA",	NULL },
+{ OAKLEY_ATTR_AUTH_METHOD_RSAREV,		"Revised encryption with RSA",	NULL },
+{ OAKLEY_ATTR_AUTH_METHOD_EGENC,		"Encryption with El-Gamal",	NULL },
+{ OAKLEY_ATTR_AUTH_METHOD_EGREV,		"Revised encryption with El-Gamal",	NULL },
+#ifdef HAVE_GSSAPI
+{ OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB,		"GSS-API on Kerberos 5", NULL },
+#endif
+#ifdef ENABLE_HYBRID
+{ OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_R,		"Hybrid DSS server",	NULL },
+{ OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_R,		"Hybrid RSA server",	NULL },
+{ OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_I,		"Hybrid DSS client",	NULL },
+{ OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_I,		"Hybrid RSA client",	NULL },
+{ OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_I,	"XAuth pskey client",	NULL },
+{ OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_R,	"XAuth pskey server",	NULL },
+{ OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_I,	"XAuth RSASIG client",	NULL },
+{ OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_R,	"XAuth RSASIG server",	NULL },
+#endif
+};
+
+char *
+s_oakley_attr_method(k)
+	int k;
+{
+	int i;
+	for (i = 0; i < ARRAYLEN(name_attr_isakmp_method); i++)
+		if (name_attr_isakmp_method[i].key == k)
+			return name_attr_isakmp_method[i].str;
+	return num2str(k);
+}
+
+static struct ksmap name_attr_isakmp_desc[] = {
+{ OAKLEY_ATTR_GRP_DESC_MODP768,		"768-bit MODP group",	NULL },
+{ OAKLEY_ATTR_GRP_DESC_MODP1024,	"1024-bit MODP group",	NULL },
+{ OAKLEY_ATTR_GRP_DESC_EC2N155,		"EC2N group on GP[2^155]",	NULL },
+{ OAKLEY_ATTR_GRP_DESC_EC2N185,		"EC2N group on GP[2^185]",	NULL },
+{ OAKLEY_ATTR_GRP_DESC_MODP1536,	"1536-bit MODP group",	NULL },
+{ OAKLEY_ATTR_GRP_DESC_MODP2048,	"2048-bit MODP group",	NULL },
+{ OAKLEY_ATTR_GRP_DESC_MODP3072,	"3072-bit MODP group",	NULL },
+{ OAKLEY_ATTR_GRP_DESC_MODP4096,	"4096-bit MODP group",	NULL },
+{ OAKLEY_ATTR_GRP_DESC_MODP6144,	"6144-bit MODP group",	NULL },
+{ OAKLEY_ATTR_GRP_DESC_MODP8192,	"8192-bit MODP group",	NULL },
+};
+
+char *
+s_attr_isakmp_desc(k)
+	int k;
+{
+	int i;
+	for (i = 0; i < ARRAYLEN(name_attr_isakmp_desc); i++)
+		if (name_attr_isakmp_desc[i].key == k)
+			return name_attr_isakmp_desc[i].str;
+	return num2str(k);
+}
+
+static struct ksmap name_attr_isakmp_group[] = {
+{ OAKLEY_ATTR_GRP_TYPE_MODP,	"MODP",	NULL },
+{ OAKLEY_ATTR_GRP_TYPE_ECP,	"ECP",	NULL },
+{ OAKLEY_ATTR_GRP_TYPE_EC2N,	"EC2N",	NULL },
+};
+
+char *
+s_attr_isakmp_group(k)
+	int k;
+{
+	int i;
+	for (i = 0; i < ARRAYLEN(name_attr_isakmp_group); i++)
+		if (name_attr_isakmp_group[i].key == k)
+			return name_attr_isakmp_group[i].str;
+	return num2str(k);
+}
+
+static struct ksmap name_attr_isakmp_ltype[] = {
+{ OAKLEY_ATTR_SA_LD_TYPE_SEC,	"seconds",	NULL },
+{ OAKLEY_ATTR_SA_LD_TYPE_KB,	"kilobytes",	NULL },
+};
+
+char *
+s_attr_isakmp_ltype(k)
+	int k;
+{
+	int i;
+	for (i = 0; i < ARRAYLEN(name_attr_isakmp_ltype); i++)
+		if (name_attr_isakmp_ltype[i].key == k)
+			return name_attr_isakmp_ltype[i].str;
+	return num2str(k);
+}
+
+char *
+s_oakley_attr_v(type, val)
+	int type, val;
+{
+	int i;
+	for (i = 0; i < ARRAYLEN(name_oakley_attr); i++)
+		if (name_oakley_attr[i].key == type
+		 && name_oakley_attr[i].f)
+			return (name_oakley_attr[i].f)(val);
+	return num2str(val);
+}
+
+/* netinet6/ipsec.h */
+static struct ksmap name_ipsec_level[] = {
+{ IPSEC_LEVEL_USE,	"use",		NULL },
+{ IPSEC_LEVEL_REQUIRE,	"require",	NULL },
+{ IPSEC_LEVEL_UNIQUE,	"unique",	NULL },
+};
+
+char *
+s_ipsec_level(k)
+	int k;
+{
+	int i;
+	for (i = 0; i < ARRAYLEN(name_ipsec_level); i++)
+		if (name_ipsec_level[i].key == k)
+			return name_ipsec_level[i].str;
+	return num2str(k);
+}
+
+static struct ksmap name_algclass[] = {
+{ algclass_ipsec_enc,	"ipsec enc",	s_ipsecdoi_trns_esp },
+{ algclass_ipsec_auth,	"ipsec auth",	s_ipsecdoi_trns_ah },
+{ algclass_ipsec_comp,	"ipsec comp",	s_ipsecdoi_trns_ipcomp },
+{ algclass_isakmp_enc,	"isakmp enc",	s_attr_isakmp_enc },
+{ algclass_isakmp_hash,	"isakmp hash",	s_attr_isakmp_hash },
+{ algclass_isakmp_dh,	"isakmp dh",	s_attr_isakmp_desc },
+{ algclass_isakmp_ameth, "isakmp auth method",	s_oakley_attr_method },
+};
+
+char *
+s_algclass(k)
+	int k;
+{
+	int i;
+	for (i = 0; i < ARRAYLEN(name_algclass); i++)
+		if (name_algclass[i].key == k)
+			return name_algclass[i].str;
+	return num2str(k);
+}
+
+char *
+s_algtype(class, n)
+	int class, n;
+{
+	int i;
+	for (i = 0; i < ARRAYLEN(name_algclass); i++)
+		if (name_algclass[i].key == class
+		 && name_algclass[i].f)
+			return (name_algclass[i].f)(n);
+	return num2str(n);
+}
+
+/* pfkey.h */
+static struct ksmap name_pfkey_type[] = {
+{ SADB_GETSPI,		"GETSPI",	NULL },
+{ SADB_UPDATE,		"UPDATE",	NULL },
+{ SADB_ADD,		"ADD",		NULL },
+{ SADB_DELETE,		"DELETE",	NULL },
+{ SADB_GET,		"GET",		NULL },
+{ SADB_ACQUIRE,		"ACQUIRE",	NULL },
+{ SADB_REGISTER,	"REGISTER",	NULL },
+{ SADB_EXPIRE,		"EXPIRE",	NULL },
+{ SADB_FLUSH,		"FLUSH",	NULL },
+{ SADB_DUMP,		"DUMP",		NULL },
+{ SADB_X_PROMISC,	"X_PROMISC",	NULL },
+{ SADB_X_PCHANGE,	"X_PCHANGE",	NULL },
+{ SADB_X_SPDUPDATE,	"X_SPDUPDATE",	NULL },
+{ SADB_X_SPDADD,	"X_SPDADD",	NULL },
+{ SADB_X_SPDDELETE,	"X_SPDDELETE",	NULL },
+{ SADB_X_SPDGET,	"X_SPDGET",	NULL },
+{ SADB_X_SPDACQUIRE,	"X_SPDACQUIRE",	NULL },
+{ SADB_X_SPDDUMP,	"X_SPDDUMP",	NULL },
+{ SADB_X_SPDFLUSH,	"X_SPDFLUSH",	NULL },
+{ SADB_X_SPDSETIDX,	"X_SPDSETIDX",	NULL },
+{ SADB_X_SPDEXPIRE,	"X_SPDEXPIRE",	NULL },
+{ SADB_X_SPDDELETE2,	"X_SPDDELETE2",	NULL },
+#ifdef SADB_X_NAT_T_NEW_MAPPING
+{ SADB_X_NAT_T_NEW_MAPPING, "X_NAT_T_NEW_MAPPING", NULL },
+#endif
+#ifdef SADB_X_MIGRATE
+{ SADB_X_MIGRATE,	"X_MIGRATE",	NULL },
+#endif
+};
+
+char *
+s_pfkey_type(k)
+	int k;
+{
+	int i;
+	for (i = 0; i < ARRAYLEN(name_pfkey_type); i++)
+		if (name_pfkey_type[i].key == k)
+			return name_pfkey_type[i].str;
+	return num2str(k);
+}
+
+static struct ksmap name_pfkey_satype[] = {
+{ SADB_SATYPE_UNSPEC,	"UNSPEC",	NULL },
+{ SADB_SATYPE_AH,	"AH",		NULL },
+{ SADB_SATYPE_ESP,	"ESP",		NULL },
+{ SADB_SATYPE_RSVP,	"RSVP",		NULL },
+{ SADB_SATYPE_OSPFV2,	"OSPFV2",	NULL },
+{ SADB_SATYPE_RIPV2,	"RIPV2",	NULL },
+{ SADB_SATYPE_MIP,	"MIP",		NULL },
+{ SADB_X_SATYPE_IPCOMP,	"IPCOMP",	NULL },
+};
+
+char *
+s_pfkey_satype(k)
+	int k;
+{
+	int i;
+	for (i = 0; i < ARRAYLEN(name_pfkey_satype); i++)
+		if (name_pfkey_satype[i].key == k)
+			return name_pfkey_satype[i].str;
+	return num2str(k);
+}
+
+static struct ksmap name_direction[] = {
+{ IPSEC_DIR_INBOUND,	"in",	NULL },
+{ IPSEC_DIR_OUTBOUND,	"out",	NULL },
+#ifdef HAVE_POLICY_FWD
+{ IPSEC_DIR_FWD,	"fwd",	NULL },
+#endif
+};
+
+char *
+s_direction(k)
+	int k;
+{
+	int i;
+	for (i = 0; i < ARRAYLEN(name_direction); i++)
+		if (name_direction[i].key == k)
+			return name_direction[i].str;
+	return num2str(k);
+}
+
+char *
+s_proto(k)
+	int k;
+{
+	switch (k) {
+	case IPPROTO_ICMP:
+		return "icmp";
+	case IPPROTO_TCP:
+		return "tcp";
+	case IPPROTO_UDP:
+		return "udp";
+	case IPPROTO_ICMPV6:
+		return "icmpv6";
+	case IPSEC_ULPROTO_ANY:
+		return "any";
+	}
+
+	return num2str(k);
+}
+
+char *
+s_doi(int k)
+{
+  switch (k) {
+    case IPSEC_DOI:
+      return "ipsec_doi";
+    default:
+      return num2str(k);
+  }
+}
+
+char *
+s_etype (int k)
+{
+  switch (k) {
+    case ISAKMP_ETYPE_NONE:
+      return "_none";
+    case ISAKMP_ETYPE_BASE:
+      return "base";
+    case ISAKMP_ETYPE_IDENT:
+      return "main";
+    case ISAKMP_ETYPE_AUTH:
+      return "_auth";
+    case ISAKMP_ETYPE_AGG:
+      return "aggressive";
+    case ISAKMP_ETYPE_INFO:
+      return "_info";
+    case ISAKMP_ETYPE_QUICK:
+      return "_quick";
+    case ISAKMP_ETYPE_NEWGRP:
+      return "_newgrp";
+    case ISAKMP_ETYPE_ACKINFO:
+      return "_ackinfo";
+    default:
+      return num2str(k);
+  }
+}
+
+char *
+s_idtype (int k)
+{
+  switch (k) {
+    case IDTYPE_FQDN:
+      return "fqdn";
+    case IDTYPE_USERFQDN:
+      return "user_fqdn";
+    case IDTYPE_KEYID:
+      return "keyid";
+    case IDTYPE_ADDRESS:
+      return "address";
+    case IDTYPE_ASN1DN:
+      return "asn1dn";
+    default:
+      return num2str(k);
+  }
+}
+
+char *
+s_switch (int k)
+{
+  switch (k) {
+    case FALSE:
+      return "off";
+    case TRUE:
+      return "on";
+    default:
+      return num2str(k);
+  }
+}
diff --git a/src/racoon/strnames.h b/src/racoon/strnames.h
new file mode 100644
index 0000000..02ebbb5
--- /dev/null
+++ b/src/racoon/strnames.h
@@ -0,0 +1,80 @@
+/*	$NetBSD: strnames.h,v 1.4 2006/09/09 16:22:10 manu Exp $	*/
+
+/* Id: strnames.h,v 1.7 2005/04/18 10:04:26 manubsd Exp */
+
+/*
+ * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _STRNAMES_H
+#define _STRNAMES_H
+
+extern char *num2str __P((int n));
+
+extern char *s_isakmp_state __P((int, int, int));
+extern char *s_isakmp_certtype __P((int));
+extern char *s_isakmp_etype __P((int));
+extern char *s_isakmp_notify_msg __P((int));
+extern char *s_isakmp_nptype __P((int));
+extern char *s_ipsecdoi_proto __P((int));
+extern char *s_ipsecdoi_trns_isakmp __P((int));
+extern char *s_ipsecdoi_trns_ah __P((int));
+extern char *s_ipsecdoi_trns_esp __P((int));
+extern char *s_ipsecdoi_trns_ipcomp __P((int));
+extern char *s_ipsecdoi_trns __P((int, int));
+extern char *s_ipsecdoi_attr __P((int));
+extern char *s_ipsecdoi_ltype __P((int));
+extern char *s_ipsecdoi_encmode __P((int));
+extern char *s_ipsecdoi_auth __P((int));
+extern char *s_ipsecdoi_attr_v __P((int, int));
+extern char *s_ipsecdoi_ident __P((int));
+extern char *s_oakley_attr __P((int));
+extern char *s_attr_isakmp_enc __P((int));
+extern char *s_attr_isakmp_hash __P((int));
+extern char *s_oakley_attr_method __P((int));
+extern char *s_attr_isakmp_desc __P((int));
+extern char *s_attr_isakmp_group __P((int));
+extern char *s_attr_isakmp_ltype __P((int));
+extern char *s_oakley_attr_v __P((int, int));
+extern char *s_ipsec_level __P((int));
+extern char *s_algclass __P((int));
+extern char *s_algtype __P((int, int));
+extern char *s_pfkey_type __P((int));
+extern char *s_pfkey_satype __P((int));
+extern char *s_direction __P((int));
+extern char *s_proto __P((int));
+extern char *s_doi __P((int));
+extern char *s_etype __P((int));
+extern char *s_idtype __P((int));
+extern char *s_switch __P((int));
+#ifdef ENABLE_HYBRID
+extern char *s_isakmp_cfg_type __P((int));
+extern char *s_isakmp_cfg_ptype __P((int));
+#endif
+
+#endif /* _STRNAMES_H */
diff --git a/src/racoon/throttle.c b/src/racoon/throttle.c
new file mode 100644
index 0000000..cd7de1f
--- /dev/null
+++ b/src/racoon/throttle.c
@@ -0,0 +1,158 @@
+/*	$NetBSD: throttle.c,v 1.4 2006/09/09 16:22:10 manu Exp $	*/
+
+/* Id: throttle.c,v 1.5 2006/04/05 20:54:50 manubsd Exp */
+
+/*
+ * Copyright (C) 2004 Emmanuel Dreyfus
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#if TIME_WITH_SYS_TIME
+# include <sys/time.h>
+# include <time.h> 
+#else 
+# if HAVE_SYS_TIME_H
+#  include <sys/time.h>
+# else
+#  include <time.h>
+# endif 
+#endif
+#include <sys/param.h>
+#include <sys/queue.h>
+#include <sys/socket.h>
+
+#include <netinet/in.h>
+#include <resolv.h>
+
+#include "vmbuf.h"
+#include "misc.h"
+#include "plog.h"
+#include "throttle.h"
+#include "sockmisc.h"
+#include "libpfkey.h"
+#include "isakmp_var.h"
+#include "isakmp.h"
+#include "isakmp_xauth.h"
+#include "isakmp_cfg.h"
+#include "gcmalloc.h"
+
+struct throttle_list throttle_list = TAILQ_HEAD_INITIALIZER(throttle_list);
+
+
+struct throttle_entry *
+throttle_add(addr)
+	struct sockaddr *addr;
+{
+	struct throttle_entry *te;
+	size_t len;
+
+	len = sizeof(*te) 
+	    - sizeof(struct sockaddr_storage) 
+	    + sysdep_sa_len(addr);
+
+	if ((te = racoon_malloc(len)) == NULL)
+		return NULL;
+
+	te->penalty = time(NULL) + isakmp_cfg_config.auth_throttle;
+	memcpy(&te->host, addr, sysdep_sa_len(addr));
+	TAILQ_INSERT_HEAD(&throttle_list, te, next);
+
+	return te;
+}
+
+int
+throttle_host(addr, authfail) 
+	struct sockaddr *addr;
+	int authfail;
+{
+	struct throttle_entry *te;
+	int found = 0;
+	time_t now;
+
+	if (isakmp_cfg_config.auth_throttle == 0)
+		return 0;
+
+	now = time(NULL);
+
+restart:
+	RACOON_TAILQ_FOREACH_REVERSE(te, &throttle_list, throttle_list, next) {
+	  /*
+	   * Remove outdated entries 
+	   */
+		if (te->penalty < now) {
+			TAILQ_REMOVE(&throttle_list, te, next);
+			racoon_free(te);
+			goto restart;
+		}
+			
+		if (cmpsaddrwop(addr, (struct sockaddr *)&te->host) == 0) {
+			found = 1;
+			break;
+		}
+	}
+
+	/* 
+	 * No match, if auth failed, allocate a new throttle entry
+	 * give no penalty even on error: this is the first time
+	 * and we are indulgent.
+	 */
+	if (!found) {
+		if (authfail) {
+			if ((te = throttle_add(addr)) == NULL) {
+				plog(LLV_ERROR, LOCATION, NULL, 
+				    "Throttle insertion failed\n");
+				return (time(NULL) 
+				    + isakmp_cfg_config.auth_throttle);
+			}
+		}
+		return 0;
+	} else {
+		/*
+		 * We had a match and auth failed, increase penalty.
+		 */
+		if (authfail) {
+			time_t remaining;
+			time_t new;
+
+			remaining = te->penalty - now;
+			new = remaining + isakmp_cfg_config.auth_throttle;
+
+			if (new > THROTTLE_PENALTY_MAX)
+				new = THROTTLE_PENALTY_MAX;
+
+			te->penalty = now + new;
+		}
+	}
+	
+	return te->penalty;
+}
+
diff --git a/src/racoon/throttle.h b/src/racoon/throttle.h
new file mode 100644
index 0000000..baa9af5
--- /dev/null
+++ b/src/racoon/throttle.h
@@ -0,0 +1,51 @@
+/*	$NetBSD: throttle.h,v 1.4 2006/09/09 16:22:10 manu Exp $	*/
+
+/* Id: throttle.h,v 1.1 2004/11/30 00:46:09 manubsd Exp */
+
+/*
+ * Copyright (C) 2004 Emmanuel Dreyfus
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _THROTTLE_H
+#define _THROTTLE_H
+
+struct throttle_entry {
+	int penalty;
+	TAILQ_ENTRY(throttle_entry) next;
+	struct sockaddr_storage host;
+};
+
+TAILQ_HEAD(throttle_list, throttle_entry);
+
+#define THROTTLE_PENALTY 1
+#define THROTTLE_PENALTY_MAX 10
+
+struct throttle_entry *throttle_add(struct sockaddr *);
+int throttle_host(struct sockaddr *, int);
+
+#endif /* _THROTTLE_H */
diff --git a/src/racoon/var.h b/src/racoon/var.h
new file mode 100644
index 0000000..8abb1c2
--- /dev/null
+++ b/src/racoon/var.h
@@ -0,0 +1,107 @@
+/*	$NetBSD: var.h,v 1.4.6.1 2007/06/06 15:36:38 vanhu Exp $	*/
+
+/* Id: var.h,v 1.6 2004/11/20 16:16:59 monas Exp */
+
+/*
+ * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _VAR_H
+#define _VAR_H
+
+#if !defined(_VAR_H_)
+#define _VAR_H_
+
+#define MAX3(a, b, c) (a > b ? (a > c ? a : c) : (b > c ? b : c))
+
+#define ISSET(exp, bit) (((exp) & (bit)) == (bit))
+
+#define LALIGN(a) \
+    ((a) > 0 ? ((a) &~ (sizeof(long) - 1)) : sizeof(long))
+
+#define RNDUP(a) \
+    ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
+
+#define ARRAYLEN(a)	(sizeof(a)/sizeof(a[0]))
+
+#define BUFSIZE    5120
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+#ifndef TRUE
+#define TRUE 1
+#endif
+
+#ifdef ENABLE_STATS
+#include <sys/time.h>
+#endif
+#include <sys/socket.h>
+
+/*
+ * use of GETNAMEINFO(x, y, NULL) is not politically correct,
+ * as sizeof(NULL) would be 4, not 0. Also, gcc-3.4.2+ bombs on it.
+ * In such cases, use GETNAMEINFO_NULL(x, y)
+ */
+#include <sys/socket.h>
+#include <netdb.h>
+
+/* var.h is used from non-racoon code (like eaytest), so we can't use niflags */
+#define NIFLAGS	(NI_NUMERICHOST | NI_NUMERICSERV)
+
+#define GETNAMEINFO(x, y, z) \
+do { \
+	if (getnameinfo((x), sysdep_sa_len(x), (y), sizeof(y), (z), sizeof(z), \
+			NIFLAGS) != 0) { \
+		if (y != NULL) \
+			strncpy((y), "(invalid)", sizeof(y)); \
+		if (z != NULL) \
+			strncpy((z), "(invalid)", sizeof(z)); \
+	} \
+} while (0);
+
+#define GETNAMEINFO_NULL(x, y) \
+do { \
+	if (getnameinfo((x), sysdep_sa_len(x), (y), sizeof(y), NULL, 0, \
+			NIFLAGS) != 0) { \
+		if (y != NULL) \
+			strncpy((y), "(invalid)", sizeof(y)); \
+	} \
+} while (0);
+
+#include <sys/queue.h>
+#ifndef LIST_FOREACH
+#define LIST_FOREACH(elm, head, field) \
+	for (elm = LIST_FIRST(head); elm; elm = LIST_NEXT(elm, field))
+#endif
+
+#include "gcmalloc.h"
+
+#endif /*!defined(_VAR_H_)*/
+
+#endif /* _VAR_H */
diff --git a/src/racoon/vendorid.c b/src/racoon/vendorid.c
new file mode 100644
index 0000000..82ddfe4
--- /dev/null
+++ b/src/racoon/vendorid.c
@@ -0,0 +1,272 @@
+/*	$NetBSD: vendorid.c,v 1.4 2006/09/09 16:22:10 manu Exp $	*/
+
+/* Id: vendorid.c,v 1.10 2006/02/22 16:10:21 vanhu Exp */
+
+/*
+ * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include <sys/types.h>
+#include <sys/param.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <ctype.h>
+
+#include "var.h"
+#include "misc.h"
+#include "vmbuf.h"
+#include "plog.h"
+#include "debug.h"
+
+#include "localconf.h"
+#include "isakmp_var.h"
+#include "isakmp.h"
+#include "vendorid.h"
+#include "crypto_openssl.h"
+
+static struct vendor_id all_vendor_ids[] = {
+{ VENDORID_IPSEC_TOOLS, "IPSec-Tools" },
+{ VENDORID_GSSAPI_LONG, "A GSS-API Authentication Method for IKE" },
+{ VENDORID_GSSAPI     , "GSSAPI" },
+{ VENDORID_MS_NT5     , "MS NT5 ISAKMPOAKLEY" },
+{ VENDORID_NATT_00    , "draft-ietf-ipsec-nat-t-ike-00" },
+{ VENDORID_NATT_01    , "draft-ietf-ipsec-nat-t-ike-01" },
+{ VENDORID_NATT_02    , "draft-ietf-ipsec-nat-t-ike-02" },
+{ VENDORID_NATT_02_N  , "draft-ietf-ipsec-nat-t-ike-02\n" },
+{ VENDORID_NATT_03    , "draft-ietf-ipsec-nat-t-ike-03" },
+{ VENDORID_NATT_04    , "draft-ietf-ipsec-nat-t-ike-04" },
+{ VENDORID_NATT_05    , "draft-ietf-ipsec-nat-t-ike-05" },
+{ VENDORID_NATT_06    , "draft-ietf-ipsec-nat-t-ike-06" },
+{ VENDORID_NATT_07    , "draft-ietf-ipsec-nat-t-ike-07" },
+{ VENDORID_NATT_08    , "draft-ietf-ipsec-nat-t-ike-08" },
+{ VENDORID_NATT_RFC   , "RFC 3947" },
+{ VENDORID_XAUTH      , "draft-ietf-ipsra-isakmp-xauth-06.txt" },
+{ VENDORID_UNITY      , "CISCO-UNITY" },
+{ VENDORID_FRAG       , "FRAGMENTATION" },
+/* Just a readable string for DPD ... */
+{ VENDORID_DPD        , "DPD" },
+/* Other known Vendor IDs */
+{ VENDORID_KAME       , "KAME/racoon" },
+};
+
+#define NUMVENDORIDS	(sizeof(all_vendor_ids)/sizeof(all_vendor_ids[0]))
+
+#define DPD_MAJOR_VERSION	0x01
+#define DPD_MINOR_VERSION	0x00
+
+const char vendorid_dpd_hash[] = {
+	0xAF, 0xCA, 0xD7, 0x13,
+	0x68, 0xA1, 0xF1, 0xC9,
+	0x6B, 0x86, 0x96, 0xFC,
+	0x77, 0x57, DPD_MAJOR_VERSION, DPD_MINOR_VERSION
+};
+
+
+static vchar_t *vendorid_fixup(int, vchar_t *t);
+
+static struct vendor_id *
+lookup_vendor_id_by_id (int id)
+{
+	int i;
+
+	for (i = 0; i < NUMVENDORIDS; i++)
+		if (all_vendor_ids[i].id == id)
+			return &all_vendor_ids[i];
+
+	return NULL;
+}
+
+const char *
+vid_string_by_id (int id)
+{
+	struct vendor_id *current;
+
+	if (id == VENDORID_DPD)
+		return vendorid_dpd_hash;
+
+	current = lookup_vendor_id_by_id(id);
+
+	return current ? current->string : NULL;
+}
+
+static struct vendor_id *
+lookup_vendor_id_by_hash (const char *hash)
+{
+	int i;
+	unsigned char *h = (unsigned char *)hash;
+
+	for (i = 0; i < NUMVENDORIDS; i++)
+		if (strncmp(all_vendor_ids[i].hash->v, hash,
+			    all_vendor_ids[i].hash->l) == 0)
+			return &all_vendor_ids[i];
+
+	return NULL;
+}
+
+void
+compute_vendorids (void)
+{
+	int i;
+	vchar_t vid;
+
+	for (i = 0; i < NUMVENDORIDS; i++) {
+		/* VENDORID_DPD is not a MD5 sum... */
+		if(all_vendor_ids[i].id == VENDORID_DPD){
+			all_vendor_ids[i].hash = vmalloc(sizeof(vendorid_dpd_hash));
+			if (all_vendor_ids[i].hash == NULL) {
+				plog(LLV_ERROR, LOCATION, NULL,
+					"unable to get memory for VID hash\n");
+				exit(1); /* this really shouldn't happen */
+			}
+			memcpy(all_vendor_ids[i].hash->v, vendorid_dpd_hash,
+				   sizeof(vendorid_dpd_hash));
+			continue;
+		}
+
+		vid.v = (char *) all_vendor_ids[i].string;
+		vid.l = strlen(vid.v);
+
+		all_vendor_ids[i].hash = eay_md5_one(&vid);
+		if (all_vendor_ids[i].hash == NULL)
+			plog(LLV_ERROR, LOCATION, NULL,
+			    "unable to hash vendor ID string\n");
+
+		/* Special cases */
+		all_vendor_ids[i].hash =
+			vendorid_fixup(all_vendor_ids[i].id,
+				       all_vendor_ids[i].hash);
+	}
+}
+
+/*
+ * set hashed vendor id.
+ * hash function is always MD5.
+ */
+vchar_t *
+set_vendorid(int vendorid)
+{
+	struct vendor_id *current;
+	vchar_t vid, *new;
+
+	if (vendorid == VENDORID_UNKNOWN) {
+		/*
+		 * The default unknown ID gets translated to
+		 * KAME/racoon.
+		 */
+		vendorid = VENDORID_DEFAULT;
+	}
+
+	current = lookup_vendor_id_by_id(vendorid);
+	if (current == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL,
+		    "invalid vendor ID index: %d\n", vendorid);
+		return (NULL);
+	}
+
+	/* The rest of racoon expects a private copy 
+	 * of the VID that could be free'd after use.
+	 * That's why we don't return the original pointer. */
+	return vdup(current->hash);
+}
+
+/*
+ * Check the vendor ID payload -- return the vendor ID index
+ * if we find a recognized one, or UNKNOWN if we don't.
+ *
+ * gen ... points to Vendor ID payload.
+ */
+int
+check_vendorid(struct isakmp_gen *gen)
+{
+	vchar_t vid, *vidhash;
+	int i, vidlen;
+	struct vendor_id *current;
+
+	if (gen == NULL)
+		return (VENDORID_UNKNOWN);
+
+	vidlen = ntohs(gen->len) - sizeof(*gen);
+
+	current = lookup_vendor_id_by_hash((char *)(gen + 1));
+	if (!current)
+		goto unknown;
+	
+	if (current->hash->l < vidlen)
+		plog(LLV_INFO, LOCATION, NULL,
+		     "received broken Microsoft ID: %s\n",
+		     current->string);
+	else
+		plog(LLV_INFO, LOCATION, NULL,
+		     "received Vendor ID: %s\n",
+		     current->string);
+
+	return current->id;
+
+unknown:
+	plog(LLV_DEBUG, LOCATION, NULL, "received unknown Vendor ID\n");
+	plogdump(LLV_DEBUG, (char *)(gen + 1), vidlen);
+	return (VENDORID_UNKNOWN);
+}
+
+static vchar_t * 
+vendorid_fixup(vendorid, vidhash)
+	int vendorid;		 
+	vchar_t *vidhash;
+{			   
+	switch(vendorid) {
+	case VENDORID_XAUTH: {	/* The vendor Id is truncated */
+		vchar_t *tmp;					    
+				  
+		if ((tmp = vmalloc(8)) == NULL) {
+			plog(LLV_ERROR, LOCATION, NULL,
+			    "unable to hash vendor ID string\n");
+			return NULL;				    
+		}			
+		  
+		memcpy(tmp->v, vidhash->v, 8);
+		vfree(vidhash);		  
+		vidhash = tmp;
+				   
+		break;
+	} 
+	case VENDORID_UNITY:	/* Two bytes tweak */
+		vidhash->v[14] = 0x01;		  
+		vidhash->v[15] = 0x00;
+		break;		   
+
+	default:     
+		break;
+	}		
+	
+	return vidhash;
+}			 
diff --git a/src/racoon/vendorid.h b/src/racoon/vendorid.h
new file mode 100644
index 0000000..7e2dcda
--- /dev/null
+++ b/src/racoon/vendorid.h
@@ -0,0 +1,106 @@
+/*	$NetBSD: vendorid.h,v 1.4 2006/09/09 16:22:10 manu Exp $	*/
+
+/* Id: vendorid.h,v 1.11 2006/02/17 14:09:10 vanhu Exp */
+
+/*
+ * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _VENDORID_H
+#define _VENDORID_H
+
+/* The unknown vendor ID. */
+#define	VENDORID_UNKNOWN	-1
+
+
+/* Our default vendor ID. */
+#define	VENDORID_DEFAULT	VENDORID_IPSEC_TOOLS
+
+#define	VENDORID_IPSEC_TOOLS 0		
+
+/*
+ * Refer to draft-ietf-ipsec-isakmp-gss-auth-06.txt.
+ */
+#define	VENDORID_GSSAPI_LONG	1
+#define	VENDORID_GSSAPI		2
+#define	VENDORID_MS_NT5		3
+#define	VENDOR_SUPPORTS_GSSAPI(x)					\
+	((x) == VENDORID_GSSAPI_LONG ||					\
+	 (x) == VENDORID_GSSAPI ||					\
+	 (x) == VENDORID_MS_NT5)
+
+/* NAT-T support */
+#define VENDORID_NATT_00	4
+#define VENDORID_NATT_01	5
+#define VENDORID_NATT_02	6
+#define VENDORID_NATT_02_N	7
+#define VENDORID_NATT_03	8
+#define VENDORID_NATT_04	9
+#define VENDORID_NATT_05	10
+#define VENDORID_NATT_06	11
+#define VENDORID_NATT_07	12
+#define VENDORID_NATT_08	13
+#define VENDORID_NATT_RFC	14
+
+#define VENDORID_NATT_FIRST	VENDORID_NATT_00
+#define VENDORID_NATT_LAST	VENDORID_NATT_RFC
+
+
+#define MAX_NATT_VID_COUNT	(VENDORID_NATT_LAST - VENDORID_NATT_FIRST + 1 )
+
+/* Hybrid auth */
+#define VENDORID_XAUTH		15
+#define VENDORID_UNITY		16
+
+/* IKE fragmentation */
+#define VENDORID_FRAG		17
+
+/* Dead Peer Detection */
+#define VENDORID_DPD		18
+
+
+/* Other Vendors...
+ * XXX: do some cleanup to have separate lists for "real" vendors (to complete)
+ * and "features" VendorIDs
+ */
+#define	VENDORID_KAME		19
+
+
+struct vendor_id {
+	int		id;
+	const char	*string;
+	vchar_t		*hash;
+};
+
+vchar_t *set_vendorid __P((int));
+int check_vendorid __P((struct isakmp_gen *));
+
+void compute_vendorids __P((void));
+const char *vid_string_by_id __P((int id));
+
+#endif /* _VENDORID_H */
diff --git a/src/racoon/vmbuf.c b/src/racoon/vmbuf.c
new file mode 100644
index 0000000..6c1aed1
--- /dev/null
+++ b/src/racoon/vmbuf.c
@@ -0,0 +1,137 @@
+/*	$NetBSD: vmbuf.c,v 1.4 2006/09/09 16:22:10 manu Exp $	*/
+
+/*	$KAME: vmbuf.c,v 1.11 2001/11/26 16:54:29 sakane Exp $	*/
+
+/*
+ * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#define NONEED_DRM
+
+#include <sys/types.h>
+#include <sys/param.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "var.h"
+#include "misc.h"
+#include "vmbuf.h"
+#include "debug.h"
+#include "plog.h"
+#include "gcmalloc.h"
+
+vchar_t *
+vmalloc(size)
+	size_t size;
+{
+	vchar_t *var;
+
+	if ((var = (vchar_t *)racoon_malloc(sizeof(*var))) == NULL)
+		return NULL;
+
+	var->l = size;
+	if (size == 0) {
+		var->v = NULL;
+	} else {
+		var->v = (caddr_t)racoon_calloc(1, size);
+		if (var->v == NULL) {
+			(void)racoon_free(var);
+			return NULL;
+		}
+	}
+
+	return var;
+}
+
+vchar_t *
+vrealloc(ptr, size)
+	vchar_t *ptr;
+	size_t size;
+{
+	caddr_t v;
+	
+	if (ptr != NULL) {
+		if (ptr->l == 0) {
+			(void)vfree(ptr);
+			return vmalloc(size); /* zero-fill it? */
+		}
+
+		if ((v = (caddr_t)racoon_realloc(ptr->v, size)) == NULL) {
+			(void)vfree(ptr);
+			return NULL;
+		}
+
+		if ( size > ptr->l)
+			memset(v + ptr->l, 0, size - ptr->l);
+		ptr->v = v;
+		ptr->l = size;
+	} else {
+		if ((ptr = vmalloc(size)) == NULL)
+			return NULL;
+	}
+
+	return ptr;
+}
+
+void
+vfree(var)
+	vchar_t *var;
+{
+	if (var == NULL)
+		return;
+
+	if (var->v)
+		(void)racoon_free(var->v);
+
+	(void)racoon_free(var);
+
+	return;
+}
+
+vchar_t *
+vdup(src)
+	vchar_t *src;
+{
+	vchar_t *new;
+
+	if (src == NULL) {
+		plog(LLV_ERROR, LOCATION, NULL, "vdup(NULL) called\n");
+		return NULL;
+	}
+
+	if ((new = vmalloc(src->l)) == NULL)
+		return NULL;
+
+	memcpy(new->v, src->v, src->l);
+
+	return new;
+}
diff --git a/src/racoon/vmbuf.h b/src/racoon/vmbuf.h
new file mode 100644
index 0000000..3f2f4ea
--- /dev/null
+++ b/src/racoon/vmbuf.h
@@ -0,0 +1,73 @@
+/*	$NetBSD: vmbuf.h,v 1.4 2006/09/09 16:22:10 manu Exp $	*/
+
+/* Id: vmbuf.h,v 1.4 2005/10/30 10:28:44 vanhu Exp */
+
+/*
+ * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _VMBUF_H
+#define _VMBUF_H
+
+/*
+ *	bp      v
+ *	v       v
+ *	........................
+ *	        <--------------> l
+ *	<----------------------> bl
+ */
+typedef struct _vchar_t_ {
+#if notyet
+	u_int32_t t;	/* type of the value */
+	vchar_t *n;	/* next vchar_t buffer */
+	size_t bl;	/* length of the buffer */
+	caddr_t bp;	/* pointer to the buffer */
+#endif
+	size_t l;	/* length of the value */
+	caddr_t v;	/* place holder to the pointer to the value */
+} vchar_t;
+
+#define VPTRINIT(p) \
+do { \
+	if (p) { \
+		vfree(p); \
+		(p) = NULL; \
+	} \
+} while(0);
+
+#if defined(__APPLE__) && defined(__MACH__)
+/* vfree is already defined in Apple's system libraries */
+#define vfree   vmbuf_free
+#endif
+
+extern vchar_t *vmalloc __P((size_t));
+extern vchar_t *vrealloc __P((vchar_t *, size_t));
+extern void vfree __P((vchar_t *));
+extern vchar_t *vdup __P((vchar_t *));
+
+#endif /* _VMBUF_H */
diff --git a/src/setkey/Android.mk b/src/setkey/Android.mk
new file mode 100755
index 0000000..3d36ded
--- /dev/null
+++ b/src/setkey/Android.mk
@@ -0,0 +1,32 @@
+LOCAL_PATH:= $(call my-dir)
+
+# Build setkey utility.
+
+L_CFLAGS += -O3 -DANDROID_CHANGES -DHAVE_CONFIG_H
+
+
+EXE_SRC_FILES := setkey.c parse.c token.c
+
+EXE_LIBS := libcutils libcrypto libssl
+
+common_C_INCLUDES += \
+	$(LOCAL_PATH)/../..
+
+L_CFLAGS += -include $(LOCAL_PATH)/../../src/include-glibc/glibc-bugs.h \
+  -I$(LOCAL_PATH)/../../src/include-glibc -I$(LOCAL_PATH)/../../src/libipsec \
+  -Iexternal/openssl/include -I bionic/libc/private \
+  -DSYSCONFDIR=\"/etc\" -DADMINPORTDIR=\"/var/racoon\" -g -O2
+
+
+# For setkey
+# =====================================================
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := $(EXE_SRC_FILES)
+LOCAL_C_INCLUDES += $(common_C_INCLUDES)
+LOCAL_SHARED_LIBRARIES += $(EXE_LIBS)
+LOCAL_STATIC_LIBRARIES += libipsec
+LOCAL_CFLAGS += $(L_CFLAGS)
+LOCAL_MODULE := setkey
+include $(BUILD_EXECUTABLE)
diff --git a/src/setkey/Makefile.am b/src/setkey/Makefile.am
new file mode 100644
index 0000000..746c1f1
--- /dev/null
+++ b/src/setkey/Makefile.am
@@ -0,0 +1,22 @@
+
+sbin_PROGRAMS = setkey
+
+AM_CFLAGS = -I${top_srcdir}/src/libipsec @GLIBC_BUGS@
+AM_YFLAGS = -d
+
+BUILT_SOURCES = parse.h
+
+setkey_SOURCES = \
+  setkey.c \
+  parse.y \
+  token.l
+
+setkey_LDFLAGS = ../libipsec/libipsec.la
+setkey_DEPENDENCIES = ../libipsec/libipsec.la
+setkey_LDADD = $(LEXLIB)
+
+noinst_HEADERS = vchar.h extern.h
+man8_MANS = setkey.8
+
+EXTRA_DIST = ${man8_MANS} sample-policy01.cf sample-policy02.cf sample.cf \
+	scriptdump.pl test-pfkey.c
diff --git a/src/setkey/Makefile.in b/src/setkey/Makefile.in
new file mode 100644
index 0000000..9c017f6
--- /dev/null
+++ b/src/setkey/Makefile.in
@@ -0,0 +1,577 @@
+# Makefile.in generated by automake 1.10.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008  Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+sbin_PROGRAMS = setkey$(EXEEXT)
+subdir = src/setkey
+DIST_COMMON = $(noinst_HEADERS) $(srcdir)/Makefile.am \
+	$(srcdir)/Makefile.in parse.c parse.h token.c
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/acracoon.m4 \
+	$(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+	$(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+am__installdirs = "$(DESTDIR)$(sbindir)" "$(DESTDIR)$(man8dir)"
+sbinPROGRAMS_INSTALL = $(INSTALL_PROGRAM)
+PROGRAMS = $(sbin_PROGRAMS)
+am_setkey_OBJECTS = setkey.$(OBJEXT) parse.$(OBJEXT) token.$(OBJEXT)
+setkey_OBJECTS = $(am_setkey_OBJECTS)
+am__DEPENDENCIES_1 =
+setkey_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+	--mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(setkey_LDFLAGS) \
+	$(LDFLAGS) -o $@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+	$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+	--mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+	$(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+	--mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+	$(LDFLAGS) -o $@
+LEXCOMPILE = $(LEX) $(LFLAGS) $(AM_LFLAGS)
+LTLEXCOMPILE = $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+	--mode=compile $(LEX) $(LFLAGS) $(AM_LFLAGS)
+YLWRAP = $(top_srcdir)/ylwrap
+YACCCOMPILE = $(YACC) $(YFLAGS) $(AM_YFLAGS)
+LTYACCCOMPILE = $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+	--mode=compile $(YACC) $(YFLAGS) $(AM_YFLAGS)
+SOURCES = $(setkey_SOURCES)
+DIST_SOURCES = $(setkey_SOURCES)
+man8dir = $(mandir)/man8
+NROFF = nroff
+MANS = $(man8_MANS)
+HEADERS = $(noinst_HEADERS)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CONFIGURE_AMFLAGS = @CONFIGURE_AMFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CRYPTOBJS = @CRYPTOBJS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DSYMUTIL = @DSYMUTIL@
+ECHO = @ECHO@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+EXTRA_CRYPTO = @EXTRA_CRYPTO@
+F77 = @F77@
+FFLAGS = @FFLAGS@
+FRAG_OBJS = @FRAG_OBJS@
+GLIBC_BUGS = @GLIBC_BUGS@
+GREP = @GREP@
+HYBRID_OBJS = @HYBRID_OBJS@
+INCLUDE_GLIBC = @INCLUDE_GLIBC@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_OPTS = @INSTALL_OPTS@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+KERNEL_INCLUDE = @KERNEL_INCLUDE@
+KRB5_CONFIG = @KRB5_CONFIG@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+NATT_OBJS = @NATT_OBJS@
+NMEDIT = @NMEDIT@
+OBJEXT = @OBJEXT@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+RANLIB = @RANLIB@
+RPM = @RPM@
+SECCTX_OBJS = @SECCTX_OBJS@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+YACC = @YACC@
+YFLAGS = @YFLAGS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_F77 = @ac_ct_F77@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+include_racoondir = @include_racoondir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+AM_CFLAGS = -I${top_srcdir}/src/libipsec @GLIBC_BUGS@
+AM_YFLAGS = -d
+BUILT_SOURCES = parse.h
+setkey_SOURCES = \
+  setkey.c \
+  parse.y \
+  token.l
+
+setkey_LDFLAGS = ../libipsec/libipsec.la
+setkey_DEPENDENCIES = ../libipsec/libipsec.la
+setkey_LDADD = $(LEXLIB)
+noinst_HEADERS = vchar.h extern.h
+man8_MANS = setkey.8
+EXTRA_DIST = ${man8_MANS} sample-policy01.cf sample-policy02.cf sample.cf \
+	scriptdump.pl test-pfkey.c
+
+all: $(BUILT_SOURCES)
+	$(MAKE) $(AM_MAKEFLAGS) all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .l .lo .o .obj .y
+$(srcdir)/Makefile.in:  $(srcdir)/Makefile.am  $(am__configure_deps)
+	@for dep in $?; do \
+	  case '$(am__configure_deps)' in \
+	    *$$dep*) \
+	      cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
+		&& exit 0; \
+	      exit 1;; \
+	  esac; \
+	done; \
+	echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign  src/setkey/Makefile'; \
+	cd $(top_srcdir) && \
+	  $(AUTOMAKE) --foreign  src/setkey/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+	@case '$?' in \
+	  *config.status*) \
+	    cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+	  *) \
+	    echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+	    cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+	esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure:  $(am__configure_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4):  $(am__aclocal_m4_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+install-sbinPROGRAMS: $(sbin_PROGRAMS)
+	@$(NORMAL_INSTALL)
+	test -z "$(sbindir)" || $(MKDIR_P) "$(DESTDIR)$(sbindir)"
+	@list='$(sbin_PROGRAMS)'; for p in $$list; do \
+	  p1=`echo $$p|sed 's/$(EXEEXT)$$//'`; \
+	  if test -f $$p \
+	     || test -f $$p1 \
+	  ; then \
+	    f=`echo "$$p1" | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'`; \
+	   echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(sbinPROGRAMS_INSTALL) '$$p' '$(DESTDIR)$(sbindir)/$$f'"; \
+	   $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(sbinPROGRAMS_INSTALL) "$$p" "$(DESTDIR)$(sbindir)/$$f" || exit 1; \
+	  else :; fi; \
+	done
+
+uninstall-sbinPROGRAMS:
+	@$(NORMAL_UNINSTALL)
+	@list='$(sbin_PROGRAMS)'; for p in $$list; do \
+	  f=`echo "$$p" | sed 's,^.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \
+	  echo " rm -f '$(DESTDIR)$(sbindir)/$$f'"; \
+	  rm -f "$(DESTDIR)$(sbindir)/$$f"; \
+	done
+
+clean-sbinPROGRAMS:
+	@list='$(sbin_PROGRAMS)'; for p in $$list; do \
+	  f=`echo $$p|sed 's/$(EXEEXT)$$//'`; \
+	  echo " rm -f $$p $$f"; \
+	  rm -f $$p $$f ; \
+	done
+parse.h: parse.c
+	@if test ! -f $@; then \
+	  rm -f parse.c; \
+	  $(MAKE) $(AM_MAKEFLAGS) parse.c; \
+	else :; fi
+setkey$(EXEEXT): $(setkey_OBJECTS) $(setkey_DEPENDENCIES) 
+	@rm -f setkey$(EXEEXT)
+	$(setkey_LINK) $(setkey_OBJECTS) $(setkey_LDADD) $(LIBS)
+
+mostlyclean-compile:
+	-rm -f *.$(OBJEXT)
+
+distclean-compile:
+	-rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/parse.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/setkey.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/token.Po@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@	$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@	mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@	$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@	mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@	$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@	mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LTCOMPILE) -c -o $@ $<
+
+.l.c:
+	$(am__skiplex) $(SHELL) $(YLWRAP) $< $(LEX_OUTPUT_ROOT).c $@ -- $(LEXCOMPILE)
+
+.y.c:
+	$(am__skipyacc) $(SHELL) $(YLWRAP) $< y.tab.c $@ y.tab.h $*.h y.output $*.output -- $(YACCCOMPILE)
+
+mostlyclean-libtool:
+	-rm -f *.lo
+
+clean-libtool:
+	-rm -rf .libs _libs
+install-man8: $(man8_MANS) $(man_MANS)
+	@$(NORMAL_INSTALL)
+	test -z "$(man8dir)" || $(MKDIR_P) "$(DESTDIR)$(man8dir)"
+	@list='$(man8_MANS) $(dist_man8_MANS) $(nodist_man8_MANS)'; \
+	l2='$(man_MANS) $(dist_man_MANS) $(nodist_man_MANS)'; \
+	for i in $$l2; do \
+	  case "$$i" in \
+	    *.8*) list="$$list $$i" ;; \
+	  esac; \
+	done; \
+	for i in $$list; do \
+	  if test -f $(srcdir)/$$i; then file=$(srcdir)/$$i; \
+	  else file=$$i; fi; \
+	  ext=`echo $$i | sed -e 's/^.*\\.//'`; \
+	  case "$$ext" in \
+	    8*) ;; \
+	    *) ext='8' ;; \
+	  esac; \
+	  inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \
+	  inst=`echo $$inst | sed -e 's/^.*\///'`; \
+	  inst=`echo $$inst | sed '$(transform)'`.$$ext; \
+	  echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man8dir)/$$inst'"; \
+	  $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man8dir)/$$inst"; \
+	done
+uninstall-man8:
+	@$(NORMAL_UNINSTALL)
+	@list='$(man8_MANS) $(dist_man8_MANS) $(nodist_man8_MANS)'; \
+	l2='$(man_MANS) $(dist_man_MANS) $(nodist_man_MANS)'; \
+	for i in $$l2; do \
+	  case "$$i" in \
+	    *.8*) list="$$list $$i" ;; \
+	  esac; \
+	done; \
+	for i in $$list; do \
+	  ext=`echo $$i | sed -e 's/^.*\\.//'`; \
+	  case "$$ext" in \
+	    8*) ;; \
+	    *) ext='8' ;; \
+	  esac; \
+	  inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \
+	  inst=`echo $$inst | sed -e 's/^.*\///'`; \
+	  inst=`echo $$inst | sed '$(transform)'`.$$ext; \
+	  echo " rm -f '$(DESTDIR)$(man8dir)/$$inst'"; \
+	  rm -f "$(DESTDIR)$(man8dir)/$$inst"; \
+	done
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+	list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '{ files[$$0] = 1; nonemtpy = 1; } \
+	      END { if (nonempty) { for (i in files) print i; }; }'`; \
+	mkid -fID $$unique
+tags: TAGS
+
+TAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+		$(TAGS_FILES) $(LISP)
+	tags=; \
+	here=`pwd`; \
+	list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+	      END { if (nonempty) { for (i in files) print i; }; }'`; \
+	if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
+	  test -n "$$unique" || unique=$$empty_fix; \
+	  $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+	    $$tags $$unique; \
+	fi
+ctags: CTAGS
+CTAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+		$(TAGS_FILES) $(LISP)
+	tags=; \
+	list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+	      END { if (nonempty) { for (i in files) print i; }; }'`; \
+	test -z "$(CTAGS_ARGS)$$tags$$unique" \
+	  || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+	     $$tags $$unique
+
+GTAGS:
+	here=`$(am__cd) $(top_builddir) && pwd` \
+	  && cd $(top_srcdir) \
+	  && gtags -i $(GTAGS_ARGS) $$here
+
+distclean-tags:
+	-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+	@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+	topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+	list='$(DISTFILES)'; \
+	  dist_files=`for file in $$list; do echo $$file; done | \
+	  sed -e "s|^$$srcdirstrip/||;t" \
+	      -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+	case $$dist_files in \
+	  */*) $(MKDIR_P) `echo "$$dist_files" | \
+			   sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+			   sort -u` ;; \
+	esac; \
+	for file in $$dist_files; do \
+	  if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+	  if test -d $$d/$$file; then \
+	    dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+	    if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+	      cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+	    fi; \
+	    cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
+	  else \
+	    test -f $(distdir)/$$file \
+	    || cp -p $$d/$$file $(distdir)/$$file \
+	    || exit 1; \
+	  fi; \
+	done
+check-am: all-am
+check: $(BUILT_SOURCES)
+	$(MAKE) $(AM_MAKEFLAGS) check-am
+all-am: Makefile $(PROGRAMS) $(MANS) $(HEADERS)
+installdirs:
+	for dir in "$(DESTDIR)$(sbindir)" "$(DESTDIR)$(man8dir)"; do \
+	  test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+	done
+install: $(BUILT_SOURCES)
+	$(MAKE) $(AM_MAKEFLAGS) install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+	@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+	$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+	  install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+	  `test -z '$(STRIP)' || \
+	    echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+	-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+	@echo "This command is intended for maintainers to use"
+	@echo "it deletes files that may require special tools to rebuild."
+	-rm -f parse.c
+	-rm -f parse.h
+	-rm -f token.c
+	-test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES)
+clean: clean-am
+
+clean-am: clean-generic clean-libtool clean-sbinPROGRAMS \
+	mostlyclean-am
+
+distclean: distclean-am
+	-rm -rf ./$(DEPDIR)
+	-rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+	distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+info: info-am
+
+info-am:
+
+install-data-am: install-man
+
+install-dvi: install-dvi-am
+
+install-exec-am: install-sbinPROGRAMS
+
+install-html: install-html-am
+
+install-info: install-info-am
+
+install-man: install-man8
+
+install-pdf: install-pdf-am
+
+install-ps: install-ps-am
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+	-rm -rf ./$(DEPDIR)
+	-rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+	mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-man uninstall-sbinPROGRAMS
+
+uninstall-man: uninstall-man8
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+	clean-libtool clean-sbinPROGRAMS ctags distclean \
+	distclean-compile distclean-generic distclean-libtool \
+	distclean-tags distdir dvi dvi-am html html-am info info-am \
+	install install-am install-data install-data-am install-dvi \
+	install-dvi-am install-exec install-exec-am install-html \
+	install-html-am install-info install-info-am install-man \
+	install-man8 install-pdf install-pdf-am install-ps \
+	install-ps-am install-sbinPROGRAMS install-strip installcheck \
+	installcheck-am installdirs maintainer-clean \
+	maintainer-clean-generic mostlyclean mostlyclean-compile \
+	mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
+	tags uninstall uninstall-am uninstall-man uninstall-man8 \
+	uninstall-sbinPROGRAMS
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/src/setkey/extern.h b/src/setkey/extern.h
new file mode 100644
index 0000000..93eea43
--- /dev/null
+++ b/src/setkey/extern.h
@@ -0,0 +1,30 @@
+/*	$NetBSD: extern.h,v 1.4 2006/09/09 16:22:37 manu Exp $	*/
+
+
+
+void parse_init __P((void));
+int parse __P((FILE **));
+int parse_string __P((char *));
+
+int setkeymsg __P((char *, size_t *));
+int sendkeymsg __P((char *, size_t));
+
+int yylex __P((void));
+int yyparse __P((void));
+void yyfatal __P((const char *));
+void yyerror __P((const char *));
+
+extern int f_rfcmode;
+extern int lineno;
+extern int last_msg_type;
+extern u_int32_t last_priority;
+extern int exit_now;
+
+extern u_char m_buf[BUFSIZ];
+extern u_int m_len;
+extern int f_debug;
+
+#ifdef HAVE_PFKEY_POLICY_PRIORITY
+extern int last_msg_type;
+extern u_int32_t last_priority;
+#endif
diff --git a/src/setkey/parse.c b/src/setkey/parse.c
new file mode 100644
index 0000000..fa8d39d
--- /dev/null
+++ b/src/setkey/parse.c
@@ -0,0 +1,3411 @@
+/* A Bison parser, made by GNU Bison 2.3.  */
+
+/* Skeleton implementation for Bison's Yacc-like parsers in C
+
+   Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
+   Free Software Foundation, Inc.
+
+   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, or (at your option)
+   any later version.
+
+   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.
+
+   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., 51 Franklin Street, Fifth Floor,
+   Boston, MA 02110-1301, USA.  */
+
+/* As a special exception, you may create a larger work that contains
+   part or all of the Bison parser skeleton and distribute that work
+   under terms of your choice, so long as that work isn't itself a
+   parser generator using the skeleton or a modified version thereof
+   as a parser skeleton.  Alternatively, if you modify or redistribute
+   the parser skeleton itself, you may (at your option) remove this
+   special exception, which will cause the skeleton and the resulting
+   Bison output files to be licensed under the GNU General Public
+   License without this special exception.
+
+   This special exception was added by the Free Software Foundation in
+   version 2.2 of Bison.  */
+
+/* C LALR(1) parser skeleton written by Richard Stallman, by
+   simplifying the original so-called "semantic" parser.  */
+
+/* All symbols defined below should begin with yy or YY, to avoid
+   infringing on user name space.  This should be done even for local
+   variables, as they might otherwise be expanded by user macros.
+   There are some unavoidable exceptions within include files to
+   define necessary library symbols; they are noted "INFRINGES ON
+   USER NAME SPACE" below.  */
+
+/* Identify Bison output.  */
+#define YYBISON 1
+
+/* Bison version.  */
+#define YYBISON_VERSION "2.3"
+
+/* Skeleton name.  */
+#define YYSKELETON_NAME "yacc.c"
+
+/* Pure parsers.  */
+#define YYPURE 0
+
+/* Using locations.  */
+#define YYLSP_NEEDED 0
+
+
+
+/* Tokens.  */
+#ifndef YYTOKENTYPE
+# define YYTOKENTYPE
+   /* Put the tokens into the symbol table, so that GDB and other debuggers
+      know about them.  */
+   enum yytokentype {
+     EOT = 258,
+     SLASH = 259,
+     BLCL = 260,
+     ELCL = 261,
+     ADD = 262,
+     GET = 263,
+     DELETE = 264,
+     DELETEALL = 265,
+     FLUSH = 266,
+     DUMP = 267,
+     EXIT = 268,
+     PR_ESP = 269,
+     PR_AH = 270,
+     PR_IPCOMP = 271,
+     PR_ESPUDP = 272,
+     PR_TCP = 273,
+     F_PROTOCOL = 274,
+     F_AUTH = 275,
+     F_ENC = 276,
+     F_REPLAY = 277,
+     F_COMP = 278,
+     F_RAWCPI = 279,
+     F_MODE = 280,
+     MODE = 281,
+     F_REQID = 282,
+     F_EXT = 283,
+     EXTENSION = 284,
+     NOCYCLICSEQ = 285,
+     ALG_AUTH = 286,
+     ALG_AUTH_NOKEY = 287,
+     ALG_ENC = 288,
+     ALG_ENC_NOKEY = 289,
+     ALG_ENC_DESDERIV = 290,
+     ALG_ENC_DES32IV = 291,
+     ALG_ENC_OLD = 292,
+     ALG_COMP = 293,
+     F_LIFETIME_HARD = 294,
+     F_LIFETIME_SOFT = 295,
+     F_LIFEBYTE_HARD = 296,
+     F_LIFEBYTE_SOFT = 297,
+     DECSTRING = 298,
+     QUOTEDSTRING = 299,
+     HEXSTRING = 300,
+     STRING = 301,
+     ANY = 302,
+     SPDADD = 303,
+     SPDDELETE = 304,
+     SPDDUMP = 305,
+     SPDFLUSH = 306,
+     F_POLICY = 307,
+     PL_REQUESTS = 308,
+     F_AIFLAGS = 309,
+     TAGGED = 310,
+     SECURITY_CTX = 311
+   };
+#endif
+/* Tokens.  */
+#define EOT 258
+#define SLASH 259
+#define BLCL 260
+#define ELCL 261
+#define ADD 262
+#define GET 263
+#define DELETE 264
+#define DELETEALL 265
+#define FLUSH 266
+#define DUMP 267
+#define EXIT 268
+#define PR_ESP 269
+#define PR_AH 270
+#define PR_IPCOMP 271
+#define PR_ESPUDP 272
+#define PR_TCP 273
+#define F_PROTOCOL 274
+#define F_AUTH 275
+#define F_ENC 276
+#define F_REPLAY 277
+#define F_COMP 278
+#define F_RAWCPI 279
+#define F_MODE 280
+#define MODE 281
+#define F_REQID 282
+#define F_EXT 283
+#define EXTENSION 284
+#define NOCYCLICSEQ 285
+#define ALG_AUTH 286
+#define ALG_AUTH_NOKEY 287
+#define ALG_ENC 288
+#define ALG_ENC_NOKEY 289
+#define ALG_ENC_DESDERIV 290
+#define ALG_ENC_DES32IV 291
+#define ALG_ENC_OLD 292
+#define ALG_COMP 293
+#define F_LIFETIME_HARD 294
+#define F_LIFETIME_SOFT 295
+#define F_LIFEBYTE_HARD 296
+#define F_LIFEBYTE_SOFT 297
+#define DECSTRING 298
+#define QUOTEDSTRING 299
+#define HEXSTRING 300
+#define STRING 301
+#define ANY 302
+#define SPDADD 303
+#define SPDDELETE 304
+#define SPDDUMP 305
+#define SPDFLUSH 306
+#define F_POLICY 307
+#define PL_REQUESTS 308
+#define F_AIFLAGS 309
+#define TAGGED 310
+#define SECURITY_CTX 311
+
+
+
+
+/* Copy the first part of user declarations.  */
+#line 34 "parse.y"
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+
+#include <netinet/in.h>
+#include <net/pfkeyv2.h>
+#include PATH_IPSEC_H
+#include <arpa/inet.h>
+
+#include <string.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <netdb.h>
+#include <ctype.h>
+#include <errno.h>
+#include <stdlib.h>
+
+#include "libpfkey.h"
+#include "vchar.h"
+#include "extern.h"
+
+#ifndef IPPROTO_MH
+#define IPPROTO_MH		135
+#endif
+
+#define DEFAULT_NATT_PORT	4500
+
+#ifndef UDP_ENCAP_ESPINUDP
+#define UDP_ENCAP_ESPINUDP	2
+#endif
+
+#define ATOX(c) \
+  (isdigit((int)c) ? (c - '0') : \
+    (isupper((int)c) ? (c - 'A' + 10) : (c - 'a' + 10)))
+
+u_int32_t p_spi;
+u_int p_ext, p_alg_enc, p_alg_auth, p_replay, p_mode;
+u_int32_t p_reqid;
+u_int p_key_enc_len, p_key_auth_len;
+const char *p_key_enc;
+const char *p_key_auth;
+time_t p_lt_hard, p_lt_soft;
+size_t p_lb_hard, p_lb_soft;
+
+struct security_ctx {
+	u_int8_t doi;
+	u_int8_t alg;
+	u_int16_t len;
+	char *buf;
+};
+
+struct security_ctx sec_ctx;
+
+static u_int p_natt_type;
+static struct addrinfo * p_natt_oa = NULL;
+
+static int p_aiflags = 0, p_aifamily = PF_UNSPEC;
+
+static struct addrinfo *parse_addr __P((char *, char *));
+static int fix_portstr __P((vchar_t *, vchar_t *, vchar_t *));
+static int setvarbuf __P((char *, int *, struct sadb_ext *, int, 
+    const void *, int));
+void parse_init __P((void));
+void free_buffer __P((void));
+
+int setkeymsg0 __P((struct sadb_msg *, unsigned int, unsigned int, size_t));
+static int setkeymsg_spdaddr __P((unsigned int, unsigned int, vchar_t *,
+	struct addrinfo *, int, struct addrinfo *, int));
+static int setkeymsg_spdaddr_tag __P((unsigned int, char *, vchar_t *));
+static int setkeymsg_addr __P((unsigned int, unsigned int,
+	struct addrinfo *, struct addrinfo *, int));
+static int setkeymsg_add __P((unsigned int, unsigned int,
+	struct addrinfo *, struct addrinfo *));
+
+
+/* Enabling traces.  */
+#ifndef YYDEBUG
+# define YYDEBUG 0
+#endif
+
+/* Enabling verbose error messages.  */
+#ifdef YYERROR_VERBOSE
+# undef YYERROR_VERBOSE
+# define YYERROR_VERBOSE 1
+#else
+# define YYERROR_VERBOSE 0
+#endif
+
+/* Enabling the token table.  */
+#ifndef YYTOKEN_TABLE
+# define YYTOKEN_TABLE 0
+#endif
+
+#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
+typedef union YYSTYPE
+#line 114 "parse.y"
+{
+	int num;
+	unsigned long ulnum;
+	vchar_t val;
+	struct addrinfo *res;
+}
+/* Line 187 of yacc.c.  */
+#line 295 "parse.c"
+	YYSTYPE;
+# define yystype YYSTYPE /* obsolescent; will be withdrawn */
+# define YYSTYPE_IS_DECLARED 1
+# define YYSTYPE_IS_TRIVIAL 1
+#endif
+
+
+
+/* Copy the second part of user declarations.  */
+
+
+/* Line 216 of yacc.c.  */
+#line 308 "parse.c"
+
+#ifdef short
+# undef short
+#endif
+
+#ifdef YYTYPE_UINT8
+typedef YYTYPE_UINT8 yytype_uint8;
+#else
+typedef unsigned char yytype_uint8;
+#endif
+
+#ifdef YYTYPE_INT8
+typedef YYTYPE_INT8 yytype_int8;
+#elif (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+typedef signed char yytype_int8;
+#else
+typedef short int yytype_int8;
+#endif
+
+#ifdef YYTYPE_UINT16
+typedef YYTYPE_UINT16 yytype_uint16;
+#else
+typedef unsigned short int yytype_uint16;
+#endif
+
+#ifdef YYTYPE_INT16
+typedef YYTYPE_INT16 yytype_int16;
+#else
+typedef short int yytype_int16;
+#endif
+
+#ifndef YYSIZE_T
+# ifdef __SIZE_TYPE__
+#  define YYSIZE_T __SIZE_TYPE__
+# elif defined size_t
+#  define YYSIZE_T size_t
+# elif ! defined YYSIZE_T && (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+#  include <stddef.h> /* INFRINGES ON USER NAME SPACE */
+#  define YYSIZE_T size_t
+# else
+#  define YYSIZE_T unsigned int
+# endif
+#endif
+
+#define YYSIZE_MAXIMUM ((YYSIZE_T) -1)
+
+#ifndef YY_
+# if YYENABLE_NLS
+#  if ENABLE_NLS
+#   include <libintl.h> /* INFRINGES ON USER NAME SPACE */
+#   define YY_(msgid) dgettext ("bison-runtime", msgid)
+#  endif
+# endif
+# ifndef YY_
+#  define YY_(msgid) msgid
+# endif
+#endif
+
+/* Suppress unused-variable warnings by "using" E.  */
+#if ! defined lint || defined __GNUC__
+# define YYUSE(e) ((void) (e))
+#else
+# define YYUSE(e) /* empty */
+#endif
+
+/* Identity function, used to suppress warnings about constant conditions.  */
+#ifndef lint
+# define YYID(n) (n)
+#else
+#if (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+static int
+YYID (int i)
+#else
+static int
+YYID (i)
+    int i;
+#endif
+{
+  return i;
+}
+#endif
+
+#if ! defined yyoverflow || YYERROR_VERBOSE
+
+/* The parser invokes alloca or malloc; define the necessary symbols.  */
+
+# ifdef YYSTACK_USE_ALLOCA
+#  if YYSTACK_USE_ALLOCA
+#   ifdef __GNUC__
+#    define YYSTACK_ALLOC __builtin_alloca
+#   elif defined __BUILTIN_VA_ARG_INCR
+#    include <alloca.h> /* INFRINGES ON USER NAME SPACE */
+#   elif defined _AIX
+#    define YYSTACK_ALLOC __alloca
+#   elif defined _MSC_VER
+#    include <malloc.h> /* INFRINGES ON USER NAME SPACE */
+#    define alloca _alloca
+#   else
+#    define YYSTACK_ALLOC alloca
+#    if ! defined _ALLOCA_H && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+#     include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
+#     ifndef _STDLIB_H
+#      define _STDLIB_H 1
+#     endif
+#    endif
+#   endif
+#  endif
+# endif
+
+# ifdef YYSTACK_ALLOC
+   /* Pacify GCC's `empty if-body' warning.  */
+#  define YYSTACK_FREE(Ptr) do { /* empty */; } while (YYID (0))
+#  ifndef YYSTACK_ALLOC_MAXIMUM
+    /* The OS might guarantee only one guard page at the bottom of the stack,
+       and a page size can be as small as 4096 bytes.  So we cannot safely
+       invoke alloca (N) if N exceeds 4096.  Use a slightly smaller number
+       to allow for a few compiler-allocated temporary stack slots.  */
+#   define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */
+#  endif
+# else
+#  define YYSTACK_ALLOC YYMALLOC
+#  define YYSTACK_FREE YYFREE
+#  ifndef YYSTACK_ALLOC_MAXIMUM
+#   define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM
+#  endif
+#  if (defined __cplusplus && ! defined _STDLIB_H \
+       && ! ((defined YYMALLOC || defined malloc) \
+	     && (defined YYFREE || defined free)))
+#   include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
+#   ifndef _STDLIB_H
+#    define _STDLIB_H 1
+#   endif
+#  endif
+#  ifndef YYMALLOC
+#   define YYMALLOC malloc
+#   if ! defined malloc && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */
+#   endif
+#  endif
+#  ifndef YYFREE
+#   define YYFREE free
+#   if ! defined free && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+void free (void *); /* INFRINGES ON USER NAME SPACE */
+#   endif
+#  endif
+# endif
+#endif /* ! defined yyoverflow || YYERROR_VERBOSE */
+
+
+#if (! defined yyoverflow \
+     && (! defined __cplusplus \
+	 || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL)))
+
+/* A type that is properly aligned for any stack member.  */
+union yyalloc
+{
+  yytype_int16 yyss;
+  YYSTYPE yyvs;
+  };
+
+/* The size of the maximum gap between one aligned stack and the next.  */
+# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1)
+
+/* The size of an array large to enough to hold all stacks, each with
+   N elements.  */
+# define YYSTACK_BYTES(N) \
+     ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \
+      + YYSTACK_GAP_MAXIMUM)
+
+/* Copy COUNT objects from FROM to TO.  The source and destination do
+   not overlap.  */
+# ifndef YYCOPY
+#  if defined __GNUC__ && 1 < __GNUC__
+#   define YYCOPY(To, From, Count) \
+      __builtin_memcpy (To, From, (Count) * sizeof (*(From)))
+#  else
+#   define YYCOPY(To, From, Count)		\
+      do					\
+	{					\
+	  YYSIZE_T yyi;				\
+	  for (yyi = 0; yyi < (Count); yyi++)	\
+	    (To)[yyi] = (From)[yyi];		\
+	}					\
+      while (YYID (0))
+#  endif
+# endif
+
+/* Relocate STACK from its old location to the new one.  The
+   local variables YYSIZE and YYSTACKSIZE give the old and new number of
+   elements in the stack, and YYPTR gives the new location of the
+   stack.  Advance YYPTR to a properly aligned location for the next
+   stack.  */
+# define YYSTACK_RELOCATE(Stack)					\
+    do									\
+      {									\
+	YYSIZE_T yynewbytes;						\
+	YYCOPY (&yyptr->Stack, Stack, yysize);				\
+	Stack = &yyptr->Stack;						\
+	yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
+	yyptr += yynewbytes / sizeof (*yyptr);				\
+      }									\
+    while (YYID (0))
+
+#endif
+
+/* YYFINAL -- State number of the termination state.  */
+#define YYFINAL  2
+/* YYLAST -- Last index in YYTABLE.  */
+#define YYLAST   157
+
+/* YYNTOKENS -- Number of terminals.  */
+#define YYNTOKENS  57
+/* YYNNTS -- Number of nonterminals.  */
+#define YYNNTS  36
+/* YYNRULES -- Number of rules.  */
+#define YYNRULES  87
+/* YYNRULES -- Number of states.  */
+#define YYNSTATES  170
+
+/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX.  */
+#define YYUNDEFTOK  2
+#define YYMAXUTOK   311
+
+#define YYTRANSLATE(YYX)						\
+  ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
+
+/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX.  */
+static const yytype_uint8 yytranslate[] =
+{
+       0,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     1,     2,     3,     4,
+       5,     6,     7,     8,     9,    10,    11,    12,    13,    14,
+      15,    16,    17,    18,    19,    20,    21,    22,    23,    24,
+      25,    26,    27,    28,    29,    30,    31,    32,    33,    34,
+      35,    36,    37,    38,    39,    40,    41,    42,    43,    44,
+      45,    46,    47,    48,    49,    50,    51,    52,    53,    54,
+      55,    56
+};
+
+#if YYDEBUG
+/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in
+   YYRHS.  */
+static const yytype_uint16 yyprhs[] =
+{
+       0,     0,     3,     4,     7,     9,    11,    13,    15,    17,
+      19,    21,    23,    25,    27,    29,    39,    48,    55,    64,
+      68,    72,    73,    75,    77,    79,    81,    84,    86,    88,
+      90,    92,    94,    96,   101,   104,   107,   110,   114,   116,
+     119,   121,   124,   127,   130,   132,   134,   136,   137,   140,
+     143,   146,   149,   152,   155,   158,   161,   164,   167,   170,
+     175,   189,   195,   209,   212,   215,   216,   219,   221,   223,
+     225,   228,   229,   232,   233,   237,   241,   245,   247,   249,
+     251,   253,   254,   256,   257,   262,   265,   267
+};
+
+/* YYRHS -- A `-1'-separated list of the rules' RHS.  */
+static const yytype_int8 yyrhs[] =
+{
+      58,     0,    -1,    -1,    58,    59,    -1,    60,    -1,    63,
+      -1,    61,    -1,    62,    -1,    64,    -1,    65,    -1,    92,
+      -1,    77,    -1,    78,    -1,    79,    -1,    80,    -1,     7,
+      81,    84,    84,    66,    67,    75,    68,     3,    -1,     9,
+      81,    84,    84,    66,    67,    75,     3,    -1,    10,    81,
+      83,    83,    66,     3,    -1,     8,    81,    84,    84,    66,
+      67,    75,     3,    -1,    11,    66,     3,    -1,    12,    66,
+       3,    -1,    -1,    14,    -1,    15,    -1,    16,    -1,    17,
+      -1,    17,    83,    -1,    18,    -1,    43,    -1,    45,    -1,
+      69,    -1,    70,    -1,    71,    -1,    21,    72,    20,    73,
+      -1,    21,    72,    -1,    20,    73,    -1,    23,    38,    -1,
+      23,    38,    24,    -1,    34,    -1,    33,    74,    -1,    37,
+      -1,    35,    74,    -1,    36,    74,    -1,    31,    74,    -1,
+      32,    -1,    44,    -1,    45,    -1,    -1,    75,    76,    -1,
+      28,    29,    -1,    28,    30,    -1,    25,    26,    -1,    25,
+      47,    -1,    27,    43,    -1,    22,    43,    -1,    39,    43,
+      -1,    40,    43,    -1,    41,    43,    -1,    42,    43,    -1,
+      56,    43,    43,    44,    -1,    48,    81,    46,    85,    86,
+      46,    85,    86,    87,    88,    89,    90,     3,    -1,    48,
+      55,    44,    90,     3,    -1,    49,    81,    46,    85,    86,
+      46,    85,    86,    87,    88,    89,    90,     3,    -1,    50,
+       3,    -1,    51,     3,    -1,    -1,    81,    82,    -1,    54,
+      -1,    46,    -1,    46,    -1,    46,    86,    -1,    -1,     4,
+      43,    -1,    -1,     5,    47,     6,    -1,     5,    43,     6,
+      -1,     5,    46,     6,    -1,    43,    -1,    47,    -1,    18,
+      -1,    46,    -1,    -1,    46,    -1,    -1,    56,    43,    43,
+      44,    -1,    52,    91,    -1,    53,    -1,    13,     3,    -1
+};
+
+/* YYRLINE[YYN] -- source line where rule number YYN was defined.  */
+static const yytype_uint16 yyrline[] =
+{
+       0,   155,   155,   157,   165,   166,   167,   168,   169,   170,
+     171,   172,   173,   174,   175,   181,   193,   212,   224,   239,
+     249,   259,   262,   270,   278,   282,   289,   296,   305,   306,
+     327,   328,   329,   333,   334,   338,   342,   350,   362,   377,
+     392,   408,   429,   453,   478,   491,   495,   524,   526,   530,
+     531,   532,   533,   534,   535,   544,   545,   546,   547,   548,
+     559,   599,   611,   650,   661,   670,   672,   676,   701,   712,
+     720,   731,   732,   737,   745,   754,   765,   772,   773,   774,
+     777,   800,   804,   815,   817,   826,   850,   855
+};
+#endif
+
+#if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE
+/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
+   First, the terminals, then, starting at YYNTOKENS, nonterminals.  */
+static const char *const yytname[] =
+{
+  "$end", "error", "$undefined", "EOT", "SLASH", "BLCL", "ELCL", "ADD",
+  "GET", "DELETE", "DELETEALL", "FLUSH", "DUMP", "EXIT", "PR_ESP", "PR_AH",
+  "PR_IPCOMP", "PR_ESPUDP", "PR_TCP", "F_PROTOCOL", "F_AUTH", "F_ENC",
+  "F_REPLAY", "F_COMP", "F_RAWCPI", "F_MODE", "MODE", "F_REQID", "F_EXT",
+  "EXTENSION", "NOCYCLICSEQ", "ALG_AUTH", "ALG_AUTH_NOKEY", "ALG_ENC",
+  "ALG_ENC_NOKEY", "ALG_ENC_DESDERIV", "ALG_ENC_DES32IV", "ALG_ENC_OLD",
+  "ALG_COMP", "F_LIFETIME_HARD", "F_LIFETIME_SOFT", "F_LIFEBYTE_HARD",
+  "F_LIFEBYTE_SOFT", "DECSTRING", "QUOTEDSTRING", "HEXSTRING", "STRING",
+  "ANY", "SPDADD", "SPDDELETE", "SPDDUMP", "SPDFLUSH", "F_POLICY",
+  "PL_REQUESTS", "F_AIFLAGS", "TAGGED", "SECURITY_CTX", "$accept",
+  "commands", "command", "add_command", "delete_command",
+  "deleteall_command", "get_command", "flush_command", "dump_command",
+  "protocol_spec", "spi", "algorithm_spec", "esp_spec", "ah_spec",
+  "ipcomp_spec", "enc_alg", "auth_alg", "key_string", "extension_spec",
+  "extension", "spdadd_command", "spddelete_command", "spddump_command",
+  "spdflush_command", "ipaddropts", "ipaddropt", "ipaddr", "ipandport",
+  "prefix", "portstr", "upper_spec", "upper_misc_spec", "context_spec",
+  "policy_spec", "policy_requests", "exit_command", 0
+};
+#endif
+
+# ifdef YYPRINT
+/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to
+   token YYLEX-NUM.  */
+static const yytype_uint16 yytoknum[] =
+{
+       0,   256,   257,   258,   259,   260,   261,   262,   263,   264,
+     265,   266,   267,   268,   269,   270,   271,   272,   273,   274,
+     275,   276,   277,   278,   279,   280,   281,   282,   283,   284,
+     285,   286,   287,   288,   289,   290,   291,   292,   293,   294,
+     295,   296,   297,   298,   299,   300,   301,   302,   303,   304,
+     305,   306,   307,   308,   309,   310,   311
+};
+# endif
+
+/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives.  */
+static const yytype_uint8 yyr1[] =
+{
+       0,    57,    58,    58,    59,    59,    59,    59,    59,    59,
+      59,    59,    59,    59,    59,    60,    61,    62,    63,    64,
+      65,    66,    66,    66,    66,    66,    66,    66,    67,    67,
+      68,    68,    68,    69,    69,    70,    71,    71,    72,    72,
+      72,    72,    72,    73,    73,    74,    74,    75,    75,    76,
+      76,    76,    76,    76,    76,    76,    76,    76,    76,    76,
+      77,    77,    78,    79,    80,    81,    81,    82,    83,    84,
+      84,    85,    85,    86,    86,    86,    86,    87,    87,    87,
+      87,    88,    88,    89,    89,    90,    91,    92
+};
+
+/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN.  */
+static const yytype_uint8 yyr2[] =
+{
+       0,     2,     0,     2,     1,     1,     1,     1,     1,     1,
+       1,     1,     1,     1,     1,     9,     8,     6,     8,     3,
+       3,     0,     1,     1,     1,     1,     2,     1,     1,     1,
+       1,     1,     1,     4,     2,     2,     2,     3,     1,     2,
+       1,     2,     2,     2,     1,     1,     1,     0,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     4,
+      13,     5,    13,     2,     2,     0,     2,     1,     1,     1,
+       2,     0,     2,     0,     3,     3,     3,     1,     1,     1,
+       1,     0,     1,     0,     4,     2,     1,     2
+};
+
+/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state
+   STATE-NUM when YYTABLE doesn't specify something else to do.  Zero
+   means the default is an error.  */
+static const yytype_uint8 yydefact[] =
+{
+       2,     0,     1,    65,    65,    65,    65,    21,    21,     0,
+      65,    65,     0,     0,     3,     4,     6,     7,     5,     8,
+       9,    11,    12,    13,    14,    10,     0,     0,     0,     0,
+      22,    23,    24,    25,    27,     0,     0,    87,     0,     0,
+       0,    63,    64,    69,    67,    66,     0,     0,     0,    68,
+       0,    26,    19,    20,     0,    71,    71,     0,    70,    21,
+      21,    21,    21,     0,     0,     0,    73,    73,     0,     0,
+       0,     0,     0,     0,     0,    86,    85,    61,    72,     0,
+       0,    75,    76,    74,    28,    29,    47,    47,    47,    17,
+      71,    71,     0,     0,     0,    73,    73,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+      30,    31,    32,    48,    18,    16,     0,     0,     0,    44,
+      35,     0,    38,     0,     0,    40,    34,    54,    36,    51,
+      52,    53,    49,    50,    55,    56,    57,    58,     0,    15,
+      79,    77,    80,    78,    81,    81,    45,    46,    43,    39,
+      41,    42,     0,    37,     0,    82,    83,    83,    33,    59,
+       0,     0,     0,     0,     0,     0,     0,    60,    62,    84
+};
+
+/* YYDEFGOTO[NTERM-NUM].  */
+static const yytype_int16 yydefgoto[] =
+{
+      -1,     1,    14,    15,    16,    17,    18,    19,    20,    35,
+      86,   109,   110,   111,   112,   126,   120,   148,    92,   113,
+      21,    22,    23,    24,    26,    45,    50,    46,    66,    58,
+     144,   156,   161,    64,    76,    25
+};
+
+/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
+   STATE-NUM.  */
+#define YYPACT_NINF -64
+static const yytype_int16 yypact[] =
+{
+     -64,    56,   -64,   -64,   -64,   -64,   -64,    32,    32,    10,
+     -32,   -64,    13,    17,   -64,   -64,   -64,   -64,   -64,   -64,
+     -64,   -64,   -64,   -64,   -64,   -64,   -39,   -39,   -39,   -37,
+     -64,   -64,   -64,   -12,   -64,    34,    73,   -64,    16,   -36,
+     -35,   -64,   -64,    82,   -64,   -64,    44,    44,    44,   -64,
+     -12,   -64,   -64,   -64,    26,   115,   115,    15,   -64,    32,
+      32,    32,    32,    69,   122,    83,    82,    82,   121,   123,
+     124,   -31,   -31,   -31,   125,   -64,   -64,   -64,   -64,    85,
+      86,   -64,   -64,   -64,   -64,   -64,   -64,   -64,   -64,   -64,
+     115,   115,    52,    -1,     3,    82,    82,    57,    64,    90,
+      96,   -18,    92,    41,    93,    94,    95,    97,    98,   136,
+     -64,   -64,   -64,   -64,   -64,   -64,    39,    39,    58,   -64,
+     -64,    58,   -64,    58,    58,   -64,   126,   -64,   118,   -64,
+     -64,   -64,   -64,   -64,   -64,   -64,   -64,   -64,   100,   -64,
+     -64,   -64,   -64,   -64,    99,    99,   -64,   -64,   -64,   -64,
+     -64,   -64,    57,   -64,   103,   -64,    88,    88,   -64,   -64,
+     105,    26,    26,   106,   147,   148,   108,   -64,   -64,   -64
+};
+
+/* YYPGOTO[NTERM-NUM].  */
+static const yytype_int8 yypgoto[] =
+{
+     -64,   -64,   -64,   -64,   -64,   -64,   -64,   -64,   -64,    -8,
+      37,   -64,   -64,   -64,   -64,   -64,     1,   -40,    33,   -64,
+     -64,   -64,   -64,   -64,   107,   -64,   -28,    68,   -55,   -63,
+      38,     9,     0,   -38,   -64,   -64
+};
+
+/* YYTABLE[YYPACT[STATE-NUM]].  What to do in state STATE-NUM.  If
+   positive, shift that token.  If negative, reduce the rule which
+   number is the opposite.  If zero, do what YYDEFACT says.
+   If YYTABLE_NINF, syntax error.  */
+#define YYTABLE_NINF -1
+static const yytype_uint8 yytable[] =
+{
+      36,    67,   114,    79,    80,    51,   115,    43,   129,    49,
+      55,    56,    84,    37,    85,    44,    41,    44,    44,    44,
+      42,    99,    62,    38,   101,    99,   102,   103,   101,   130,
+     102,   103,   116,   117,    49,    95,    96,    52,   104,   105,
+     106,   107,   104,   105,   106,   107,    30,    31,    32,    33,
+      34,    71,    72,    73,    74,   108,     2,   140,    68,   108,
+      54,    69,    70,     3,     4,     5,     6,     7,     8,     9,
+     132,   133,    97,    98,    99,   100,    53,   101,    63,   102,
+     103,   149,   141,   150,   151,   142,   143,    57,   118,   119,
+      43,   104,   105,   106,   107,    47,    48,   121,   122,   123,
+     124,   125,   146,   147,    10,    11,    12,    13,   108,    87,
+      88,    27,    28,    29,    59,    60,    61,    39,    40,    65,
+      93,    94,    75,   164,   165,    77,    78,    81,    89,    82,
+      83,    90,    91,   127,   128,   131,   134,   135,   136,   139,
+     137,   138,   153,   154,   160,   155,   152,   159,   163,   166,
+     167,   168,   169,   158,   157,   145,     0,   162
+};
+
+static const yytype_int16 yycheck[] =
+{
+       8,    56,     3,    66,    67,    33,     3,    46,    26,    46,
+      46,    46,    43,     3,    45,    54,     3,    54,    54,    54,
+       3,    22,    50,    55,    25,    22,    27,    28,    25,    47,
+      27,    28,    95,    96,    46,    90,    91,     3,    39,    40,
+      41,    42,    39,    40,    41,    42,    14,    15,    16,    17,
+      18,    59,    60,    61,    62,    56,     0,    18,    43,    56,
+      44,    46,    47,     7,     8,     9,    10,    11,    12,    13,
+      29,    30,    20,    21,    22,    23,     3,    25,    52,    27,
+      28,   121,    43,   123,   124,    46,    47,     5,    31,    32,
+      46,    39,    40,    41,    42,    27,    28,    33,    34,    35,
+      36,    37,    44,    45,    48,    49,    50,    51,    56,    72,
+      73,     4,     5,     6,    46,    47,    48,    10,    11,     4,
+      87,    88,    53,   161,   162,     3,    43,     6,     3,     6,
+       6,    46,    46,    43,    38,    43,    43,    43,    43,     3,
+      43,    43,    24,    43,    56,    46,    20,    44,    43,    43,
+       3,     3,    44,   152,   145,   117,    -1,   157
+};
+
+/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
+   symbol of state STATE-NUM.  */
+static const yytype_uint8 yystos[] =
+{
+       0,    58,     0,     7,     8,     9,    10,    11,    12,    13,
+      48,    49,    50,    51,    59,    60,    61,    62,    63,    64,
+      65,    77,    78,    79,    80,    92,    81,    81,    81,    81,
+      14,    15,    16,    17,    18,    66,    66,     3,    55,    81,
+      81,     3,     3,    46,    54,    82,    84,    84,    84,    46,
+      83,    83,     3,     3,    44,    46,    46,     5,    86,    84,
+      84,    84,    83,    52,    90,     4,    85,    85,    43,    46,
+      47,    66,    66,    66,    66,    53,    91,     3,    43,    86,
+      86,     6,     6,     6,    43,    45,    67,    67,    67,     3,
+      46,    46,    75,    75,    75,    85,    85,    20,    21,    22,
+      23,    25,    27,    28,    39,    40,    41,    42,    56,    68,
+      69,    70,    71,    76,     3,     3,    86,    86,    31,    32,
+      73,    33,    34,    35,    36,    37,    72,    43,    38,    26,
+      47,    43,    29,    30,    43,    43,    43,    43,    43,     3,
+      18,    43,    46,    47,    87,    87,    44,    45,    74,    74,
+      74,    74,    20,    24,    43,    46,    88,    88,    73,    44,
+      56,    89,    89,    43,    90,    90,    43,     3,     3,    44
+};
+
+#define yyerrok		(yyerrstatus = 0)
+#define yyclearin	(yychar = YYEMPTY)
+#define YYEMPTY		(-2)
+#define YYEOF		0
+
+#define YYACCEPT	goto yyacceptlab
+#define YYABORT		goto yyabortlab
+#define YYERROR		goto yyerrorlab
+
+
+/* Like YYERROR except do call yyerror.  This remains here temporarily
+   to ease the transition to the new meaning of YYERROR, for GCC.
+   Once GCC version 2 has supplanted version 1, this can go.  */
+
+#define YYFAIL		goto yyerrlab
+
+#define YYRECOVERING()  (!!yyerrstatus)
+
+#define YYBACKUP(Token, Value)					\
+do								\
+  if (yychar == YYEMPTY && yylen == 1)				\
+    {								\
+      yychar = (Token);						\
+      yylval = (Value);						\
+      yytoken = YYTRANSLATE (yychar);				\
+      YYPOPSTACK (1);						\
+      goto yybackup;						\
+    }								\
+  else								\
+    {								\
+      yyerror (YY_("syntax error: cannot back up")); \
+      YYERROR;							\
+    }								\
+while (YYID (0))
+
+
+#define YYTERROR	1
+#define YYERRCODE	256
+
+
+/* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N].
+   If N is 0, then set CURRENT to the empty location which ends
+   the previous symbol: RHS[0] (always defined).  */
+
+#define YYRHSLOC(Rhs, K) ((Rhs)[K])
+#ifndef YYLLOC_DEFAULT
+# define YYLLOC_DEFAULT(Current, Rhs, N)				\
+    do									\
+      if (YYID (N))                                                    \
+	{								\
+	  (Current).first_line   = YYRHSLOC (Rhs, 1).first_line;	\
+	  (Current).first_column = YYRHSLOC (Rhs, 1).first_column;	\
+	  (Current).last_line    = YYRHSLOC (Rhs, N).last_line;		\
+	  (Current).last_column  = YYRHSLOC (Rhs, N).last_column;	\
+	}								\
+      else								\
+	{								\
+	  (Current).first_line   = (Current).last_line   =		\
+	    YYRHSLOC (Rhs, 0).last_line;				\
+	  (Current).first_column = (Current).last_column =		\
+	    YYRHSLOC (Rhs, 0).last_column;				\
+	}								\
+    while (YYID (0))
+#endif
+
+
+/* YY_LOCATION_PRINT -- Print the location on the stream.
+   This macro was not mandated originally: define only if we know
+   we won't break user code: when these are the locations we know.  */
+
+#ifndef YY_LOCATION_PRINT
+# if YYLTYPE_IS_TRIVIAL
+#  define YY_LOCATION_PRINT(File, Loc)			\
+     fprintf (File, "%d.%d-%d.%d",			\
+	      (Loc).first_line, (Loc).first_column,	\
+	      (Loc).last_line,  (Loc).last_column)
+# else
+#  define YY_LOCATION_PRINT(File, Loc) ((void) 0)
+# endif
+#endif
+
+
+/* YYLEX -- calling `yylex' with the right arguments.  */
+
+#ifdef YYLEX_PARAM
+# define YYLEX yylex (YYLEX_PARAM)
+#else
+# define YYLEX yylex ()
+#endif
+
+/* Enable debugging if requested.  */
+#if YYDEBUG
+
+# ifndef YYFPRINTF
+#  include <stdio.h> /* INFRINGES ON USER NAME SPACE */
+#  define YYFPRINTF fprintf
+# endif
+
+# define YYDPRINTF(Args)			\
+do {						\
+  if (yydebug)					\
+    YYFPRINTF Args;				\
+} while (YYID (0))
+
+# define YY_SYMBOL_PRINT(Title, Type, Value, Location)			  \
+do {									  \
+  if (yydebug)								  \
+    {									  \
+      YYFPRINTF (stderr, "%s ", Title);					  \
+      yy_symbol_print (stderr,						  \
+		  Type, Value); \
+      YYFPRINTF (stderr, "\n");						  \
+    }									  \
+} while (YYID (0))
+
+
+/*--------------------------------.
+| Print this symbol on YYOUTPUT.  |
+`--------------------------------*/
+
+/*ARGSUSED*/
+#if (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+static void
+yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep)
+#else
+static void
+yy_symbol_value_print (yyoutput, yytype, yyvaluep)
+    FILE *yyoutput;
+    int yytype;
+    YYSTYPE const * const yyvaluep;
+#endif
+{
+  if (!yyvaluep)
+    return;
+# ifdef YYPRINT
+  if (yytype < YYNTOKENS)
+    YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep);
+# else
+  YYUSE (yyoutput);
+# endif
+  switch (yytype)
+    {
+      default:
+	break;
+    }
+}
+
+
+/*--------------------------------.
+| Print this symbol on YYOUTPUT.  |
+`--------------------------------*/
+
+#if (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+static void
+yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep)
+#else
+static void
+yy_symbol_print (yyoutput, yytype, yyvaluep)
+    FILE *yyoutput;
+    int yytype;
+    YYSTYPE const * const yyvaluep;
+#endif
+{
+  if (yytype < YYNTOKENS)
+    YYFPRINTF (yyoutput, "token %s (", yytname[yytype]);
+  else
+    YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]);
+
+  yy_symbol_value_print (yyoutput, yytype, yyvaluep);
+  YYFPRINTF (yyoutput, ")");
+}
+
+/*------------------------------------------------------------------.
+| yy_stack_print -- Print the state stack from its BOTTOM up to its |
+| TOP (included).                                                   |
+`------------------------------------------------------------------*/
+
+#if (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+static void
+yy_stack_print (yytype_int16 *bottom, yytype_int16 *top)
+#else
+static void
+yy_stack_print (bottom, top)
+    yytype_int16 *bottom;
+    yytype_int16 *top;
+#endif
+{
+  YYFPRINTF (stderr, "Stack now");
+  for (; bottom <= top; ++bottom)
+    YYFPRINTF (stderr, " %d", *bottom);
+  YYFPRINTF (stderr, "\n");
+}
+
+# define YY_STACK_PRINT(Bottom, Top)				\
+do {								\
+  if (yydebug)							\
+    yy_stack_print ((Bottom), (Top));				\
+} while (YYID (0))
+
+
+/*------------------------------------------------.
+| Report that the YYRULE is going to be reduced.  |
+`------------------------------------------------*/
+
+#if (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+static void
+yy_reduce_print (YYSTYPE *yyvsp, int yyrule)
+#else
+static void
+yy_reduce_print (yyvsp, yyrule)
+    YYSTYPE *yyvsp;
+    int yyrule;
+#endif
+{
+  int yynrhs = yyr2[yyrule];
+  int yyi;
+  unsigned long int yylno = yyrline[yyrule];
+  YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n",
+	     yyrule - 1, yylno);
+  /* The symbols being reduced.  */
+  for (yyi = 0; yyi < yynrhs; yyi++)
+    {
+      fprintf (stderr, "   $%d = ", yyi + 1);
+      yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi],
+		       &(yyvsp[(yyi + 1) - (yynrhs)])
+		       		       );
+      fprintf (stderr, "\n");
+    }
+}
+
+# define YY_REDUCE_PRINT(Rule)		\
+do {					\
+  if (yydebug)				\
+    yy_reduce_print (yyvsp, Rule); \
+} while (YYID (0))
+
+/* Nonzero means print parse trace.  It is left uninitialized so that
+   multiple parsers can coexist.  */
+int yydebug;
+#else /* !YYDEBUG */
+# define YYDPRINTF(Args)
+# define YY_SYMBOL_PRINT(Title, Type, Value, Location)
+# define YY_STACK_PRINT(Bottom, Top)
+# define YY_REDUCE_PRINT(Rule)
+#endif /* !YYDEBUG */
+
+
+/* YYINITDEPTH -- initial size of the parser's stacks.  */
+#ifndef	YYINITDEPTH
+# define YYINITDEPTH 200
+#endif
+
+/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only
+   if the built-in stack extension method is used).
+
+   Do not make this value too large; the results are undefined if
+   YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH)
+   evaluated with infinite-precision integer arithmetic.  */
+
+#ifndef YYMAXDEPTH
+# define YYMAXDEPTH 10000
+#endif
+
+
+
+#if YYERROR_VERBOSE
+
+# ifndef yystrlen
+#  if defined __GLIBC__ && defined _STRING_H
+#   define yystrlen strlen
+#  else
+/* Return the length of YYSTR.  */
+#if (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+static YYSIZE_T
+yystrlen (const char *yystr)
+#else
+static YYSIZE_T
+yystrlen (yystr)
+    const char *yystr;
+#endif
+{
+  YYSIZE_T yylen;
+  for (yylen = 0; yystr[yylen]; yylen++)
+    continue;
+  return yylen;
+}
+#  endif
+# endif
+
+# ifndef yystpcpy
+#  if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE
+#   define yystpcpy stpcpy
+#  else
+/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in
+   YYDEST.  */
+#if (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+static char *
+yystpcpy (char *yydest, const char *yysrc)
+#else
+static char *
+yystpcpy (yydest, yysrc)
+    char *yydest;
+    const char *yysrc;
+#endif
+{
+  char *yyd = yydest;
+  const char *yys = yysrc;
+
+  while ((*yyd++ = *yys++) != '\0')
+    continue;
+
+  return yyd - 1;
+}
+#  endif
+# endif
+
+# ifndef yytnamerr
+/* Copy to YYRES the contents of YYSTR after stripping away unnecessary
+   quotes and backslashes, so that it's suitable for yyerror.  The
+   heuristic is that double-quoting is unnecessary unless the string
+   contains an apostrophe, a comma, or backslash (other than
+   backslash-backslash).  YYSTR is taken from yytname.  If YYRES is
+   null, do not copy; instead, return the length of what the result
+   would have been.  */
+static YYSIZE_T
+yytnamerr (char *yyres, const char *yystr)
+{
+  if (*yystr == '"')
+    {
+      YYSIZE_T yyn = 0;
+      char const *yyp = yystr;
+
+      for (;;)
+	switch (*++yyp)
+	  {
+	  case '\'':
+	  case ',':
+	    goto do_not_strip_quotes;
+
+	  case '\\':
+	    if (*++yyp != '\\')
+	      goto do_not_strip_quotes;
+	    /* Fall through.  */
+	  default:
+	    if (yyres)
+	      yyres[yyn] = *yyp;
+	    yyn++;
+	    break;
+
+	  case '"':
+	    if (yyres)
+	      yyres[yyn] = '\0';
+	    return yyn;
+	  }
+    do_not_strip_quotes: ;
+    }
+
+  if (! yyres)
+    return yystrlen (yystr);
+
+  return yystpcpy (yyres, yystr) - yyres;
+}
+# endif
+
+/* Copy into YYRESULT an error message about the unexpected token
+   YYCHAR while in state YYSTATE.  Return the number of bytes copied,
+   including the terminating null byte.  If YYRESULT is null, do not
+   copy anything; just return the number of bytes that would be
+   copied.  As a special case, return 0 if an ordinary "syntax error"
+   message will do.  Return YYSIZE_MAXIMUM if overflow occurs during
+   size calculation.  */
+static YYSIZE_T
+yysyntax_error (char *yyresult, int yystate, int yychar)
+{
+  int yyn = yypact[yystate];
+
+  if (! (YYPACT_NINF < yyn && yyn <= YYLAST))
+    return 0;
+  else
+    {
+      int yytype = YYTRANSLATE (yychar);
+      YYSIZE_T yysize0 = yytnamerr (0, yytname[yytype]);
+      YYSIZE_T yysize = yysize0;
+      YYSIZE_T yysize1;
+      int yysize_overflow = 0;
+      enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 };
+      char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM];
+      int yyx;
+
+# if 0
+      /* This is so xgettext sees the translatable formats that are
+	 constructed on the fly.  */
+      YY_("syntax error, unexpected %s");
+      YY_("syntax error, unexpected %s, expecting %s");
+      YY_("syntax error, unexpected %s, expecting %s or %s");
+      YY_("syntax error, unexpected %s, expecting %s or %s or %s");
+      YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s");
+# endif
+      char *yyfmt;
+      char const *yyf;
+      static char const yyunexpected[] = "syntax error, unexpected %s";
+      static char const yyexpecting[] = ", expecting %s";
+      static char const yyor[] = " or %s";
+      char yyformat[sizeof yyunexpected
+		    + sizeof yyexpecting - 1
+		    + ((YYERROR_VERBOSE_ARGS_MAXIMUM - 2)
+		       * (sizeof yyor - 1))];
+      char const *yyprefix = yyexpecting;
+
+      /* Start YYX at -YYN if negative to avoid negative indexes in
+	 YYCHECK.  */
+      int yyxbegin = yyn < 0 ? -yyn : 0;
+
+      /* Stay within bounds of both yycheck and yytname.  */
+      int yychecklim = YYLAST - yyn + 1;
+      int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
+      int yycount = 1;
+
+      yyarg[0] = yytname[yytype];
+      yyfmt = yystpcpy (yyformat, yyunexpected);
+
+      for (yyx = yyxbegin; yyx < yyxend; ++yyx)
+	if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR)
+	  {
+	    if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM)
+	      {
+		yycount = 1;
+		yysize = yysize0;
+		yyformat[sizeof yyunexpected - 1] = '\0';
+		break;
+	      }
+	    yyarg[yycount++] = yytname[yyx];
+	    yysize1 = yysize + yytnamerr (0, yytname[yyx]);
+	    yysize_overflow |= (yysize1 < yysize);
+	    yysize = yysize1;
+	    yyfmt = yystpcpy (yyfmt, yyprefix);
+	    yyprefix = yyor;
+	  }
+
+      yyf = YY_(yyformat);
+      yysize1 = yysize + yystrlen (yyf);
+      yysize_overflow |= (yysize1 < yysize);
+      yysize = yysize1;
+
+      if (yysize_overflow)
+	return YYSIZE_MAXIMUM;
+
+      if (yyresult)
+	{
+	  /* Avoid sprintf, as that infringes on the user's name space.
+	     Don't have undefined behavior even if the translation
+	     produced a string with the wrong number of "%s"s.  */
+	  char *yyp = yyresult;
+	  int yyi = 0;
+	  while ((*yyp = *yyf) != '\0')
+	    {
+	      if (*yyp == '%' && yyf[1] == 's' && yyi < yycount)
+		{
+		  yyp += yytnamerr (yyp, yyarg[yyi++]);
+		  yyf += 2;
+		}
+	      else
+		{
+		  yyp++;
+		  yyf++;
+		}
+	    }
+	}
+      return yysize;
+    }
+}
+#endif /* YYERROR_VERBOSE */
+
+
+/*-----------------------------------------------.
+| Release the memory associated to this symbol.  |
+`-----------------------------------------------*/
+
+/*ARGSUSED*/
+#if (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+static void
+yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep)
+#else
+static void
+yydestruct (yymsg, yytype, yyvaluep)
+    const char *yymsg;
+    int yytype;
+    YYSTYPE *yyvaluep;
+#endif
+{
+  YYUSE (yyvaluep);
+
+  if (!yymsg)
+    yymsg = "Deleting";
+  YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp);
+
+  switch (yytype)
+    {
+
+      default:
+	break;
+    }
+}
+
+
+/* Prevent warnings from -Wmissing-prototypes.  */
+
+#ifdef YYPARSE_PARAM
+#if defined __STDC__ || defined __cplusplus
+int yyparse (void *YYPARSE_PARAM);
+#else
+int yyparse ();
+#endif
+#else /* ! YYPARSE_PARAM */
+#if defined __STDC__ || defined __cplusplus
+int yyparse (void);
+#else
+int yyparse ();
+#endif
+#endif /* ! YYPARSE_PARAM */
+
+
+
+/* The look-ahead symbol.  */
+int yychar;
+
+/* The semantic value of the look-ahead symbol.  */
+YYSTYPE yylval;
+
+/* Number of syntax errors so far.  */
+int yynerrs;
+
+#ifdef ANDROID_CHANGES
+struct protoent udp = {
+	"udp",
+	{ "UDP" },
+	17
+};
+struct protoent *agetprotobyname(char *name) {
+  if(memcmp(name, "udp", 4) == 0) {
+    return &udp;
+  } else {
+    printf("FIXME! agetprotobyname() does not support protocol %s\n", name);
+    return getprotobyname(name);
+  }
+}
+#endif
+
+/*----------.
+| yyparse.  |
+`----------*/
+
+#ifdef YYPARSE_PARAM
+#if (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+int
+yyparse (void *YYPARSE_PARAM)
+#else
+int
+yyparse (YYPARSE_PARAM)
+    void *YYPARSE_PARAM;
+#endif
+#else /* ! YYPARSE_PARAM */
+#if (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+int
+yyparse (void)
+#else
+int
+yyparse ()
+
+#endif
+#endif
+{
+  
+  int yystate;
+  int yyn;
+  int yyresult;
+  /* Number of tokens to shift before error messages enabled.  */
+  int yyerrstatus;
+  /* Look-ahead token as an internal (translated) token number.  */
+  int yytoken = 0;
+#if YYERROR_VERBOSE
+  /* Buffer for error messages, and its allocated size.  */
+  char yymsgbuf[128];
+  char *yymsg = yymsgbuf;
+  YYSIZE_T yymsg_alloc = sizeof yymsgbuf;
+#endif
+
+  /* Three stacks and their tools:
+     `yyss': related to states,
+     `yyvs': related to semantic values,
+     `yyls': related to locations.
+
+     Refer to the stacks thru separate pointers, to allow yyoverflow
+     to reallocate them elsewhere.  */
+
+  /* The state stack.  */
+  yytype_int16 yyssa[YYINITDEPTH];
+  yytype_int16 *yyss = yyssa;
+  yytype_int16 *yyssp;
+
+  /* The semantic value stack.  */
+  YYSTYPE yyvsa[YYINITDEPTH];
+  YYSTYPE *yyvs = yyvsa;
+  YYSTYPE *yyvsp;
+
+
+
+#define YYPOPSTACK(N)   (yyvsp -= (N), yyssp -= (N))
+
+  YYSIZE_T yystacksize = YYINITDEPTH;
+
+  /* The variables used to return semantic value and location from the
+     action routines.  */
+  YYSTYPE yyval;
+
+
+  /* The number of symbols on the RHS of the reduced rule.
+     Keep to zero when no symbol should be popped.  */
+  int yylen = 0;
+
+  YYDPRINTF ((stderr, "Starting parse\n"));
+
+  yystate = 0;
+  yyerrstatus = 0;
+  yynerrs = 0;
+  yychar = YYEMPTY;		/* Cause a token to be read.  */
+
+  /* Initialize stack pointers.
+     Waste one element of value and location stack
+     so that they stay on the same level as the state stack.
+     The wasted elements are never initialized.  */
+
+  yyssp = yyss;
+  yyvsp = yyvs;
+
+  goto yysetstate;
+
+/*------------------------------------------------------------.
+| yynewstate -- Push a new state, which is found in yystate.  |
+`------------------------------------------------------------*/
+ yynewstate:
+  /* In all cases, when you get here, the value and location stacks
+     have just been pushed.  So pushing a state here evens the stacks.  */
+  yyssp++;
+
+ yysetstate:
+  *yyssp = yystate;
+
+  if (yyss + yystacksize - 1 <= yyssp)
+    {
+      /* Get the current used size of the three stacks, in elements.  */
+      YYSIZE_T yysize = yyssp - yyss + 1;
+
+#ifdef yyoverflow
+      {
+	/* Give user a chance to reallocate the stack.  Use copies of
+	   these so that the &'s don't force the real ones into
+	   memory.  */
+	YYSTYPE *yyvs1 = yyvs;
+	yytype_int16 *yyss1 = yyss;
+
+
+	/* Each stack pointer address is followed by the size of the
+	   data in use in that stack, in bytes.  This used to be a
+	   conditional around just the two extra args, but that might
+	   be undefined if yyoverflow is a macro.  */
+	yyoverflow (YY_("memory exhausted"),
+		    &yyss1, yysize * sizeof (*yyssp),
+		    &yyvs1, yysize * sizeof (*yyvsp),
+
+		    &yystacksize);
+
+	yyss = yyss1;
+	yyvs = yyvs1;
+      }
+#else /* no yyoverflow */
+# ifndef YYSTACK_RELOCATE
+      goto yyexhaustedlab;
+# else
+      /* Extend the stack our own way.  */
+      if (YYMAXDEPTH <= yystacksize)
+	goto yyexhaustedlab;
+      yystacksize *= 2;
+      if (YYMAXDEPTH < yystacksize)
+	yystacksize = YYMAXDEPTH;
+
+      {
+	yytype_int16 *yyss1 = yyss;
+	union yyalloc *yyptr =
+	  (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
+	if (! yyptr)
+	  goto yyexhaustedlab;
+	YYSTACK_RELOCATE (yyss);
+	YYSTACK_RELOCATE (yyvs);
+
+#  undef YYSTACK_RELOCATE
+	if (yyss1 != yyssa)
+	  YYSTACK_FREE (yyss1);
+      }
+# endif
+#endif /* no yyoverflow */
+
+      yyssp = yyss + yysize - 1;
+      yyvsp = yyvs + yysize - 1;
+
+
+      YYDPRINTF ((stderr, "Stack size increased to %lu\n",
+		  (unsigned long int) yystacksize));
+
+      if (yyss + yystacksize - 1 <= yyssp)
+	YYABORT;
+    }
+
+  YYDPRINTF ((stderr, "Entering state %d\n", yystate));
+
+  goto yybackup;
+
+/*-----------.
+| yybackup.  |
+`-----------*/
+yybackup:
+
+  /* Do appropriate processing given the current state.  Read a
+     look-ahead token if we need one and don't already have one.  */
+
+  /* First try to decide what to do without reference to look-ahead token.  */
+  yyn = yypact[yystate];
+  if (yyn == YYPACT_NINF)
+    goto yydefault;
+
+  /* Not known => get a look-ahead token if don't already have one.  */
+
+  /* YYCHAR is either YYEMPTY or YYEOF or a valid look-ahead symbol.  */
+  if (yychar == YYEMPTY)
+    {
+      YYDPRINTF ((stderr, "Reading a token: "));
+      yychar = YYLEX;
+    }
+
+  if (yychar <= YYEOF)
+    {
+      yychar = yytoken = YYEOF;
+      YYDPRINTF ((stderr, "Now at end of input.\n"));
+    }
+  else
+    {
+      yytoken = YYTRANSLATE (yychar);
+      YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc);
+    }
+
+  /* If the proper action on seeing token YYTOKEN is to reduce or to
+     detect an error, take that action.  */
+  yyn += yytoken;
+  if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken)
+    goto yydefault;
+  yyn = yytable[yyn];
+  if (yyn <= 0)
+    {
+      if (yyn == 0 || yyn == YYTABLE_NINF)
+	goto yyerrlab;
+      yyn = -yyn;
+      goto yyreduce;
+    }
+
+  if (yyn == YYFINAL)
+    YYACCEPT;
+
+  /* Count tokens shifted since error; after three, turn off error
+     status.  */
+  if (yyerrstatus)
+    yyerrstatus--;
+
+  /* Shift the look-ahead token.  */
+  YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc);
+
+  /* Discard the shifted token unless it is eof.  */
+  if (yychar != YYEOF)
+    yychar = YYEMPTY;
+
+  yystate = yyn;
+  *++yyvsp = yylval;
+
+  goto yynewstate;
+
+
+/*-----------------------------------------------------------.
+| yydefault -- do the default action for the current state.  |
+`-----------------------------------------------------------*/
+yydefault:
+  yyn = yydefact[yystate];
+  if (yyn == 0)
+    goto yyerrlab;
+  goto yyreduce;
+
+
+/*-----------------------------.
+| yyreduce -- Do a reduction.  |
+`-----------------------------*/
+yyreduce:
+  /* yyn is the number of a rule to reduce with.  */
+  yylen = yyr2[yyn];
+
+  /* If YYLEN is nonzero, implement the default value of the action:
+     `$$ = $1'.
+
+     Otherwise, the following line sets YYVAL to garbage.
+     This behavior is undocumented and Bison
+     users should not rely upon it.  Assigning to YYVAL
+     unconditionally makes the parser a bit smaller, and it avoids a
+     GCC warning that YYVAL may be used uninitialized.  */
+  yyval = yyvsp[1-yylen];
+
+
+  YY_REDUCE_PRINT (yyn);
+  switch (yyn)
+    {
+        case 3:
+#line 158 "parse.y"
+    {
+			free_buffer();
+			parse_init();
+		}
+    break;
+
+  case 15:
+#line 182 "parse.y"
+    {
+			int status;
+
+			status = setkeymsg_add(SADB_ADD, (yyvsp[(5) - (9)].num), (yyvsp[(3) - (9)].res), (yyvsp[(4) - (9)].res));
+			if (status < 0)
+				return -1;
+		}
+    break;
+
+  case 16:
+#line 194 "parse.y"
+    {
+			int status;
+
+			if ((yyvsp[(3) - (8)].res)->ai_next || (yyvsp[(4) - (8)].res)->ai_next) {
+				yyerror("multiple address specified");
+				return -1;
+			}
+			if (p_mode != IPSEC_MODE_ANY)
+				yyerror("WARNING: mode is obsolete");
+
+			status = setkeymsg_addr(SADB_DELETE, (yyvsp[(5) - (8)].num), (yyvsp[(3) - (8)].res), (yyvsp[(4) - (8)].res), 0);
+			if (status < 0)
+				return -1;
+		}
+    break;
+
+  case 17:
+#line 213 "parse.y"
+    {
+			int status;
+
+			status = setkeymsg_addr(SADB_DELETE, (yyvsp[(5) - (6)].num), (yyvsp[(3) - (6)].res), (yyvsp[(4) - (6)].res), 1);
+			if (status < 0)
+				return -1;
+		}
+    break;
+
+  case 18:
+#line 225 "parse.y"
+    {
+			int status;
+
+			if (p_mode != IPSEC_MODE_ANY)
+				yyerror("WARNING: mode is obsolete");
+
+			status = setkeymsg_addr(SADB_GET, (yyvsp[(5) - (8)].num), (yyvsp[(3) - (8)].res), (yyvsp[(4) - (8)].res), 0);
+			if (status < 0)
+				return -1;
+		}
+    break;
+
+  case 19:
+#line 240 "parse.y"
+    {
+			struct sadb_msg msg;
+			setkeymsg0(&msg, SADB_FLUSH, (yyvsp[(2) - (3)].num), sizeof(msg));
+			sendkeymsg((char *)&msg, sizeof(msg));
+		}
+    break;
+
+  case 20:
+#line 250 "parse.y"
+    {
+			struct sadb_msg msg;
+			setkeymsg0(&msg, SADB_DUMP, (yyvsp[(2) - (3)].num), sizeof(msg));
+			sendkeymsg((char *)&msg, sizeof(msg));
+		}
+    break;
+
+  case 21:
+#line 259 "parse.y"
+    {
+			(yyval.num) = SADB_SATYPE_UNSPEC;
+		}
+    break;
+
+  case 22:
+#line 263 "parse.y"
+    {
+			(yyval.num) = SADB_SATYPE_ESP;
+			if ((yyvsp[(1) - (1)].num) == 1)
+				p_ext |= SADB_X_EXT_OLD;
+			else
+				p_ext &= ~SADB_X_EXT_OLD;
+		}
+    break;
+
+  case 23:
+#line 271 "parse.y"
+    {
+			(yyval.num) = SADB_SATYPE_AH;
+			if ((yyvsp[(1) - (1)].num) == 1)
+				p_ext |= SADB_X_EXT_OLD;
+			else
+				p_ext &= ~SADB_X_EXT_OLD;
+		}
+    break;
+
+  case 24:
+#line 279 "parse.y"
+    {
+			(yyval.num) = SADB_X_SATYPE_IPCOMP;
+		}
+    break;
+
+  case 25:
+#line 283 "parse.y"
+    {
+			(yyval.num) = SADB_SATYPE_ESP;
+			p_ext &= ~SADB_X_EXT_OLD;
+			p_natt_oa = 0;
+			p_natt_type = UDP_ENCAP_ESPINUDP;
+		}
+    break;
+
+  case 26:
+#line 290 "parse.y"
+    {
+			(yyval.num) = SADB_SATYPE_ESP;
+			p_ext &= ~SADB_X_EXT_OLD;
+			p_natt_oa = (yyvsp[(2) - (2)].res);
+			p_natt_type = UDP_ENCAP_ESPINUDP;
+		}
+    break;
+
+  case 27:
+#line 297 "parse.y"
+    {
+#ifdef SADB_X_SATYPE_TCPSIGNATURE
+			(yyval.num) = SADB_X_SATYPE_TCPSIGNATURE;
+#endif
+		}
+    break;
+
+  case 28:
+#line 305 "parse.y"
+    { p_spi = (yyvsp[(1) - (1)].ulnum); }
+    break;
+
+  case 29:
+#line 307 "parse.y"
+    {
+			char *ep;
+			unsigned long v;
+
+			ep = NULL;
+			v = strtoul((yyvsp[(1) - (1)].val).buf, &ep, 16);
+			if (!ep || *ep) {
+				yyerror("invalid SPI");
+				return -1;
+			}
+			if (v & ~0xffffffff) {
+				yyerror("SPI too big.");
+				return -1;
+			}
+
+			p_spi = v;
+		}
+    break;
+
+  case 36:
+#line 343 "parse.y"
+    {
+			if ((yyvsp[(2) - (2)].num) < 0) {
+				yyerror("unsupported algorithm");
+				return -1;
+			}
+			p_alg_enc = (yyvsp[(2) - (2)].num);
+		}
+    break;
+
+  case 37:
+#line 351 "parse.y"
+    {
+			if ((yyvsp[(2) - (3)].num) < 0) {
+				yyerror("unsupported algorithm");
+				return -1;
+			}
+			p_alg_enc = (yyvsp[(2) - (3)].num);
+			p_ext |= SADB_X_EXT_RAWCPI;
+		}
+    break;
+
+  case 38:
+#line 362 "parse.y"
+    {
+			if ((yyvsp[(1) - (1)].num) < 0) {
+				yyerror("unsupported algorithm");
+				return -1;
+			}
+			p_alg_enc = (yyvsp[(1) - (1)].num);
+
+			p_key_enc_len = 0;
+			p_key_enc = "";
+			if (ipsec_check_keylen(SADB_EXT_SUPPORTED_ENCRYPT,
+			    p_alg_enc, PFKEY_UNUNIT64(p_key_enc_len)) < 0) {
+				yyerror(ipsec_strerror());
+				return -1;
+			}
+		}
+    break;
+
+  case 39:
+#line 377 "parse.y"
+    {
+			if ((yyvsp[(1) - (2)].num) < 0) {
+				yyerror("unsupported algorithm");
+				return -1;
+			}
+			p_alg_enc = (yyvsp[(1) - (2)].num);
+
+			p_key_enc_len = (yyvsp[(2) - (2)].val).len;
+			p_key_enc = (yyvsp[(2) - (2)].val).buf;
+			if (ipsec_check_keylen(SADB_EXT_SUPPORTED_ENCRYPT,
+			    p_alg_enc, PFKEY_UNUNIT64(p_key_enc_len)) < 0) {
+				yyerror(ipsec_strerror());
+				return -1;
+			}
+		}
+    break;
+
+  case 40:
+#line 392 "parse.y"
+    {
+			if ((yyvsp[(1) - (1)].num) < 0) {
+				yyerror("unsupported algorithm");
+				return -1;
+			}
+			yyerror("WARNING: obsolete algorithm");
+			p_alg_enc = (yyvsp[(1) - (1)].num);
+
+			p_key_enc_len = 0;
+			p_key_enc = "";
+			if (ipsec_check_keylen(SADB_EXT_SUPPORTED_ENCRYPT,
+			    p_alg_enc, PFKEY_UNUNIT64(p_key_enc_len)) < 0) {
+				yyerror(ipsec_strerror());
+				return -1;
+			}
+		}
+    break;
+
+  case 41:
+#line 409 "parse.y"
+    {
+			if ((yyvsp[(1) - (2)].num) < 0) {
+				yyerror("unsupported algorithm");
+				return -1;
+			}
+			p_alg_enc = (yyvsp[(1) - (2)].num);
+			if (p_ext & SADB_X_EXT_OLD) {
+				yyerror("algorithm mismatched");
+				return -1;
+			}
+			p_ext |= SADB_X_EXT_DERIV;
+
+			p_key_enc_len = (yyvsp[(2) - (2)].val).len;
+			p_key_enc = (yyvsp[(2) - (2)].val).buf;
+			if (ipsec_check_keylen(SADB_EXT_SUPPORTED_ENCRYPT,
+			    p_alg_enc, PFKEY_UNUNIT64(p_key_enc_len)) < 0) {
+				yyerror(ipsec_strerror());
+				return -1;
+			}
+		}
+    break;
+
+  case 42:
+#line 430 "parse.y"
+    {
+			if ((yyvsp[(1) - (2)].num) < 0) {
+				yyerror("unsupported algorithm");
+				return -1;
+			}
+			p_alg_enc = (yyvsp[(1) - (2)].num);
+			if (!(p_ext & SADB_X_EXT_OLD)) {
+				yyerror("algorithm mismatched");
+				return -1;
+			}
+			p_ext |= SADB_X_EXT_IV4B;
+
+			p_key_enc_len = (yyvsp[(2) - (2)].val).len;
+			p_key_enc = (yyvsp[(2) - (2)].val).buf;
+			if (ipsec_check_keylen(SADB_EXT_SUPPORTED_ENCRYPT,
+			    p_alg_enc, PFKEY_UNUNIT64(p_key_enc_len)) < 0) {
+				yyerror(ipsec_strerror());
+				return -1;
+			}
+		}
+    break;
+
+  case 43:
+#line 453 "parse.y"
+    {
+			if ((yyvsp[(1) - (2)].num) < 0) {
+				yyerror("unsupported algorithm");
+				return -1;
+			}
+			p_alg_auth = (yyvsp[(1) - (2)].num);
+
+			p_key_auth_len = (yyvsp[(2) - (2)].val).len;
+			p_key_auth = (yyvsp[(2) - (2)].val).buf;
+#ifdef SADB_X_AALG_TCP_MD5
+			if (p_alg_auth == SADB_X_AALG_TCP_MD5) {
+				if ((p_key_auth_len < 1) || 
+				    (p_key_auth_len > 80))
+					return -1;
+			} else 
+#endif
+			{
+				if (ipsec_check_keylen(SADB_EXT_SUPPORTED_AUTH,
+				    p_alg_auth, 
+				    PFKEY_UNUNIT64(p_key_auth_len)) < 0) {
+					yyerror(ipsec_strerror());
+					return -1;
+				}
+			}
+		}
+    break;
+
+  case 44:
+#line 478 "parse.y"
+    {
+			if ((yyvsp[(1) - (1)].num) < 0) {
+				yyerror("unsupported algorithm");
+				return -1;
+			}
+			p_alg_auth = (yyvsp[(1) - (1)].num);
+
+			p_key_auth_len = 0;
+			p_key_auth = NULL;
+		}
+    break;
+
+  case 45:
+#line 492 "parse.y"
+    {
+			(yyval.val) = (yyvsp[(1) - (1)].val);
+		}
+    break;
+
+  case 46:
+#line 496 "parse.y"
+    {
+			caddr_t pp_key;
+			caddr_t bp;
+			caddr_t yp = (yyvsp[(1) - (1)].val).buf;
+			int l;
+
+			l = strlen(yp) % 2 + strlen(yp) / 2;
+			if ((pp_key = malloc(l)) == 0) {
+				yyerror("not enough core");
+				return -1;
+			}
+			memset(pp_key, 0, l);
+
+			bp = pp_key;
+			if (strlen(yp) % 2) {
+				*bp = ATOX(yp[0]);
+				yp++, bp++;
+			}
+			while (*yp) {
+				*bp = (ATOX(yp[0]) << 4) | ATOX(yp[1]);
+				yp += 2, bp++;
+			}
+
+			(yyval.val).len = l;
+			(yyval.val).buf = pp_key;
+		}
+    break;
+
+  case 49:
+#line 530 "parse.y"
+    { p_ext |= (yyvsp[(2) - (2)].num); }
+    break;
+
+  case 50:
+#line 531 "parse.y"
+    { p_ext &= ~SADB_X_EXT_CYCSEQ; }
+    break;
+
+  case 51:
+#line 532 "parse.y"
+    { p_mode = (yyvsp[(2) - (2)].num); }
+    break;
+
+  case 52:
+#line 533 "parse.y"
+    { p_mode = IPSEC_MODE_ANY; }
+    break;
+
+  case 53:
+#line 534 "parse.y"
+    { p_reqid = (yyvsp[(2) - (2)].ulnum); }
+    break;
+
+  case 54:
+#line 536 "parse.y"
+    {
+			if ((p_ext & SADB_X_EXT_OLD) != 0) {
+				yyerror("replay prevention cannot be used with "
+				    "ah/esp-old");
+				return -1;
+			}
+			p_replay = (yyvsp[(2) - (2)].ulnum);
+		}
+    break;
+
+  case 55:
+#line 544 "parse.y"
+    { p_lt_hard = (yyvsp[(2) - (2)].ulnum); }
+    break;
+
+  case 56:
+#line 545 "parse.y"
+    { p_lt_soft = (yyvsp[(2) - (2)].ulnum); }
+    break;
+
+  case 57:
+#line 546 "parse.y"
+    { p_lb_hard = (yyvsp[(2) - (2)].ulnum); }
+    break;
+
+  case 58:
+#line 547 "parse.y"
+    { p_lb_soft = (yyvsp[(2) - (2)].ulnum); }
+    break;
+
+  case 59:
+#line 548 "parse.y"
+    {
+		sec_ctx.doi = (yyvsp[(2) - (4)].ulnum);
+		sec_ctx.alg = (yyvsp[(3) - (4)].ulnum);
+		sec_ctx.len = (yyvsp[(4) - (4)].val).len+1;
+		sec_ctx.buf = (yyvsp[(4) - (4)].val).buf;
+	}
+    break;
+
+  case 60:
+#line 560 "parse.y"
+    {
+			int status;
+			struct addrinfo *src, *dst;
+
+#ifdef HAVE_PFKEY_POLICY_PRIORITY
+			last_msg_type = SADB_X_SPDADD;
+#endif
+
+			/* fixed port fields if ulp is icmpv6 */
+			if ((yyvsp[(10) - (13)].val).buf != NULL) {
+				if ( ((yyvsp[(9) - (13)].num) != IPPROTO_ICMPV6) &&
+					 ((yyvsp[(9) - (13)].num) != IPPROTO_MH))
+					return -1;
+				free((yyvsp[(5) - (13)].val).buf);
+				free((yyvsp[(8) - (13)].val).buf);
+				if (fix_portstr(&(yyvsp[(10) - (13)].val), &(yyvsp[(5) - (13)].val), &(yyvsp[(8) - (13)].val)))
+					return -1;
+			}
+
+			src = parse_addr((yyvsp[(3) - (13)].val).buf, (yyvsp[(5) - (13)].val).buf);
+			dst = parse_addr((yyvsp[(6) - (13)].val).buf, (yyvsp[(8) - (13)].val).buf);
+			if (!src || !dst) {
+				/* yyerror is already called */
+				return -1;
+			}
+			if (src->ai_next || dst->ai_next) {
+				yyerror("multiple address specified");
+				freeaddrinfo(src);
+				freeaddrinfo(dst);
+				return -1;
+			}
+
+			status = setkeymsg_spdaddr(SADB_X_SPDADD, (yyvsp[(9) - (13)].num), &(yyvsp[(12) - (13)].val),
+			    src, (yyvsp[(4) - (13)].num), dst, (yyvsp[(7) - (13)].num));
+			freeaddrinfo(src);
+			freeaddrinfo(dst);
+			if (status < 0)
+				return -1;
+		}
+    break;
+
+  case 61:
+#line 600 "parse.y"
+    {
+			int status;
+
+			status = setkeymsg_spdaddr_tag(SADB_X_SPDADD,
+			    (yyvsp[(3) - (5)].val).buf, &(yyvsp[(4) - (5)].val));
+			if (status < 0)
+				return -1;
+		}
+    break;
+
+  case 62:
+#line 612 "parse.y"
+    {
+			int status;
+			struct addrinfo *src, *dst;
+
+			/* fixed port fields if ulp is icmpv6 */
+			if ((yyvsp[(10) - (13)].val).buf != NULL) {
+				if (((yyvsp[(9) - (13)].num) != IPPROTO_ICMPV6) &&
+					((yyvsp[(9) - (13)].num) != IPPROTO_MH))
+					return -1;
+				free((yyvsp[(5) - (13)].val).buf);
+				free((yyvsp[(8) - (13)].val).buf);
+				if (fix_portstr(&(yyvsp[(10) - (13)].val), &(yyvsp[(5) - (13)].val), &(yyvsp[(8) - (13)].val)))
+					return -1;
+			}
+
+			src = parse_addr((yyvsp[(3) - (13)].val).buf, (yyvsp[(5) - (13)].val).buf);
+			dst = parse_addr((yyvsp[(6) - (13)].val).buf, (yyvsp[(8) - (13)].val).buf);
+			if (!src || !dst) {
+				/* yyerror is already called */
+				return -1;
+			}
+			if (src->ai_next || dst->ai_next) {
+				yyerror("multiple address specified");
+				freeaddrinfo(src);
+				freeaddrinfo(dst);
+				return -1;
+			}
+
+			status = setkeymsg_spdaddr(SADB_X_SPDDELETE, (yyvsp[(9) - (13)].num), &(yyvsp[(12) - (13)].val),
+			    src, (yyvsp[(4) - (13)].num), dst, (yyvsp[(7) - (13)].num));
+			freeaddrinfo(src);
+			freeaddrinfo(dst);
+			if (status < 0)
+				return -1;
+		}
+    break;
+
+  case 63:
+#line 651 "parse.y"
+    {
+			struct sadb_msg msg;
+			setkeymsg0(&msg, SADB_X_SPDDUMP, SADB_SATYPE_UNSPEC,
+			    sizeof(msg));
+			sendkeymsg((char *)&msg, sizeof(msg));
+		}
+    break;
+
+  case 64:
+#line 662 "parse.y"
+    {
+			struct sadb_msg msg;
+			setkeymsg0(&msg, SADB_X_SPDFLUSH, SADB_SATYPE_UNSPEC,
+			    sizeof(msg));
+			sendkeymsg((char *)&msg, sizeof(msg));
+		}
+    break;
+
+  case 67:
+#line 677 "parse.y"
+    {
+			char *p;
+
+			for (p = (yyvsp[(1) - (1)].val).buf + 1; *p; p++)
+				switch (*p) {
+				case '4':
+					p_aifamily = AF_INET;
+					break;
+#ifdef INET6
+				case '6':
+					p_aifamily = AF_INET6;
+					break;
+#endif
+				case 'n':
+					p_aiflags = AI_NUMERICHOST;
+					break;
+				default:
+					yyerror("invalid flag");
+					return -1;
+				}
+		}
+    break;
+
+  case 68:
+#line 702 "parse.y"
+    {
+			(yyval.res) = parse_addr((yyvsp[(1) - (1)].val).buf, NULL);
+			if ((yyval.res) == NULL) {
+				/* yyerror already called by parse_addr */
+				return -1;
+			}
+		}
+    break;
+
+  case 69:
+#line 713 "parse.y"
+    {
+			(yyval.res) = parse_addr((yyvsp[(1) - (1)].val).buf, NULL);
+			if ((yyval.res) == NULL) {
+				/* yyerror already called by parse_addr */
+				return -1;
+			}
+		}
+    break;
+
+  case 70:
+#line 721 "parse.y"
+    {
+			(yyval.res) = parse_addr((yyvsp[(1) - (2)].val).buf, (yyvsp[(2) - (2)].val).buf);
+			if ((yyval.res) == NULL) {
+				/* yyerror already called by parse_addr */
+				return -1;
+			}
+		}
+    break;
+
+  case 71:
+#line 731 "parse.y"
+    { (yyval.num) = -1; }
+    break;
+
+  case 72:
+#line 732 "parse.y"
+    { (yyval.num) = (yyvsp[(2) - (2)].ulnum); }
+    break;
+
+  case 73:
+#line 737 "parse.y"
+    {
+			(yyval.val).buf = strdup("0");
+			if (!(yyval.val).buf) {
+				yyerror("insufficient memory");
+				return -1;
+			}
+			(yyval.val).len = strlen((yyval.val).buf);
+		}
+    break;
+
+  case 74:
+#line 746 "parse.y"
+    {
+			(yyval.val).buf = strdup("0");
+			if (!(yyval.val).buf) {
+				yyerror("insufficient memory");
+				return -1;
+			}
+			(yyval.val).len = strlen((yyval.val).buf);
+		}
+    break;
+
+  case 75:
+#line 755 "parse.y"
+    {
+			char buf[20];
+			snprintf(buf, sizeof(buf), "%lu", (yyvsp[(2) - (3)].ulnum));
+			(yyval.val).buf = strdup(buf);
+			if (!(yyval.val).buf) {
+				yyerror("insufficient memory");
+				return -1;
+			}
+			(yyval.val).len = strlen((yyval.val).buf);
+		}
+    break;
+
+  case 76:
+#line 766 "parse.y"
+    {
+			(yyval.val) = (yyvsp[(2) - (3)].val);
+		}
+    break;
+
+  case 77:
+#line 772 "parse.y"
+    { (yyval.num) = (yyvsp[(1) - (1)].ulnum); }
+    break;
+
+  case 78:
+#line 773 "parse.y"
+    { (yyval.num) = IPSEC_ULPROTO_ANY; }
+    break;
+
+  case 79:
+#line 774 "parse.y"
+    { 
+				(yyval.num) = IPPROTO_TCP; 
+			}
+    break;
+
+  case 80:
+#line 778 "parse.y"
+    {
+			struct protoent *ent;
+#ifdef ANDROID_CHANGES
+			ent = agetprotobyname((yyvsp[(1) - (1)].val).buf);
+#else
+			ent = getprotobyname((yyvsp[(1) - (1)].val).buf);
+#endif
+			if (ent)
+				(yyval.num) = ent->p_proto;
+			else {
+				if (strcmp("icmp6", (yyvsp[(1) - (1)].val).buf) == 0) {
+					(yyval.num) = IPPROTO_ICMPV6;
+				} else if(strcmp("ip4", (yyvsp[(1) - (1)].val).buf) == 0) {
+					(yyval.num) = IPPROTO_IPV4;
+				} else {
+					yyerror("invalid upper layer protocol");
+					return -1;
+				}
+			}
+			endprotoent();
+		}
+    break;
+
+  case 81:
+#line 800 "parse.y"
+    {
+			(yyval.val).buf = NULL;
+			(yyval.val).len = 0;
+		}
+    break;
+
+  case 82:
+#line 805 "parse.y"
+    {
+			(yyval.val).buf = strdup((yyvsp[(1) - (1)].val).buf);
+			if (!(yyval.val).buf) {
+				yyerror("insufficient memory");
+				return -1;
+			}
+			(yyval.val).len = strlen((yyval.val).buf);
+		}
+    break;
+
+  case 84:
+#line 817 "parse.y"
+    {
+			sec_ctx.doi = (yyvsp[(2) - (4)].ulnum);
+			sec_ctx.alg = (yyvsp[(3) - (4)].ulnum);
+			sec_ctx.len = (yyvsp[(4) - (4)].val).len+1;
+			sec_ctx.buf = (yyvsp[(4) - (4)].val).buf;
+		}
+    break;
+
+  case 85:
+#line 827 "parse.y"
+    {
+			char *policy;
+#ifdef HAVE_PFKEY_POLICY_PRIORITY
+			struct sadb_x_policy *xpl;
+#endif
+
+			policy = ipsec_set_policy((yyvsp[(2) - (2)].val).buf, (yyvsp[(2) - (2)].val).len);
+			if (policy == NULL) {
+				yyerror(ipsec_strerror());
+				return -1;
+			}
+
+			(yyval.val).buf = policy;
+			(yyval.val).len = ipsec_get_policylen(policy);
+
+#ifdef HAVE_PFKEY_POLICY_PRIORITY
+			xpl = (struct sadb_x_policy *) (yyval.val).buf;
+			last_priority = xpl->sadb_x_policy_priority;
+#endif
+		}
+    break;
+
+  case 86:
+#line 850 "parse.y"
+    { (yyval.val) = (yyvsp[(1) - (1)].val); }
+    break;
+
+  case 87:
+#line 856 "parse.y"
+    {
+			exit_now = 1;
+			YYACCEPT;
+		}
+    break;
+
+
+/* Line 1267 of yacc.c.  */
+#line 2436 "parse.c"
+      default: break;
+    }
+  YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
+
+  YYPOPSTACK (yylen);
+  yylen = 0;
+  YY_STACK_PRINT (yyss, yyssp);
+
+  *++yyvsp = yyval;
+
+
+  /* Now `shift' the result of the reduction.  Determine what state
+     that goes to, based on the state we popped back to and the rule
+     number reduced by.  */
+
+  yyn = yyr1[yyn];
+
+  yystate = yypgoto[yyn - YYNTOKENS] + *yyssp;
+  if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp)
+    yystate = yytable[yystate];
+  else
+    yystate = yydefgoto[yyn - YYNTOKENS];
+
+  goto yynewstate;
+
+
+/*------------------------------------.
+| yyerrlab -- here on detecting error |
+`------------------------------------*/
+yyerrlab:
+  /* If not already recovering from an error, report this error.  */
+  if (!yyerrstatus)
+    {
+      ++yynerrs;
+#if ! YYERROR_VERBOSE
+      yyerror (YY_("syntax error"));
+#else
+      {
+	YYSIZE_T yysize = yysyntax_error (0, yystate, yychar);
+	if (yymsg_alloc < yysize && yymsg_alloc < YYSTACK_ALLOC_MAXIMUM)
+	  {
+	    YYSIZE_T yyalloc = 2 * yysize;
+	    if (! (yysize <= yyalloc && yyalloc <= YYSTACK_ALLOC_MAXIMUM))
+	      yyalloc = YYSTACK_ALLOC_MAXIMUM;
+	    if (yymsg != yymsgbuf)
+	      YYSTACK_FREE (yymsg);
+	    yymsg = (char *) YYSTACK_ALLOC (yyalloc);
+	    if (yymsg)
+	      yymsg_alloc = yyalloc;
+	    else
+	      {
+		yymsg = yymsgbuf;
+		yymsg_alloc = sizeof yymsgbuf;
+	      }
+	  }
+
+	if (0 < yysize && yysize <= yymsg_alloc)
+	  {
+	    (void) yysyntax_error (yymsg, yystate, yychar);
+	    yyerror (yymsg);
+	  }
+	else
+	  {
+	    yyerror (YY_("syntax error"));
+	    if (yysize != 0)
+	      goto yyexhaustedlab;
+	  }
+      }
+#endif
+    }
+
+
+
+  if (yyerrstatus == 3)
+    {
+      /* If just tried and failed to reuse look-ahead token after an
+	 error, discard it.  */
+
+      if (yychar <= YYEOF)
+	{
+	  /* Return failure if at end of input.  */
+	  if (yychar == YYEOF)
+	    YYABORT;
+	}
+      else
+	{
+	  yydestruct ("Error: discarding",
+		      yytoken, &yylval);
+	  yychar = YYEMPTY;
+	}
+    }
+
+  /* Else will try to reuse look-ahead token after shifting the error
+     token.  */
+  goto yyerrlab1;
+
+
+/*---------------------------------------------------.
+| yyerrorlab -- error raised explicitly by YYERROR.  |
+`---------------------------------------------------*/
+yyerrorlab:
+
+  /* Pacify compilers like GCC when the user code never invokes
+     YYERROR and the label yyerrorlab therefore never appears in user
+     code.  */
+  if (/*CONSTCOND*/ 0)
+     goto yyerrorlab;
+
+  /* Do not reclaim the symbols of the rule which action triggered
+     this YYERROR.  */
+  YYPOPSTACK (yylen);
+  yylen = 0;
+  YY_STACK_PRINT (yyss, yyssp);
+  yystate = *yyssp;
+  goto yyerrlab1;
+
+
+/*-------------------------------------------------------------.
+| yyerrlab1 -- common code for both syntax error and YYERROR.  |
+`-------------------------------------------------------------*/
+yyerrlab1:
+  yyerrstatus = 3;	/* Each real token shifted decrements this.  */
+
+  for (;;)
+    {
+      yyn = yypact[yystate];
+      if (yyn != YYPACT_NINF)
+	{
+	  yyn += YYTERROR;
+	  if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR)
+	    {
+	      yyn = yytable[yyn];
+	      if (0 < yyn)
+		break;
+	    }
+	}
+
+      /* Pop the current state because it cannot handle the error token.  */
+      if (yyssp == yyss)
+	YYABORT;
+
+
+      yydestruct ("Error: popping",
+		  yystos[yystate], yyvsp);
+      YYPOPSTACK (1);
+      yystate = *yyssp;
+      YY_STACK_PRINT (yyss, yyssp);
+    }
+
+  if (yyn == YYFINAL)
+    YYACCEPT;
+
+  *++yyvsp = yylval;
+
+
+  /* Shift the error token.  */
+  YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp);
+
+  yystate = yyn;
+  goto yynewstate;
+
+
+/*-------------------------------------.
+| yyacceptlab -- YYACCEPT comes here.  |
+`-------------------------------------*/
+yyacceptlab:
+  yyresult = 0;
+  goto yyreturn;
+
+/*-----------------------------------.
+| yyabortlab -- YYABORT comes here.  |
+`-----------------------------------*/
+yyabortlab:
+  yyresult = 1;
+  goto yyreturn;
+
+#ifndef yyoverflow
+/*-------------------------------------------------.
+| yyexhaustedlab -- memory exhaustion comes here.  |
+`-------------------------------------------------*/
+yyexhaustedlab:
+  yyerror (YY_("memory exhausted"));
+  yyresult = 2;
+  /* Fall through.  */
+#endif
+
+yyreturn:
+  if (yychar != YYEOF && yychar != YYEMPTY)
+     yydestruct ("Cleanup: discarding lookahead",
+		 yytoken, &yylval);
+  /* Do not reclaim the symbols of the rule which action triggered
+     this YYABORT or YYACCEPT.  */
+  YYPOPSTACK (yylen);
+  YY_STACK_PRINT (yyss, yyssp);
+  while (yyssp != yyss)
+    {
+      yydestruct ("Cleanup: popping",
+		  yystos[*yyssp], yyvsp);
+      YYPOPSTACK (1);
+    }
+#ifndef yyoverflow
+  if (yyss != yyssa)
+    YYSTACK_FREE (yyss);
+#endif
+#if YYERROR_VERBOSE
+  if (yymsg != yymsgbuf)
+    YYSTACK_FREE (yymsg);
+#endif
+  /* Make sure YYID is used.  */
+  return YYID (yyresult);
+}
+
+
+#line 861 "parse.y"
+
+
+int
+setkeymsg0(msg, type, satype, l)
+	struct sadb_msg *msg;
+	unsigned int type;
+	unsigned int satype;
+	size_t l;
+{
+
+	msg->sadb_msg_version = PF_KEY_V2;
+	msg->sadb_msg_type = type;
+	msg->sadb_msg_errno = 0;
+	msg->sadb_msg_satype = satype;
+	msg->sadb_msg_reserved = 0;
+	msg->sadb_msg_seq = 0;
+	msg->sadb_msg_pid = getpid();
+	msg->sadb_msg_len = PFKEY_UNIT64(l);
+	return 0;
+}
+
+/* XXX NO BUFFER OVERRUN CHECK! BAD BAD! */
+static int
+setkeymsg_spdaddr(type, upper, policy, srcs, splen, dsts, dplen)
+	unsigned int type;
+	unsigned int upper;
+	vchar_t *policy;
+	struct addrinfo *srcs;
+	int splen;
+	struct addrinfo *dsts;
+	int dplen;
+{
+	struct sadb_msg *msg;
+	char buf[BUFSIZ];
+	int l, l0;
+	struct sadb_address m_addr;
+	struct addrinfo *s, *d;
+	int n;
+	int plen;
+	struct sockaddr *sa;
+	int salen;
+	struct sadb_x_policy *sp;
+#ifdef HAVE_POLICY_FWD
+	struct sadb_x_ipsecrequest *ps = NULL;
+	int saved_level, saved_id = 0;
+#endif
+
+	msg = (struct sadb_msg *)buf;
+
+	if (!srcs || !dsts)
+		return -1;
+
+	/* fix up length afterwards */
+	setkeymsg0(msg, type, SADB_SATYPE_UNSPEC, 0);
+	l = sizeof(struct sadb_msg);
+
+	sp = (struct sadb_x_policy*) (buf + l);
+	memcpy(buf + l, policy->buf, policy->len);
+	l += policy->len;
+
+	l0 = l;
+	n = 0;
+
+	/* do it for all src/dst pairs */
+	for (s = srcs; s; s = s->ai_next) {
+		for (d = dsts; d; d = d->ai_next) {
+			/* rewind pointer */
+			l = l0;
+
+			if (s->ai_addr->sa_family != d->ai_addr->sa_family)
+				continue;
+			switch (s->ai_addr->sa_family) {
+			case AF_INET:
+				plen = sizeof(struct in_addr) << 3;
+				break;
+#ifdef INET6
+			case AF_INET6:
+				plen = sizeof(struct in6_addr) << 3;
+				break;
+#endif
+			default:
+				continue;
+			}
+
+			/* set src */
+			sa = s->ai_addr;
+			salen = sysdep_sa_len(s->ai_addr);
+			m_addr.sadb_address_len = PFKEY_UNIT64(sizeof(m_addr) +
+			    PFKEY_ALIGN8(salen));
+			m_addr.sadb_address_exttype = SADB_EXT_ADDRESS_SRC;
+			m_addr.sadb_address_proto = upper;
+			m_addr.sadb_address_prefixlen =
+			    (splen >= 0 ? splen : plen);
+			m_addr.sadb_address_reserved = 0;
+
+			setvarbuf(buf, &l, (struct sadb_ext *)&m_addr,
+			    sizeof(m_addr), (caddr_t)sa, salen);
+
+			/* set dst */
+			sa = d->ai_addr;
+			salen = sysdep_sa_len(d->ai_addr);
+			m_addr.sadb_address_len = PFKEY_UNIT64(sizeof(m_addr) +
+			    PFKEY_ALIGN8(salen));
+			m_addr.sadb_address_exttype = SADB_EXT_ADDRESS_DST;
+			m_addr.sadb_address_proto = upper;
+			m_addr.sadb_address_prefixlen =
+			    (dplen >= 0 ? dplen : plen);
+			m_addr.sadb_address_reserved = 0;
+
+			setvarbuf(buf, &l, (struct sadb_ext *)&m_addr,
+			    sizeof(m_addr), sa, salen);
+#ifdef SADB_X_EXT_SEC_CTX
+			/* Add security context label */
+			if (sec_ctx.doi) {
+				struct sadb_x_sec_ctx m_sec_ctx;
+				u_int slen = sizeof(struct sadb_x_sec_ctx);
+
+				memset(&m_sec_ctx, 0, slen);
+
+				m_sec_ctx.sadb_x_sec_len =
+				PFKEY_UNIT64(slen + PFKEY_ALIGN8(sec_ctx.len));
+
+				m_sec_ctx.sadb_x_sec_exttype = 
+					SADB_X_EXT_SEC_CTX;
+				m_sec_ctx.sadb_x_ctx_len = sec_ctx.len;/*bytes*/
+				m_sec_ctx.sadb_x_ctx_doi = sec_ctx.doi;
+				m_sec_ctx.sadb_x_ctx_alg = sec_ctx.alg;
+				setvarbuf(buf, &l, 
+					  (struct sadb_ext *)&m_sec_ctx, slen, 
+					  (caddr_t)sec_ctx.buf, sec_ctx.len);
+			}
+#endif
+			msg->sadb_msg_len = PFKEY_UNIT64(l);
+
+			sendkeymsg(buf, l);
+
+#ifdef HAVE_POLICY_FWD
+			/* create extra call for FWD policy */
+			if (f_rfcmode && sp->sadb_x_policy_dir == IPSEC_DIR_INBOUND) {
+				sp->sadb_x_policy_dir = IPSEC_DIR_FWD;
+				ps = (struct sadb_x_ipsecrequest*) (sp+1);
+
+				/* if request level is unique, change it to
+				 * require for fwd policy */
+				/* XXX: currently, only first policy is updated
+				 * only. Update following too... */
+				saved_level = ps->sadb_x_ipsecrequest_level;
+				if (saved_level == IPSEC_LEVEL_UNIQUE) {
+					saved_id = ps->sadb_x_ipsecrequest_reqid;
+					ps->sadb_x_ipsecrequest_reqid=0;
+					ps->sadb_x_ipsecrequest_level=IPSEC_LEVEL_REQUIRE;
+				}
+
+				sendkeymsg(buf, l);
+				/* restoring for next message */
+				sp->sadb_x_policy_dir = IPSEC_DIR_INBOUND;
+				if (saved_level == IPSEC_LEVEL_UNIQUE) {
+					ps->sadb_x_ipsecrequest_reqid = saved_id;
+					ps->sadb_x_ipsecrequest_level = saved_level;
+				}
+			}
+#endif
+
+			n++;
+		}
+	}
+
+	if (n == 0)
+		return -1;
+	else
+		return 0;
+}
+
+static int
+setkeymsg_spdaddr_tag(type, tag, policy)
+	unsigned int type;
+	char *tag;
+	vchar_t *policy;
+{
+	struct sadb_msg *msg;
+	char buf[BUFSIZ];
+	int l, l0;
+#ifdef SADB_X_EXT_TAG
+	struct sadb_x_tag m_tag;
+#endif
+	int n;
+
+	msg = (struct sadb_msg *)buf;
+
+	/* fix up length afterwards */
+	setkeymsg0(msg, type, SADB_SATYPE_UNSPEC, 0);
+	l = sizeof(struct sadb_msg);
+
+	memcpy(buf + l, policy->buf, policy->len);
+	l += policy->len;
+
+	l0 = l;
+	n = 0;
+
+#ifdef SADB_X_EXT_TAG
+	memset(&m_tag, 0, sizeof(m_tag));
+	m_tag.sadb_x_tag_len = PFKEY_UNIT64(sizeof(m_tag));
+	m_tag.sadb_x_tag_exttype = SADB_X_EXT_TAG;
+	if (strlcpy(m_tag.sadb_x_tag_name, tag,
+	    sizeof(m_tag.sadb_x_tag_name)) >= sizeof(m_tag.sadb_x_tag_name))
+		return -1;
+	memcpy(buf + l, &m_tag, sizeof(m_tag));
+	l += sizeof(m_tag);
+#endif
+
+	msg->sadb_msg_len = PFKEY_UNIT64(l);
+
+	sendkeymsg(buf, l);
+
+	return 0;
+}
+
+/* XXX NO BUFFER OVERRUN CHECK! BAD BAD! */
+static int
+setkeymsg_addr(type, satype, srcs, dsts, no_spi)
+	unsigned int type;
+	unsigned int satype;
+	struct addrinfo *srcs;
+	struct addrinfo *dsts;
+	int no_spi;
+{
+	struct sadb_msg *msg;
+	char buf[BUFSIZ];
+	int l, l0, len;
+	struct sadb_sa m_sa;
+	struct sadb_x_sa2 m_sa2;
+	struct sadb_address m_addr;
+	struct addrinfo *s, *d;
+	int n;
+	int plen;
+	struct sockaddr *sa;
+	int salen;
+
+	msg = (struct sadb_msg *)buf;
+
+	if (!srcs || !dsts)
+		return -1;
+
+	/* fix up length afterwards */
+	setkeymsg0(msg, type, satype, 0);
+	l = sizeof(struct sadb_msg);
+
+	if (!no_spi) {
+		len = sizeof(struct sadb_sa);
+		m_sa.sadb_sa_len = PFKEY_UNIT64(len);
+		m_sa.sadb_sa_exttype = SADB_EXT_SA;
+		m_sa.sadb_sa_spi = htonl(p_spi);
+		m_sa.sadb_sa_replay = p_replay;
+		m_sa.sadb_sa_state = 0;
+		m_sa.sadb_sa_auth = p_alg_auth;
+		m_sa.sadb_sa_encrypt = p_alg_enc;
+		m_sa.sadb_sa_flags = p_ext;
+
+		memcpy(buf + l, &m_sa, len);
+		l += len;
+
+		len = sizeof(struct sadb_x_sa2);
+		m_sa2.sadb_x_sa2_len = PFKEY_UNIT64(len);
+		m_sa2.sadb_x_sa2_exttype = SADB_X_EXT_SA2;
+		m_sa2.sadb_x_sa2_mode = p_mode;
+		m_sa2.sadb_x_sa2_reqid = p_reqid;
+
+		memcpy(buf + l, &m_sa2, len);
+		l += len;
+	}
+
+	l0 = l;
+	n = 0;
+
+	/* do it for all src/dst pairs */
+	for (s = srcs; s; s = s->ai_next) {
+		for (d = dsts; d; d = d->ai_next) {
+			/* rewind pointer */
+			l = l0;
+
+			if (s->ai_addr->sa_family != d->ai_addr->sa_family)
+				continue;
+			switch (s->ai_addr->sa_family) {
+			case AF_INET:
+				plen = sizeof(struct in_addr) << 3;
+				break;
+#ifdef INET6
+			case AF_INET6:
+				plen = sizeof(struct in6_addr) << 3;
+				break;
+#endif
+			default:
+				continue;
+			}
+
+			/* set src */
+			sa = s->ai_addr;
+			salen = sysdep_sa_len(s->ai_addr);
+			m_addr.sadb_address_len = PFKEY_UNIT64(sizeof(m_addr) +
+			    PFKEY_ALIGN8(salen));
+			m_addr.sadb_address_exttype = SADB_EXT_ADDRESS_SRC;
+			m_addr.sadb_address_proto = IPSEC_ULPROTO_ANY;
+			m_addr.sadb_address_prefixlen = plen;
+			m_addr.sadb_address_reserved = 0;
+
+			setvarbuf(buf, &l, (struct sadb_ext *)&m_addr,
+			    sizeof(m_addr), sa, salen);
+
+			/* set dst */
+			sa = d->ai_addr;
+			salen = sysdep_sa_len(d->ai_addr);
+			m_addr.sadb_address_len = PFKEY_UNIT64(sizeof(m_addr) +
+			    PFKEY_ALIGN8(salen));
+			m_addr.sadb_address_exttype = SADB_EXT_ADDRESS_DST;
+			m_addr.sadb_address_proto = IPSEC_ULPROTO_ANY;
+			m_addr.sadb_address_prefixlen = plen;
+			m_addr.sadb_address_reserved = 0;
+
+			setvarbuf(buf, &l, (struct sadb_ext *)&m_addr,
+			    sizeof(m_addr), sa, salen);
+
+			msg->sadb_msg_len = PFKEY_UNIT64(l);
+
+			sendkeymsg(buf, l);
+
+			n++;
+		}
+	}
+
+	if (n == 0)
+		return -1;
+	else
+		return 0;
+}
+
+#ifdef SADB_X_EXT_NAT_T_TYPE
+static u_int16_t get_port (struct addrinfo *addr)
+{
+	struct sockaddr *s = addr->ai_addr;
+	u_int16_t port = 0;
+
+	switch (s->sa_family) {
+	case AF_INET:
+	  {
+		struct sockaddr_in *sin4 = (struct sockaddr_in *)s;
+		port = ntohs(sin4->sin_port);
+		break;
+	  }
+	case AF_INET6:
+	  {
+		struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)s;
+		port = ntohs(sin6->sin6_port);
+		break;
+	  }
+	}
+
+	if (port == 0)
+		port = DEFAULT_NATT_PORT;
+
+	return port;
+}
+#endif
+
+/* XXX NO BUFFER OVERRUN CHECK! BAD BAD! */
+static int
+setkeymsg_add(type, satype, srcs, dsts)
+	unsigned int type;
+	unsigned int satype;
+	struct addrinfo *srcs;
+	struct addrinfo *dsts;
+{
+	struct sadb_msg *msg;
+	char buf[BUFSIZ];
+	int l, l0, len;
+	struct sadb_sa m_sa;
+	struct sadb_x_sa2 m_sa2;
+	struct sadb_address m_addr;
+	struct addrinfo *s, *d;
+	int n;
+	int plen;
+	struct sockaddr *sa;
+	int salen;
+
+	msg = (struct sadb_msg *)buf;
+
+	if (!srcs || !dsts)
+		return -1;
+
+	/* fix up length afterwards */
+	setkeymsg0(msg, type, satype, 0);
+	l = sizeof(struct sadb_msg);
+
+	/* set encryption algorithm, if present. */
+	if (satype != SADB_X_SATYPE_IPCOMP && p_key_enc) {
+		union {
+			struct sadb_key key;
+			struct sadb_ext ext;
+		} m;
+
+		m.key.sadb_key_len =
+			PFKEY_UNIT64(sizeof(m.key)
+				   + PFKEY_ALIGN8(p_key_enc_len));
+		m.key.sadb_key_exttype = SADB_EXT_KEY_ENCRYPT;
+		m.key.sadb_key_bits = p_key_enc_len * 8;
+		m.key.sadb_key_reserved = 0;
+
+		setvarbuf(buf, &l, &m.ext, sizeof(m.key),
+			p_key_enc, p_key_enc_len);
+	}
+
+	/* set authentication algorithm, if present. */
+	if (p_key_auth) {
+		union {
+			struct sadb_key key;
+			struct sadb_ext ext;
+		} m;
+
+		m.key.sadb_key_len =
+			PFKEY_UNIT64(sizeof(m.key)
+				   + PFKEY_ALIGN8(p_key_auth_len));
+		m.key.sadb_key_exttype = SADB_EXT_KEY_AUTH;
+		m.key.sadb_key_bits = p_key_auth_len * 8;
+		m.key.sadb_key_reserved = 0;
+
+		setvarbuf(buf, &l, &m.ext, sizeof(m.key),
+			p_key_auth, p_key_auth_len);
+	}
+
+	/* set lifetime for HARD */
+	if (p_lt_hard != 0 || p_lb_hard != 0) {
+		struct sadb_lifetime m_lt;
+		u_int slen = sizeof(struct sadb_lifetime);
+
+		m_lt.sadb_lifetime_len = PFKEY_UNIT64(slen);
+		m_lt.sadb_lifetime_exttype = SADB_EXT_LIFETIME_HARD;
+		m_lt.sadb_lifetime_allocations = 0;
+		m_lt.sadb_lifetime_bytes = p_lb_hard;
+		m_lt.sadb_lifetime_addtime = p_lt_hard;
+		m_lt.sadb_lifetime_usetime = 0;
+
+		memcpy(buf + l, &m_lt, slen);
+		l += slen;
+	}
+
+	/* set lifetime for SOFT */
+	if (p_lt_soft != 0 || p_lb_soft != 0) {
+		struct sadb_lifetime m_lt;
+		u_int slen = sizeof(struct sadb_lifetime);
+
+		m_lt.sadb_lifetime_len = PFKEY_UNIT64(slen);
+		m_lt.sadb_lifetime_exttype = SADB_EXT_LIFETIME_SOFT;
+		m_lt.sadb_lifetime_allocations = 0;
+		m_lt.sadb_lifetime_bytes = p_lb_soft;
+		m_lt.sadb_lifetime_addtime = p_lt_soft;
+		m_lt.sadb_lifetime_usetime = 0;
+
+		memcpy(buf + l, &m_lt, slen);
+		l += slen;
+	}
+
+#ifdef SADB_X_EXT_SEC_CTX
+	/* Add security context label */
+	if (sec_ctx.doi) {
+		struct sadb_x_sec_ctx m_sec_ctx;
+		u_int slen = sizeof(struct sadb_x_sec_ctx);
+
+		memset(&m_sec_ctx, 0, slen);
+
+		m_sec_ctx.sadb_x_sec_len = PFKEY_UNIT64(slen +
+					PFKEY_ALIGN8(sec_ctx.len));
+		m_sec_ctx.sadb_x_sec_exttype = SADB_X_EXT_SEC_CTX;
+		m_sec_ctx.sadb_x_ctx_len = sec_ctx.len; /* bytes */
+		m_sec_ctx.sadb_x_ctx_doi = sec_ctx.doi;
+		m_sec_ctx.sadb_x_ctx_alg = sec_ctx.alg;
+		setvarbuf(buf, &l, (struct sadb_ext *)&m_sec_ctx, slen,
+			  (caddr_t)sec_ctx.buf, sec_ctx.len); 
+	}
+#endif
+
+	len = sizeof(struct sadb_sa);
+	m_sa.sadb_sa_len = PFKEY_UNIT64(len);
+	m_sa.sadb_sa_exttype = SADB_EXT_SA;
+	m_sa.sadb_sa_spi = htonl(p_spi);
+	m_sa.sadb_sa_replay = p_replay;
+	m_sa.sadb_sa_state = 0;
+	m_sa.sadb_sa_auth = p_alg_auth;
+	m_sa.sadb_sa_encrypt = p_alg_enc;
+	m_sa.sadb_sa_flags = p_ext;
+
+	memcpy(buf + l, &m_sa, len);
+	l += len;
+
+	len = sizeof(struct sadb_x_sa2);
+	m_sa2.sadb_x_sa2_len = PFKEY_UNIT64(len);
+	m_sa2.sadb_x_sa2_exttype = SADB_X_EXT_SA2;
+	m_sa2.sadb_x_sa2_mode = p_mode;
+	m_sa2.sadb_x_sa2_reqid = p_reqid;
+
+	memcpy(buf + l, &m_sa2, len);
+	l += len;
+
+#ifdef SADB_X_EXT_NAT_T_TYPE
+	if (p_natt_type) {
+		struct sadb_x_nat_t_type natt_type;
+
+		len = sizeof(struct sadb_x_nat_t_type);
+		memset(&natt_type, 0, len);
+		natt_type.sadb_x_nat_t_type_len = PFKEY_UNIT64(len);
+		natt_type.sadb_x_nat_t_type_exttype = SADB_X_EXT_NAT_T_TYPE;
+		natt_type.sadb_x_nat_t_type_type = p_natt_type;
+
+		memcpy(buf + l, &natt_type, len);
+		l += len;
+
+		if (p_natt_oa) {
+			sa = p_natt_oa->ai_addr;
+			switch (sa->sa_family) {
+			case AF_INET:
+				plen = sizeof(struct in_addr) << 3;
+				break;
+#ifdef INET6
+			case AF_INET6:
+				plen = sizeof(struct in6_addr) << 3;
+				break;
+#endif
+			default:
+				return -1;
+			}
+			salen = sysdep_sa_len(sa);
+			m_addr.sadb_address_len = PFKEY_UNIT64(sizeof(m_addr) +
+			    PFKEY_ALIGN8(salen));
+			m_addr.sadb_address_exttype = SADB_X_EXT_NAT_T_OA;
+			m_addr.sadb_address_proto = IPSEC_ULPROTO_ANY;
+			m_addr.sadb_address_prefixlen = plen;
+			m_addr.sadb_address_reserved = 0;
+
+			setvarbuf(buf, &l, (struct sadb_ext *)&m_addr,
+			    sizeof(m_addr), sa, salen);
+		}
+	}
+#endif
+
+	l0 = l;
+	n = 0;
+
+	/* do it for all src/dst pairs */
+	for (s = srcs; s; s = s->ai_next) {
+		for (d = dsts; d; d = d->ai_next) {
+			/* rewind pointer */
+			l = l0;
+
+			if (s->ai_addr->sa_family != d->ai_addr->sa_family)
+				continue;
+			switch (s->ai_addr->sa_family) {
+			case AF_INET:
+				plen = sizeof(struct in_addr) << 3;
+				break;
+#ifdef INET6
+			case AF_INET6:
+				plen = sizeof(struct in6_addr) << 3;
+				break;
+#endif
+			default:
+				continue;
+			}
+
+			/* set src */
+			sa = s->ai_addr;
+			salen = sysdep_sa_len(s->ai_addr);
+			m_addr.sadb_address_len = PFKEY_UNIT64(sizeof(m_addr) +
+			    PFKEY_ALIGN8(salen));
+			m_addr.sadb_address_exttype = SADB_EXT_ADDRESS_SRC;
+			m_addr.sadb_address_proto = IPSEC_ULPROTO_ANY;
+			m_addr.sadb_address_prefixlen = plen;
+			m_addr.sadb_address_reserved = 0;
+
+			setvarbuf(buf, &l, (struct sadb_ext *)&m_addr,
+			    sizeof(m_addr), sa, salen);
+
+			/* set dst */
+			sa = d->ai_addr;
+			salen = sysdep_sa_len(d->ai_addr);
+			m_addr.sadb_address_len = PFKEY_UNIT64(sizeof(m_addr) +
+			    PFKEY_ALIGN8(salen));
+			m_addr.sadb_address_exttype = SADB_EXT_ADDRESS_DST;
+			m_addr.sadb_address_proto = IPSEC_ULPROTO_ANY;
+			m_addr.sadb_address_prefixlen = plen;
+			m_addr.sadb_address_reserved = 0;
+
+			setvarbuf(buf, &l, (struct sadb_ext *)&m_addr,
+			    sizeof(m_addr), sa, salen);
+
+#ifdef SADB_X_EXT_NAT_T_TYPE
+			if (p_natt_type) {
+				struct sadb_x_nat_t_port natt_port;
+
+				/* NATT_SPORT */
+				len = sizeof(struct sadb_x_nat_t_port);
+				memset(&natt_port, 0, len);
+				natt_port.sadb_x_nat_t_port_len = PFKEY_UNIT64(len);
+				natt_port.sadb_x_nat_t_port_exttype =
+					SADB_X_EXT_NAT_T_SPORT;
+				natt_port.sadb_x_nat_t_port_port = htons(get_port(s));
+				
+				memcpy(buf + l, &natt_port, len);
+				l += len;
+
+				/* NATT_DPORT */
+				natt_port.sadb_x_nat_t_port_exttype =
+					SADB_X_EXT_NAT_T_DPORT;
+				natt_port.sadb_x_nat_t_port_port = htons(get_port(d));
+				
+				memcpy(buf + l, &natt_port, len);
+				l += len;
+			}
+#endif
+			msg->sadb_msg_len = PFKEY_UNIT64(l);
+
+			sendkeymsg(buf, l);
+
+			n++;
+		}
+	}
+
+	if (n == 0)
+		return -1;
+	else
+		return 0;
+}
+
+static struct addrinfo *
+parse_addr(host, port)
+	char *host;
+	char *port;
+{
+	struct addrinfo hints, *res = NULL;
+	int error;
+
+	memset(&hints, 0, sizeof(hints));
+	hints.ai_family = p_aifamily;
+	hints.ai_socktype = SOCK_DGRAM;		/*dummy*/
+	hints.ai_protocol = IPPROTO_UDP;	/*dummy*/
+	hints.ai_flags = p_aiflags;
+	error = getaddrinfo(host, port, &hints, &res);
+	if (error != 0) {
+		yyerror(gai_strerror(error));
+		return NULL;
+	}
+	return res;
+}
+
+static int
+fix_portstr(spec, sport, dport)
+	vchar_t *spec, *sport, *dport;
+{
+	const char *p, *p2 = "0";
+	char *q;
+	u_int l;
+
+	l = 0;
+	for (q = spec->buf; *q != ',' && *q != '\0' && l < spec->len; q++, l++)
+		;
+	if (*q != '\0') {
+		if (*q == ',') {
+			*q = '\0';
+			p2 = ++q;
+		}
+		for (p = p2; *p != '\0' && l < spec->len; p++, l++)
+			;
+		if (*p != '\0' || *p2 == '\0') {
+			yyerror("invalid an upper layer protocol spec");
+			return -1;
+		}
+	}
+
+	sport->buf = strdup(spec->buf);
+	if (!sport->buf) {
+		yyerror("insufficient memory");
+		return -1;
+	}
+	sport->len = strlen(sport->buf);
+	dport->buf = strdup(p2);
+	if (!dport->buf) {
+		yyerror("insufficient memory");
+		return -1;
+	}
+	dport->len = strlen(dport->buf);
+
+	return 0;
+}
+
+static int
+setvarbuf(buf, off, ebuf, elen, vbuf, vlen)
+	char *buf;
+	int *off;
+	struct sadb_ext *ebuf;
+	int elen;
+	const void *vbuf;
+	int vlen;
+{
+	memset(buf + *off, 0, PFKEY_UNUNIT64(ebuf->sadb_ext_len));
+	memcpy(buf + *off, (caddr_t)ebuf, elen);
+	memcpy(buf + *off + elen, vbuf, vlen);
+	(*off) += PFKEY_ALIGN8(elen + vlen);
+
+	return 0;
+}
+
+void
+parse_init()
+{
+	p_spi = 0;
+
+	p_ext = SADB_X_EXT_CYCSEQ;
+	p_alg_enc = SADB_EALG_NONE;
+	p_alg_auth = SADB_AALG_NONE;
+	p_mode = IPSEC_MODE_ANY;
+	p_reqid = 0;
+	p_replay = 0;
+	p_key_enc_len = p_key_auth_len = 0;
+	p_key_enc = p_key_auth = 0;
+	p_lt_hard = p_lt_soft = 0;
+	p_lb_hard = p_lb_soft = 0;
+
+	memset(&sec_ctx, 0, sizeof(struct security_ctx));
+
+	p_aiflags = 0;
+	p_aifamily = PF_UNSPEC;
+
+	/* Clear out any natt OA information */
+	if (p_natt_oa)
+		freeaddrinfo (p_natt_oa);
+	p_natt_oa = NULL;
+	p_natt_type = 0;
+
+	return;
+}
+
+void
+free_buffer()
+{
+	/* we got tons of memory leaks in the parser anyways, leave them */
+
+	return;
+}
diff --git a/src/setkey/parse.h b/src/setkey/parse.h
new file mode 100644
index 0000000..49140ae
--- /dev/null
+++ b/src/setkey/parse.h
@@ -0,0 +1,175 @@
+/* A Bison parser, made by GNU Bison 2.3.  */
+
+/* Skeleton interface for Bison's Yacc-like parsers in C
+
+   Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
+   Free Software Foundation, Inc.
+
+   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, or (at your option)
+   any later version.
+
+   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.
+
+   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., 51 Franklin Street, Fifth Floor,
+   Boston, MA 02110-1301, USA.  */
+
+/* As a special exception, you may create a larger work that contains
+   part or all of the Bison parser skeleton and distribute that work
+   under terms of your choice, so long as that work isn't itself a
+   parser generator using the skeleton or a modified version thereof
+   as a parser skeleton.  Alternatively, if you modify or redistribute
+   the parser skeleton itself, you may (at your option) remove this
+   special exception, which will cause the skeleton and the resulting
+   Bison output files to be licensed under the GNU General Public
+   License without this special exception.
+
+   This special exception was added by the Free Software Foundation in
+   version 2.2 of Bison.  */
+
+/* Tokens.  */
+#ifndef YYTOKENTYPE
+# define YYTOKENTYPE
+   /* Put the tokens into the symbol table, so that GDB and other debuggers
+      know about them.  */
+   enum yytokentype {
+     EOT = 258,
+     SLASH = 259,
+     BLCL = 260,
+     ELCL = 261,
+     ADD = 262,
+     GET = 263,
+     DELETE = 264,
+     DELETEALL = 265,
+     FLUSH = 266,
+     DUMP = 267,
+     EXIT = 268,
+     PR_ESP = 269,
+     PR_AH = 270,
+     PR_IPCOMP = 271,
+     PR_ESPUDP = 272,
+     PR_TCP = 273,
+     F_PROTOCOL = 274,
+     F_AUTH = 275,
+     F_ENC = 276,
+     F_REPLAY = 277,
+     F_COMP = 278,
+     F_RAWCPI = 279,
+     F_MODE = 280,
+     MODE = 281,
+     F_REQID = 282,
+     F_EXT = 283,
+     EXTENSION = 284,
+     NOCYCLICSEQ = 285,
+     ALG_AUTH = 286,
+     ALG_AUTH_NOKEY = 287,
+     ALG_ENC = 288,
+     ALG_ENC_NOKEY = 289,
+     ALG_ENC_DESDERIV = 290,
+     ALG_ENC_DES32IV = 291,
+     ALG_ENC_OLD = 292,
+     ALG_COMP = 293,
+     F_LIFETIME_HARD = 294,
+     F_LIFETIME_SOFT = 295,
+     F_LIFEBYTE_HARD = 296,
+     F_LIFEBYTE_SOFT = 297,
+     DECSTRING = 298,
+     QUOTEDSTRING = 299,
+     HEXSTRING = 300,
+     STRING = 301,
+     ANY = 302,
+     SPDADD = 303,
+     SPDDELETE = 304,
+     SPDDUMP = 305,
+     SPDFLUSH = 306,
+     F_POLICY = 307,
+     PL_REQUESTS = 308,
+     F_AIFLAGS = 309,
+     TAGGED = 310,
+     SECURITY_CTX = 311
+   };
+#endif
+/* Tokens.  */
+#define EOT 258
+#define SLASH 259
+#define BLCL 260
+#define ELCL 261
+#define ADD 262
+#define GET 263
+#define DELETE 264
+#define DELETEALL 265
+#define FLUSH 266
+#define DUMP 267
+#define EXIT 268
+#define PR_ESP 269
+#define PR_AH 270
+#define PR_IPCOMP 271
+#define PR_ESPUDP 272
+#define PR_TCP 273
+#define F_PROTOCOL 274
+#define F_AUTH 275
+#define F_ENC 276
+#define F_REPLAY 277
+#define F_COMP 278
+#define F_RAWCPI 279
+#define F_MODE 280
+#define MODE 281
+#define F_REQID 282
+#define F_EXT 283
+#define EXTENSION 284
+#define NOCYCLICSEQ 285
+#define ALG_AUTH 286
+#define ALG_AUTH_NOKEY 287
+#define ALG_ENC 288
+#define ALG_ENC_NOKEY 289
+#define ALG_ENC_DESDERIV 290
+#define ALG_ENC_DES32IV 291
+#define ALG_ENC_OLD 292
+#define ALG_COMP 293
+#define F_LIFETIME_HARD 294
+#define F_LIFETIME_SOFT 295
+#define F_LIFEBYTE_HARD 296
+#define F_LIFEBYTE_SOFT 297
+#define DECSTRING 298
+#define QUOTEDSTRING 299
+#define HEXSTRING 300
+#define STRING 301
+#define ANY 302
+#define SPDADD 303
+#define SPDDELETE 304
+#define SPDDUMP 305
+#define SPDFLUSH 306
+#define F_POLICY 307
+#define PL_REQUESTS 308
+#define F_AIFLAGS 309
+#define TAGGED 310
+#define SECURITY_CTX 311
+
+
+
+
+#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
+typedef union YYSTYPE
+#line 114 "parse.y"
+{
+	int num;
+	unsigned long ulnum;
+	vchar_t val;
+	struct addrinfo *res;
+}
+/* Line 1489 of yacc.c.  */
+#line 168 "parse.h"
+	YYSTYPE;
+# define yystype YYSTYPE /* obsolescent; will be withdrawn */
+# define YYSTYPE_IS_DECLARED 1
+# define YYSTYPE_IS_TRIVIAL 1
+#endif
+
+extern YYSTYPE yylval;
+
diff --git a/src/setkey/parse.y b/src/setkey/parse.y
new file mode 100644
index 0000000..1e9b6df
--- /dev/null
+++ b/src/setkey/parse.y
@@ -0,0 +1,1605 @@
+/*	$NetBSD: parse.y,v 1.9.6.1 2007/08/01 11:52:23 vanhu Exp $	*/
+
+/*	$KAME: parse.y,v 1.81 2003/07/01 04:01:48 itojun Exp $	*/
+
+/*
+ * Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+%{
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+
+#include <netinet/in.h>
+#include <net/pfkeyv2.h>
+#include PATH_IPSEC_H
+#include <arpa/inet.h>
+
+#include <string.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <netdb.h>
+#include <ctype.h>
+#include <errno.h>
+#include <stdlib.h>
+
+#include "libpfkey.h"
+#include "vchar.h"
+#include "extern.h"
+
+#ifndef IPPROTO_MH
+#define IPPROTO_MH		135
+#endif
+
+#define DEFAULT_NATT_PORT	4500
+
+#ifndef UDP_ENCAP_ESPINUDP
+#define UDP_ENCAP_ESPINUDP	2
+#endif
+
+#define ATOX(c) \
+  (isdigit((int)c) ? (c - '0') : \
+    (isupper((int)c) ? (c - 'A' + 10) : (c - 'a' + 10)))
+
+u_int32_t p_spi;
+u_int p_ext, p_alg_enc, p_alg_auth, p_replay, p_mode;
+u_int32_t p_reqid;
+u_int p_key_enc_len, p_key_auth_len;
+const char *p_key_enc;
+const char *p_key_auth;
+time_t p_lt_hard, p_lt_soft;
+size_t p_lb_hard, p_lb_soft;
+
+struct security_ctx {
+	u_int8_t doi;
+	u_int8_t alg;
+	u_int16_t len;
+	char *buf;
+};
+
+struct security_ctx sec_ctx;
+
+static u_int p_natt_type;
+static struct addrinfo * p_natt_oa = NULL;
+
+static int p_aiflags = 0, p_aifamily = PF_UNSPEC;
+
+static struct addrinfo *parse_addr __P((char *, char *));
+static int fix_portstr __P((vchar_t *, vchar_t *, vchar_t *));
+static int setvarbuf __P((char *, int *, struct sadb_ext *, int, 
+    const void *, int));
+void parse_init __P((void));
+void free_buffer __P((void));
+
+int setkeymsg0 __P((struct sadb_msg *, unsigned int, unsigned int, size_t));
+static int setkeymsg_spdaddr __P((unsigned int, unsigned int, vchar_t *,
+	struct addrinfo *, int, struct addrinfo *, int));
+static int setkeymsg_spdaddr_tag __P((unsigned int, char *, vchar_t *));
+static int setkeymsg_addr __P((unsigned int, unsigned int,
+	struct addrinfo *, struct addrinfo *, int));
+static int setkeymsg_add __P((unsigned int, unsigned int,
+	struct addrinfo *, struct addrinfo *));
+%}
+
+%union {
+	int num;
+	unsigned long ulnum;
+	vchar_t val;
+	struct addrinfo *res;
+}
+
+%token EOT SLASH BLCL ELCL
+%token ADD GET DELETE DELETEALL FLUSH DUMP EXIT
+%token PR_ESP PR_AH PR_IPCOMP PR_ESPUDP PR_TCP
+%token F_PROTOCOL F_AUTH F_ENC F_REPLAY F_COMP F_RAWCPI
+%token F_MODE MODE F_REQID
+%token F_EXT EXTENSION NOCYCLICSEQ
+%token ALG_AUTH ALG_AUTH_NOKEY
+%token ALG_ENC ALG_ENC_NOKEY ALG_ENC_DESDERIV ALG_ENC_DES32IV ALG_ENC_OLD
+%token ALG_COMP
+%token F_LIFETIME_HARD F_LIFETIME_SOFT
+%token F_LIFEBYTE_HARD F_LIFEBYTE_SOFT
+%token DECSTRING QUOTEDSTRING HEXSTRING STRING ANY
+	/* SPD management */
+%token SPDADD SPDDELETE SPDDUMP SPDFLUSH
+%token F_POLICY PL_REQUESTS
+%token F_AIFLAGS
+%token TAGGED
+%token SECURITY_CTX
+
+%type <num> prefix protocol_spec upper_spec
+%type <num> ALG_ENC ALG_ENC_DESDERIV ALG_ENC_DES32IV ALG_ENC_OLD ALG_ENC_NOKEY
+%type <num> ALG_AUTH ALG_AUTH_NOKEY
+%type <num> ALG_COMP
+%type <num> PR_ESP PR_AH PR_IPCOMP PR_ESPUDP PR_TCP
+%type <num> EXTENSION MODE
+%type <ulnum> DECSTRING
+%type <val> PL_REQUESTS portstr key_string
+%type <val> policy_requests
+%type <val> QUOTEDSTRING HEXSTRING STRING
+%type <val> F_AIFLAGS
+%type <val> upper_misc_spec policy_spec
+%type <res> ipaddr ipandport
+
+%%
+commands
+	:	/*NOTHING*/
+	|	commands command
+		{
+			free_buffer();
+			parse_init();
+		}
+	;
+
+command
+	:	add_command
+	|	get_command
+	|	delete_command
+	|	deleteall_command
+	|	flush_command
+	|	dump_command
+	|	exit_command
+	|	spdadd_command
+	|	spddelete_command
+	|	spddump_command
+	|	spdflush_command
+	;
+	/* commands concerned with management, there is in tail of this file. */
+
+	/* add command */
+add_command
+	:	ADD ipaddropts ipandport ipandport protocol_spec spi extension_spec algorithm_spec EOT
+		{
+			int status;
+
+			status = setkeymsg_add(SADB_ADD, $5, $3, $4);
+			if (status < 0)
+				return -1;
+		}
+	;
+
+	/* delete */
+delete_command
+	:	DELETE ipaddropts ipandport ipandport protocol_spec spi extension_spec EOT
+		{
+			int status;
+
+			if ($3->ai_next || $4->ai_next) {
+				yyerror("multiple address specified");
+				return -1;
+			}
+			if (p_mode != IPSEC_MODE_ANY)
+				yyerror("WARNING: mode is obsolete");
+
+			status = setkeymsg_addr(SADB_DELETE, $5, $3, $4, 0);
+			if (status < 0)
+				return -1;
+		}
+	;
+
+	/* deleteall command */
+deleteall_command
+	:	DELETEALL ipaddropts ipaddr ipaddr protocol_spec EOT
+		{
+			int status;
+
+			status = setkeymsg_addr(SADB_DELETE, $5, $3, $4, 1);
+			if (status < 0)
+				return -1;
+		}
+	;
+
+	/* get command */
+get_command
+	:	GET ipaddropts ipandport ipandport protocol_spec spi extension_spec EOT
+		{
+			int status;
+
+			if (p_mode != IPSEC_MODE_ANY)
+				yyerror("WARNING: mode is obsolete");
+
+			status = setkeymsg_addr(SADB_GET, $5, $3, $4, 0);
+			if (status < 0)
+				return -1;
+		}
+	;
+
+	/* flush */
+flush_command
+	:	FLUSH protocol_spec EOT
+		{
+			struct sadb_msg msg;
+			setkeymsg0(&msg, SADB_FLUSH, $2, sizeof(msg));
+			sendkeymsg((char *)&msg, sizeof(msg));
+		}
+	;
+
+	/* dump */
+dump_command
+	:	DUMP protocol_spec EOT
+		{
+			struct sadb_msg msg;
+			setkeymsg0(&msg, SADB_DUMP, $2, sizeof(msg));
+			sendkeymsg((char *)&msg, sizeof(msg));
+		}
+	;
+
+protocol_spec
+	:	/*NOTHING*/
+		{
+			$$ = SADB_SATYPE_UNSPEC;
+		}
+	|	PR_ESP
+		{
+			$$ = SADB_SATYPE_ESP;
+			if ($1 == 1)
+				p_ext |= SADB_X_EXT_OLD;
+			else
+				p_ext &= ~SADB_X_EXT_OLD;
+		}
+	|	PR_AH
+		{
+			$$ = SADB_SATYPE_AH;
+			if ($1 == 1)
+				p_ext |= SADB_X_EXT_OLD;
+			else
+				p_ext &= ~SADB_X_EXT_OLD;
+		}
+	|	PR_IPCOMP
+		{
+			$$ = SADB_X_SATYPE_IPCOMP;
+		}
+	|	PR_ESPUDP
+		{
+			$$ = SADB_SATYPE_ESP;
+			p_ext &= ~SADB_X_EXT_OLD;
+			p_natt_oa = 0;
+			p_natt_type = UDP_ENCAP_ESPINUDP;
+		}
+	|	PR_ESPUDP ipaddr
+		{
+			$$ = SADB_SATYPE_ESP;
+			p_ext &= ~SADB_X_EXT_OLD;
+			p_natt_oa = $2;
+			p_natt_type = UDP_ENCAP_ESPINUDP;
+		}
+	|	PR_TCP
+		{
+#ifdef SADB_X_SATYPE_TCPSIGNATURE
+			$$ = SADB_X_SATYPE_TCPSIGNATURE;
+#endif
+		}
+	;
+	
+spi
+	:	DECSTRING { p_spi = $1; }
+	|	HEXSTRING
+		{
+			char *ep;
+			unsigned long v;
+
+			ep = NULL;
+			v = strtoul($1.buf, &ep, 16);
+			if (!ep || *ep) {
+				yyerror("invalid SPI");
+				return -1;
+			}
+			if (v & ~0xffffffff) {
+				yyerror("SPI too big.");
+				return -1;
+			}
+
+			p_spi = v;
+		}
+	;
+
+algorithm_spec
+	:	esp_spec
+	|	ah_spec
+	|	ipcomp_spec
+	;
+
+esp_spec
+	:	F_ENC enc_alg F_AUTH auth_alg
+	|	F_ENC enc_alg
+	;
+
+ah_spec
+	:	F_AUTH auth_alg
+	;
+
+ipcomp_spec
+	:	F_COMP ALG_COMP
+		{
+			if ($2 < 0) {
+				yyerror("unsupported algorithm");
+				return -1;
+			}
+			p_alg_enc = $2;
+		}
+	|	F_COMP ALG_COMP F_RAWCPI
+		{
+			if ($2 < 0) {
+				yyerror("unsupported algorithm");
+				return -1;
+			}
+			p_alg_enc = $2;
+			p_ext |= SADB_X_EXT_RAWCPI;
+		}
+	;
+
+enc_alg
+	:	ALG_ENC_NOKEY {
+			if ($1 < 0) {
+				yyerror("unsupported algorithm");
+				return -1;
+			}
+			p_alg_enc = $1;
+
+			p_key_enc_len = 0;
+			p_key_enc = "";
+			if (ipsec_check_keylen(SADB_EXT_SUPPORTED_ENCRYPT,
+			    p_alg_enc, PFKEY_UNUNIT64(p_key_enc_len)) < 0) {
+				yyerror(ipsec_strerror());
+				return -1;
+			}
+		}
+	|	ALG_ENC key_string {
+			if ($1 < 0) {
+				yyerror("unsupported algorithm");
+				return -1;
+			}
+			p_alg_enc = $1;
+
+			p_key_enc_len = $2.len;
+			p_key_enc = $2.buf;
+			if (ipsec_check_keylen(SADB_EXT_SUPPORTED_ENCRYPT,
+			    p_alg_enc, PFKEY_UNUNIT64(p_key_enc_len)) < 0) {
+				yyerror(ipsec_strerror());
+				return -1;
+			}
+		}
+	|	ALG_ENC_OLD {
+			if ($1 < 0) {
+				yyerror("unsupported algorithm");
+				return -1;
+			}
+			yyerror("WARNING: obsolete algorithm");
+			p_alg_enc = $1;
+
+			p_key_enc_len = 0;
+			p_key_enc = "";
+			if (ipsec_check_keylen(SADB_EXT_SUPPORTED_ENCRYPT,
+			    p_alg_enc, PFKEY_UNUNIT64(p_key_enc_len)) < 0) {
+				yyerror(ipsec_strerror());
+				return -1;
+			}
+		}
+	|	ALG_ENC_DESDERIV key_string
+		{
+			if ($1 < 0) {
+				yyerror("unsupported algorithm");
+				return -1;
+			}
+			p_alg_enc = $1;
+			if (p_ext & SADB_X_EXT_OLD) {
+				yyerror("algorithm mismatched");
+				return -1;
+			}
+			p_ext |= SADB_X_EXT_DERIV;
+
+			p_key_enc_len = $2.len;
+			p_key_enc = $2.buf;
+			if (ipsec_check_keylen(SADB_EXT_SUPPORTED_ENCRYPT,
+			    p_alg_enc, PFKEY_UNUNIT64(p_key_enc_len)) < 0) {
+				yyerror(ipsec_strerror());
+				return -1;
+			}
+		}
+	|	ALG_ENC_DES32IV key_string
+		{
+			if ($1 < 0) {
+				yyerror("unsupported algorithm");
+				return -1;
+			}
+			p_alg_enc = $1;
+			if (!(p_ext & SADB_X_EXT_OLD)) {
+				yyerror("algorithm mismatched");
+				return -1;
+			}
+			p_ext |= SADB_X_EXT_IV4B;
+
+			p_key_enc_len = $2.len;
+			p_key_enc = $2.buf;
+			if (ipsec_check_keylen(SADB_EXT_SUPPORTED_ENCRYPT,
+			    p_alg_enc, PFKEY_UNUNIT64(p_key_enc_len)) < 0) {
+				yyerror(ipsec_strerror());
+				return -1;
+			}
+		}
+	;
+
+auth_alg
+	:	ALG_AUTH key_string {
+			if ($1 < 0) {
+				yyerror("unsupported algorithm");
+				return -1;
+			}
+			p_alg_auth = $1;
+
+			p_key_auth_len = $2.len;
+			p_key_auth = $2.buf;
+#ifdef SADB_X_AALG_TCP_MD5
+			if (p_alg_auth == SADB_X_AALG_TCP_MD5) {
+				if ((p_key_auth_len < 1) || 
+				    (p_key_auth_len > 80))
+					return -1;
+			} else 
+#endif
+			{
+				if (ipsec_check_keylen(SADB_EXT_SUPPORTED_AUTH,
+				    p_alg_auth, 
+				    PFKEY_UNUNIT64(p_key_auth_len)) < 0) {
+					yyerror(ipsec_strerror());
+					return -1;
+				}
+			}
+		}
+	|	ALG_AUTH_NOKEY {
+			if ($1 < 0) {
+				yyerror("unsupported algorithm");
+				return -1;
+			}
+			p_alg_auth = $1;
+
+			p_key_auth_len = 0;
+			p_key_auth = NULL;
+		}
+	;
+
+key_string
+	:	QUOTEDSTRING
+		{
+			$$ = $1;
+		}
+	|	HEXSTRING
+		{
+			caddr_t pp_key;
+			caddr_t bp;
+			caddr_t yp = $1.buf;
+			int l;
+
+			l = strlen(yp) % 2 + strlen(yp) / 2;
+			if ((pp_key = malloc(l)) == 0) {
+				yyerror("not enough core");
+				return -1;
+			}
+			memset(pp_key, 0, l);
+
+			bp = pp_key;
+			if (strlen(yp) % 2) {
+				*bp = ATOX(yp[0]);
+				yp++, bp++;
+			}
+			while (*yp) {
+				*bp = (ATOX(yp[0]) << 4) | ATOX(yp[1]);
+				yp += 2, bp++;
+			}
+
+			$$.len = l;
+			$$.buf = pp_key;
+		}
+	;
+
+extension_spec
+	:	/*NOTHING*/
+	|	extension_spec extension
+	;
+
+extension
+	:	F_EXT EXTENSION { p_ext |= $2; }
+	|	F_EXT NOCYCLICSEQ { p_ext &= ~SADB_X_EXT_CYCSEQ; }
+	|	F_MODE MODE { p_mode = $2; }
+	|	F_MODE ANY { p_mode = IPSEC_MODE_ANY; }
+	|	F_REQID DECSTRING { p_reqid = $2; }
+	|	F_REPLAY DECSTRING
+		{
+			if ((p_ext & SADB_X_EXT_OLD) != 0) {
+				yyerror("replay prevention cannot be used with "
+				    "ah/esp-old");
+				return -1;
+			}
+			p_replay = $2;
+		}
+	|	F_LIFETIME_HARD DECSTRING { p_lt_hard = $2; }
+	|	F_LIFETIME_SOFT DECSTRING { p_lt_soft = $2; }
+	|	F_LIFEBYTE_HARD DECSTRING { p_lb_hard = $2; }
+	|	F_LIFEBYTE_SOFT DECSTRING { p_lb_soft = $2; }
+	|	SECURITY_CTX DECSTRING DECSTRING QUOTEDSTRING {
+		sec_ctx.doi = $2;
+		sec_ctx.alg = $3;
+		sec_ctx.len = $4.len+1;
+		sec_ctx.buf = $4.buf;
+	}
+	;
+
+	/* definition about command for SPD management */
+	/* spdadd */
+spdadd_command
+	:	SPDADD ipaddropts STRING prefix portstr STRING prefix portstr upper_spec upper_misc_spec context_spec policy_spec EOT
+		{
+			int status;
+			struct addrinfo *src, *dst;
+
+#ifdef HAVE_PFKEY_POLICY_PRIORITY
+			last_msg_type = SADB_X_SPDADD;
+#endif
+
+			/* fixed port fields if ulp is icmpv6 */
+			if ($10.buf != NULL) {
+				if ( ($9 != IPPROTO_ICMPV6) &&
+					 ($9 != IPPROTO_MH))
+					return -1;
+				free($5.buf);
+				free($8.buf);
+				if (fix_portstr(&$10, &$5, &$8))
+					return -1;
+			}
+
+			src = parse_addr($3.buf, $5.buf);
+			dst = parse_addr($6.buf, $8.buf);
+			if (!src || !dst) {
+				/* yyerror is already called */
+				return -1;
+			}
+			if (src->ai_next || dst->ai_next) {
+				yyerror("multiple address specified");
+				freeaddrinfo(src);
+				freeaddrinfo(dst);
+				return -1;
+			}
+
+			status = setkeymsg_spdaddr(SADB_X_SPDADD, $9, &$12,
+			    src, $4, dst, $7);
+			freeaddrinfo(src);
+			freeaddrinfo(dst);
+			if (status < 0)
+				return -1;
+		}
+	|	SPDADD TAGGED QUOTEDSTRING policy_spec EOT
+		{
+			int status;
+
+			status = setkeymsg_spdaddr_tag(SADB_X_SPDADD,
+			    $3.buf, &$4);
+			if (status < 0)
+				return -1;
+		}
+	;
+
+spddelete_command
+	:	SPDDELETE ipaddropts STRING prefix portstr STRING prefix portstr upper_spec upper_misc_spec context_spec policy_spec EOT
+		{
+			int status;
+			struct addrinfo *src, *dst;
+
+			/* fixed port fields if ulp is icmpv6 */
+			if ($10.buf != NULL) {
+				if (($9 != IPPROTO_ICMPV6) &&
+					($9 != IPPROTO_MH))
+					return -1;
+				free($5.buf);
+				free($8.buf);
+				if (fix_portstr(&$10, &$5, &$8))
+					return -1;
+			}
+
+			src = parse_addr($3.buf, $5.buf);
+			dst = parse_addr($6.buf, $8.buf);
+			if (!src || !dst) {
+				/* yyerror is already called */
+				return -1;
+			}
+			if (src->ai_next || dst->ai_next) {
+				yyerror("multiple address specified");
+				freeaddrinfo(src);
+				freeaddrinfo(dst);
+				return -1;
+			}
+
+			status = setkeymsg_spdaddr(SADB_X_SPDDELETE, $9, &$12,
+			    src, $4, dst, $7);
+			freeaddrinfo(src);
+			freeaddrinfo(dst);
+			if (status < 0)
+				return -1;
+		}
+	;
+
+spddump_command:
+		SPDDUMP EOT
+		{
+			struct sadb_msg msg;
+			setkeymsg0(&msg, SADB_X_SPDDUMP, SADB_SATYPE_UNSPEC,
+			    sizeof(msg));
+			sendkeymsg((char *)&msg, sizeof(msg));
+		}
+	;
+
+spdflush_command
+	:
+		SPDFLUSH EOT
+		{
+			struct sadb_msg msg;
+			setkeymsg0(&msg, SADB_X_SPDFLUSH, SADB_SATYPE_UNSPEC,
+			    sizeof(msg));
+			sendkeymsg((char *)&msg, sizeof(msg));
+		}
+	;
+
+ipaddropts
+	:	/* nothing */
+	|	ipaddropts ipaddropt
+	;
+
+ipaddropt
+	:	F_AIFLAGS
+		{
+			char *p;
+
+			for (p = $1.buf + 1; *p; p++)
+				switch (*p) {
+				case '4':
+					p_aifamily = AF_INET;
+					break;
+#ifdef INET6
+				case '6':
+					p_aifamily = AF_INET6;
+					break;
+#endif
+				case 'n':
+					p_aiflags = AI_NUMERICHOST;
+					break;
+				default:
+					yyerror("invalid flag");
+					return -1;
+				}
+		}
+	;
+
+ipaddr
+	:	STRING
+		{
+			$$ = parse_addr($1.buf, NULL);
+			if ($$ == NULL) {
+				/* yyerror already called by parse_addr */
+				return -1;
+			}
+		}
+	;
+
+ipandport
+	:	STRING
+		{
+			$$ = parse_addr($1.buf, NULL);
+			if ($$ == NULL) {
+				/* yyerror already called by parse_addr */
+				return -1;
+			}
+		}
+	|	STRING portstr
+		{
+			$$ = parse_addr($1.buf, $2.buf);
+			if ($$ == NULL) {
+				/* yyerror already called by parse_addr */
+				return -1;
+			}
+		}
+	;
+
+prefix
+	:	/*NOTHING*/ { $$ = -1; }
+	|	SLASH DECSTRING { $$ = $2; }
+	;
+
+portstr
+	:	/*NOTHING*/
+		{
+			$$.buf = strdup("0");
+			if (!$$.buf) {
+				yyerror("insufficient memory");
+				return -1;
+			}
+			$$.len = strlen($$.buf);
+		}
+	|	BLCL ANY ELCL
+		{
+			$$.buf = strdup("0");
+			if (!$$.buf) {
+				yyerror("insufficient memory");
+				return -1;
+			}
+			$$.len = strlen($$.buf);
+		}
+	|	BLCL DECSTRING ELCL
+		{
+			char buf[20];
+			snprintf(buf, sizeof(buf), "%lu", $2);
+			$$.buf = strdup(buf);
+			if (!$$.buf) {
+				yyerror("insufficient memory");
+				return -1;
+			}
+			$$.len = strlen($$.buf);
+		}
+	|	BLCL STRING ELCL
+		{
+			$$ = $2;
+		}
+	;
+
+upper_spec
+	:	DECSTRING { $$ = $1; }
+	|	ANY { $$ = IPSEC_ULPROTO_ANY; }
+	|	PR_TCP { 
+				$$ = IPPROTO_TCP; 
+			}
+	|	STRING
+		{
+			struct protoent *ent;
+
+			ent = getprotobyname($1.buf);
+			if (ent)
+				$$ = ent->p_proto;
+			else {
+				if (strcmp("icmp6", $1.buf) == 0) {
+					$$ = IPPROTO_ICMPV6;
+				} else if(strcmp("ip4", $1.buf) == 0) {
+					$$ = IPPROTO_IPV4;
+				} else {
+					yyerror("invalid upper layer protocol");
+					return -1;
+				}
+			}
+			endprotoent();
+		}
+	;
+
+upper_misc_spec
+	:	/*NOTHING*/
+		{
+			$$.buf = NULL;
+			$$.len = 0;
+		}
+	|	STRING
+		{
+			$$.buf = strdup($1.buf);
+			if (!$$.buf) {
+				yyerror("insufficient memory");
+				return -1;
+			}
+			$$.len = strlen($$.buf);
+		}
+	;
+
+context_spec
+	:	/* NOTHING */
+	|	SECURITY_CTX DECSTRING DECSTRING QUOTEDSTRING {
+			sec_ctx.doi = $2;
+			sec_ctx.alg = $3;
+			sec_ctx.len = $4.len+1;
+			sec_ctx.buf = $4.buf;
+		}
+	;
+
+policy_spec
+	:	F_POLICY policy_requests
+		{
+			char *policy;
+#ifdef HAVE_PFKEY_POLICY_PRIORITY
+			struct sadb_x_policy *xpl;
+#endif
+
+			policy = ipsec_set_policy($2.buf, $2.len);
+			if (policy == NULL) {
+				yyerror(ipsec_strerror());
+				return -1;
+			}
+
+			$$.buf = policy;
+			$$.len = ipsec_get_policylen(policy);
+
+#ifdef HAVE_PFKEY_POLICY_PRIORITY
+			xpl = (struct sadb_x_policy *) $$.buf;
+			last_priority = xpl->sadb_x_policy_priority;
+#endif
+		}
+	;
+
+policy_requests
+	:	PL_REQUESTS { $$ = $1; }
+	;
+
+	/* exit */
+exit_command
+	:	EXIT EOT
+		{
+			exit_now = 1;
+			YYACCEPT;
+		}
+	;
+%%
+
+int
+setkeymsg0(msg, type, satype, l)
+	struct sadb_msg *msg;
+	unsigned int type;
+	unsigned int satype;
+	size_t l;
+{
+
+	msg->sadb_msg_version = PF_KEY_V2;
+	msg->sadb_msg_type = type;
+	msg->sadb_msg_errno = 0;
+	msg->sadb_msg_satype = satype;
+	msg->sadb_msg_reserved = 0;
+	msg->sadb_msg_seq = 0;
+	msg->sadb_msg_pid = getpid();
+	msg->sadb_msg_len = PFKEY_UNIT64(l);
+	return 0;
+}
+
+/* XXX NO BUFFER OVERRUN CHECK! BAD BAD! */
+static int
+setkeymsg_spdaddr(type, upper, policy, srcs, splen, dsts, dplen)
+	unsigned int type;
+	unsigned int upper;
+	vchar_t *policy;
+	struct addrinfo *srcs;
+	int splen;
+	struct addrinfo *dsts;
+	int dplen;
+{
+	struct sadb_msg *msg;
+	char buf[BUFSIZ];
+	int l, l0;
+	struct sadb_address m_addr;
+	struct addrinfo *s, *d;
+	int n;
+	int plen;
+	struct sockaddr *sa;
+	int salen;
+	struct sadb_x_policy *sp;
+#ifdef HAVE_POLICY_FWD
+	struct sadb_x_ipsecrequest *ps = NULL;
+	int saved_level, saved_id = 0;
+#endif
+
+	msg = (struct sadb_msg *)buf;
+
+	if (!srcs || !dsts)
+		return -1;
+
+	/* fix up length afterwards */
+	setkeymsg0(msg, type, SADB_SATYPE_UNSPEC, 0);
+	l = sizeof(struct sadb_msg);
+
+	sp = (struct sadb_x_policy*) (buf + l);
+	memcpy(buf + l, policy->buf, policy->len);
+	l += policy->len;
+
+	l0 = l;
+	n = 0;
+
+	/* do it for all src/dst pairs */
+	for (s = srcs; s; s = s->ai_next) {
+		for (d = dsts; d; d = d->ai_next) {
+			/* rewind pointer */
+			l = l0;
+
+			if (s->ai_addr->sa_family != d->ai_addr->sa_family)
+				continue;
+			switch (s->ai_addr->sa_family) {
+			case AF_INET:
+				plen = sizeof(struct in_addr) << 3;
+				break;
+#ifdef INET6
+			case AF_INET6:
+				plen = sizeof(struct in6_addr) << 3;
+				break;
+#endif
+			default:
+				continue;
+			}
+
+			/* set src */
+			sa = s->ai_addr;
+			salen = sysdep_sa_len(s->ai_addr);
+			m_addr.sadb_address_len = PFKEY_UNIT64(sizeof(m_addr) +
+			    PFKEY_ALIGN8(salen));
+			m_addr.sadb_address_exttype = SADB_EXT_ADDRESS_SRC;
+			m_addr.sadb_address_proto = upper;
+			m_addr.sadb_address_prefixlen =
+			    (splen >= 0 ? splen : plen);
+			m_addr.sadb_address_reserved = 0;
+
+			setvarbuf(buf, &l, (struct sadb_ext *)&m_addr,
+			    sizeof(m_addr), (caddr_t)sa, salen);
+
+			/* set dst */
+			sa = d->ai_addr;
+			salen = sysdep_sa_len(d->ai_addr);
+			m_addr.sadb_address_len = PFKEY_UNIT64(sizeof(m_addr) +
+			    PFKEY_ALIGN8(salen));
+			m_addr.sadb_address_exttype = SADB_EXT_ADDRESS_DST;
+			m_addr.sadb_address_proto = upper;
+			m_addr.sadb_address_prefixlen =
+			    (dplen >= 0 ? dplen : plen);
+			m_addr.sadb_address_reserved = 0;
+
+			setvarbuf(buf, &l, (struct sadb_ext *)&m_addr,
+			    sizeof(m_addr), sa, salen);
+#ifdef SADB_X_EXT_SEC_CTX
+			/* Add security context label */
+			if (sec_ctx.doi) {
+				struct sadb_x_sec_ctx m_sec_ctx;
+				u_int slen = sizeof(struct sadb_x_sec_ctx);
+
+				memset(&m_sec_ctx, 0, slen);
+
+				m_sec_ctx.sadb_x_sec_len =
+				PFKEY_UNIT64(slen + PFKEY_ALIGN8(sec_ctx.len));
+
+				m_sec_ctx.sadb_x_sec_exttype = 
+					SADB_X_EXT_SEC_CTX;
+				m_sec_ctx.sadb_x_ctx_len = sec_ctx.len;/*bytes*/
+				m_sec_ctx.sadb_x_ctx_doi = sec_ctx.doi;
+				m_sec_ctx.sadb_x_ctx_alg = sec_ctx.alg;
+				setvarbuf(buf, &l, 
+					  (struct sadb_ext *)&m_sec_ctx, slen, 
+					  (caddr_t)sec_ctx.buf, sec_ctx.len);
+			}
+#endif
+			msg->sadb_msg_len = PFKEY_UNIT64(l);
+
+			sendkeymsg(buf, l);
+
+#ifdef HAVE_POLICY_FWD
+			/* create extra call for FWD policy */
+			if (f_rfcmode && sp->sadb_x_policy_dir == IPSEC_DIR_INBOUND) {
+				sp->sadb_x_policy_dir = IPSEC_DIR_FWD;
+				ps = (struct sadb_x_ipsecrequest*) (sp+1);
+
+				/* if request level is unique, change it to
+				 * require for fwd policy */
+				/* XXX: currently, only first policy is updated
+				 * only. Update following too... */
+				saved_level = ps->sadb_x_ipsecrequest_level;
+				if (saved_level == IPSEC_LEVEL_UNIQUE) {
+					saved_id = ps->sadb_x_ipsecrequest_reqid;
+					ps->sadb_x_ipsecrequest_reqid=0;
+					ps->sadb_x_ipsecrequest_level=IPSEC_LEVEL_REQUIRE;
+				}
+
+				sendkeymsg(buf, l);
+				/* restoring for next message */
+				sp->sadb_x_policy_dir = IPSEC_DIR_INBOUND;
+				if (saved_level == IPSEC_LEVEL_UNIQUE) {
+					ps->sadb_x_ipsecrequest_reqid = saved_id;
+					ps->sadb_x_ipsecrequest_level = saved_level;
+				}
+			}
+#endif
+
+			n++;
+		}
+	}
+
+	if (n == 0)
+		return -1;
+	else
+		return 0;
+}
+
+static int
+setkeymsg_spdaddr_tag(type, tag, policy)
+	unsigned int type;
+	char *tag;
+	vchar_t *policy;
+{
+	struct sadb_msg *msg;
+	char buf[BUFSIZ];
+	int l, l0;
+#ifdef SADB_X_EXT_TAG
+	struct sadb_x_tag m_tag;
+#endif
+	int n;
+
+	msg = (struct sadb_msg *)buf;
+
+	/* fix up length afterwards */
+	setkeymsg0(msg, type, SADB_SATYPE_UNSPEC, 0);
+	l = sizeof(struct sadb_msg);
+
+	memcpy(buf + l, policy->buf, policy->len);
+	l += policy->len;
+
+	l0 = l;
+	n = 0;
+
+#ifdef SADB_X_EXT_TAG
+	memset(&m_tag, 0, sizeof(m_tag));
+	m_tag.sadb_x_tag_len = PFKEY_UNIT64(sizeof(m_tag));
+	m_tag.sadb_x_tag_exttype = SADB_X_EXT_TAG;
+	if (strlcpy(m_tag.sadb_x_tag_name, tag,
+	    sizeof(m_tag.sadb_x_tag_name)) >= sizeof(m_tag.sadb_x_tag_name))
+		return -1;
+	memcpy(buf + l, &m_tag, sizeof(m_tag));
+	l += sizeof(m_tag);
+#endif
+
+	msg->sadb_msg_len = PFKEY_UNIT64(l);
+
+	sendkeymsg(buf, l);
+
+	return 0;
+}
+
+/* XXX NO BUFFER OVERRUN CHECK! BAD BAD! */
+static int
+setkeymsg_addr(type, satype, srcs, dsts, no_spi)
+	unsigned int type;
+	unsigned int satype;
+	struct addrinfo *srcs;
+	struct addrinfo *dsts;
+	int no_spi;
+{
+	struct sadb_msg *msg;
+	char buf[BUFSIZ];
+	int l, l0, len;
+	struct sadb_sa m_sa;
+	struct sadb_x_sa2 m_sa2;
+	struct sadb_address m_addr;
+	struct addrinfo *s, *d;
+	int n;
+	int plen;
+	struct sockaddr *sa;
+	int salen;
+
+	msg = (struct sadb_msg *)buf;
+
+	if (!srcs || !dsts)
+		return -1;
+
+	/* fix up length afterwards */
+	setkeymsg0(msg, type, satype, 0);
+	l = sizeof(struct sadb_msg);
+
+	if (!no_spi) {
+		len = sizeof(struct sadb_sa);
+		m_sa.sadb_sa_len = PFKEY_UNIT64(len);
+		m_sa.sadb_sa_exttype = SADB_EXT_SA;
+		m_sa.sadb_sa_spi = htonl(p_spi);
+		m_sa.sadb_sa_replay = p_replay;
+		m_sa.sadb_sa_state = 0;
+		m_sa.sadb_sa_auth = p_alg_auth;
+		m_sa.sadb_sa_encrypt = p_alg_enc;
+		m_sa.sadb_sa_flags = p_ext;
+
+		memcpy(buf + l, &m_sa, len);
+		l += len;
+
+		len = sizeof(struct sadb_x_sa2);
+		m_sa2.sadb_x_sa2_len = PFKEY_UNIT64(len);
+		m_sa2.sadb_x_sa2_exttype = SADB_X_EXT_SA2;
+		m_sa2.sadb_x_sa2_mode = p_mode;
+		m_sa2.sadb_x_sa2_reqid = p_reqid;
+
+		memcpy(buf + l, &m_sa2, len);
+		l += len;
+	}
+
+	l0 = l;
+	n = 0;
+
+	/* do it for all src/dst pairs */
+	for (s = srcs; s; s = s->ai_next) {
+		for (d = dsts; d; d = d->ai_next) {
+			/* rewind pointer */
+			l = l0;
+
+			if (s->ai_addr->sa_family != d->ai_addr->sa_family)
+				continue;
+			switch (s->ai_addr->sa_family) {
+			case AF_INET:
+				plen = sizeof(struct in_addr) << 3;
+				break;
+#ifdef INET6
+			case AF_INET6:
+				plen = sizeof(struct in6_addr) << 3;
+				break;
+#endif
+			default:
+				continue;
+			}
+
+			/* set src */
+			sa = s->ai_addr;
+			salen = sysdep_sa_len(s->ai_addr);
+			m_addr.sadb_address_len = PFKEY_UNIT64(sizeof(m_addr) +
+			    PFKEY_ALIGN8(salen));
+			m_addr.sadb_address_exttype = SADB_EXT_ADDRESS_SRC;
+			m_addr.sadb_address_proto = IPSEC_ULPROTO_ANY;
+			m_addr.sadb_address_prefixlen = plen;
+			m_addr.sadb_address_reserved = 0;
+
+			setvarbuf(buf, &l, (struct sadb_ext *)&m_addr,
+			    sizeof(m_addr), sa, salen);
+
+			/* set dst */
+			sa = d->ai_addr;
+			salen = sysdep_sa_len(d->ai_addr);
+			m_addr.sadb_address_len = PFKEY_UNIT64(sizeof(m_addr) +
+			    PFKEY_ALIGN8(salen));
+			m_addr.sadb_address_exttype = SADB_EXT_ADDRESS_DST;
+			m_addr.sadb_address_proto = IPSEC_ULPROTO_ANY;
+			m_addr.sadb_address_prefixlen = plen;
+			m_addr.sadb_address_reserved = 0;
+
+			setvarbuf(buf, &l, (struct sadb_ext *)&m_addr,
+			    sizeof(m_addr), sa, salen);
+
+			msg->sadb_msg_len = PFKEY_UNIT64(l);
+
+			sendkeymsg(buf, l);
+
+			n++;
+		}
+	}
+
+	if (n == 0)
+		return -1;
+	else
+		return 0;
+}
+
+#ifdef SADB_X_EXT_NAT_T_TYPE
+static u_int16_t get_port (struct addrinfo *addr)
+{
+	struct sockaddr *s = addr->ai_addr;
+	u_int16_t port = 0;
+
+	switch (s->sa_family) {
+	case AF_INET:
+	  {
+		struct sockaddr_in *sin4 = (struct sockaddr_in *)s;
+		port = ntohs(sin4->sin_port);
+		break;
+	  }
+	case AF_INET6:
+	  {
+		struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)s;
+		port = ntohs(sin6->sin6_port);
+		break;
+	  }
+	}
+
+	if (port == 0)
+		port = DEFAULT_NATT_PORT;
+
+	return port;
+}
+#endif
+
+/* XXX NO BUFFER OVERRUN CHECK! BAD BAD! */
+static int
+setkeymsg_add(type, satype, srcs, dsts)
+	unsigned int type;
+	unsigned int satype;
+	struct addrinfo *srcs;
+	struct addrinfo *dsts;
+{
+	struct sadb_msg *msg;
+	char buf[BUFSIZ];
+	int l, l0, len;
+	struct sadb_sa m_sa;
+	struct sadb_x_sa2 m_sa2;
+	struct sadb_address m_addr;
+	struct addrinfo *s, *d;
+	int n;
+	int plen;
+	struct sockaddr *sa;
+	int salen;
+
+	msg = (struct sadb_msg *)buf;
+
+	if (!srcs || !dsts)
+		return -1;
+
+	/* fix up length afterwards */
+	setkeymsg0(msg, type, satype, 0);
+	l = sizeof(struct sadb_msg);
+
+	/* set encryption algorithm, if present. */
+	if (satype != SADB_X_SATYPE_IPCOMP && p_key_enc) {
+		union {
+			struct sadb_key key;
+			struct sadb_ext ext;
+		} m;
+
+		m.key.sadb_key_len =
+			PFKEY_UNIT64(sizeof(m.key)
+				   + PFKEY_ALIGN8(p_key_enc_len));
+		m.key.sadb_key_exttype = SADB_EXT_KEY_ENCRYPT;
+		m.key.sadb_key_bits = p_key_enc_len * 8;
+		m.key.sadb_key_reserved = 0;
+
+		setvarbuf(buf, &l, &m.ext, sizeof(m.key),
+			p_key_enc, p_key_enc_len);
+	}
+
+	/* set authentication algorithm, if present. */
+	if (p_key_auth) {
+		union {
+			struct sadb_key key;
+			struct sadb_ext ext;
+		} m;
+
+		m.key.sadb_key_len =
+			PFKEY_UNIT64(sizeof(m.key)
+				   + PFKEY_ALIGN8(p_key_auth_len));
+		m.key.sadb_key_exttype = SADB_EXT_KEY_AUTH;
+		m.key.sadb_key_bits = p_key_auth_len * 8;
+		m.key.sadb_key_reserved = 0;
+
+		setvarbuf(buf, &l, &m.ext, sizeof(m.key),
+			p_key_auth, p_key_auth_len);
+	}
+
+	/* set lifetime for HARD */
+	if (p_lt_hard != 0 || p_lb_hard != 0) {
+		struct sadb_lifetime m_lt;
+		u_int slen = sizeof(struct sadb_lifetime);
+
+		m_lt.sadb_lifetime_len = PFKEY_UNIT64(slen);
+		m_lt.sadb_lifetime_exttype = SADB_EXT_LIFETIME_HARD;
+		m_lt.sadb_lifetime_allocations = 0;
+		m_lt.sadb_lifetime_bytes = p_lb_hard;
+		m_lt.sadb_lifetime_addtime = p_lt_hard;
+		m_lt.sadb_lifetime_usetime = 0;
+
+		memcpy(buf + l, &m_lt, slen);
+		l += slen;
+	}
+
+	/* set lifetime for SOFT */
+	if (p_lt_soft != 0 || p_lb_soft != 0) {
+		struct sadb_lifetime m_lt;
+		u_int slen = sizeof(struct sadb_lifetime);
+
+		m_lt.sadb_lifetime_len = PFKEY_UNIT64(slen);
+		m_lt.sadb_lifetime_exttype = SADB_EXT_LIFETIME_SOFT;
+		m_lt.sadb_lifetime_allocations = 0;
+		m_lt.sadb_lifetime_bytes = p_lb_soft;
+		m_lt.sadb_lifetime_addtime = p_lt_soft;
+		m_lt.sadb_lifetime_usetime = 0;
+
+		memcpy(buf + l, &m_lt, slen);
+		l += slen;
+	}
+
+#ifdef SADB_X_EXT_SEC_CTX
+	/* Add security context label */
+	if (sec_ctx.doi) {
+		struct sadb_x_sec_ctx m_sec_ctx;
+		u_int slen = sizeof(struct sadb_x_sec_ctx);
+
+		memset(&m_sec_ctx, 0, slen);
+
+		m_sec_ctx.sadb_x_sec_len = PFKEY_UNIT64(slen +
+					PFKEY_ALIGN8(sec_ctx.len));
+		m_sec_ctx.sadb_x_sec_exttype = SADB_X_EXT_SEC_CTX;
+		m_sec_ctx.sadb_x_ctx_len = sec_ctx.len; /* bytes */
+		m_sec_ctx.sadb_x_ctx_doi = sec_ctx.doi;
+		m_sec_ctx.sadb_x_ctx_alg = sec_ctx.alg;
+		setvarbuf(buf, &l, (struct sadb_ext *)&m_sec_ctx, slen,
+			  (caddr_t)sec_ctx.buf, sec_ctx.len); 
+	}
+#endif
+
+	len = sizeof(struct sadb_sa);
+	m_sa.sadb_sa_len = PFKEY_UNIT64(len);
+	m_sa.sadb_sa_exttype = SADB_EXT_SA;
+	m_sa.sadb_sa_spi = htonl(p_spi);
+	m_sa.sadb_sa_replay = p_replay;
+	m_sa.sadb_sa_state = 0;
+	m_sa.sadb_sa_auth = p_alg_auth;
+	m_sa.sadb_sa_encrypt = p_alg_enc;
+	m_sa.sadb_sa_flags = p_ext;
+
+	memcpy(buf + l, &m_sa, len);
+	l += len;
+
+	len = sizeof(struct sadb_x_sa2);
+	m_sa2.sadb_x_sa2_len = PFKEY_UNIT64(len);
+	m_sa2.sadb_x_sa2_exttype = SADB_X_EXT_SA2;
+	m_sa2.sadb_x_sa2_mode = p_mode;
+	m_sa2.sadb_x_sa2_reqid = p_reqid;
+
+	memcpy(buf + l, &m_sa2, len);
+	l += len;
+
+#ifdef SADB_X_EXT_NAT_T_TYPE
+	if (p_natt_type) {
+		struct sadb_x_nat_t_type natt_type;
+
+		len = sizeof(struct sadb_x_nat_t_type);
+		memset(&natt_type, 0, len);
+		natt_type.sadb_x_nat_t_type_len = PFKEY_UNIT64(len);
+		natt_type.sadb_x_nat_t_type_exttype = SADB_X_EXT_NAT_T_TYPE;
+		natt_type.sadb_x_nat_t_type_type = p_natt_type;
+
+		memcpy(buf + l, &natt_type, len);
+		l += len;
+
+		if (p_natt_oa) {
+			sa = p_natt_oa->ai_addr;
+			switch (sa->sa_family) {
+			case AF_INET:
+				plen = sizeof(struct in_addr) << 3;
+				break;
+#ifdef INET6
+			case AF_INET6:
+				plen = sizeof(struct in6_addr) << 3;
+				break;
+#endif
+			default:
+				return -1;
+			}
+			salen = sysdep_sa_len(sa);
+			m_addr.sadb_address_len = PFKEY_UNIT64(sizeof(m_addr) +
+			    PFKEY_ALIGN8(salen));
+			m_addr.sadb_address_exttype = SADB_X_EXT_NAT_T_OA;
+			m_addr.sadb_address_proto = IPSEC_ULPROTO_ANY;
+			m_addr.sadb_address_prefixlen = plen;
+			m_addr.sadb_address_reserved = 0;
+
+			setvarbuf(buf, &l, (struct sadb_ext *)&m_addr,
+			    sizeof(m_addr), sa, salen);
+		}
+	}
+#endif
+
+	l0 = l;
+	n = 0;
+
+	/* do it for all src/dst pairs */
+	for (s = srcs; s; s = s->ai_next) {
+		for (d = dsts; d; d = d->ai_next) {
+			/* rewind pointer */
+			l = l0;
+
+			if (s->ai_addr->sa_family != d->ai_addr->sa_family)
+				continue;
+			switch (s->ai_addr->sa_family) {
+			case AF_INET:
+				plen = sizeof(struct in_addr) << 3;
+				break;
+#ifdef INET6
+			case AF_INET6:
+				plen = sizeof(struct in6_addr) << 3;
+				break;
+#endif
+			default:
+				continue;
+			}
+
+			/* set src */
+			sa = s->ai_addr;
+			salen = sysdep_sa_len(s->ai_addr);
+			m_addr.sadb_address_len = PFKEY_UNIT64(sizeof(m_addr) +
+			    PFKEY_ALIGN8(salen));
+			m_addr.sadb_address_exttype = SADB_EXT_ADDRESS_SRC;
+			m_addr.sadb_address_proto = IPSEC_ULPROTO_ANY;
+			m_addr.sadb_address_prefixlen = plen;
+			m_addr.sadb_address_reserved = 0;
+
+			setvarbuf(buf, &l, (struct sadb_ext *)&m_addr,
+			    sizeof(m_addr), sa, salen);
+
+			/* set dst */
+			sa = d->ai_addr;
+			salen = sysdep_sa_len(d->ai_addr);
+			m_addr.sadb_address_len = PFKEY_UNIT64(sizeof(m_addr) +
+			    PFKEY_ALIGN8(salen));
+			m_addr.sadb_address_exttype = SADB_EXT_ADDRESS_DST;
+			m_addr.sadb_address_proto = IPSEC_ULPROTO_ANY;
+			m_addr.sadb_address_prefixlen = plen;
+			m_addr.sadb_address_reserved = 0;
+
+			setvarbuf(buf, &l, (struct sadb_ext *)&m_addr,
+			    sizeof(m_addr), sa, salen);
+
+#ifdef SADB_X_EXT_NAT_T_TYPE
+			if (p_natt_type) {
+				struct sadb_x_nat_t_port natt_port;
+
+				/* NATT_SPORT */
+				len = sizeof(struct sadb_x_nat_t_port);
+				memset(&natt_port, 0, len);
+				natt_port.sadb_x_nat_t_port_len = PFKEY_UNIT64(len);
+				natt_port.sadb_x_nat_t_port_exttype =
+					SADB_X_EXT_NAT_T_SPORT;
+				natt_port.sadb_x_nat_t_port_port = htons(get_port(s));
+				
+				memcpy(buf + l, &natt_port, len);
+				l += len;
+
+				/* NATT_DPORT */
+				natt_port.sadb_x_nat_t_port_exttype =
+					SADB_X_EXT_NAT_T_DPORT;
+				natt_port.sadb_x_nat_t_port_port = htons(get_port(d));
+				
+				memcpy(buf + l, &natt_port, len);
+				l += len;
+			}
+#endif
+			msg->sadb_msg_len = PFKEY_UNIT64(l);
+
+			sendkeymsg(buf, l);
+
+			n++;
+		}
+	}
+
+	if (n == 0)
+		return -1;
+	else
+		return 0;
+}
+
+static struct addrinfo *
+parse_addr(host, port)
+	char *host;
+	char *port;
+{
+	struct addrinfo hints, *res = NULL;
+	int error;
+
+	memset(&hints, 0, sizeof(hints));
+	hints.ai_family = p_aifamily;
+	hints.ai_socktype = SOCK_DGRAM;		/*dummy*/
+	hints.ai_protocol = IPPROTO_UDP;	/*dummy*/
+	hints.ai_flags = p_aiflags;
+	error = getaddrinfo(host, port, &hints, &res);
+	if (error != 0) {
+		yyerror(gai_strerror(error));
+		return NULL;
+	}
+	return res;
+}
+
+static int
+fix_portstr(spec, sport, dport)
+	vchar_t *spec, *sport, *dport;
+{
+	const char *p, *p2 = "0";
+	char *q;
+	u_int l;
+
+	l = 0;
+	for (q = spec->buf; *q != ',' && *q != '\0' && l < spec->len; q++, l++)
+		;
+	if (*q != '\0') {
+		if (*q == ',') {
+			*q = '\0';
+			p2 = ++q;
+		}
+		for (p = p2; *p != '\0' && l < spec->len; p++, l++)
+			;
+		if (*p != '\0' || *p2 == '\0') {
+			yyerror("invalid an upper layer protocol spec");
+			return -1;
+		}
+	}
+
+	sport->buf = strdup(spec->buf);
+	if (!sport->buf) {
+		yyerror("insufficient memory");
+		return -1;
+	}
+	sport->len = strlen(sport->buf);
+	dport->buf = strdup(p2);
+	if (!dport->buf) {
+		yyerror("insufficient memory");
+		return -1;
+	}
+	dport->len = strlen(dport->buf);
+
+	return 0;
+}
+
+static int
+setvarbuf(buf, off, ebuf, elen, vbuf, vlen)
+	char *buf;
+	int *off;
+	struct sadb_ext *ebuf;
+	int elen;
+	const void *vbuf;
+	int vlen;
+{
+	memset(buf + *off, 0, PFKEY_UNUNIT64(ebuf->sadb_ext_len));
+	memcpy(buf + *off, (caddr_t)ebuf, elen);
+	memcpy(buf + *off + elen, vbuf, vlen);
+	(*off) += PFKEY_ALIGN8(elen + vlen);
+
+	return 0;
+}
+
+void
+parse_init()
+{
+	p_spi = 0;
+
+	p_ext = SADB_X_EXT_CYCSEQ;
+	p_alg_enc = SADB_EALG_NONE;
+	p_alg_auth = SADB_AALG_NONE;
+	p_mode = IPSEC_MODE_ANY;
+	p_reqid = 0;
+	p_replay = 0;
+	p_key_enc_len = p_key_auth_len = 0;
+	p_key_enc = p_key_auth = 0;
+	p_lt_hard = p_lt_soft = 0;
+	p_lb_hard = p_lb_soft = 0;
+
+	memset(&sec_ctx, 0, sizeof(struct security_ctx));
+
+	p_aiflags = 0;
+	p_aifamily = PF_UNSPEC;
+
+	/* Clear out any natt OA information */
+	if (p_natt_oa)
+		freeaddrinfo (p_natt_oa);
+	p_natt_oa = NULL;
+	p_natt_type = 0;
+
+	return;
+}
+
+void
+free_buffer()
+{
+	/* we got tons of memory leaks in the parser anyways, leave them */
+
+	return;
+}
diff --git a/src/setkey/sample-policy01.cf b/src/setkey/sample-policy01.cf
new file mode 100644
index 0000000..42c16b2
--- /dev/null
+++ b/src/setkey/sample-policy01.cf
@@ -0,0 +1,20 @@
+#
+# This is for basic policy test on loopback.
+#
+
+spdflush;
+spdadd 127.0.0.1 127.0.0.1 icmp
+	-P out ipsec
+	esp/transport//require ;
+spdadd ::1 ::1 icmp6
+	-P out ipsec
+	esp/transport//require ;
+
+flush;
+add 127.0.0.1 127.0.0.1 esp 0x1000
+	-m transport
+	-E des-cbc "kamekame";
+add ::1 ::1 esp 0x1001
+	-m transport
+	-E des-cbc "hagehage";
+flush;
diff --git a/src/setkey/sample-policy02.cf b/src/setkey/sample-policy02.cf
new file mode 100644
index 0000000..8c5134a
--- /dev/null
+++ b/src/setkey/sample-policy02.cf
@@ -0,0 +1,43 @@
+#
+# this is test configuration for unique policy on loopback.
+#
+
+spdflush;
+# connection to 9999 encrypted, reverse no encrypted.
+spdadd ::1 ::1[9999] tcp
+	-P out ipsec
+	esp/transport//unique:2 ;
+
+# Session encrypted.  Inbound policy check takes place non-strictly.
+spdadd ::1 ::1[9998] tcp
+	-P out ipsec
+	esp/transport//unique:1 ;
+spdadd ::1[9998] ::1 tcp
+	-P in ipsec
+	esp/transport//unique:2 ;
+spdadd ::1[9998] ::1 tcp
+	-P out ipsec
+	esp/transport//unique:1 ;
+
+# Cause new SA to be acquired.
+spdadd ::1 ::1[9997] tcp
+	-P out ipsec
+	esp/transport//unique ;
+
+# Used proper SA.
+spdadd ::1 ::1[9996] tcp
+	-P out ipsec
+	esp/transport//require ;
+
+# reqid will be updated by kernel.
+spdadd ::1 ::1[9995] tcp
+	-P out ipsec
+	esp/transport//unique:28000 ;
+
+flush;
+add ::1 ::1 esp 0x1001
+	-u 1
+	-E des-cbc "kamekame";
+add ::1 ::1 esp 0x1002
+	-u 2
+	-E des-cbc "hogehoge";
diff --git a/src/setkey/sample.cf b/src/setkey/sample.cf
new file mode 100644
index 0000000..c64fd36
--- /dev/null
+++ b/src/setkey/sample.cf
@@ -0,0 +1,217 @@
+# Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project.
+# All rights reserved.
+# 
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+# 3. Neither the name of the project nor the names of its contributors
+#    may be used to endorse or promote products derived from this software
+#    without specific prior written permission.
+# 
+# THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+
+# There are sample scripts for IPsec configuration by manual keying.
+# A security association is uniquely identified by a triple consisting
+# of a Security Parameter Index (SPI), an IP Destination Address, and a
+# security protocol (AH or ESP) identifier.  You must take care of these
+# parameters when you configure by manual keying.
+
+# ESP transport mode is recommended for TCP port number 110 between
+# Host-A and Host-B. Encryption algorithm is blowfish-cbc whose key
+# is "kamekame", and authentication algorithm is hmac-sha1 whose key
+# is "this is the test key".
+#
+#       ============ ESP ============
+#       |                           |
+#    Host-A                        Host-B
+#   fec0::10 -------------------- fec0::11
+#
+# At Host-A and Host-B,
+spdadd fec0::10[any] fec0::11[110] tcp -P out ipsec
+	esp/transport//use ;
+spdadd fec0::11[110] fec0::10[any] tcp -P in ipsec
+	esp/transport//use ;
+add fec0::10 fec0::11 esp 0x10001
+	-m transport
+	-E blowfish-cbc "kamekame"
+	-A hmac-sha1 "this is the test key" ;
+add fec0::11 fec0::10 esp 0x10002
+	-m transport
+	-E blowfish-cbc "kamekame"
+	-A hmac-sha1 "this is the test key" ;
+
+# "[any]" is wildcard of port number.  Note that "[0]" is the number of
+# zero in port number.
+
+# Security protocol is old AH tunnel mode, i.e. RFC1826, with keyed-md5
+# whose key is "this is the test" as authentication algorithm.
+# That protocol takes place between Gateway-A and Gateway-B.
+#
+#                        ======= AH =======
+#                        |                |
+#    Network-A       Gateway-A        Gateway-B        Network-B
+#   10.0.1.0/24 ---- 172.16.0.1 ----- 172.16.0.2 ---- 10.0.2.0/24
+#
+# At Gateway-A:
+spdadd 10.0.1.0/24 10.0.2.0/24 any -P out ipsec
+	ah/tunnel/172.16.0.1-172.16.0.2/require ;
+spdadd 10.0.2.0/24 10.0.1.0/24 any -P in ipsec
+	ah/tunnel/172.16.0.2-172.16.0.1/require ;
+add 172.16.0.1 172.16.0.2 ah-old 0x10003
+	-m any
+	-A keyed-md5 "this is the test" ;
+add 172.16.0.2 172.16.0.1 ah-old 0x10004
+	-m any
+	-A keyed-md5 "this is the test" ;
+
+# If port number field is omitted such above then "[any]" is employed.
+# -m specifies the mode of SA to be used.  "-m any" means wildcard of
+# mode of security protocol.  You can use this SAs for both tunnel and
+# transport mode.
+
+# At Gateway-B.  Attention to the selector and peer's IP address for tunnel.
+spdadd 10.0.2.0/24 10.0.1.0/24 any -P out ipsec
+	ah/tunnel/172.16.0.2-172.16.0.1/require ;
+spdadd 10.0.1.0/24 10.0.2.0/24 any -P in ipsec
+	ah/tunnel/172.16.0.1-172.16.0.2/require ;
+add 172.16.0.1 172.16.0.2 ah-old 0x10003
+	-m tunnel
+	-A keyed-md5 "this is the test" ;
+add 172.16.0.2 172.16.0.1 ah-old 0x10004
+	-m tunnel
+	-A keyed-md5 "this is the test" ;
+
+# AH transport mode followed by ESP tunnel mode is required between
+# Gateway-A and Gateway-B.
+# Encryption algorithm is 3des-cbc, and authentication algorithm for ESP
+# is hmac-sha1.  Authentication algorithm for AH is hmac-md5.
+#
+#                           ========== AH =========
+#                           |  ======= ESP =====  |
+#                           |  |               |  |
+#      Network-A          Gateway-A        Gateway-B           Network-B
+#   fec0:0:0:1::/64 --- fec0:0:0:1::1 ---- fec0:0:0:2::1 --- fec0:0:0:2::/64
+#
+# At Gateway-A:
+spdadd fec0:0:0:1::/64 fec0:0:0:2::/64 any -P out ipsec
+	esp/tunnel/fec0:0:0:1::1-fec0:0:0:2::1/require
+	ah/transport//require ;
+spdadd fec0:0:0:2::/64 fec0:0:0:1::/64 any -P in ipsec
+	esp/tunnel/fec0:0:0:2::1-fec0:0:0:1::1/require
+	ah/transport//require ;
+add fec0:0:0:1::1 fec0:0:0:2::1 esp 0x10001
+	-m tunnel
+	-E 3des-cbc "kamekame12341234kame1234"
+	-A hmac-sha1 "this is the test key" ;
+add fec0:0:0:1::1 fec0:0:0:2::1 ah 0x10001
+	-m transport
+	-A hmac-md5 "this is the test" ;
+add fec0:0:0:2::1 fec0:0:0:1::1 esp 0x10001
+	-m tunnel
+	-E 3des-cbc "kamekame12341234kame1234"
+	-A hmac-sha1 "this is the test key" ;
+add fec0:0:0:2::1 fec0:0:0:1::1 ah 0x10001
+	-m transport
+	-A hmac-md5 "this is the test" ;
+
+# ESP tunnel mode is required between Host-A and Gateway-A.
+# Encryption algorithm is cast128-cbc, and authentication algorithm
+# for ESP is hmac-sha1.
+# ESP transport mode is recommended between Host-A and Host-B.
+# Encryption algorithm is rc5-cbc,  and authentication algorithm
+# for ESP is hmac-md5.
+#
+#       ================== ESP =================
+#       |  ======= ESP =======                 |
+#       |  |                 |                 |
+#      Host-A            Gateway-A           Host-B
+#   fec0:0:0:1::1 ---- fec0:0:0:2::1 ---- fec0:0:0:2::2
+#
+# At Host-A:
+spdadd fec0:0:0:1::1[any] fec0:0:0:2::2[80] tcp -P out ipsec
+	esp/transport//use
+	esp/tunnel/fec0:0:0:1::1-fec0:0:0:2::1/require ;
+spdadd fec0:0:0:2::1[80] fec0:0:0:1::1[any] tcp -P in ipsec
+	esp/transport//use
+	esp/tunnel/fec0:0:0:2::1-fec0:0:0:1::1/require ;
+add fec0:0:0:1::1 fec0:0:0:2::2 esp 0x10001
+	-m transport
+	-E cast128-cbc "12341234"
+	-A hmac-sha1 "this is the test key" ;
+add fec0:0:0:1::1 fec0:0:0:2::1 esp 0x10002
+	-E rc5-cbc "kamekame"
+	-A hmac-md5 "this is the test" ;
+add fec0:0:0:2::2 fec0:0:0:1::1 esp 0x10003
+	-m transport
+	-E cast128-cbc "12341234"
+	-A hmac-sha1 "this is the test key" ;
+add fec0:0:0:2::1 fec0:0:0:1::1 esp 0x10004
+	-E rc5-cbc "kamekame"
+	-A hmac-md5 "this is the test" ;
+
+# By "get" command, you can get a entry of either SP or SA.
+get fec0:0:0:1::1 fec0:0:0:2::2 ah 0x10004 ;
+
+# Also delete command, you can delete a entry of either SP or SA.
+spddelete fec0:0:0:1::/64 fec0:0:0:2::/64 any -P out;
+delete fec0:0:0:1::1 fec0:0:0:2::2 ah 0x10004 ;
+
+# By dump command, you can dump all entry of either SP or SA.
+dump ;
+spddump ;
+dump esp ;
+flush esp ;
+
+# By flush command, you can flush all entry of either SP or SA.
+flush ;
+spdflush ;
+
+# "flush" and "dump" commands can specify a security protocol.
+dump esp ;
+flush ah ;
+
+# XXX
+add ::1 ::1 esp 10001 -m transport -E null ;
+add ::1 ::1 esp 10002 -m transport -E des-deriv "12341234" ;
+add ::1 ::1 esp-old 10003 -m transport -E des-32iv "12341234" ;
+add ::1 ::1 esp 10004 -m transport -E null -A null ;
+add ::1 ::1 esp 10005 -m transport -E null -A hmac-md5 "1234123412341234" ;
+add ::1 ::1 esp 10006 -m tunnel -E null -A hmac-sha1 "12341234123412341234" ;
+add ::1 ::1 esp 10007 -m transport -E null -A keyed-md5 "1234123412341234" ;
+add ::1 ::1 esp 10008 -m any -E null -A keyed-sha1 "12341234123412341234" ;
+add ::1 ::1 esp 10009 -m transport -E des-cbc "testtest" ;
+add ::1 ::1 esp 10010 -m transport -E 3des-cbc "testtest12341234testtest" ;
+add ::1 ::1 esp 10011 -m tunnel -E cast128-cbc "testtest1234" ;
+add ::1 ::1 esp 10012 -m tunnel -E blowfish-cbc "testtest1234" ;
+add ::1 ::1 esp 10013 -m tunnel -E rc5-cbc "testtest1234" ;
+add ::1 ::1 esp 10014 -m any -E rc5-cbc "testtest1234" ;
+add ::1 ::1 esp 10015 -m transport -f zero-pad -E null ;
+add ::1 ::1 esp 10016 -m tunnel -f random-pad -r 8 -lh 100 -ls 80 -E null ;
+add ::1 ::1 esp 10017 -m transport -f seq-pad -f nocyclic-seq -E null ;
+add ::1 ::1 esp 10018 -m transport -E null ;
+#add ::1 ::1 ah 20000 -m transport -A null ;
+add ::1 ::1 ah 20001 -m any -A hmac-md5 "1234123412341234";
+add ::1 ::1 ah 20002 -m tunnel -A hmac-sha1 "12341234123412341234";
+add ::1 ::1 ah 20003 -m transport -A keyed-md5 "1234123412341234";
+add ::1 ::1 ah-old 20004 -m transport -A keyed-md5 "1234123412341234";
+add ::1 ::1 ah 20005 -m transport -A keyed-sha1 "12341234123412341234";
+#add ::1 ::1 ipcomp 30000 -C oui ;
+add ::1 ::1 ipcomp 30001 -C deflate ;
+#add ::1 ::1 ipcomp 30002 -C lzs ;
+
+# enjoy.
diff --git a/src/setkey/scriptdump.pl b/src/setkey/scriptdump.pl
new file mode 100644
index 0000000..f5b9f25
--- /dev/null
+++ b/src/setkey/scriptdump.pl
@@ -0,0 +1,55 @@
+#! @LOCALPREFIX@/bin/perl
+
+if ($< != 0) {
+	print STDERR "must be root to invoke this\n";
+	exit 1;
+}
+
+$mode = 'add';
+while ($i = shift @ARGV) {
+	if ($i eq '-d') {
+		$mode = 'delete';
+	} else {
+		print STDERR "usage: scriptdump [-d]\n";
+		exit 1;
+	}
+}
+
+open(IN, "setkey -D |") || die;
+foreach $_ (<IN>) {
+	if (/^[^\t]/) {
+		($src, $dst) = split(/\s+/, $_);
+	} elsif (/^\t(esp|ah) mode=(\S+) spi=(\d+).*reqid=(\d+)/) {
+		($proto, $ipsecmode, $spi, $reqid) = ($1, $2, $3, $4);
+	} elsif (/^\tE: (\S+) (.*)/) {
+		$ealgo = $1;
+		$ekey = $2;
+		$ekey =~ s/\s//g;
+		$ekey =~ s/^/0x/g;
+	} elsif (/^\tA: (\S+) (.*)/) {
+		$aalgo = $1;
+		$akey = $2;
+		$akey =~ s/\s//g;
+		$akey =~ s/^/0x/g;
+	} elsif (/^\tseq=(0x\d+) replay=(\d+) flags=(0x\d+) state=/) {
+		print "$mode $src $dst $proto $spi";
+		$replay = $2;
+		print " -u $reqid" if $reqid;
+		if ($mode eq 'add') {
+			print " -m $ipsecmode -r $replay" if $replay;
+			if ($proto eq 'esp') {
+				print " -E $ealgo $ekey" if $ealgo;
+				print " -A $aalgo $akey" if $aalgo;
+			} elsif ($proto eq 'ah') {
+				print " -A $aalgo $akey" if $aalgo;
+			}
+		} 
+		print ";\n";
+
+		$src = $dst = $upper = $proxy = '';
+		$ealgo = $ekey = $aalgo = $akey = '';
+	}
+}
+close(IN);
+
+exit 0;
diff --git a/src/setkey/setkey.8 b/src/setkey/setkey.8
new file mode 100644
index 0000000..845015d
--- /dev/null
+++ b/src/setkey/setkey.8
@@ -0,0 +1,872 @@
+.\"	$NetBSD: setkey.8,v 1.20 2006/10/06 12:02:27 manu Exp $
+.\"
+.\" Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project.
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\" 3. Neither the name of the project nor the names of its contributors
+.\"    may be used to endorse or promote products derived from this software
+.\"    without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.Dd March 19, 2004
+.Dt SETKEY 8
+.Os
+.\"
+.Sh NAME
+.Nm setkey
+.Nd manually manipulate the IPsec SA/SP database
+.\"
+.Sh SYNOPSIS
+.Nm setkey
+.Op Fl knrv
+.Ar file ...
+.Nm setkey
+.Op Fl knrv
+.Fl c
+.Nm setkey
+.Op Fl krv
+.Fl f Ar filename
+.Nm setkey
+.Op Fl aklPrv
+.Fl D
+.Nm setkey
+.Op Fl Pvp
+.Fl F
+.Nm setkey
+.Op Fl H
+.Fl x
+.Nm setkey
+.Op Fl ?V
+.\"
+.Sh DESCRIPTION
+.Nm
+adds, updates, dumps, or flushes
+Security Association Database (SAD) entries
+as well as Security Policy Database (SPD) entries in the kernel.
+.Pp
+.Nm
+takes a series of operations from standard input
+.Po
+if invoked with
+.Fl c
+.Pc
+or the file named
+.Ar filename
+.Po
+if invoked with
+.Fl f Ar filename
+.Pc .
+.Bl -tag -width Ds
+.It (no flag)
+Dump the SAD entries or SPD entries contained in the specified
+.Ar file .
+.It Fl ?
+Print short help.
+.It Fl a
+.Nm
+usually does not display dead SAD entries with
+.Fl D .
+If
+.Fl a
+is also specified, the dead SAD entries will be displayed as well.
+A dead SAD entry is one that has expired but remains in the
+system because it is referenced by some SPD entries.
+.It Fl D
+Dump the SAD entries.
+If
+.Fl P
+is also specified, the SPD entries are dumped.
+If
+.Fl p
+is specified, the ports are displayed.
+.It Fl F
+Flush the SAD entries.
+If
+.Fl P
+is also specified, the SPD entries are flushed.
+.It Fl H
+Add hexadecimal dump in
+.Fl x
+mode.
+.It Fl h
+On
+.Nx ,
+synonym for
+.Fl H .
+On other systems, synonym for
+.Fl ? .
+.It Fl k
+Use semantics used in kernel.
+Available only in Linux.
+See also
+.Fl r .
+.It Fl l
+Loop forever with short output on
+.Fl D .
+.It Fl n
+No action.
+The program will check validity of the input, but no changes to
+the SPD will be made.
+.It Fl r
+Use semantics described in IPsec RFCs.
+This mode is default.
+For details see section
+.Sx RFC vs Linux kernel semantics .
+Available only in Linux.
+See also
+.Fl k .
+.It Fl x
+Loop forever and dump all the messages transmitted to the
+.Dv PF_KEY
+socket.
+.Fl xx
+prints the unformatted timestamps.
+.It Fl V
+Print version string.
+.It Fl v
+Be verbose.
+The program will dump messages exchanged on the
+.Dv PF_KEY
+socket, including messages sent from other processes to the kernel.
+.El
+.Ss Configuration syntax
+With
+.Fl c
+or
+.Fl f
+on the command line,
+.Nm
+accepts the following configuration syntax.
+Lines starting with hash signs
+.Pq Sq #
+are treated as comment lines.
+.Bl -tag -width Ds
+.It Xo
+.Li add
+.Op Fl 46n
+.Ar src Ar dst Ar protocol Ar spi
+.Op Ar extensions
+.Ar algorithm ...
+.Li ;
+.Xc
+Add an SAD entry.
+.Li add
+can fail for multiple reasons, including when the key length does
+not match the specified algorithm.
+.\"
+.It Xo
+.Li get
+.Op Fl 46n
+.Ar src Ar dst Ar protocol Ar spi
+.Li ;
+.Xc
+Show an SAD entry.
+.\"
+.It Xo
+.Li delete
+.Op Fl 46n
+.Ar src Ar dst Ar protocol Ar spi
+.Li ;
+.Xc
+Remove an SAD entry.
+.\"
+.It Xo
+.Li deleteall
+.Op Fl 46n
+.Ar src Ar dst Ar protocol
+.Li ;
+.Xc
+Remove all SAD entries that match the specification.
+.\"
+.It Xo
+.Li flush
+.Op Ar protocol
+.Li ;
+.Xc
+Clear all SAD entries matched by the options.
+.Fl F
+on the command line achieves the same functionality.
+.\"
+.It Xo
+.Li dump
+.Op Ar protocol
+.Li ;
+.Xc
+Dumps all SAD entries matched by the options.
+.Fl D
+on the command line achieves the same functionality.
+.\"
+.It Xo
+.Li spdadd
+.Op Fl 46n
+.Ar src_range Ar dst_range Ar upperspec Ar label Ar policy
+.Li ;
+.Xc
+Add an SPD entry.
+.\"
+.It Xo
+.Li spdadd tagged
+.Ar tag Ar policy
+.Li ;
+.Xc
+Add an SPD entry based on a PF tag.
+.Ar tag
+must be a string surrounded by double quotes.
+.\"
+.It Xo
+.Li spddelete
+.Op Fl 46n
+.Ar src_range Ar dst_range Ar upperspec Fl P Ar direction
+.Li ;
+.Xc
+Delete an SPD entry.
+.\"
+.It Xo
+.Li spdflush
+.Li ;
+.Xc
+Clear all SPD entries.
+.Fl FP
+on the command line achieves the same functionality.
+.\"
+.It Xo
+.Li spddump
+.Li ;
+.Xc
+Dumps all SPD entries.
+.Fl DP
+on the command line achieves the same functionality.
+.El
+.\"
+.Pp
+Meta-arguments are as follows:
+.Pp
+.Bl -tag -compact -width Ds
+.It Ar src
+.It Ar dst
+Source/destination of the secure communication is specified as
+an IPv4/v6 address, and an optional port number between square
+brackets.
+.Nm
+can resolve a FQDN into numeric addresses.
+If the FQDN resolves into multiple addresses,
+.Nm
+will install multiple SAD/SPD entries into the kernel
+by trying all possible combinations.
+.Fl 4 ,
+.Fl 6 ,
+and
+.Fl n
+restrict the address resolution of FQDN in certain ways.
+.Fl 4
+and
+.Fl 6
+restrict results into IPv4/v6 addresses only, respectively.
+.Fl n
+avoids FQDN resolution and requires addresses to be numeric addresses.
+.\"
+.Pp
+.It Ar protocol
+.Ar protocol
+is one of following:
+.Bl -tag -width Fl -compact
+.It Li esp
+ESP based on rfc2406
+.It Li esp-old
+ESP based on rfc1827
+.It Li ah
+AH based on rfc2402
+.It Li ah-old
+AH based on rfc1826
+.It Li ipcomp
+IPComp
+.It Li tcp
+TCP-MD5 based on rfc2385
+.El
+.\"
+.Pp
+.It Ar spi
+Security Parameter Index
+.Pq SPI
+for the SAD and the SPD.
+.Ar spi
+must be a decimal number, or a hexadecimal number with a
+.Dq Li 0x
+prefix.
+SPI values between 0 and 255 are reserved for future use by IANA
+and cannot be used.
+TCP-MD5 associations must use 0x1000 and therefore only have per-host
+granularity at this time.
+.\"
+.Pp
+.It Ar extensions
+take some of the following:
+.Bl -tag -width Fl -compact
+.\"
+.It Fl m Ar mode
+Specify a security protocol mode for use.
+.Ar mode
+is one of following:
+.Li transport , tunnel ,
+or
+.Li any .
+The default value is
+.Li any .
+.\"
+.It Fl r Ar size
+Specify window size of bytes for replay prevention.
+.Ar size
+must be decimal number in 32-bit word.
+If
+.Ar size
+is zero or not specified, replay checks don't take place.
+.\"
+.It Fl u Ar id
+Specify the identifier of the policy entry in the SPD.
+See
+.Ar policy .
+.\"
+.It Fl f Ar pad_option
+defines the content of the ESP padding.
+.Ar pad_option
+is one of following:
+.Bl -tag -width random-pad -compact
+.It Li zero-pad
+All the paddings are zero.
+.It Li random-pad
+A series of randomized values are used.
+.It Li seq-pad
+A series of sequential increasing numbers started from 1 are used.
+.El
+.\"
+.It Fl f Li nocyclic-seq
+Don't allow cyclic sequence numbers.
+.\"
+.It Fl lh Ar time
+.It Fl ls Ar time
+Specify hard/soft life time duration of the SA measured in seconds.
+.\"
+.It Fl bh Ar bytes
+.It Fl bs Ar bytes
+Specify hard/soft life time duration of the SA measured in bytes transported.
+.\"
+.It Fl ctx Ar doi Ar algorithm Ar context-name
+Specify an access control label. The access control label is interpreted 
+by the LSM (e.g., SELinux). Ultimately, it enables MAC on network 
+communications. 
+.Bl -tag -width Fl -compact
+.It Ar doi
+The domain of interpretation, which is used by the
+IKE daemon to identify the domain in which negotiation takes place. 
+.It Ar algorithm
+Indicates the LSM for which the label is generated (e.g., SELinux).
+.It Ar context-name 
+The string representation of the label that is interpreted by the LSM.
+.El
+.El
+.\"
+.Pp
+.It Ar algorithm
+.Bl -tag -width Fl -compact
+.It Fl E Ar ealgo Ar key
+Specify an encryption algorithm
+.Ar ealgo
+for ESP.
+.It Xo
+.Fl E Ar ealgo Ar key
+.Fl A Ar aalgo Ar key
+.Xc
+Specify an encryption algorithm
+.Ar ealgo ,
+as well as a payload authentication algorithm
+.Ar aalgo ,
+for ESP.
+.It Fl A Ar aalgo Ar key
+Specify an authentication algorithm for AH.
+.It Fl C Ar calgo Op Fl R
+Specify a compression algorithm for IPComp.
+If
+.Fl R
+is specified, the
+.Ar spi
+field value will be used as the IPComp CPI
+.Pq compression parameter index
+on wire as-is.
+If
+.Fl R
+is not specified,
+the kernel will use well-known CPI on wire, and
+.Ar spi
+field will be used only as an index for kernel internal usage.
+.El
+.Pp
+.Ar key
+must be a double-quoted character string, or a series of hexadecimal
+digits preceded by
+.Dq Li 0x .
+.Pp
+Possible values for
+.Ar ealgo ,
+.Ar aalgo ,
+and
+.Ar calgo
+are specified in the
+.Sx Algorithms
+sections.
+.\"
+.Pp
+.It Ar src_range
+.It Ar dst_range
+These select the communications that should be secured by IPsec.
+They can be an IPv4/v6 address or an IPv4/v6 address range, and
+may be accompanied by a TCP/UDP port specification.
+This takes the following form:
+.Bd -literal -offset
+.Ar address
+.Ar address/prefixlen
+.Ar address[port]
+.Ar address/prefixlen[port]
+.Ed
+.Pp
+.Ar prefixlen
+and
+.Ar port
+must be decimal numbers.
+The square brackets around
+.Ar port
+are really necessary,
+they are not man page meta-characters.
+For FQDN resolution, the rules applicable to
+.Ar src
+and
+.Ar dst
+apply here as well.
+.\"
+.Pp
+.It Ar upperspec
+Upper-layer protocol to be used.
+You can use one of the words in
+.Pa /etc/protocols
+as
+.Ar upperspec ,
+or
+.Li icmp6 ,
+.Li ip4 ,
+or
+.Li any .
+.Li any
+stands for
+.Dq any protocol .
+You can also use the protocol number.
+You can specify a type and/or a code of ICMPv6 when the
+upper-layer protocol is ICMPv6.
+The specification can be placed after
+.Li icmp6 .
+A type is separated from a code by single comma.
+A code must always be specified.
+When a zero is specified, the kernel deals with it as a wildcard.
+Note that the kernel can not distinguish a wildcard from an ICPMv6
+type of zero.
+For example, the following means that the policy doesn't require IPsec
+for any inbound Neighbor Solicitation.
+.Dl spdadd ::/0 ::/0 icmp6 135,0 -P in none ;
+.Pp
+.Em Note :
+.Ar upperspec
+does not work against forwarding case at this moment,
+as it requires extra reassembly at the forwarding node
+.Pq not implemented at this moment .
+There are many protocols in
+.Pa /etc/protocols ,
+but all protocols except of TCP, UDP, and ICMP may not be suitable
+to use with IPsec.
+You have to consider carefully what to use.
+.\"
+.Pp
+.It Ar label
+.Ar label 
+is the access control label for the policy. This label is interpreted
+by the LSM (e.g., SELinux). Ultimately, it enables MAC on network
+communications. When a policy contains an access control label, SAs
+negotiated with this policy will contain the label. It's format:
+.Bl -tag -width Fl -compact
+.\"
+.It Fl ctx Ar doi Ar algorithm Ar context-name
+.Bl -tag -width Fl -compact
+.It Ar doi
+The domain of interpretation, which is used by the
+IKE daemon to identify the domain in which negotiation takes place.
+.It Ar algorithm
+Indicates the LSM for which the label is generated (e.g., SELinux).
+.It Ar context-name
+The string representation of the label that is interpreted by the LSM.
+.El
+.El
+.\"
+.Pp
+.It Ar policy
+.Ar policy
+is in one of the following three formats:
+.Bd -literal -offset indent
+.It Fl P Ar direction [priority specification] Li discard
+.It Fl P Ar direction [priority specification] Li none
+.It Xo Fl P Ar direction [priority specification] Li ipsec
+.Ar protocol/mode/src-dst/level Op ...
+.Xc
+.Ed
+.Pp
+You must specify the direction of its policy as
+.Ar direction .
+Either
+.Ar out ,
+.Ar in ,
+or
+.Ar fwd
+can be used.
+.Pp
+.Ar priority specification
+is used to control the placement of the policy within the SPD.
+Policy position is determined by
+a signed integer where higher priorities indicate the policy is placed
+closer to the beginning of the list and lower priorities indicate the
+policy is placed closer to the end of the list.
+Policies with equal priorities are added at the end of groups
+of such policies.
+.Pp
+Priority can only
+be specified when setkey has been compiled against kernel headers that
+support policy priorities (Linux \*[Gt]= 2.6.6).
+If the kernel does not support priorities, a warning message will
+be printed the first time a priority specification is used.
+Policy priority takes one of the following formats:
+.Bl -tag  -width "discard"
+.It Xo
+.Ar {priority,prio} offset
+.Xc
+.Ar offset
+is an integer in the range from \-2147483647 to 214783648.
+.It Xo
+.Ar {priority,prio} base {+,\-} offset
+.Xc
+.Ar base
+is either
+.Li low (\-1073741824) ,
+.Li def (0) ,
+or
+.Li high (1073741824)
+.Pp
+.Ar offset
+is an unsigned integer.
+It can be up to 1073741824 for
+positive offsets, and up to 1073741823 for negative offsets.
+.El
+.Pp
+.Li discard
+means the packet matching indexes will be discarded.
+.Li none
+means that IPsec operation will not take place onto the packet.
+.Li ipsec
+means that IPsec operation will take place onto the packet.
+.Pp
+The
+.Ar protocol/mode/src-dst/level
+part specifies the rule how to process the packet.
+Either
+.Li ah ,
+.Li esp ,
+or
+.Li ipcomp
+must be used as
+.Ar protocol .
+.Ar mode
+is either
+.Li transport
+or
+.Li tunnel .
+If
+.Ar mode
+is
+.Li tunnel ,
+you must specify the end-point addresses of the SA as
+.Ar src
+and
+.Ar dst
+with
+.Sq -
+between these addresses, which is used to specify the SA to use.
+If
+.Ar mode
+is
+.Li transport ,
+both
+.Ar src
+and
+.Ar dst
+can be omitted.
+.Ar level
+is to be one of the following:
+.Li default , use , require ,
+or
+.Li unique .
+If the SA is not available in every level, the kernel will
+ask the key exchange daemon to establish a suitable SA.
+.Li default
+means the kernel consults the system wide default for the protocol
+you specified, e.g. the
+.Li esp_trans_deflev
+sysctl variable, when the kernel processes the packet.
+.Li use
+means that the kernel uses an SA if it's available,
+otherwise the kernel keeps normal operation.
+.Li require
+means SA is required whenever the kernel sends a packet matched
+with the policy.
+.Li unique
+is the same as
+.Li require ;
+in addition, it allows the policy to match the unique out-bound SA.
+You just specify the policy level
+.Li unique ,
+.Xr racoon 8
+will configure the SA for the policy.
+If you configure the SA by manual keying for that policy,
+you can put a decimal number as the policy identifier after
+.Li unique
+separated by a colon
+.Sq \&:
+like:
+.Li unique:number
+in order to bind this policy to the SA.
+.Li number
+must be between 1 and 32767.
+It corresponds to
+.Ar extensions Fl u
+of the manual SA configuration.
+When you want to use SA bundle, you can define multiple rules.
+For example, if an IP header was followed by an AH header followed
+by an ESP header followed by an upper layer protocol header, the
+rule would be:
+.Dl esp/transport//require ah/transport//require ;
+The rule order is very important.
+.Pp
+When NAT-T is enabled in the kernel, policy matching for ESP over
+UDP packets may be done on endpoint addresses and port
+(this depends on the system.
+System that do not perform the port check cannot support
+multiple endpoints behind the same NAT).
+When using ESP over UDP, you can specify port numbers in the endpoint
+addresses to get the correct matching.
+Here is an example:
+.Bd -literal -offset
+spdadd 10.0.11.0/24[any] 10.0.11.33/32[any] any -P out ipsec
+    esp/tunnel/192.168.0.1[4500]-192.168.1.2[30000]/require ;
+
+.Ed
+These ports must be left unspecified (which defaults to 0) for
+anything other than ESP over UDP.
+They can be displayed in SPD dump using
+.Nm
+.Fl DPp .
+.Pp
+Note that
+.Dq Li discard
+and
+.Dq Li none
+are not in the syntax described in
+.Xr ipsec_set_policy 3 .
+There are a few differences in the syntax.
+See
+.Xr ipsec_set_policy 3
+for detail.
+.El
+.\"
+.Ss Algorithms
+The following list shows the supported algorithms.
+.Sy protocol
+and
+.Sy algorithm
+are almost orthogonal.
+These authentication algorithms can be used as
+.Ar aalgo
+in
+.Fl A Ar aalgo
+of the
+.Ar protocol
+parameter:
+.Pp
+.Bd -literal -offset indent
+algorithm	keylen (bits)
+hmac-md5	128		ah: rfc2403
+		128		ah-old: rfc2085
+hmac-sha1	160		ah: rfc2404
+		160		ah-old: 128bit ICV (no document)
+keyed-md5	128		ah: 96bit ICV (no document)
+		128		ah-old: rfc1828
+keyed-sha1	160		ah: 96bit ICV (no document)
+		160		ah-old: 128bit ICV (no document)
+null		0 to 2048	for debugging
+hmac-sha256	256		ah: 96bit ICV
+				(draft-ietf-ipsec-ciph-sha-256-00)
+		256		ah-old: 128bit ICV (no document)
+hmac-sha384	384		ah: 96bit ICV (no document)
+		384		ah-old: 128bit ICV (no document)
+hmac-sha512	512		ah: 96bit ICV (no document)
+		512		ah-old: 128bit ICV (no document)
+hmac-ripemd160	160		ah: 96bit ICV (RFC2857)
+				ah-old: 128bit ICV (no document)
+aes-xcbc-mac	128		ah: 96bit ICV (RFC3566)
+		128		ah-old: 128bit ICV (no document)
+tcp-md5		8 to 640	tcp: rfc2385
+.Ed
+.Pp
+These encryption algorithms can be used as
+.Ar ealgo
+in
+.Fl E Ar ealgo
+of the
+.Ar protocol
+parameter:
+.Pp
+.Bd -literal -offset indent
+algorithm	keylen (bits)
+des-cbc		64		esp-old: rfc1829, esp: rfc2405
+3des-cbc	192		rfc2451
+null		0 to 2048	rfc2410
+blowfish-cbc	40 to 448	rfc2451
+cast128-cbc	40 to 128	rfc2451
+des-deriv	64		ipsec-ciph-des-derived-01
+3des-deriv	192		no document
+rijndael-cbc	128/192/256	rfc3602
+twofish-cbc	0 to 256	draft-ietf-ipsec-ciph-aes-cbc-01
+aes-ctr		160/224/288	draft-ietf-ipsec-ciph-aes-ctr-03
+camellia-cbc	128/192/256	rfc4312
+.Ed
+.Pp
+Note that the first 128 bits of a key for
+.Li aes-ctr
+will be used as AES key, and the remaining 32 bits will be used as nonce.
+.Pp
+These compression algorithms can be used as
+.Ar calgo
+in
+.Fl C Ar calgo
+of the
+.Ar protocol
+parameter:
+.Pp
+.Bd -literal -offset indent
+algorithm
+deflate		rfc2394
+.Ed
+.\"
+.Ss RFC vs Linux kernel semantics
+The Linux kernel uses the
+.Ar fwd
+policy instead of the
+.Ar in
+policy for packets what are forwarded through that particular box.
+.Pp
+In
+.Ar kernel
+mode,
+.Nm
+manages and shows policies and SAs exactly as they are stored in the kernel.
+.Pp
+In
+.Ar RFC
+mode,
+.Nm
+.Bl -item
+.It
+creates
+.Ar fwd
+policies for every
+.Ar in
+policy inserted
+.It
+(not implemented yet) filters out all
+.Ar fwd
+policies
+.El
+.Sh RETURN VALUES
+The command exits with 0 on success, and non-zero on errors.
+.\"
+.Sh EXAMPLES
+.Bd -literal -offset
+add 3ffe:501:4819::1 3ffe:501:481d::1 esp 123457
+	-E des-cbc 0x3ffe05014819ffff ;
+
+add -6 myhost.example.com yourhost.example.com ah 123456
+	-A hmac-sha1 "AH SA configuration!" ;
+
+add 10.0.11.41 10.0.11.33 esp 0x10001
+	-E des-cbc 0x3ffe05014819ffff
+	-A hmac-md5 "authentication!!" ;
+
+get 3ffe:501:4819::1 3ffe:501:481d::1 ah 123456 ;
+
+flush ;
+
+dump esp ;
+
+spdadd 10.0.11.41/32[21] 10.0.11.33/32[any] any
+	-P out ipsec esp/tunnel/192.168.0.1-192.168.1.2/require ;
+
+add 10.1.10.34 10.1.10.36 tcp 0x1000 -A tcp-md5 "TCP-MD5 BGP secret" ;
+
+add 10.0.11.41 10.0.11.33 esp 0x10001
+	-ctx 1 1 "system_u:system_r:unconfined_t:SystemLow-SystemHigh"
+	-E des-cbc 0x3ffe05014819ffff;
+
+spdadd 10.0.11.41 10.0.11.33 any
+	-ctx 1 1 "system_u:system_r:unconfined_t:SystemLow-SystemHigh"
+	-P out ipsec esp/transport//require ;
+.Ed
+.\"
+.Sh SEE ALSO
+.Xr ipsec_set_policy 3 ,
+.Xr racoon 8 ,
+.Xr sysctl 8
+.Rs
+.%T "Changed manual key configuration for IPsec"
+.%O "http://www.kame.net/newsletter/19991007/"
+.%D "October 1999"
+.Re
+.\"
+.Sh HISTORY
+The
+.Nm
+command first appeared in the WIDE Hydrangea IPv6 protocol stack
+kit.
+The command was completely re-designed in June 1998.
+.\"
+.Sh BUGS
+.Nm
+should report and handle syntax errors better.
+.Pp
+For IPsec gateway configuration,
+.Ar src_range
+and
+.Ar dst_range
+with TCP/UDP port numbers does not work, as the gateway does not
+reassemble packets
+.Pq it cannot inspect upper-layer headers .
diff --git a/src/setkey/setkey.c b/src/setkey/setkey.c
new file mode 100644
index 0000000..8f42019
--- /dev/null
+++ b/src/setkey/setkey.c
@@ -0,0 +1,922 @@
+/*	$NetBSD: setkey.c,v 1.11.6.1 2007/08/01 11:52:23 vanhu Exp $	*/
+
+/*	$KAME: setkey.c,v 1.36 2003/09/24 23:52:51 itojun Exp $	*/
+
+/*
+ * Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <sys/stat.h>
+#ifndef ANDROID_CHANGES
+#include <sys/sysctl.h>
+#endif
+#include <err.h>
+#include <netinet/in.h>
+#include <net/pfkeyv2.h>
+#include PATH_IPSEC_H
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <string.h>
+#include <ctype.h>
+#include <unistd.h>
+#include <errno.h>
+#include <netdb.h>
+#include <fcntl.h>
+#include <dirent.h>
+#include <time.h>
+
+#ifdef HAVE_READLINE
+#include <readline/readline.h>
+#include <readline/history.h>
+#endif
+
+#include "config.h"
+#include "libpfkey.h"
+#include "package_version.h"
+#define extern /* so that variables in extern.h are not extern... */
+#include "extern.h"
+
+#define strlcpy(d,s,l) (strncpy(d,s,l), (d)[(l)-1] = '\0')
+
+void usage __P((int));
+int main __P((int, char **));
+int get_supported __P((void));
+void sendkeyshort __P((u_int));
+void promisc __P((void));
+int postproc __P((struct sadb_msg *, int));
+int verifypriority __P((struct sadb_msg *m));
+int fileproc __P((const char *));
+const char *numstr __P((int));
+void shortdump_hdr __P((void));
+void shortdump __P((struct sadb_msg *));
+static void printdate __P((void));
+static int32_t gmt2local __P((time_t));
+void stdin_loop __P((void));
+
+#ifdef ANDROID_CHANGES
+#include <stdarg.h>
+void err(int eval, const char *fmt, ...) {
+	va_list p;
+	va_start(p, fmt);
+	fprintf(stderr, fmt, p);
+	va_end(p);
+	exit(eval);
+}
+#define errx err
+void warnx(const char *fmt, ...) {
+	va_list p;
+	va_start(p, fmt);
+	fprintf(stderr, fmt, p);
+	va_end(p);
+}
+#endif
+
+#define MODE_SCRIPT	1
+#define MODE_CMDDUMP	2
+#define MODE_CMDFLUSH	3
+#define MODE_PROMISC	4
+#define MODE_STDIN	5
+
+int so;
+
+int f_forever = 0;
+int f_all = 0;
+int f_verbose = 0;
+int f_mode = 0;
+int f_cmddump = 0;
+int f_policy = 0;
+int f_hexdump = 0;
+int f_tflag = 0;
+int f_notreally = 0;
+int f_withports = 0;
+#ifdef HAVE_POLICY_FWD
+int f_rfcmode = 1;
+#define RK_OPTS "rk"
+#else
+int f_rkwarn = 0;
+#define RK_OPTS ""
+static void rkwarn(void);
+static void
+rkwarn(void)
+{
+	if (!f_rkwarn) {
+		f_rkwarn = 1;
+		printf("warning: -r and -k options are not supported in this environment\n");
+	}
+}
+
+#endif
+static time_t thiszone;
+
+void
+usage(int only_version)
+{
+	printf("setkey @(#) %s (%s)\n", TOP_PACKAGE_STRING, TOP_PACKAGE_URL); 
+	if (! only_version) {
+		printf("usage: setkey [-v" RK_OPTS "] file ...\n");
+		printf("       setkey [-nv" RK_OPTS "] -c\n");
+		printf("       setkey [-nv" RK_OPTS "] -f filename\n");
+		printf("       setkey [-Palpv" RK_OPTS "] -D\n");
+		printf("       setkey [-Pv] -F\n");
+		printf("       setkey [-H] -x\n");
+		printf("       setkey [-V] [-h]\n");
+	}
+	exit(1);
+}
+
+int
+main(argc, argv)
+	int argc;
+	char **argv;
+{
+	FILE *fp = stdin;
+	int c;
+
+	if (argc == 1) {
+		usage(0);
+		/* NOTREACHED */
+	}
+
+	thiszone = gmt2local(0);
+
+	while ((c = getopt(argc, argv, "acdf:HlnvxDFPphVrk?")) != -1) {
+		switch (c) {
+		case 'c':
+			f_mode = MODE_STDIN;
+#ifdef HAVE_READLINE
+			/* disable filename completion */
+			rl_bind_key('\t', rl_insert);
+#endif
+			break;
+		case 'f':
+			f_mode = MODE_SCRIPT;
+			if ((fp = fopen(optarg, "r")) == NULL) {
+				err(1, "fopen");
+				/*NOTREACHED*/
+			}
+			break;
+		case 'D':
+			f_mode = MODE_CMDDUMP;
+			break;
+		case 'F':
+			f_mode = MODE_CMDFLUSH;
+			break;
+		case 'a':
+			f_all = 1;
+			break;
+		case 'l':
+			f_forever = 1;
+			break;
+		case 'n':
+			f_notreally = 1;
+			break;
+#ifdef __NetBSD__
+		case 'h':
+#endif
+		case 'H':
+			f_hexdump = 1;
+			break;
+		case 'x':
+			f_mode = MODE_PROMISC;
+			f_tflag++;
+			break;
+		case 'P':
+			f_policy = 1;
+			break;
+		case 'p':
+			f_withports = 1;
+			break;
+		case 'v':
+			f_verbose = 1;
+			break;
+		case 'r':
+#ifdef HAVE_POLICY_FWD
+			f_rfcmode = 1;
+#else
+			rkwarn();
+#endif
+			break;
+		case 'k':
+#ifdef HAVE_POLICY_FWD
+			f_rfcmode = 0;
+#else
+			rkwarn();
+#endif
+			break;
+		case 'V':
+			usage(1);
+			break;
+			/*NOTREACHED*/
+#ifndef __NetBSD__
+		case 'h':
+#endif
+		case '?':
+		default:
+			usage(0);
+			/*NOTREACHED*/
+		}
+	}
+
+	argc -= optind;
+	argv += optind;
+
+	if (argc > 0) {
+		while (argc--)
+			if (fileproc(*argv++) < 0) {
+				err(1, "%s", argv[-1]);
+				/*NOTREACHED*/
+			}
+		exit(0);
+	}
+
+	so = pfkey_open();
+	if (so < 0) {
+		perror("pfkey_open");
+		exit(1);
+	}
+
+	switch (f_mode) {
+	case MODE_CMDDUMP:
+		sendkeyshort(f_policy ? SADB_X_SPDDUMP : SADB_DUMP);
+		break;
+	case MODE_CMDFLUSH:
+		sendkeyshort(f_policy ? SADB_X_SPDFLUSH: SADB_FLUSH);
+		break;
+	case MODE_SCRIPT:
+		if (get_supported() < 0) {
+			errx(1, "%s", ipsec_strerror());
+			/*NOTREACHED*/
+		}
+		if (parse(&fp))
+			exit (1);
+		break;
+	case MODE_STDIN:
+		if (get_supported() < 0) {
+			errx(1, "%s", ipsec_strerror());
+			/*NOTREACHED*/
+		}
+		stdin_loop();
+		break;
+	case MODE_PROMISC:
+		promisc();
+		/*NOTREACHED*/
+	default:
+		usage(0);
+		/*NOTREACHED*/
+	}
+
+	exit(0);
+}
+
+int
+get_supported()
+{
+
+	if (pfkey_send_register(so, SADB_SATYPE_UNSPEC) < 0)
+		return -1;
+
+	if (pfkey_recv_register(so) < 0)
+		return -1;
+
+	return (0);
+}
+
+void
+stdin_loop()
+{
+	char line[1024], *semicolon, *comment;
+	size_t linelen = 0;
+	
+	memset (line, 0, sizeof(line));
+
+	parse_init();
+	while (1) {
+#ifdef HAVE_READLINE
+		char *rbuf;
+		rbuf = readline ("");
+		if (! rbuf)
+			break;
+#else
+		char rbuf[1024];
+		rbuf[0] = '\0';
+		fgets (rbuf, sizeof(rbuf), stdin);
+		if (!rbuf[0])
+			break;
+		if (rbuf[strlen(rbuf)-1] == '\n')
+			rbuf[strlen(rbuf)-1] = '\0';
+#endif
+		comment = strchr(rbuf, '#');
+		if (comment)
+			*comment = '\0';
+
+		if (!rbuf[0])
+			continue;
+
+		linelen += snprintf (&line[linelen], sizeof(line) - linelen,
+				     "%s%s", linelen > 0 ? " " : "", rbuf);
+
+		semicolon = strchr(line, ';');
+		while (semicolon) {
+			char saved_char = *++semicolon;
+			*semicolon = '\0';
+#ifdef HAVE_READLINE
+			add_history (line);
+#endif
+
+#ifdef HAVE_PFKEY_POLICY_PRIORITY
+			last_msg_type = -1;  /* invalid message type */
+#endif
+
+			parse_string (line);
+			if (exit_now)
+				return;
+			if (saved_char) {
+				*semicolon = saved_char;
+				linelen = strlen (semicolon);
+				memmove (line, semicolon, linelen + 1);
+				semicolon = strchr(line, ';');
+			}
+			else {
+				semicolon = NULL;
+				linelen = 0;
+			}
+		}
+	}
+}
+
+void
+sendkeyshort(type)
+        u_int type;
+{
+	struct sadb_msg msg;
+
+	msg.sadb_msg_version = PF_KEY_V2;
+	msg.sadb_msg_type = type;
+	msg.sadb_msg_errno = 0;
+	msg.sadb_msg_satype = SADB_SATYPE_UNSPEC;
+	msg.sadb_msg_len = PFKEY_UNIT64(sizeof(msg));
+	msg.sadb_msg_reserved = 0;
+	msg.sadb_msg_seq = 0;
+	msg.sadb_msg_pid = getpid();
+
+	sendkeymsg((char *)&msg, sizeof(msg));
+
+	return;
+}
+
+void
+promisc()
+{
+	struct sadb_msg msg;
+	u_char rbuf[1024 * 32];	/* XXX: Enough ? Should I do MSG_PEEK ? */
+	ssize_t l;
+
+	msg.sadb_msg_version = PF_KEY_V2;
+	msg.sadb_msg_type = SADB_X_PROMISC;
+	msg.sadb_msg_errno = 0;
+	msg.sadb_msg_satype = 1;
+	msg.sadb_msg_len = PFKEY_UNIT64(sizeof(msg));
+	msg.sadb_msg_reserved = 0;
+	msg.sadb_msg_seq = 0;
+	msg.sadb_msg_pid = getpid();
+
+	if ((l = send(so, &msg, sizeof(msg), 0)) < 0) {
+		err(1, "send");
+		/*NOTREACHED*/
+	}
+
+	while (1) {
+		struct sadb_msg *base;
+
+		if ((l = recv(so, rbuf, sizeof(*base), MSG_PEEK)) < 0) {
+			err(1, "recv");
+			/*NOTREACHED*/
+		}
+
+		if (l != sizeof(*base))
+			continue;
+
+		base = (struct sadb_msg *)rbuf;
+		if ((l = recv(so, rbuf, PFKEY_UNUNIT64(base->sadb_msg_len),
+				0)) < 0) {
+			err(1, "recv");
+			/*NOTREACHED*/
+		}
+		printdate();
+		if (f_hexdump) {
+			int i;
+			for (i = 0; i < l; i++) {
+				if (i % 16 == 0)
+					printf("%08x: ", i);
+				printf("%02x ", rbuf[i] & 0xff);
+				if (i % 16 == 15)
+					printf("\n");
+			}
+			if (l % 16)
+				printf("\n");
+		}
+		/* adjust base pointer for promisc mode */
+		if (base->sadb_msg_type == SADB_X_PROMISC) {
+			if ((ssize_t)sizeof(*base) < l)
+				base++;
+			else
+				base = NULL;
+		}
+		if (base) {
+			kdebug_sadb(base);
+			printf("\n");
+			fflush(stdout);
+		}
+	}
+}
+
+int
+sendkeymsg(buf, len)
+	char *buf;
+	size_t len;
+{
+	u_char rbuf[1024 * 32];	/* XXX: Enough ? Should I do MSG_PEEK ? */
+	ssize_t l;
+	struct sadb_msg *msg;
+
+	if (f_notreally) {
+		goto end;
+	}
+
+    {
+	struct timeval tv;
+	tv.tv_sec = 1;
+	tv.tv_usec = 0;
+	if (setsockopt(so, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) < 0) {
+		perror("setsockopt");
+		goto end;
+	}
+    }
+
+	if (f_forever)
+		shortdump_hdr();
+again:
+	if (f_verbose) {
+		kdebug_sadb((struct sadb_msg *)buf);
+		printf("\n");
+	}
+	if (f_hexdump) {
+		int i;
+		for (i = 0; i < len; i++) {
+			if (i % 16 == 0)
+				printf("%08x: ", i);
+			printf("%02x ", buf[i] & 0xff);
+			if (i % 16 == 15)
+				printf("\n");
+		}
+		if (len % 16)
+			printf("\n");
+	}
+
+	if ((l = send(so, buf, len, 0)) < 0) {
+		perror("send");
+		goto end;
+	}
+
+	msg = (struct sadb_msg *)rbuf;
+	do {
+		if ((l = recv(so, rbuf, sizeof(rbuf), 0)) < 0) {
+			perror("recv");
+			goto end;
+		}
+
+		if (PFKEY_UNUNIT64(msg->sadb_msg_len) != l) {
+			warnx("invalid keymsg length");
+			break;
+		}
+
+		if (f_verbose) {
+			kdebug_sadb((struct sadb_msg *)rbuf);
+			printf("\n");
+		}
+		if (postproc(msg, l) < 0)
+			break;
+	} while (msg->sadb_msg_errno || msg->sadb_msg_seq);
+
+	if (f_forever) {
+		fflush(stdout);
+		sleep(1);
+		goto again;
+	}
+
+end:
+	return (0);
+}
+
+int
+postproc(msg, len)
+	struct sadb_msg *msg;
+	int len;
+{
+#ifdef HAVE_PFKEY_POLICY_PRIORITY
+	static int priority_support_check = 0;
+#endif
+
+	if (msg->sadb_msg_errno != 0) {
+		char inf[80];
+		const char *errmsg = NULL;
+
+		if (f_mode == MODE_SCRIPT)
+			snprintf(inf, sizeof(inf), "The result of line %d: ", lineno);
+		else
+			inf[0] = '\0';
+
+		switch (msg->sadb_msg_errno) {
+		case ENOENT:
+			switch (msg->sadb_msg_type) {
+			case SADB_DELETE:
+			case SADB_GET:
+			case SADB_X_SPDDELETE:
+				errmsg = "No entry";
+				break;
+			case SADB_DUMP:
+				errmsg = "No SAD entries";
+				break;
+			case SADB_X_SPDDUMP:
+				errmsg = "No SPD entries";
+				break;
+			}
+			break;
+		default:
+			errmsg = strerror(msg->sadb_msg_errno);
+		}
+		printf("%s%s.\n", inf, errmsg);
+		return (-1);
+	}
+
+	switch (msg->sadb_msg_type) {
+	case SADB_GET:
+		if (f_withports)
+			pfkey_sadump_withports(msg);
+		else
+			pfkey_sadump(msg);
+		break;
+
+	case SADB_DUMP:
+		/* filter out DEAD SAs */
+		if (!f_all) {
+			caddr_t mhp[SADB_EXT_MAX + 1];
+			struct sadb_sa *sa;
+			pfkey_align(msg, mhp);
+			pfkey_check(mhp);
+			if ((sa = (struct sadb_sa *)mhp[SADB_EXT_SA]) != NULL) {
+				if (sa->sadb_sa_state == SADB_SASTATE_DEAD)
+					break;
+			}
+		}
+		if (f_forever) {
+			/* TODO: f_withports */
+			shortdump(msg);
+		} else {
+			if (f_withports)
+				pfkey_sadump_withports(msg);
+			else
+				pfkey_sadump(msg);
+		}
+		msg = (struct sadb_msg *)((caddr_t)msg +
+				     PFKEY_UNUNIT64(msg->sadb_msg_len));
+		if (f_verbose) {
+			kdebug_sadb((struct sadb_msg *)msg);
+			printf("\n");
+		}
+		break;
+
+	case SADB_X_SPDGET:
+		if (f_withports) 
+			pfkey_spdump_withports(msg);
+		else
+			pfkey_spdump(msg);
+		break;
+
+	case SADB_X_SPDDUMP:
+		if (f_withports) 
+			pfkey_spdump_withports(msg);
+		else
+			pfkey_spdump(msg);
+		if (msg->sadb_msg_seq == 0) break;
+		msg = (struct sadb_msg *)((caddr_t)msg +
+				     PFKEY_UNUNIT64(msg->sadb_msg_len));
+		if (f_verbose) {
+			kdebug_sadb((struct sadb_msg *)msg);
+			printf("\n");
+		}
+		break;
+#ifdef HAVE_PFKEY_POLICY_PRIORITY
+	case SADB_X_SPDADD:
+		if (last_msg_type == SADB_X_SPDADD && last_priority != 0 && 
+		    msg->sadb_msg_pid == getpid() && !priority_support_check) {
+			priority_support_check = 1;	
+			if (!verifypriority(msg))
+				printf ("WARNING: Kernel does not support policy priorities\n");
+		}
+		break;
+#endif
+	}
+
+	return (0);
+}
+
+#ifdef HAVE_PFKEY_POLICY_PRIORITY
+int
+verifypriority(m)
+	struct sadb_msg *m;
+{
+	caddr_t mhp[SADB_EXT_MAX + 1];
+	struct sadb_x_policy *xpl;
+
+	/* check pfkey message. */
+	if (pfkey_align(m, mhp)) {
+		printf("(%s\n", ipsec_strerror());
+		return 0;
+	}
+	if (pfkey_check(mhp)) {
+		printf("%s\n", ipsec_strerror());
+		return 0;
+	}
+
+	xpl = (struct sadb_x_policy *) mhp[SADB_X_EXT_POLICY];
+
+	if (xpl == NULL) {
+		printf("no X_POLICY extension.\n");
+		return 0;
+	}
+
+	/* now make sure they match */
+	if (last_priority != xpl->sadb_x_policy_priority)
+		return 0;
+
+	return 1; 
+}
+#endif
+
+int
+fileproc(filename)
+	const char *filename;
+{
+	int fd;
+	ssize_t len, l;
+	u_char *p, *ep;
+	struct sadb_msg *msg;
+	u_char rbuf[1024 * 32];	/* XXX: Enough ? Should I do MSG_PEEK ? */
+
+	fd = open(filename, O_RDONLY);
+	if (fd < 0)
+		return -1;
+
+	l = 0;
+	while (1) {
+		len = read(fd, rbuf + l, sizeof(rbuf) - l);
+		if (len < 0) {
+			close(fd);
+			return -1;
+		} else if (len == 0)
+			break;
+		l += len;
+	}
+
+	if (l < sizeof(struct sadb_msg)) {
+		close(fd);
+		errno = EINVAL;
+		return -1;
+	}
+	close(fd);
+
+	p = rbuf;
+	ep = rbuf + l;
+
+	while (p < ep) {
+		msg = (struct sadb_msg *)p;
+		len = PFKEY_UNUNIT64(msg->sadb_msg_len);
+		postproc(msg, len);
+		p += len;
+	}
+
+	return (0);
+}
+
+
+/*------------------------------------------------------------*/
+static const char *satype[] = {
+	NULL, NULL, "ah", "esp"
+};
+static const char *sastate[] = {
+	"L", "M", "D", "d"
+};
+static const char *ipproto[] = {
+/*0*/	"ip", "icmp", "igmp", "ggp", "ip4",
+	NULL, "tcp", NULL, "egp", NULL,
+/*10*/	NULL, NULL, NULL, NULL, NULL,
+	NULL, NULL, "udp", NULL, NULL,
+/*20*/	NULL, NULL, "idp", NULL, NULL,
+	NULL, NULL, NULL, NULL, "tp",
+/*30*/	NULL, NULL, NULL, NULL, NULL,
+	NULL, NULL, NULL, NULL, NULL,
+/*40*/	NULL, "ip6", NULL, "rt6", "frag6",
+	NULL, "rsvp", "gre", NULL, NULL,
+/*50*/	"esp", "ah", NULL, NULL, NULL,
+	NULL, NULL, NULL, "icmp6", "none",
+/*60*/	"dst6",
+};
+
+#define STR_OR_ID(x, tab) \
+	(((x) < sizeof(tab)/sizeof(tab[0]) && tab[(x)])	? tab[(x)] : numstr(x))
+
+const char *
+numstr(x)
+	int x;
+{
+	static char buf[20];
+	snprintf(buf, sizeof(buf), "#%d", x);
+	return buf;
+}
+
+void
+shortdump_hdr()
+{
+	printf("%-4s %-3s %-1s %-8s %-7s %s -> %s\n",
+		"time", "p", "s", "spi", "ltime", "src", "dst");
+}
+
+void
+shortdump(msg)
+	struct sadb_msg *msg;
+{
+	caddr_t mhp[SADB_EXT_MAX + 1];
+	char buf[NI_MAXHOST], pbuf[NI_MAXSERV];
+	struct sadb_sa *sa;
+	struct sadb_address *saddr;
+	struct sadb_lifetime *lts, *lth, *ltc;
+	struct sockaddr *s;
+	u_int t;
+	time_t cur = time(0);
+
+	pfkey_align(msg, mhp);
+	pfkey_check(mhp);
+
+	printf("%02lu%02lu", (u_long)(cur % 3600) / 60, (u_long)(cur % 60));
+
+	printf(" %-3s", STR_OR_ID(msg->sadb_msg_satype, satype));
+
+	if ((sa = (struct sadb_sa *)mhp[SADB_EXT_SA]) != NULL) {
+		printf(" %-1s", STR_OR_ID(sa->sadb_sa_state, sastate));
+		printf(" %08x", (u_int32_t)ntohl(sa->sadb_sa_spi));
+	} else
+		printf("%-1s %-8s", "?", "?");
+
+	lts = (struct sadb_lifetime *)mhp[SADB_EXT_LIFETIME_SOFT];
+	lth = (struct sadb_lifetime *)mhp[SADB_EXT_LIFETIME_HARD];
+	ltc = (struct sadb_lifetime *)mhp[SADB_EXT_LIFETIME_CURRENT];
+	if (lts && lth && ltc) {
+		if (ltc->sadb_lifetime_addtime == 0)
+			t = (u_long)0;
+		else
+			t = (u_long)(cur - ltc->sadb_lifetime_addtime);
+		if (t >= 1000)
+			strlcpy(buf, " big/", sizeof(buf));
+		else
+			snprintf(buf, sizeof(buf), " %3lu/", (u_long)t);
+		printf("%s", buf);
+
+		t = (u_long)lth->sadb_lifetime_addtime;
+		if (t >= 1000)
+			strlcpy(buf, "big", sizeof(buf));
+		else
+			snprintf(buf, sizeof(buf), "%-3lu", (u_long)t);
+		printf("%s", buf);
+	} else
+		printf(" ??\?/???");	/* backslash to avoid trigraph ??/ */
+
+	printf(" ");
+
+	if ((saddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_SRC]) != NULL) {
+		if (saddr->sadb_address_proto)
+			printf("%s ", STR_OR_ID(saddr->sadb_address_proto, ipproto));
+		s = (struct sockaddr *)(saddr + 1);
+		getnameinfo(s, sysdep_sa_len(s), buf, sizeof(buf),
+			pbuf, sizeof(pbuf), NI_NUMERICHOST|NI_NUMERICSERV);
+		if (strcmp(pbuf, "0") != 0)
+			printf("%s[%s]", buf, pbuf);
+		else
+			printf("%s", buf);
+	} else
+		printf("?");
+
+	printf(" -> ");
+
+	if ((saddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_DST]) != NULL) {
+		if (saddr->sadb_address_proto)
+			printf("%s ", STR_OR_ID(saddr->sadb_address_proto, ipproto));
+
+		s = (struct sockaddr *)(saddr + 1);
+		getnameinfo(s, sysdep_sa_len(s), buf, sizeof(buf),
+			pbuf, sizeof(pbuf), NI_NUMERICHOST|NI_NUMERICSERV);
+		if (strcmp(pbuf, "0") != 0)
+			printf("%s[%s]", buf, pbuf);
+		else
+			printf("%s", buf);
+	} else
+		printf("?");
+
+	printf("\n");
+}
+
+/* From: tcpdump(1):gmt2local.c and util.c */
+/*
+ * Print the timestamp
+ */
+static void
+printdate()
+{
+	struct timeval tp;
+	int s;
+
+	if (gettimeofday(&tp, NULL) == -1) {
+		perror("gettimeofday");
+		return;
+	}
+
+	if (f_tflag == 1) {
+		/* Default */
+		s = (tp.tv_sec + thiszone ) % 86400;
+		(void)printf("%02d:%02d:%02d.%06u ",
+		    s / 3600, (s % 3600) / 60, s % 60, (u_int32_t)tp.tv_usec);
+	} else if (f_tflag > 1) {
+		/* Unix timeval style */
+		(void)printf("%u.%06u ",
+		    (u_int32_t)tp.tv_sec, (u_int32_t)tp.tv_usec);
+	}
+
+	printf("\n");
+}
+
+/*
+ * Returns the difference between gmt and local time in seconds.
+ * Use gmtime() and localtime() to keep things simple.
+ */
+int32_t
+gmt2local(time_t t)
+{
+	register int dt, dir;
+	register struct tm *gmt, *loc;
+	struct tm sgmt;
+
+	if (t == 0)
+		t = time(NULL);
+	gmt = &sgmt;
+	*gmt = *gmtime(&t);
+	loc = localtime(&t);
+	dt = (loc->tm_hour - gmt->tm_hour) * 60 * 60 +
+	    (loc->tm_min - gmt->tm_min) * 60;
+
+	/*
+	 * If the year or julian day is different, we span 00:00 GMT
+	 * and must add or subtract a day. Check the year first to
+	 * avoid problems when the julian day wraps.
+	 */
+	dir = loc->tm_year - gmt->tm_year;
+	if (dir == 0)
+		dir = loc->tm_yday - gmt->tm_yday;
+	dt += dir * 24 * 60 * 60;
+
+	return (dt);
+}
diff --git a/src/setkey/test-pfkey.c b/src/setkey/test-pfkey.c
new file mode 100644
index 0000000..bb0ad7b
--- /dev/null
+++ b/src/setkey/test-pfkey.c
@@ -0,0 +1,590 @@
+/*	$NetBSD: test-pfkey.c,v 1.7 2006/10/06 12:02:27 manu Exp $	*/
+
+/*	$KAME: test-pfkey.c,v 1.4 2000/06/07 00:29:14 itojun Exp $	*/
+
+/*
+ * Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <net/route.h>
+#include <net/pfkeyv2.h>
+#include <netinet/in.h>
+#include <netkey/keydb.h>
+#include <netkey/key_var.h>
+#include <netkey/key_debug.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <string.h>
+#include <ctype.h>
+#include <unistd.h>
+#include <errno.h>
+#include <netdb.h>
+
+u_char m_buf[BUFSIZ];
+u_int m_len;
+char *pname;
+
+void Usage __P((void));
+int sendkeymsg __P((void));
+void key_setsadbmsg __P((u_int));
+void key_setsadbsens __P((void));
+void key_setsadbprop __P((void));
+void key_setsadbid __P((u_int, caddr_t));
+void key_setsadblft __P((u_int, u_int));
+void key_setspirange __P((void));
+void key_setsadbkey __P((u_int, caddr_t));
+void key_setsadbsa __P((void));
+void key_setsadbaddr __P((u_int, u_int, caddr_t));
+void key_setsadbextbuf __P((caddr_t, int, caddr_t, int, caddr_t, int));
+
+void
+Usage()
+{
+	printf("Usage:\t%s number\n", pname);
+	exit(0);
+}
+
+int
+main(ac, av)
+	int ac;
+	char **av;
+{
+	pname = *av;
+
+	if (ac == 1) Usage();
+
+	key_setsadbmsg(atoi(*(av+1)));
+	sendkeymsg();
+
+	exit(0);
+}
+
+/* %%% */
+int
+sendkeymsg()
+{
+	u_char rbuf[1024 * 32];	/* XXX: Enough ? Should I do MSG_PEEK ? */
+	int so, len;
+
+	if ((so = socket(PF_KEY, SOCK_RAW, PF_KEY_V2)) < 0) {
+		perror("socket(PF_KEY)");
+		goto end;
+	}
+#if 0
+    {
+#include <sys/time.h>
+	struct timeval tv;
+	tv.tv_sec = 1;
+	tv.tv_usec = 0;
+	if (setsockopt(so, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) < 0) {
+		perror("setsockopt");
+		goto end;
+	}
+    }
+#endif
+
+	pfkey_sadump((struct sadb_msg *)m_buf);
+
+	if ((len = send(so, m_buf, m_len, 0)) < 0) {
+		perror("send");
+		goto end;
+	}
+
+	if ((len = recv(so, rbuf, sizeof(rbuf), 0)) < 0) {
+		perror("recv");
+		goto end;
+	}
+
+	pfkey_sadump((struct sadb_msg *)rbuf);
+
+end:
+	(void)close(so);
+	return(0);
+}
+
+void
+key_setsadbmsg(type)
+	u_int type;
+{
+	struct sadb_msg m_msg;
+
+	memset(&m_msg, 0, sizeof(m_msg));
+	m_msg.sadb_msg_version = PF_KEY_V2;
+	m_msg.sadb_msg_type = type;
+	m_msg.sadb_msg_errno = 0;
+	m_msg.sadb_msg_satype = SADB_SATYPE_ESP;
+#if 0
+	m_msg.sadb_msg_reserved = 0;
+#endif
+	m_msg.sadb_msg_seq = 0;
+	m_msg.sadb_msg_pid = getpid();
+
+	m_len = sizeof(struct sadb_msg);
+	memcpy(m_buf, &m_msg, m_len);
+
+	switch (type) {
+	case SADB_GETSPI:
+		/*<base, address(SD), SPI range>*/
+		key_setsadbaddr(SADB_EXT_ADDRESS_SRC, AF_INET, "10.0.3.4");
+		key_setsadbaddr(SADB_EXT_ADDRESS_DST, AF_INET, "127.0.0.1");
+		key_setspirange();
+		/*<base, SA(*), address(SD)>*/
+		break;
+
+	case SADB_ADD:
+		/* <base, SA, (lifetime(HSC),) address(SD), (address(P),)
+		   key(AE), (identity(SD),) (sensitivity)> */
+		key_setsadbaddr(SADB_EXT_ADDRESS_PROXY, AF_INET6, "3ffe::1");
+	case SADB_UPDATE:
+		key_setsadbsa();
+		key_setsadblft(SADB_EXT_LIFETIME_HARD, 10);
+		key_setsadblft(SADB_EXT_LIFETIME_SOFT, 5);
+		key_setsadbaddr(SADB_EXT_ADDRESS_SRC, AF_INET, "192.168.1.1");
+		key_setsadbaddr(SADB_EXT_ADDRESS_DST, AF_INET, "10.0.3.4");
+		/* XXX key_setsadbkey(SADB_EXT_KEY_AUTH, "abcde"); */
+		key_setsadbkey(SADB_EXT_KEY_AUTH, "1234567812345678");
+		key_setsadbkey(SADB_EXT_KEY_ENCRYPT, "12345678");
+		key_setsadbid(SADB_EXT_IDENTITY_SRC, "hoge1234@hoge.com");
+		key_setsadbid(SADB_EXT_IDENTITY_DST, "hage5678@hage.net");
+		key_setsadbsens();
+		/* <base, SA, (lifetime(HSC),) address(SD), (address(P),)
+		  (identity(SD),) (sensitivity)> */
+		break;
+
+	case SADB_DELETE:
+		/* <base, SA(*), address(SDP)> */
+		key_setsadbsa();
+		key_setsadbaddr(SADB_EXT_ADDRESS_SRC, AF_INET, "192.168.1.1");
+		key_setsadbaddr(SADB_EXT_ADDRESS_DST, AF_INET, "10.0.3.4");
+		key_setsadbaddr(SADB_EXT_ADDRESS_PROXY, AF_INET6, "3ffe::1");
+		/* <base, SA(*), address(SDP)> */
+		break;
+
+	case SADB_GET:
+		/* <base, SA(*), address(SDP)> */
+		key_setsadbsa();
+		key_setsadbaddr(SADB_EXT_ADDRESS_SRC, AF_INET, "192.168.1.1");
+		key_setsadbaddr(SADB_EXT_ADDRESS_DST, AF_INET, "10.0.3.4");
+		key_setsadbaddr(SADB_EXT_ADDRESS_PROXY, AF_INET6, "3ffe::1");
+		/* <base, SA, (lifetime(HSC),) address(SD), (address(P),)
+		   key(AE), (identity(SD),) (sensitivity)> */
+		break;
+
+	case SADB_ACQUIRE:
+		/* <base, address(SD), (address(P),) (identity(SD),)
+		   (sensitivity,) proposal> */
+		key_setsadbaddr(SADB_EXT_ADDRESS_SRC, AF_INET, "192.168.1.1");
+		key_setsadbaddr(SADB_EXT_ADDRESS_DST, AF_INET, "10.0.3.4");
+		key_setsadbaddr(SADB_EXT_ADDRESS_PROXY, AF_INET6, "3ffe::1");
+		key_setsadbid(SADB_EXT_IDENTITY_SRC, "hoge1234@hoge.com");
+		key_setsadbid(SADB_EXT_IDENTITY_DST, "hage5678@hage.net");
+		key_setsadbsens();
+		key_setsadbprop();
+		/* <base, address(SD), (address(P),) (identity(SD),)
+		   (sensitivity,) proposal> */
+		break;
+
+	case SADB_REGISTER:
+		/* <base> */
+		/* <base, supported> */
+		break;
+
+	case SADB_EXPIRE:
+	case SADB_FLUSH:
+		break;
+
+	case SADB_DUMP:
+		break;
+
+	case SADB_X_PROMISC:
+		/* <base> */
+		/* <base, base(, others)> */
+		break;
+
+	case SADB_X_PCHANGE:
+		break;
+
+	/* for SPD management */
+	case SADB_X_SPDFLUSH:
+	case SADB_X_SPDDUMP:
+		break;
+
+	case SADB_X_SPDADD:
+#if 0
+	    {
+		struct sadb_x_policy m_policy;
+
+		m_policy.sadb_x_policy_len = PFKEY_UNIT64(sizeof(m_policy));
+		m_policy.sadb_x_policy_exttype = SADB_X_EXT_POLICY;
+		m_policy.sadb_x_policy_type = SADB_X_PL_IPSEC;
+		m_policy.sadb_x_policy_esp_trans = 1;
+		m_policy.sadb_x_policy_ah_trans = 2;
+		m_policy.sadb_x_policy_esp_network = 3;
+		m_policy.sadb_x_policy_ah_network = 4;
+		m_policy.sadb_x_policy_reserved = 0;
+
+		memcpy(m_buf + m_len, &m_policy, sizeof(struct sadb_x_policy));
+		m_len += sizeof(struct sadb_x_policy);
+	    }
+#endif
+
+	case SADB_X_SPDDELETE:
+		key_setsadbaddr(SADB_EXT_ADDRESS_SRC, AF_INET, "192.168.1.1");
+		key_setsadbaddr(SADB_EXT_ADDRESS_DST, AF_INET, "10.0.3.4");
+		break;
+	}
+
+	((struct sadb_msg *)m_buf)->sadb_msg_len = PFKEY_UNIT64(m_len);
+
+	return;
+}
+
+void
+key_setsadbsens()
+{
+	struct sadb_sens m_sens;
+	u_char buf[64];
+	u_int s, i, slen, ilen, len;
+
+	/* make sens & integ */
+	s = htonl(0x01234567);
+	i = htonl(0x89abcdef);
+	slen = sizeof(s);
+	ilen = sizeof(i);
+	memcpy(buf, &s, slen);
+	memcpy(buf + slen, &i, ilen);
+
+	len = sizeof(m_sens) + PFKEY_ALIGN8(slen) + PFKEY_ALIGN8(ilen);
+	m_sens.sadb_sens_len = PFKEY_UNIT64(len);
+	m_sens.sadb_sens_exttype = SADB_EXT_SENSITIVITY;
+	m_sens.sadb_sens_dpd = 1;
+	m_sens.sadb_sens_sens_level = 2;
+	m_sens.sadb_sens_sens_len = PFKEY_ALIGN8(slen);
+	m_sens.sadb_sens_integ_level = 3;
+	m_sens.sadb_sens_integ_len = PFKEY_ALIGN8(ilen);
+	m_sens.sadb_sens_reserved = 0;
+
+	key_setsadbextbuf(m_buf, m_len,
+			(caddr_t)&m_sens, sizeof(struct sadb_sens),
+			buf, slen + ilen);
+	m_len += len;
+
+	return;
+}
+
+void
+key_setsadbprop()
+{
+	struct sadb_prop m_prop;
+	struct sadb_comb *m_comb;
+	u_char buf[256];
+#if (defined(SADB_X_EALG_AESCBC) || defined(SADB_X_EALG_CAMELLIACBC)) && defined(SADB_X_AALG_SHA2_256)
+	u_int len = sizeof(m_prop) + sizeof(m_comb) * 3;
+#else
+	u_int len = sizeof(m_prop) + sizeof(m_comb) * 2;
+#endif
+
+	/* make prop & comb */
+	m_prop.sadb_prop_len = PFKEY_UNIT64(len);
+	m_prop.sadb_prop_exttype = SADB_EXT_PROPOSAL;
+	m_prop.sadb_prop_replay = 0;
+	m_prop.sadb_prop_reserved[0] = 0;
+	m_prop.sadb_prop_reserved[1] = 0;
+	m_prop.sadb_prop_reserved[2] = 0;
+
+	/* the 1st is ESP DES-CBC HMAC-MD5 */
+	m_comb = (struct sadb_comb *)buf;
+	m_comb->sadb_comb_auth = SADB_AALG_MD5HMAC;
+	m_comb->sadb_comb_encrypt = SADB_EALG_DESCBC;
+	m_comb->sadb_comb_flags = 0;
+	m_comb->sadb_comb_auth_minbits = 8;
+	m_comb->sadb_comb_auth_maxbits = 96;
+	m_comb->sadb_comb_encrypt_minbits = 64;
+	m_comb->sadb_comb_encrypt_maxbits = 64;
+	m_comb->sadb_comb_reserved = 0;
+	m_comb->sadb_comb_soft_allocations = 0;
+	m_comb->sadb_comb_hard_allocations = 0;
+	m_comb->sadb_comb_soft_bytes = 0;
+	m_comb->sadb_comb_hard_bytes = 0;
+	m_comb->sadb_comb_soft_addtime = 0;
+	m_comb->sadb_comb_hard_addtime = 0;
+	m_comb->sadb_comb_soft_usetime = 0;
+	m_comb->sadb_comb_hard_usetime = 0;
+
+	/* the 2st is ESP 3DES-CBC and AH HMAC-SHA1 */
+	m_comb = (struct sadb_comb *)(buf + sizeof(*m_comb));
+	m_comb->sadb_comb_auth = SADB_AALG_SHA1HMAC;
+	m_comb->sadb_comb_encrypt = SADB_EALG_3DESCBC;
+	m_comb->sadb_comb_flags = 0;
+	m_comb->sadb_comb_auth_minbits = 8;
+	m_comb->sadb_comb_auth_maxbits = 96;
+	m_comb->sadb_comb_encrypt_minbits = 64;
+	m_comb->sadb_comb_encrypt_maxbits = 64;
+	m_comb->sadb_comb_reserved = 0;
+	m_comb->sadb_comb_soft_allocations = 0;
+	m_comb->sadb_comb_hard_allocations = 0;
+	m_comb->sadb_comb_soft_bytes = 0;
+	m_comb->sadb_comb_hard_bytes = 0;
+	m_comb->sadb_comb_soft_addtime = 0;
+	m_comb->sadb_comb_hard_addtime = 0;
+	m_comb->sadb_comb_soft_usetime = 0;
+	m_comb->sadb_comb_hard_usetime = 0;
+
+	key_setsadbextbuf(m_buf, m_len,
+			(caddr_t)&m_prop, sizeof(struct sadb_prop),
+			buf, sizeof(*m_comb) * 2);
+	m_len += len;
+
+ #if defined(SADB_X_EALG_AESCBC) && defined(SADB_X_AALG_SHA2_256)
+ 	/* the 3rd is ESP AES-CBC and AH HMAC-SHA256 */
+ 	m_comb = (struct sadb_comb *)(buf + sizeof(*m_comb));
+ 	m_comb->sadb_comb_auth = SADB_X_AALG_SHA2_256;
+ 	m_comb->sadb_comb_encrypt = SADB_X_EALG_AESCBC;
+ 	m_comb->sadb_comb_flags = 0;
+ 	m_comb->sadb_comb_auth_minbits = 8;
+ 	m_comb->sadb_comb_auth_maxbits = 96;
+ 	m_comb->sadb_comb_encrypt_minbits = 128;
+ 	m_comb->sadb_comb_encrypt_maxbits = 128;
+ 	m_comb->sadb_comb_reserved = 0;
+ 	m_comb->sadb_comb_soft_allocations = 0;
+ 	m_comb->sadb_comb_hard_allocations = 0;
+ 	m_comb->sadb_comb_soft_bytes = 0;
+ 	m_comb->sadb_comb_hard_bytes = 0;
+ 	m_comb->sadb_comb_soft_addtime = 0;
+ 	m_comb->sadb_comb_hard_addtime = 0;
+ 	m_comb->sadb_comb_soft_usetime = 0;
+ 	m_comb->sadb_comb_hard_usetime = 0;
+ 
+ 	key_setsadbextbuf(m_buf, m_len,
+ 			(caddr_t)&m_prop, sizeof(struct sadb_prop),
+ 			buf, sizeof(*m_comb) * 3);
+ 	m_len += len;
+ #elif defined(SADB_X_EALG_CAMELLIACBC) && defined(SADB_X_AALG_SHA2_256)
+ 	/* the 3rd is ESP CAMELLIA-CBC and AH HMAC-SHA256 */
+ 	m_comb = (struct sadb_comb *)(buf + sizeof(*m_comb));
+ 	m_comb->sadb_comb_auth = SADB_X_AALG_SHA2_256;
+ 	m_comb->sadb_comb_encrypt = SADB_X_EALG_CAMELLIACBC;
+ 	m_comb->sadb_comb_flags = 0;
+ 	m_comb->sadb_comb_auth_minbits = 8;
+ 	m_comb->sadb_comb_auth_maxbits = 96;
+ 	m_comb->sadb_comb_encrypt_minbits = 128;
+ 	m_comb->sadb_comb_encrypt_maxbits = 128;
+ 	m_comb->sadb_comb_reserved = 0;
+ 	m_comb->sadb_comb_soft_allocations = 0;
+ 	m_comb->sadb_comb_hard_allocations = 0;
+ 	m_comb->sadb_comb_soft_bytes = 0;
+ 	m_comb->sadb_comb_hard_bytes = 0;
+ 	m_comb->sadb_comb_soft_addtime = 0;
+ 	m_comb->sadb_comb_hard_addtime = 0;
+ 	m_comb->sadb_comb_soft_usetime = 0;
+ 	m_comb->sadb_comb_hard_usetime = 0;
+ 
+ 	key_setsadbextbuf(m_buf, m_len,
+ 			(caddr_t)&m_prop, sizeof(struct sadb_prop),
+ 			buf, sizeof(*m_comb) * 3);
+ 	m_len += len;
+#else
+	key_setsadbextbuf(m_buf, m_len,
+			(caddr_t)&m_prop, sizeof(struct sadb_prop),
+			buf, sizeof(*m_comb) * 2);
+ 	m_len += len;
+#endif
+	return;
+}
+
+void
+key_setsadbid(ext, str)
+	u_int ext;
+	caddr_t str;
+{
+	struct sadb_ident m_id;
+	u_int idlen = strlen(str), len;
+
+	len = sizeof(m_id) + PFKEY_ALIGN8(idlen);
+	m_id.sadb_ident_len = PFKEY_UNIT64(len);
+	m_id.sadb_ident_exttype = ext;
+	m_id.sadb_ident_type = SADB_IDENTTYPE_USERFQDN;
+	m_id.sadb_ident_reserved = 0;
+	m_id.sadb_ident_id = getpid();
+
+	key_setsadbextbuf(m_buf, m_len,
+			(caddr_t)&m_id, sizeof(struct sadb_ident),
+			str, idlen);
+	m_len += len;
+
+	return;
+}
+
+void
+key_setsadblft(ext, time)
+	u_int ext, time;
+{
+	struct sadb_lifetime m_lft;
+
+	m_lft.sadb_lifetime_len = PFKEY_UNIT64(sizeof(m_lft));
+	m_lft.sadb_lifetime_exttype = ext;
+	m_lft.sadb_lifetime_allocations = 0x2;
+	m_lft.sadb_lifetime_bytes = 0x1000;
+	m_lft.sadb_lifetime_addtime = time;
+	m_lft.sadb_lifetime_usetime = 0x0020;
+
+	memcpy(m_buf + m_len, &m_lft, sizeof(struct sadb_lifetime));
+	m_len += sizeof(struct sadb_lifetime);
+
+	return;
+}
+
+void
+key_setspirange()
+{
+	struct sadb_spirange m_spi;
+
+	m_spi.sadb_spirange_len = PFKEY_UNIT64(sizeof(m_spi));
+	m_spi.sadb_spirange_exttype = SADB_EXT_SPIRANGE;
+	m_spi.sadb_spirange_min = 0x00001000;
+	m_spi.sadb_spirange_max = 0x00002000;
+	m_spi.sadb_spirange_reserved = 0;
+
+	memcpy(m_buf + m_len, &m_spi, sizeof(struct sadb_spirange));
+	m_len += sizeof(struct sadb_spirange);
+
+	return;
+}
+
+void
+key_setsadbkey(ext, str)
+	u_int ext;
+	caddr_t str;
+{
+	struct sadb_key m_key;
+	u_int keylen = strlen(str);
+	u_int len;
+
+	len = sizeof(struct sadb_key) + PFKEY_ALIGN8(keylen);
+	m_key.sadb_key_len = PFKEY_UNIT64(len);
+	m_key.sadb_key_exttype = ext;
+	m_key.sadb_key_bits = keylen * 8;
+	m_key.sadb_key_reserved = 0;
+
+	key_setsadbextbuf(m_buf, m_len,
+			(caddr_t)&m_key, sizeof(struct sadb_key),
+			str, keylen);
+	m_len += len;
+
+	return;
+}
+
+void
+key_setsadbsa()
+{
+	struct sadb_sa m_sa;
+
+	m_sa.sadb_sa_len = PFKEY_UNIT64(sizeof(struct sadb_sa));
+	m_sa.sadb_sa_exttype = SADB_EXT_SA;
+	m_sa.sadb_sa_spi = htonl(0x12345678);
+	m_sa.sadb_sa_replay = 4;
+	m_sa.sadb_sa_state = 0;
+	m_sa.sadb_sa_auth = SADB_AALG_MD5HMAC;
+	m_sa.sadb_sa_encrypt = SADB_EALG_DESCBC;
+	m_sa.sadb_sa_flags = 0;
+
+	memcpy(m_buf + m_len, &m_sa, sizeof(struct sadb_sa));
+	m_len += sizeof(struct sadb_sa);
+
+	return;
+}
+
+void
+key_setsadbaddr(ext, af, str)
+	u_int ext, af;
+	caddr_t str;
+{
+	struct sadb_address m_addr;
+	u_int len;
+	struct addrinfo hints, *res;
+	const char *serv;
+	int plen;
+
+	switch (af) {
+	case AF_INET:
+		plen = sizeof(struct in_addr) << 3;
+		break;
+	case AF_INET6:
+		plen = sizeof(struct in6_addr) << 3;
+		break;
+	default:
+		/* XXX bark */
+		exit(1);
+	}
+
+	/* make sockaddr buffer */
+	memset(&hints, 0, sizeof(hints));
+	hints.ai_family = af;
+	hints.ai_socktype = SOCK_DGRAM;	/*dummy*/
+	hints.ai_flags = AI_NUMERICHOST;
+	serv = (ext == SADB_EXT_ADDRESS_PROXY ? "0" : "4660");	/*0x1234*/
+	if (getaddrinfo(str, serv, &hints, &res) != 0 || res->ai_next) {
+		/* XXX bark */
+		exit(1);
+	}
+	
+	len = sizeof(struct sadb_address) + PFKEY_ALIGN8(res->ai_addrlen);
+	m_addr.sadb_address_len = PFKEY_UNIT64(len);
+	m_addr.sadb_address_exttype = ext;
+	m_addr.sadb_address_proto =
+		(ext == SADB_EXT_ADDRESS_PROXY ? 0 : IPPROTO_TCP);
+	m_addr.sadb_address_prefixlen = plen;
+	m_addr.sadb_address_reserved = 0;
+
+	key_setsadbextbuf(m_buf, m_len,
+			(caddr_t)&m_addr, sizeof(struct sadb_address),
+			(caddr_t)res->ai_addr, res->ai_addrlen);
+	m_len += len;
+
+	freeaddrinfo(res);
+
+	return;
+}
+
+void
+key_setsadbextbuf(dst, off, ebuf, elen, vbuf, vlen)
+	caddr_t dst, ebuf, vbuf;
+	int off, elen, vlen;
+{
+	memset(dst + off, 0, elen + vlen);
+	memcpy(dst + off, (caddr_t)ebuf, elen);
+	memcpy(dst + off + elen, vbuf, vlen);
+
+	return;
+}
+
diff --git a/src/setkey/token.c b/src/setkey/token.c
new file mode 100644
index 0000000..c07b8e4
--- /dev/null
+++ b/src/setkey/token.c
@@ -0,0 +1,2932 @@
+
+#line 3 "token.c"
+
+#define  YY_INT_ALIGNED short int
+
+/* A lexical scanner generated by flex */
+
+#define FLEX_SCANNER
+#define YY_FLEX_MAJOR_VERSION 2
+#define YY_FLEX_MINOR_VERSION 5
+#define YY_FLEX_SUBMINOR_VERSION 35
+#if YY_FLEX_SUBMINOR_VERSION > 0
+#define FLEX_BETA
+#endif
+
+/* First, we deal with  platform-specific or compiler-specific issues. */
+
+/* begin standard C headers. */
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <stdlib.h>
+
+/* end standard C headers. */
+
+/* flex integer type definitions */
+
+#ifndef FLEXINT_H
+#define FLEXINT_H
+
+/* C99 systems have <inttypes.h>. Non-C99 systems may or may not. */
+
+#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
+
+/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h,
+ * if you want the limit (max/min) macros for int types. 
+ */
+#ifndef __STDC_LIMIT_MACROS
+#define __STDC_LIMIT_MACROS 1
+#endif
+
+#include <inttypes.h>
+typedef int8_t flex_int8_t;
+typedef uint8_t flex_uint8_t;
+typedef int16_t flex_int16_t;
+typedef uint16_t flex_uint16_t;
+typedef int32_t flex_int32_t;
+typedef uint32_t flex_uint32_t;
+#else
+typedef signed char flex_int8_t;
+typedef short int flex_int16_t;
+typedef int flex_int32_t;
+typedef unsigned char flex_uint8_t; 
+typedef unsigned short int flex_uint16_t;
+typedef unsigned int flex_uint32_t;
+
+/* Limits of integral types. */
+#ifndef INT8_MIN
+#define INT8_MIN               (-128)
+#endif
+#ifndef INT16_MIN
+#define INT16_MIN              (-32767-1)
+#endif
+#ifndef INT32_MIN
+#define INT32_MIN              (-2147483647-1)
+#endif
+#ifndef INT8_MAX
+#define INT8_MAX               (127)
+#endif
+#ifndef INT16_MAX
+#define INT16_MAX              (32767)
+#endif
+#ifndef INT32_MAX
+#define INT32_MAX              (2147483647)
+#endif
+#ifndef UINT8_MAX
+#define UINT8_MAX              (255U)
+#endif
+#ifndef UINT16_MAX
+#define UINT16_MAX             (65535U)
+#endif
+#ifndef UINT32_MAX
+#define UINT32_MAX             (4294967295U)
+#endif
+
+#endif /* ! C99 */
+
+#endif /* ! FLEXINT_H */
+
+#ifdef __cplusplus
+
+/* The "const" storage-class-modifier is valid. */
+#define YY_USE_CONST
+
+#else	/* ! __cplusplus */
+
+/* C99 requires __STDC__ to be defined as 1. */
+#if defined (__STDC__)
+
+#define YY_USE_CONST
+
+#endif	/* defined (__STDC__) */
+#endif	/* ! __cplusplus */
+
+#ifdef YY_USE_CONST
+#define yyconst const
+#else
+#define yyconst
+#endif
+
+/* Returned upon end-of-file. */
+#define YY_NULL 0
+
+/* Promotes a possibly negative, possibly signed char to an unsigned
+ * integer for use as an array index.  If the signed char is negative,
+ * we want to instead treat it as an 8-bit unsigned char, hence the
+ * double cast.
+ */
+#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c)
+
+/* Enter a start condition.  This macro really ought to take a parameter,
+ * but we do it the disgusting crufty way forced on us by the ()-less
+ * definition of BEGIN.
+ */
+#define BEGIN (yy_start) = 1 + 2 *
+
+/* Translate the current start state into a value that can be later handed
+ * to BEGIN to return to the state.  The YYSTATE alias is for lex
+ * compatibility.
+ */
+#define YY_START (((yy_start) - 1) / 2)
+#define YYSTATE YY_START
+
+/* Action number for EOF rule of a given start state. */
+#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1)
+
+/* Special action meaning "start processing a new file". */
+#define YY_NEW_FILE yyrestart(yyin  )
+
+#define YY_END_OF_BUFFER_CHAR 0
+
+/* Size of default input buffer. */
+#ifndef YY_BUF_SIZE
+#define YY_BUF_SIZE 16384
+#endif
+
+/* The state buf must be large enough to hold one state per character in the main buffer.
+ */
+#define YY_STATE_BUF_SIZE   ((YY_BUF_SIZE + 2) * sizeof(yy_state_type))
+
+#ifndef YY_TYPEDEF_YY_BUFFER_STATE
+#define YY_TYPEDEF_YY_BUFFER_STATE
+typedef struct yy_buffer_state *YY_BUFFER_STATE;
+#endif
+
+extern int yyleng;
+
+extern FILE *yyin, *yyout;
+
+#define EOB_ACT_CONTINUE_SCAN 0
+#define EOB_ACT_END_OF_FILE 1
+#define EOB_ACT_LAST_MATCH 2
+
+    #define YY_LESS_LINENO(n)
+    
+/* Return all but the first "n" matched characters back to the input stream. */
+#define yyless(n) \
+	do \
+		{ \
+		/* Undo effects of setting up yytext. */ \
+        int yyless_macro_arg = (n); \
+        YY_LESS_LINENO(yyless_macro_arg);\
+		*yy_cp = (yy_hold_char); \
+		YY_RESTORE_YY_MORE_OFFSET \
+		(yy_c_buf_p) = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \
+		YY_DO_BEFORE_ACTION; /* set up yytext again */ \
+		} \
+	while ( 0 )
+
+#define unput(c) yyunput( c, (yytext_ptr)  )
+
+#ifndef YY_TYPEDEF_YY_SIZE_T
+#define YY_TYPEDEF_YY_SIZE_T
+typedef size_t yy_size_t;
+#endif
+
+#ifndef YY_STRUCT_YY_BUFFER_STATE
+#define YY_STRUCT_YY_BUFFER_STATE
+struct yy_buffer_state
+	{
+	FILE *yy_input_file;
+
+	char *yy_ch_buf;		/* input buffer */
+	char *yy_buf_pos;		/* current position in input buffer */
+
+	/* Size of input buffer in bytes, not including room for EOB
+	 * characters.
+	 */
+	yy_size_t yy_buf_size;
+
+	/* Number of characters read into yy_ch_buf, not including EOB
+	 * characters.
+	 */
+	int yy_n_chars;
+
+	/* Whether we "own" the buffer - i.e., we know we created it,
+	 * and can realloc() it to grow it, and should free() it to
+	 * delete it.
+	 */
+	int yy_is_our_buffer;
+
+	/* Whether this is an "interactive" input source; if so, and
+	 * if we're using stdio for input, then we want to use getc()
+	 * instead of fread(), to make sure we stop fetching input after
+	 * each newline.
+	 */
+	int yy_is_interactive;
+
+	/* Whether we're considered to be at the beginning of a line.
+	 * If so, '^' rules will be active on the next match, otherwise
+	 * not.
+	 */
+	int yy_at_bol;
+
+    int yy_bs_lineno; /**< The line count. */
+    int yy_bs_column; /**< The column count. */
+    
+	/* Whether to try to fill the input buffer when we reach the
+	 * end of it.
+	 */
+	int yy_fill_buffer;
+
+	int yy_buffer_status;
+
+#define YY_BUFFER_NEW 0
+#define YY_BUFFER_NORMAL 1
+	/* When an EOF's been seen but there's still some text to process
+	 * then we mark the buffer as YY_EOF_PENDING, to indicate that we
+	 * shouldn't try reading from the input source any more.  We might
+	 * still have a bunch of tokens to match, though, because of
+	 * possible backing-up.
+	 *
+	 * When we actually see the EOF, we change the status to "new"
+	 * (via yyrestart()), so that the user can continue scanning by
+	 * just pointing yyin at a new input file.
+	 */
+#define YY_BUFFER_EOF_PENDING 2
+
+	};
+#endif /* !YY_STRUCT_YY_BUFFER_STATE */
+
+/* Stack of input buffers. */
+static size_t yy_buffer_stack_top = 0; /**< index of top of stack. */
+static size_t yy_buffer_stack_max = 0; /**< capacity of stack. */
+static YY_BUFFER_STATE * yy_buffer_stack = 0; /**< Stack as an array. */
+
+/* We provide macros for accessing buffer states in case in the
+ * future we want to put the buffer states in a more general
+ * "scanner state".
+ *
+ * Returns the top of the stack, or NULL.
+ */
+#define YY_CURRENT_BUFFER ( (yy_buffer_stack) \
+                          ? (yy_buffer_stack)[(yy_buffer_stack_top)] \
+                          : NULL)
+
+/* Same as previous macro, but useful when we know that the buffer stack is not
+ * NULL or when we need an lvalue. For internal use only.
+ */
+#define YY_CURRENT_BUFFER_LVALUE (yy_buffer_stack)[(yy_buffer_stack_top)]
+
+/* yy_hold_char holds the character lost when yytext is formed. */
+static char yy_hold_char;
+static int yy_n_chars;		/* number of characters read into yy_ch_buf */
+int yyleng;
+
+/* Points to current character in buffer. */
+static char *yy_c_buf_p = (char *) 0;
+static int yy_init = 0;		/* whether we need to initialize */
+static int yy_start = 0;	/* start state number */
+
+/* Flag which is used to allow yywrap()'s to do buffer switches
+ * instead of setting up a fresh yyin.  A bit of a hack ...
+ */
+static int yy_did_buffer_switch_on_eof;
+
+void yyrestart (FILE *input_file  );
+void yy_switch_to_buffer (YY_BUFFER_STATE new_buffer  );
+YY_BUFFER_STATE yy_create_buffer (FILE *file,int size  );
+void yy_delete_buffer (YY_BUFFER_STATE b  );
+void yy_flush_buffer (YY_BUFFER_STATE b  );
+void yypush_buffer_state (YY_BUFFER_STATE new_buffer  );
+void yypop_buffer_state (void );
+
+static void yyensure_buffer_stack (void );
+static void yy_load_buffer_state (void );
+static void yy_init_buffer (YY_BUFFER_STATE b,FILE *file  );
+
+#define YY_FLUSH_BUFFER yy_flush_buffer(YY_CURRENT_BUFFER )
+
+YY_BUFFER_STATE yy_scan_buffer (char *base,yy_size_t size  );
+YY_BUFFER_STATE yy_scan_string (yyconst char *yy_str  );
+YY_BUFFER_STATE yy_scan_bytes (yyconst char *bytes,int len  );
+
+void *yyalloc (yy_size_t  );
+void *yyrealloc (void *,yy_size_t  );
+void yyfree (void *  );
+
+#define yy_new_buffer yy_create_buffer
+
+#define yy_set_interactive(is_interactive) \
+	{ \
+	if ( ! YY_CURRENT_BUFFER ){ \
+        yyensure_buffer_stack (); \
+		YY_CURRENT_BUFFER_LVALUE =    \
+            yy_create_buffer(yyin,YY_BUF_SIZE ); \
+	} \
+	YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \
+	}
+
+#define yy_set_bol(at_bol) \
+	{ \
+	if ( ! YY_CURRENT_BUFFER ){\
+        yyensure_buffer_stack (); \
+		YY_CURRENT_BUFFER_LVALUE =    \
+            yy_create_buffer(yyin,YY_BUF_SIZE ); \
+	} \
+	YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \
+	}
+
+#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol)
+
+/* Begin user sect3 */
+
+typedef unsigned char YY_CHAR;
+
+FILE *yyin = (FILE *) 0, *yyout = (FILE *) 0;
+
+typedef int yy_state_type;
+
+extern int yylineno;
+
+int yylineno = 1;
+
+extern char *yytext;
+#define yytext_ptr yytext
+
+static yy_state_type yy_get_previous_state (void );
+static yy_state_type yy_try_NUL_trans (yy_state_type current_state  );
+static int yy_get_next_buffer (void );
+static void yy_fatal_error (yyconst char msg[]  );
+
+/* Done after the current pattern has been matched and before the
+ * corresponding action - sets up yytext.
+ */
+#define YY_DO_BEFORE_ACTION \
+	(yytext_ptr) = yy_bp; \
+	(yytext_ptr) -= (yy_more_len); \
+	yyleng = (size_t) (yy_cp - (yytext_ptr)); \
+	(yy_hold_char) = *yy_cp; \
+	*yy_cp = '\0'; \
+	(yy_c_buf_p) = yy_cp;
+
+#define YY_NUM_RULES 89
+#define YY_END_OF_BUFFER 90
+/* This struct is not used in this scanner,
+   but its presence is necessary. */
+struct yy_trans_info
+	{
+	flex_int32_t yy_verify;
+	flex_int32_t yy_nxt;
+	};
+static yyconst flex_int16_t yy_accept[552] =
+    {   0,
+        0,    0,    0,    0,    0,    0,    0,    0,   90,   88,
+       76,   77,   88,   78,   87,   88,   80,   83,   83,   86,
+       79,   81,   82,   86,   86,   86,   86,   86,   86,   86,
+       86,   86,   86,   86,   86,   86,   86,   86,   16,   16,
+       16,   16,   16,   16,   16,   16,   17,   16,   16,   16,
+       16,   16,   16,   16,   16,   16,   16,   16,   16,   16,
+       16,   16,   86,   86,   86,   86,   86,   83,   86,   86,
+       86,   86,   86,   86,   86,   86,   76,    0,   85,   78,
+       87,   18,   26,   55,   41,   15,   59,    0,    0,   64,
+        0,   60,   69,   63,   86,   83,   86,   86,   19,   86,
+
+       86,   86,   86,   86,   86,   86,   86,   86,   86,   86,
+       86,   86,   86,   86,   86,   86,   86,   86,   86,   86,
+       16,   16,   16,   16,   16,   16,   15,   16,   16,   16,
+       16,   16,   16,   16,   16,   16,   16,   16,   16,   16,
+       16,   16,   16,   16,   16,   16,   16,   16,   16,   16,
+       16,   16,   16,   16,   16,   16,   16,   16,   16,   16,
+       16,   86,   86,   86,   86,   86,   86,   86,   86,   86,
+       86,   86,   86,   86,   86,   18,   72,   73,    0,   70,
+       71,   84,    1,   86,   75,    9,   86,   86,   86,   20,
+       86,   86,    4,   86,   58,   86,   56,   86,   86,   86,
+
+       86,   86,   25,   86,   86,   86,   16,   16,   16,   16,
+       16,   16,   16,    1,   16,   16,    9,   16,   16,   16,
+       16,   16,   16,    4,   16,   16,   16,   16,   16,   16,
+       16,   16,   16,   16,   16,   16,   16,   86,   86,   86,
+       86,   25,   86,   86,   86,   86,   86,   86,   86,   86,
+       86,   86,   74,   86,   86,   86,    6,   86,    7,   86,
+       86,   86,    8,   86,   86,   86,   86,   86,   86,   86,
+       86,   86,   16,   16,   16,   16,    6,   16,    7,   16,
+       16,   16,    8,   16,   16,   16,   16,   16,   16,   16,
+       16,   16,   86,   86,   86,   40,   86,   86,   86,   86,
+
+       86,   86,   86,   44,   86,   86,   86,   86,   86,   86,
+       86,   86,    5,   86,   86,   86,   86,   86,   86,   86,
+       86,   86,   86,   86,   86,   16,   16,   16,   16,   16,
+        5,   16,   16,   16,   16,   16,   16,   16,   16,   16,
+       16,   16,   16,   86,   86,   86,   86,   86,   86,   86,
+       86,   86,   86,   86,   86,   86,   86,   86,   21,   86,
+        2,   86,   86,   24,   86,   86,   86,   10,   86,   86,
+       86,   14,   86,   62,   86,   16,   16,    2,   16,   16,
+       16,   16,   16,   16,   10,   16,   16,   16,   14,   16,
+       16,   16,   86,   86,   86,   86,   86,   86,   86,   86,
+
+       86,   86,   86,   86,   86,   86,   86,   86,   45,   86,
+       57,   86,   22,   23,   86,   86,   66,   86,   12,   86,
+       86,   86,   16,   16,   16,   16,   16,   16,   16,   16,
+       12,   16,   16,   16,   86,   86,   86,   86,   86,   86,
+       39,   86,   51,   53,   86,   86,   86,   86,   42,   86,
+       86,   86,   86,   86,   86,   86,   13,   86,   67,   16,
+       16,   16,   16,   13,   16,   16,   86,   27,   86,   86,
+       86,   86,   43,   86,   86,   86,   49,   86,   86,   86,
+        3,   86,   86,   11,   61,    3,   16,   16,   11,   16,
+       86,   86,   28,   86,   86,   86,   29,   86,   86,   86,
+
+       86,   48,   86,   86,   86,   65,   16,   16,   86,   86,
+       86,   86,   86,   86,   30,   86,   86,   86,   86,   86,
+       86,   16,   86,   86,   86,   86,   86,   32,   34,   36,
+       86,   86,   47,   86,   50,   68,   16,   38,   86,   86,
+       86,   86,   46,   54,   52,   86,   31,   33,   35,   37,
+        0
+    } ;
+
+static yyconst flex_int32_t yy_ec[256] =
+    {   0,
+        1,    1,    1,    1,    1,    1,    1,    1,    2,    3,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    2,    1,    4,    5,    1,    6,    1,    1,    1,
+        1,    1,    7,    8,    9,   10,   11,   12,   13,   14,
+       15,   16,   17,   18,   19,   20,   19,   21,   22,    1,
+        1,    1,    1,    1,   23,   24,   25,   24,   26,   24,
+       21,   21,   21,   21,   21,   21,   21,   21,   21,   27,
+       21,   28,   21,   21,   21,   21,   21,   29,   21,   21,
+       30,    1,   31,    1,   32,    1,   33,   34,   35,   36,
+
+       37,   38,   39,   40,   41,   42,   43,   44,   45,   46,
+       47,   48,   49,   50,   51,   52,   53,   54,   55,   56,
+       57,   58,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1
+    } ;
+
+static yyconst flex_int32_t yy_meta[59] =
+    {   0,
+        1,    2,    3,    1,    1,    4,    2,    5,    4,    4,
+        2,    6,    6,    6,    6,    6,    6,    6,    6,    6,
+        4,    1,    4,    4,    4,    4,    4,    4,    4,    2,
+        2,    2,    4,    4,    4,    4,    4,    4,    4,    4,
+        4,    4,    4,    4,    4,    4,    4,    4,    4,    4,
+        4,    4,    4,    4,    4,    4,    4,    4
+    } ;
+
+static yyconst flex_int16_t yy_base[558] =
+    {   0,
+        0,    0,   58,    0,   84,   85,  123,  161, 1518, 1519,
+     1515, 1519, 1512,    0,    0,  198, 1519,  244,  293, 1507,
+     1519, 1519, 1519,  114,  111,  112,  115,  118,  124,  131,
+      125,  133,  132,  134,  113,  140,  156,  126, 1512,    0,
+      298,    0,    0,  350,  405,  197, 1519,  436,  146,  194,
+      199,  107,  229,  231,  232,  234,  246,  249,  251,  282,
+      338,  301,  309,  127,  144,  137,  342, 1477,  364,  332,
+      185,  346,  241,  352,  421,  395, 1510, 1507, 1519,    0,
+        0,  313, 1519, 1519, 1519, 1519, 1519,  104, 1458, 1519,
+      127, 1519, 1519, 1519, 1501,    0,  475,  162,  193,  246,
+
+      209,  388,  275,  245,  386,  378,  382,  202,  288,  379,
+      401,  432,  230,  307,  397,  296,  403,  438,  407,  446,
+     1506,    0,  439,    0,    0,    0,    0,    0,  401, 1455,
+        0,  409,    0,    0,    0,  434,    0,  506,  509,  518,
+      510,  511,  525,  530,  532,  541,  543,  548,  555,  557,
+      569,  566,  577,  574,  585,  586,  597,  599,  608,  606,
+      613,  451,  448,  471,  290,  455,  467,  456,  469,  611,
+      620,  453,  544,  470,  526,  611, 1519, 1519, 1450, 1519,
+     1519,    0, 1497,  527, 1496, 1495,  509,  525,  457,  211,
+      603,  616, 1494,  551, 1493,  528, 1492,  608,  630,  389,
+
+      632,  498, 1491,  584,  642,  552,  656,    0,    0, 1442,
+        0,    0,    0,  633,  640,  645,  653,  654,  667,  669,
+      674,  672,  683,  685,  686,  699,  700,  701,  702,  713,
+      734,  722,  725,  727,  736,  739,  741,  669,  676,  693,
+      653,  687,  742,  719,  736,  758,  744,  775,  748,  743,
+      761,  770, 1519,  778,  782,  786, 1489,  789, 1488,  790,
+      792,  791, 1487,  793,  795,  796,  794,  797,  798,  799,
+      802,  803,    0,  777,  812,  813,  778,  815,  820,  827,
+      834,  836,  841,  848,  850,  853,  864,  867,  869,  872,
+      884,  893,  808,  811,  821, 1486,  838,  819,  884,  889,
+
+      825,  918,  917, 1485,  906,  914,  908,  920,  826,  817,
+      926,  927, 1484,  928,  929,  930,  932,  933,  935,  936,
+      937,  938,  939,  940,  943,  914,  926,  931,  949,  946,
+      958,  960,  961,  973,  981,  976,  984,  989,  996,  997,
+     1004, 1011, 1018,  953, 1018,  994,  947, 1003, 1007, 1015,
+     1002,  877, 1031,  207, 1023, 1040, 1045, 1053, 1483, 1054,
+     1057, 1059,  951, 1482, 1062, 1063, 1066, 1481, 1068, 1067,
+     1069, 1480, 1070, 1479, 1073, 1043, 1048, 1076, 1061, 1078,
+     1083, 1091, 1099, 1094, 1102, 1107, 1110, 1115, 1123, 1124,
+     1132, 1140, 1079, 1085, 1084, 1088, 1144, 1157, 1102, 1146,
+
+     1091, 1141, 1092, 1078, 1149, 1159, 1154, 1169, 1478, 1167,
+     1477, 1171, 1476, 1475, 1174, 1175, 1474, 1176, 1473, 1177,
+     1179, 1180, 1157, 1174, 1162, 1165, 1186, 1191, 1194, 1202,
+     1205, 1207, 1210, 1219, 1217, 1183, 1188, 1191, 1225, 1204,
+     1472, 1227, 1471, 1470, 1241, 1249, 1255, 1250, 1469, 1258,
+     1259, 1260, 1262, 1263, 1265, 1268, 1468, 1266, 1467, 1239,
+     1271, 1251, 1256, 1254, 1273, 1274, 1269, 1466, 1278, 1313,
+     1314, 1300, 1465, 1280, 1315, 1304, 1458, 1287, 1326, 1308,
+     1446, 1293, 1321, 1435, 1434, 1296, 1309, 1310, 1312, 1323,
+     1329, 1330, 1433, 1345, 1353, 1357, 1427, 1358, 1332, 1343,
+
+     1356, 1424, 1360, 1364, 1339, 1103, 1343, 1341, 1374, 1376,
+     1377,  674, 1380, 1205, 1072, 1385, 1389, 1378, 1391, 1392,
+      667, 1365, 1394, 1395, 1398, 1396, 1409,  972,  956,  949,
+     1401, 1402,  867, 1410,  836,  698, 1384,  643, 1413, 1420,
+     1418, 1425,  530,  478,  476, 1432,  394,  319,  214,  121,
+     1519, 1445, 1451, 1453, 1456, 1461, 1466
+    } ;
+
+static yyconst flex_int16_t yy_def[558] =
+    {   0,
+      551,    1,  551,    3,    1,    1,    1,    1,  551,  551,
+      551,  551,  552,  553,  554,  551,  551,  555,  555,  555,
+      551,  551,  551,  555,  555,  555,  555,  555,  555,  555,
+      555,  555,  555,  555,  555,  555,  555,  555,  556,  556,
+      556,  556,  556,  557,  557,  557,  551,  557,   48,   48,
+       48,   48,   48,   48,   48,   48,   48,   48,   48,   48,
+       48,   48,  555,  555,  555,  555,  555,   19,  555,  555,
+      555,  555,  555,  555,  555,  555,  551,  552,  551,  553,
+      554,  551,  551,  551,  551,  551,  551,  551,  551,  551,
+      551,  551,  551,  551,  555,   19,   19,  555,  555,  555,
+
+      555,  555,  555,  555,  555,  555,  555,  555,  555,  555,
+      555,  555,  555,  555,  555,  555,  555,  555,  555,  555,
+      556,  556,  556,  556,  556,  556,  556,  556,  556,  556,
+      556,  556,  556,  556,  556,   48,   45,   45,   48,   48,
+       48,   48,   48,   48,   48,   48,   48,   48,   48,   48,
+       48,   48,   48,   48,   48,   48,   48,   48,   48,   48,
+       48,  555,  555,  555,  555,  555,  555,  555,  555,  555,
+      555,  555,  555,  555,  555,  551,  551,  551,  551,  551,
+      551,   97,  555,  555,  555,  555,  555,  555,  555,  555,
+      555,  555,  555,  555,  555,  555,  555,  555,  555,  555,
+
+      555,  555,  555,  555,  555,  555,  556,  556,  556,  556,
+      556,  556,  138,   48,   48,   48,   48,   48,   48,   48,
+       48,   48,   48,   48,   48,   48,   48,   48,   48,   48,
+       48,   48,   48,   48,   48,   48,   48,  555,  555,  555,
+      555,  555,  555,  555,  555,  555,  555,  555,  555,  555,
+      555,  555,  551,  555,  555,  555,  555,  555,  555,  555,
+      555,  555,  555,  555,  555,  555,  555,  555,  555,  555,
+      555,  555,  556,   48,   48,   48,   48,   48,   48,   48,
+       48,   48,   48,   48,   48,   48,   48,   48,   48,   48,
+       48,   48,  555,  555,  555,  555,  555,  555,  555,  555,
+
+      555,  555,  555,  555,  555,  555,  555,  555,  555,  555,
+      555,  555,  555,  555,  555,  555,  555,  555,  555,  555,
+      555,  555,  555,  555,  555,   48,   48,   48,   48,   48,
+       48,   48,   48,   48,   48,   48,   48,   48,   48,   48,
+       48,   48,   48,  555,  555,  555,  555,  555,  555,  555,
+      555,  555,  555,  555,  555,  555,  555,  555,  555,  555,
+      555,  555,  555,  555,  555,  555,  555,  555,  555,  555,
+      555,  555,  555,  555,  555,   48,   48,   48,   48,   48,
+       48,   48,   48,   48,   48,   48,   48,   48,   48,   48,
+       48,   48,  555,  555,  555,  555,  555,  555,  555,  555,
+
+      555,  555,  555,  555,  555,  555,  555,  555,  555,  555,
+      555,  555,  555,  555,  555,  555,  555,  555,  555,  555,
+      555,  555,   48,   48,   48,   48,   48,   48,   48,   48,
+       48,   48,   48,   48,  555,  555,  555,  555,  555,  555,
+      555,  555,  555,  555,  555,  555,  555,  555,  555,  555,
+      555,  555,  555,  555,  555,  555,  555,  555,  555,   48,
+       48,   48,   48,   48,   48,   48,  555,  555,  555,  555,
+      555,  555,  555,  555,  555,  555,  555,  555,  555,  555,
+      555,  555,  555,  555,  555,   48,   48,   48,   48,   48,
+      555,  555,  555,  555,  555,  555,  555,  555,  555,  555,
+
+      555,  555,  555,  555,  555,  555,   48,   48,  555,  555,
+      555,  555,  555,  555,  555,  555,  555,  555,  555,  555,
+      555,   48,  555,  555,  555,  555,  555,  555,  555,  555,
+      555,  555,  555,  555,  555,  555,   48,  555,  555,  555,
+      555,  555,  555,  555,  555,  555,  555,  555,  555,  555,
+        0,  551,  551,  551,  551,  551,  551
+    } ;
+
+static yyconst flex_int16_t yy_nxt[1578] =
+    {   0,
+       10,   11,   12,   13,   14,   10,   10,   15,   16,   10,
+       17,   18,   19,   19,   19,   19,   19,   19,   19,   19,
+       20,   21,   20,   20,   20,   20,   20,   20,   20,   22,
+       23,   10,   24,   25,   20,   26,   27,   28,   29,   20,
+       30,   20,   20,   31,   20,   32,   33,   20,   34,   35,
+       36,   37,   20,   20,   20,   20,   20,   38,   10,   39,
+       40,   13,   14,   10,   10,   15,   41,   42,   43,   44,
+       45,   45,   45,   45,   45,   45,   45,   45,   46,   47,
+       46,   46,   46,   46,   46,   46,   46,   22,   23,   42,
+       48,   49,   46,   50,   51,   52,   53,   46,   54,   46,
+
+       46,   55,   46,   56,   57,   46,   58,   59,   60,   61,
+       46,   46,   46,   46,   46,   62,   63,   63,  551,  551,
+      551,  551,  551,   64,   64,  551,   65,   65,  551,   66,
+       66,  551,  551,  551,  551,   67,   67,   68,  551,  551,
+      551,  551,  136,  177,  551,  113,  136,  551,  102,   98,
+      147,  551,  136,   99,  178,   69,   70,   71,   72,  100,
+      107,  106,  120,  551,  103,  104,  180,  101,   73,  551,
+      105,  163,   74,   75,   76,   68,  114,  181,  108,  110,
+      164,  136,  109,  110,  111,  136,  112,  115,  116,  165,
+      117,  136,  551,   69,   70,   71,   72,  183,  122,  122,
+
+      551,  184,  142,  122,  551,  118,   73,  122,  119,  551,
+       74,   75,   76,   82,  551,   82,  551,  170,  551,  258,
+       83,  551,   84,   85,   86,   87,  122,  122,  122,  136,
+      143,   88,   89,  136,  136,   90,  194,  551,  136,  136,
+      406,   91,   92,   82,  136,  186,  144,   93,  551,  145,
+       94,   81,  551,  551,  146,   96,   96,   96,   96,   96,
+       96,   96,   96,   96,  136,  148,  136,  136,  136,  136,
+      136,  136,   97,  136,  136,  199,  136,  136,  149,  136,
+      151,  136,  551,  154,  136,  136,  136,  110,  136,  150,
+      136,  136,  190,  172,  136,  551,  136,  551,  152,   97,
+
+       81,  153,  185,  551,   96,   96,   96,   96,   96,   96,
+       96,   96,   96,  123,  551,  123,  551,  136,  155,  189,
+      124,  136,  125,  126,  127,  128,  551,  136,  176,  156,
+      176,  129,  130,  241,  202,  131,  136,  161,  195,  551,
+      136,  132,  133,  123,   98,  162,  136,  134,   99,  551,
+      135,  122,  122,  551,  100,  200,  122,   81,  176,  551,
+      122,  137,  137,  137,  137,  137,  137,  137,  137,  137,
+      157,  551,  158,  136,  116,  169,  166,  136,  138,  122,
+      122,  122,  171,  136,  113,  551,  551,  159,  101,  551,
+      160,  118,  173,  551,  119,  551,  551,  265,  103,   98,
+
+      168,  551,  551,   99,  551,  138,  122,  122,  551,  100,
+      551,  122,   81,  196,  551,  122,  137,  137,  137,  137,
+      137,  137,  137,  137,  137,  187,  191,  116,  551,  117,
+      192,  188,  201,  193,  122,  122,  122,  122,  122,  551,
+      208,  197,  122,  551,  118,  551,  122,  119,  211,  175,
+      203,  209,  205,  551,  207,  551,  207,  114,  551,  212,
+      551,  174,  551,  551,  551,  122,  122,  122,  115,  136,
+      204,  139,  198,  136,  551,  140,  551,  551,  551,  136,
+      239,  141,  551,  551,  207,  551,  182,  182,  182,  182,
+      182,  182,  182,  182,  182,  206,  249,  182,  182,  182,
+
+      182,  238,  242,  243,  257,  551,  244,  182,  182,  182,
+      182,  182,  182,  551,  251,  245,  551,  213,  213,  213,
+      213,  213,  213,  213,  213,  213,  215,  240,  213,  213,
+      213,  213,  551,  551,  551,  551,  269,  551,  213,  213,
+      213,  213,  213,  213,  214,  136,  136,  217,  136,  136,
+      136,  551,  255,  136,  136,  136,  136,  136,  551,  551,
+      136,  256,  218,  136,  136,  136,  216,  136,  219,  136,
+      136,  136,  252,  254,  220,  136,  136,  136,  136,  221,
+      136,  222,  136,  136,  262,  250,  136,  136,  136,  225,
+      136,  551,  136,  136,  136,  223,  136,  261,  272,  224,
+
+      136,  136,  136,  227,  136,  136,  228,  226,  136,  136,
+      551,  136,  136,  136,  136,  551,  136,  229,  551,  230,
+      136,  232,  136,  551,  136,  136,  176,  551,  176,  270,
+      136,  136,  136,  231,  136,  233,  136,  551,  136,  551,
+      235,  136,  136,  136,  136,  136,  234,  136,  136,  551,
+      551,  236,  136,  136,  259,  246,  176,  187,  136,  263,
+      551,  247,  237,  188,  266,  264,  260,  267,  136,  268,
+      248,  207,  136,  207,  551,  136,  551,  293,  136,  136,
+      136,  551,  278,  551,  136,  136,  274,  271,  136,  136,
+      136,  528,  136,  136,  551,  297,  296,  275,  136,  136,
+
+      551,  207,  136,  276,  136,  551,  136,  136,  136,  136,
+      294,  136,  136,  136,  136,  536,  277,  136,  136,  136,
+      136,  136,  136,  279,  136,  136,  551,  299,  136,  295,
+      136,  136,  281,  280,  136,  136,  136,  136,  136,  136,
+      136,  136,  285,  551,  136,  136,  136,  136,  284,  551,
+      551,  551,  136,  283,  286,  551,  282,  287,  136,  288,
+      136,  136,  136,  289,  136,  551,  136,  136,  551,  136,
+      136,  136,  136,  136,  136,  136,  136,  551,  136,  136,
+      136,  290,  551,  303,  291,  551,  136,  292,  305,  551,
+      300,  304,  298,  551,  301,  302,  551,  551,  551,  551,
+
+      551,  551,  551,  551,  551,  551,  551,  307,  306,  551,
+      551,  325,  136,  136,  309,  551,  136,  136,  551,  345,
+      326,  308,  136,  136,  551,  315,  551,  348,  551,  313,
+      319,  318,  551,  551,  322,  311,  314,  310,  324,  316,
+      321,  312,  317,  551,  327,  551,  320,  136,  136,  323,
+      136,  136,  136,  361,  136,  136,  346,  136,  136,  136,
+      136,  329,  136,  344,  328,  136,  331,  330,  351,  136,
+      333,  136,  136,  136,  551,  136,  136,  360,  332,  136,
+      136,  136,  347,  136,  551,  136,  136,  136,  336,  136,
+      404,  551,  136,  136,  334,  136,  551,  335,  136,  136,
+
+      337,  343,  136,  136,  136,  340,  136,  136,  136,  136,
+      339,  136,  136,  551,  136,  551,  338,  136,  349,  136,
+      342,  551,  341,  136,  551,  551,  350,  551,  136,  136,
+      352,  353,  136,  551,  551,  551,  551,  551,  136,  551,
+      551,  356,  551,  551,  551,  551,  551,  551,  358,  376,
+      551,  354,  355,  136,  551,  359,  551,  357,  551,  136,
+      551,  136,  363,  551,  367,  136,  136,  378,  368,  362,
+      136,  136,  365,  372,  366,  364,  136,  377,  369,  551,
+      370,  380,  398,  374,  136,  136,  373,  393,  136,  371,
+      375,  136,  379,  136,  136,  136,  136,  136,  414,  136,
+
+      136,  551,  397,  136,  382,  136,  136,  381,  136,  551,
+      551,  385,  136,  384,  551,  136,  136,  383,  136,  136,
+      136,  136,  551,  136,  136,  551,  136,  386,  136,  136,
+      551,  136,  389,  387,  136,  136,  136,  399,  551,  136,
+      400,  136,  136,  136,  405,  403,  136,  551,  388,  136,
+      136,  390,  551,  136,  391,  402,  136,  136,  401,  407,
+      551,  551,  394,  136,  551,  392,  551,  395,  396,  551,
+      551,  416,  408,  551,  551,  551,  551,  551,  136,  551,
+      551,  409,  136,  136,  423,  551,  551,  136,  136,  412,
+      411,  551,  551,  136,  413,  551,  425,  447,  551,  551,
+
+      136,  417,  415,  410,  418,  422,  136,  428,  424,  551,
+      551,  136,  435,  136,  419,  136,  421,  136,  136,  420,
+      436,  136,  136,  136,  437,  426,  136,  438,  136,  429,
+      136,  427,  446,  136,  136,  442,  136,  136,  136,  136,
+      444,  136,  136,  430,  136,  136,  136,  136,  551,  136,
+      136,  551,  136,  551,  136,  136,  551,  431,  136,  136,
+      136,  551,  136,  136,  551,  432,  551,  136,  136,  136,
+      433,  136,  434,  441,  551,  136,  551,  136,  551,  136,
+      443,  551,  551,  551,  551,  136,  551,  551,  439,  448,
+      551,  445,  136,  449,  440,  551,  136,  136,  551,  468,
+
+      136,  136,  136,  450,  136,  451,  452,  136,  454,  136,
+      136,  551,  551,  136,  453,  459,  457,  460,  530,  136,
+      461,  136,  455,  470,  551,  136,  136,  456,  458,  136,
+      136,  136,  551,  136,  551,  469,  136,  136,  462,  136,
+      136,  136,  136,  472,  136,  136,  464,  136,  551,  136,
+      136,  467,  136,  463,  466,  136,  551,  551,  136,  465,
+      471,  473,  551,  476,  136,  551,  551,  551,  480,  551,
+      551,  482,  551,  551,  136,  551,  551,  491,  136,  487,
+      474,  475,  486,  488,  136,  551,  136,  551,  499,  136,
+      136,  136,  489,  136,  551,  136,  136,  483,  478,  136,
+
+      551,  136,  479,  477,  484,  481,  136,  551,  136,  136,
+      136,  551,  136,  136,  492,  551,  136,  485,  136,  136,
+      551,  551,  551,  500,  490,  493,  494,  495,  551,  496,
+      497,  136,  498,  551,  503,  136,  551,  551,  501,  551,
+      502,  136,  504,  505,  136,  508,  551,  136,  136,  136,
+      551,  136,  551,  511,  136,  136,  506,  136,  136,  507,
+      551,  512,  136,  551,  551,  551,  516,  551,  136,  514,
+      515,  551,  513,  509,  510,  521,  136,  517,  136,  522,
+      136,  551,  136,  551,  551,  551,  136,  551,  136,  518,
+      525,  526,  551,  527,  519,  529,  551,  520,  551,  551,
+
+      136,  551,  551,  551,  136,  551,  523,  539,  551,  551,
+      136,  524,  533,  537,  540,  541,  551,  551,  531,  136,
+      551,  542,  532,  136,  534,  551,  535,  551,  538,  136,
+      546,  551,  551,  548,  551,  543,  544,  547,  549,  551,
+      551,  551,  551,  550,  545,   78,   78,   78,   78,   78,
+       78,   80,   80,  551,   80,   80,   80,   81,   81,   95,
+       95,   95,  122,  122,  122,  551,  122,  136,  136,  136,
+      136,  136,  551,  551,  551,  551,  551,  551,  551,  551,
+      551,  551,  551,  551,  551,  551,  551,  551,  551,  551,
+      551,  551,  551,  551,  551,  551,  551,  273,  551,  551,
+
+      551,  551,  551,  551,  551,  253,  210,  121,  551,  179,
+       79,   77,  167,  121,  551,   79,   77,  551,    9,  551,
+      551,  551,  551,  551,  551,  551,  551,  551,  551,  551,
+      551,  551,  551,  551,  551,  551,  551,  551,  551,  551,
+      551,  551,  551,  551,  551,  551,  551,  551,  551,  551,
+      551,  551,  551,  551,  551,  551,  551,  551,  551,  551,
+      551,  551,  551,  551,  551,  551,  551,  551,  551,  551,
+      551,  551,  551,  551,  551,  551,  551
+    } ;
+
+static yyconst flex_int16_t yy_chk[1578] =
+    {   0,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    3,    3,
+        3,    3,    3,    3,    3,    3,    3,    3,    3,    3,
+        3,    3,    3,    3,    3,    3,    3,    3,    3,    3,
+        3,    3,    3,    3,    3,    3,    3,    3,    3,    3,
+        3,    3,    3,    3,    3,    3,    3,    3,    3,    3,
+
+        3,    3,    3,    3,    3,    3,    3,    3,    3,    3,
+        3,    3,    3,    3,    3,    3,    5,    6,   25,   26,
+       35,   24,   27,    5,    6,   28,    5,    6,  550,    5,
+        6,   29,   31,   38,   64,    5,    6,    7,   30,   33,
+       32,   34,   52,   88,   66,   35,   52,   36,   26,   24,
+       52,   65,   52,   24,   88,    7,    7,    7,    7,   24,
+       29,   28,   38,   37,   26,   27,   91,   25,    7,   98,
+       27,   64,    7,    7,    7,    8,   36,   91,   30,   32,
+       65,   49,   31,   66,   33,   49,   34,   36,   37,   66,
+       37,   49,   71,    8,    8,    8,    8,   98,   46,   46,
+
+       99,   99,   49,   46,   46,   37,    8,   46,   37,  108,
+        8,    8,    8,   16,  354,   16,  101,   71,  190,  190,
+       16,  549,   16,   16,   16,   16,   46,   46,   46,   50,
+       50,   16,   16,   50,   51,   16,  108,  113,   51,   50,
+      354,   16,   16,   16,   51,  101,   50,   16,   73,   51,
+       16,   18,  104,  100,   51,   18,   18,   18,   18,   18,
+       18,   18,   18,   18,   53,   53,   54,   55,   53,   56,
+       54,   55,   18,   56,   53,  113,   54,   55,   54,   56,
+       56,   57,  103,   59,   58,   57,   59,   73,   58,   55,
+       59,   57,  104,   73,   58,  109,   59,  165,   57,   18,
+
+       19,   58,  100,  116,   19,   19,   19,   19,   19,   19,
+       19,   19,   19,   41,  114,   41,   63,   60,   60,  103,
+       41,   60,   41,   41,   41,   41,  548,   60,   82,   60,
+       82,   41,   41,  165,  116,   41,   62,   62,  109,   70,
+       62,   41,   41,   41,   63,   63,   62,   41,   63,   67,
+       41,   44,   44,   72,   63,  114,   44,   44,   82,   74,
+       44,   44,   44,   44,   44,   44,   44,   44,   44,   44,
+       61,   69,   61,   61,   67,   70,   67,   61,   44,   44,
+       44,   44,   72,   61,   74,  106,  110,   61,   70,  107,
+       61,   67,   74,  105,   67,  102,  200,  200,   72,   69,
+
+       69,  547,   76,   69,  115,   44,   45,   45,  111,   69,
+      117,   45,   45,  110,  119,   45,   45,   45,   45,   45,
+       45,   45,   45,   45,   45,  102,  105,   76,   75,   76,
+      106,  102,  115,  107,   45,   45,   45,   48,   48,  112,
+      129,  111,   48,   48,   76,  118,   48,   76,  132,   76,
+      117,  129,  119,  120,  123,  163,  123,   75,  162,  132,
+      172,   75,  166,  168,  189,   48,   48,   48,   75,  136,
+      118,   48,  112,  136,  167,   48,  169,  174,  164,  136,
+      163,   48,   97,  545,  123,  544,   97,   97,   97,   97,
+       97,   97,   97,   97,   97,  120,  172,   97,   97,   97,
+
+       97,  162,  166,  167,  189,  202,  168,   97,   97,   97,
+       97,   97,   97,  138,  174,  169,  187,  138,  138,  138,
+      138,  138,  138,  138,  138,  138,  140,  164,  138,  138,
+      138,  138,  188,  175,  184,  196,  202,  543,  138,  138,
+      138,  138,  138,  138,  139,  141,  142,  142,  139,  141,
+      142,  173,  187,  140,  139,  141,  142,  140,  194,  206,
+      143,  188,  143,  140,  143,  144,  141,  145,  143,  144,
+      143,  145,  175,  184,  144,  144,  146,  145,  147,  145,
+      146,  146,  147,  148,  196,  173,  146,  148,  147,  149,
+      149,  204,  150,  148,  149,  147,  150,  194,  206,  148,
+
+      149,  152,  150,  151,  151,  152,  152,  150,  151,  154,
+      191,  152,  153,  154,  151,  198,  153,  153,  170,  154,
+      155,  156,  153,  192,  155,  156,  176,  171,  176,  204,
+      155,  156,  157,  155,  158,  157,  157,  199,  158,  201,
+      159,  160,  157,  159,  158,  160,  158,  159,  161,  205,
+      538,  160,  161,  159,  191,  170,  176,  171,  161,  198,
+      241,  170,  161,  171,  201,  199,  192,  201,  214,  201,
+      171,  207,  214,  207,  521,  215,  238,  238,  214,  215,
+      216,  512,  221,  239,  216,  215,  215,  205,  217,  218,
+      216,  512,  217,  218,  242,  242,  241,  218,  217,  218,
+
+      240,  207,  219,  219,  220,  536,  219,  222,  220,  221,
+      239,  222,  219,  221,  220,  521,  220,  222,  223,  221,
+      224,  225,  223,  222,  224,  225,  244,  244,  223,  240,
+      224,  225,  225,  223,  226,  227,  228,  229,  226,  227,
+      228,  229,  231,  245,  226,  227,  228,  229,  230,  243,
+      250,  247,  230,  229,  232,  249,  227,  232,  230,  232,
+      233,  232,  234,  233,  233,  246,  234,  232,  251,  231,
+      233,  235,  234,  231,  236,  235,  237,  252,  236,  231,
+      237,  235,  248,  248,  236,  254,  237,  237,  250,  255,
+      245,  249,  243,  256,  246,  247,  258,  260,  262,  261,
+
+      264,  267,  265,  266,  268,  269,  270,  252,  251,  271,
+      272,  272,  274,  277,  255,  293,  274,  277,  294,  294,
+      274,  254,  274,  277,  310,  262,  298,  298,  295,  260,
+      267,  266,  301,  309,  269,  258,  261,  256,  271,  264,
+      268,  258,  265,  535,  275,  297,  267,  275,  276,  270,
+      278,  275,  276,  310,  278,  279,  295,  275,  276,  279,
+      278,  278,  280,  293,  276,  279,  280,  278,  301,  281,
+      282,  282,  280,  281,  533,  282,  283,  309,  281,  281,
+      283,  282,  297,  284,  352,  285,  283,  284,  286,  285,
+      352,  299,  286,  284,  284,  285,  300,  285,  286,  287,
+
+      287,  292,  288,  287,  289,  289,  288,  290,  289,  287,
+      288,  290,  288,  305,  289,  307,  287,  290,  299,  291,
+      291,  306,  290,  291,  303,  302,  300,  308,  292,  291,
+      302,  303,  292,  311,  312,  314,  315,  316,  292,  317,
+      318,  305,  319,  320,  321,  322,  323,  324,  307,  326,
+      325,  303,  303,  326,  347,  308,  530,  306,  363,  326,
+      344,  327,  312,  529,  317,  327,  328,  328,  318,  311,
+      328,  327,  315,  322,  316,  314,  328,  327,  319,  528,
+      320,  330,  347,  324,  329,  330,  323,  344,  329,  321,
+      325,  330,  329,  331,  329,  332,  333,  331,  363,  332,
+
+      333,  346,  346,  331,  333,  332,  333,  332,  334,  351,
+      348,  336,  334,  335,  349,  336,  335,  334,  334,  337,
+      335,  336,  350,  337,  338,  345,  335,  337,  338,  337,
+      355,  339,  340,  338,  338,  339,  340,  348,  353,  341,
+      349,  339,  340,  341,  353,  351,  342,  356,  339,  341,
+      342,  341,  357,  343,  342,  350,  342,  343,  349,  355,
+      358,  360,  345,  343,  361,  343,  362,  345,  345,  365,
+      366,  366,  356,  367,  370,  369,  371,  373,  376,  515,
+      375,  357,  376,  377,  377,  404,  393,  377,  376,  361,
+      360,  395,  394,  377,  362,  396,  379,  404,  401,  403,
+
+      379,  367,  365,  358,  369,  375,  379,  383,  378,  399,
+      506,  378,  393,  380,  370,  378,  373,  380,  381,  371,
+      394,  378,  381,  380,  395,  380,  382,  396,  381,  384,
+      382,  382,  403,  384,  383,  399,  382,  385,  383,  384,
+      401,  385,  386,  386,  383,  387,  386,  385,  402,  387,
+      388,  397,  386,  400,  388,  387,  405,  387,  389,  390,
+      388,  407,  389,  390,  398,  388,  406,  391,  389,  390,
+      390,  391,  392,  398,  410,  392,  408,  391,  412,  392,
+      400,  415,  416,  418,  420,  392,  421,  422,  397,  405,
+      436,  402,  423,  406,  397,  437,  423,  425,  438,  436,
+
+      426,  425,  423,  407,  426,  408,  410,  425,  415,  424,
+      426,  440,  514,  424,  412,  422,  420,  424,  514,  424,
+      427,  427,  416,  438,  435,  427,  428,  418,  421,  429,
+      428,  427,  439,  429,  442,  437,  428,  430,  428,  429,
+      431,  430,  432,  440,  431,  433,  432,  430,  445,  433,
+      431,  435,  432,  430,  434,  433,  446,  448,  434,  433,
+      439,  442,  447,  447,  434,  450,  451,  452,  452,  453,
+      454,  454,  455,  458,  460,  456,  467,  467,  460,  461,
+      445,  446,  460,  462,  460,  469,  462,  474,  474,  464,
+      462,  463,  463,  464,  478,  463,  462,  455,  450,  464,
+
+      482,  463,  451,  448,  456,  453,  461,  472,  465,  466,
+      461,  476,  465,  466,  469,  480,  461,  458,  465,  466,
+      470,  471,  475,  475,  465,  470,  470,  470,  483,  470,
+      471,  486,  472,  479,  479,  486,  491,  492,  476,  499,
+      478,  486,  480,  482,  487,  488,  505,  489,  487,  488,
+      500,  489,  494,  494,  487,  488,  483,  489,  490,  487,
+      495,  494,  490,  501,  496,  498,  499,  503,  490,  496,
+      498,  504,  495,  491,  492,  505,  508,  500,  507,  507,
+      508,  509,  507,  510,  511,  518,  508,  513,  507,  501,
+      511,  511,  516,  511,  503,  513,  517,  504,  519,  520,
+
+      522,  523,  524,  526,  522,  525,  509,  524,  531,  532,
+      522,  510,  518,  522,  525,  526,  527,  534,  516,  537,
+      539,  527,  517,  537,  519,  541,  520,  540,  523,  537,
+      539,  502,  542,  541,  497,  531,  532,  540,  542,  546,
+      493,  485,  484,  546,  534,  552,  552,  552,  552,  552,
+      552,  553,  553,  481,  553,  553,  553,  554,  554,  555,
+      555,  555,  556,  556,  556,  477,  556,  557,  557,  557,
+      557,  557,  473,  468,  459,  457,  449,  444,  443,  441,
+      419,  417,  414,  413,  411,  409,  374,  372,  368,  364,
+      359,  313,  304,  296,  263,  259,  257,  210,  203,  197,
+
+      195,  193,  186,  185,  183,  179,  130,  121,   95,   89,
+       78,   77,   68,   39,   20,   13,   11,    9,  551,  551,
+      551,  551,  551,  551,  551,  551,  551,  551,  551,  551,
+      551,  551,  551,  551,  551,  551,  551,  551,  551,  551,
+      551,  551,  551,  551,  551,  551,  551,  551,  551,  551,
+      551,  551,  551,  551,  551,  551,  551,  551,  551,  551,
+      551,  551,  551,  551,  551,  551,  551,  551,  551,  551,
+      551,  551,  551,  551,  551,  551,  551
+    } ;
+
+static yy_state_type yy_last_accepting_state;
+static char *yy_last_accepting_cpos;
+
+extern int yy_flex_debug;
+int yy_flex_debug = 0;
+
+/* The intent behind this definition is that it'll catch
+ * any uses of REJECT which flex missed.
+ */
+#define REJECT reject_used_but_not_detected
+static int yy_more_flag = 0;
+static int yy_more_len = 0;
+#define yymore() ((yy_more_flag) = 1)
+#define YY_MORE_ADJ (yy_more_len)
+#define YY_RESTORE_YY_MORE_OFFSET
+char *yytext;
+#line 1 "token.l"
+/*	$NetBSD: token.l,v 1.11.6.1 2007/08/01 11:52:23 vanhu Exp $	*/
+/*	$KAME: token.l,v 1.44 2003/10/21 07:20:58 itojun Exp $	*/
+/*
+ * Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#line 35 "token.l"
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <net/pfkeyv2.h>
+#include <netinet/in.h>
+#include PATH_IPSEC_H
+
+#include <stdlib.h>
+#include <limits.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <netdb.h>
+
+#include "vchar.h"
+#if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__linux__) || \
+(defined(__APPLE__) && defined(__MACH__))
+#include "parse.h"
+#else
+#include "y.tab.h"
+#endif
+
+#include "extern.h"
+
+/* make the code compile on *BSD-current */
+#ifndef SADB_X_AALG_SHA2_256
+#define SADB_X_AALG_SHA2_256	(-1)
+#endif
+#ifndef SADB_X_AALG_SHA2_384
+#define SADB_X_AALG_SHA2_384	(-1)
+#endif
+#ifndef SADB_X_AALG_SHA2_512
+#define SADB_X_AALG_SHA2_512	(-1)
+#endif
+#ifndef SADB_X_AALG_RIPEMD160HMAC
+#define SADB_X_AALG_RIPEMD160HMAC	(-1)
+#endif
+#ifndef SADB_X_AALG_AES_XCBC_MAC
+#define SADB_X_AALG_AES_XCBC_MAC	(-1)
+#endif
+#ifndef SADB_X_EALG_TWOFISHCBC
+#define SADB_X_EALG_TWOFISHCBC	(-1)
+#endif
+#ifndef SADB_X_EALG_AESCTR
+#define SADB_X_EALG_AESCTR	(-1)
+#endif
+#if defined(SADB_X_EALG_AES) && ! defined(SADB_X_EALG_AESCBC)
+#define SADB_X_EALG_AESCBC  SADB_X_EALG_AES
+#endif
+/* common section */
+
+#line 1069 "token.c"
+
+#define INITIAL 0
+#define S_PL 1
+#define S_AUTHALG 2
+#define S_ENCALG 3
+
+#ifndef YY_NO_UNISTD_H
+/* Special case for "unistd.h", since it is non-ANSI. We include it way
+ * down here because we want the user's section 1 to have been scanned first.
+ * The user has a chance to override it with an option.
+ */
+#include <unistd.h>
+#endif
+
+#ifndef YY_EXTRA_TYPE
+#define YY_EXTRA_TYPE void *
+#endif
+
+static int yy_init_globals (void );
+
+/* Accessor methods to globals.
+   These are made visible to non-reentrant scanners for convenience. */
+
+int yylex_destroy (void );
+
+int yyget_debug (void );
+
+void yyset_debug (int debug_flag  );
+
+YY_EXTRA_TYPE yyget_extra (void );
+
+void yyset_extra (YY_EXTRA_TYPE user_defined  );
+
+FILE *yyget_in (void );
+
+void yyset_in  (FILE * in_str  );
+
+FILE *yyget_out (void );
+
+void yyset_out  (FILE * out_str  );
+
+int yyget_leng (void );
+
+char *yyget_text (void );
+
+int yyget_lineno (void );
+
+void yyset_lineno (int line_number  );
+
+/* Macros after this point can all be overridden by user definitions in
+ * section 1.
+ */
+#ifndef YY_SKIP_YYWRAP
+#ifdef __cplusplus
+extern "C" int yywrap (void );
+#else
+extern int yywrap (void );
+#endif
+#endif
+
+    static void yyunput (int c,char *buf_ptr  );
+    
+#ifndef yytext_ptr
+static void yy_flex_strncpy (char *,yyconst char *,int );
+#endif
+
+#ifdef YY_NEED_STRLEN
+static int yy_flex_strlen (yyconst char * );
+#endif
+
+#ifndef YY_NO_INPUT
+
+#ifdef __cplusplus
+static int yyinput (void );
+#else
+static int input (void );
+#endif
+
+#endif
+
+/* Amount of stuff to slurp up with each read. */
+#ifndef YY_READ_BUF_SIZE
+#define YY_READ_BUF_SIZE 8192
+#endif
+
+/* Copy whatever the last rule matched to the standard output. */
+#ifndef ECHO
+/* This used to be an fputs(), but since the string might contain NUL's,
+ * we now use fwrite().
+ */
+#define ECHO fwrite( yytext, yyleng, 1, yyout )
+#endif
+
+/* Gets input and stuffs it into "buf".  number of characters read, or YY_NULL,
+ * is returned in "result".
+ */
+#ifndef YY_INPUT
+#define YY_INPUT(buf,result,max_size) \
+	if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \
+		{ \
+		int c = '*'; \
+		size_t n; \
+		for ( n = 0; n < max_size && \
+			     (c = getc( yyin )) != EOF && c != '\n'; ++n ) \
+			buf[n] = (char) c; \
+		if ( c == '\n' ) \
+			buf[n++] = (char) c; \
+		if ( c == EOF && ferror( yyin ) ) \
+			YY_FATAL_ERROR( "input in flex scanner failed" ); \
+		result = n; \
+		} \
+	else \
+		{ \
+		errno=0; \
+		while ( (result = fread(buf, 1, max_size, yyin))==0 && ferror(yyin)) \
+			{ \
+			if( errno != EINTR) \
+				{ \
+				YY_FATAL_ERROR( "input in flex scanner failed" ); \
+				break; \
+				} \
+			errno=0; \
+			clearerr(yyin); \
+			} \
+		}\
+\
+
+#endif
+
+/* No semi-colon after return; correct usage is to write "yyterminate();" -
+ * we don't want an extra ';' after the "return" because that will cause
+ * some compilers to complain about unreachable statements.
+ */
+#ifndef yyterminate
+#define yyterminate() return YY_NULL
+#endif
+
+/* Number of entries by which start-condition stack grows. */
+#ifndef YY_START_STACK_INCR
+#define YY_START_STACK_INCR 25
+#endif
+
+/* Report a fatal error. */
+#ifndef YY_FATAL_ERROR
+#define YY_FATAL_ERROR(msg) yy_fatal_error( msg )
+#endif
+
+/* end tables serialization structures and prototypes */
+
+/* Default declaration of generated scanner - a define so the user can
+ * easily add parameters.
+ */
+#ifndef YY_DECL
+#define YY_DECL_IS_OURS 1
+
+extern int yylex (void);
+
+#define YY_DECL int yylex (void)
+#endif /* !YY_DECL */
+
+/* Code executed at the beginning of each rule, after yytext and yyleng
+ * have been set up.
+ */
+#ifndef YY_USER_ACTION
+#define YY_USER_ACTION
+#endif
+
+/* Code executed at the end of each rule. */
+#ifndef YY_BREAK
+#define YY_BREAK break;
+#endif
+
+#define YY_RULE_SETUP \
+	YY_USER_ACTION
+
+/** The main scanner function which does all the work.
+ */
+YY_DECL
+{
+	register yy_state_type yy_current_state;
+	register char *yy_cp, *yy_bp;
+	register int yy_act;
+    
+#line 114 "token.l"
+
+
+#line 1257 "token.c"
+
+	if ( !(yy_init) )
+		{
+		(yy_init) = 1;
+
+#ifdef YY_USER_INIT
+		YY_USER_INIT;
+#endif
+
+		if ( ! (yy_start) )
+			(yy_start) = 1;	/* first start state */
+
+		if ( ! yyin )
+			yyin = stdin;
+
+		if ( ! yyout )
+			yyout = stdout;
+
+		if ( ! YY_CURRENT_BUFFER ) {
+			yyensure_buffer_stack ();
+			YY_CURRENT_BUFFER_LVALUE =
+				yy_create_buffer(yyin,YY_BUF_SIZE );
+		}
+
+		yy_load_buffer_state( );
+		}
+
+	while ( 1 )		/* loops until end-of-file is reached */
+		{
+		(yy_more_len) = 0;
+		if ( (yy_more_flag) )
+			{
+			(yy_more_len) = (yy_c_buf_p) - (yytext_ptr);
+			(yy_more_flag) = 0;
+			}
+		yy_cp = (yy_c_buf_p);
+
+		/* Support of yytext. */
+		*yy_cp = (yy_hold_char);
+
+		/* yy_bp points to the position in yy_ch_buf of the start of
+		 * the current run.
+		 */
+		yy_bp = yy_cp;
+
+		yy_current_state = (yy_start);
+yy_match:
+		do
+			{
+			register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)];
+			if ( yy_accept[yy_current_state] )
+				{
+				(yy_last_accepting_state) = yy_current_state;
+				(yy_last_accepting_cpos) = yy_cp;
+				}
+			while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+				{
+				yy_current_state = (int) yy_def[yy_current_state];
+				if ( yy_current_state >= 552 )
+					yy_c = yy_meta[(unsigned int) yy_c];
+				}
+			yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+			++yy_cp;
+			}
+		while ( yy_base[yy_current_state] != 1519 );
+
+yy_find_action:
+		yy_act = yy_accept[yy_current_state];
+		if ( yy_act == 0 )
+			{ /* have to back up */
+			yy_cp = (yy_last_accepting_cpos);
+			yy_current_state = (yy_last_accepting_state);
+			yy_act = yy_accept[yy_current_state];
+			}
+
+		YY_DO_BEFORE_ACTION;
+
+do_action:	/* This label is used only to access EOF actions. */
+
+		switch ( yy_act )
+	{ /* beginning of action switch */
+			case 0: /* must back up */
+			/* undo the effects of YY_DO_BEFORE_ACTION */
+			*yy_cp = (yy_hold_char);
+			yy_cp = (yy_last_accepting_cpos);
+			yy_current_state = (yy_last_accepting_state);
+			goto yy_find_action;
+
+case 1:
+YY_RULE_SETUP
+#line 116 "token.l"
+{ return(ADD); }
+	YY_BREAK
+case 2:
+YY_RULE_SETUP
+#line 117 "token.l"
+{ return(DELETE); }
+	YY_BREAK
+case 3:
+YY_RULE_SETUP
+#line 118 "token.l"
+{ return(DELETEALL); }
+	YY_BREAK
+case 4:
+YY_RULE_SETUP
+#line 119 "token.l"
+{ return(GET); }
+	YY_BREAK
+case 5:
+YY_RULE_SETUP
+#line 120 "token.l"
+{ return(FLUSH); }
+	YY_BREAK
+case 6:
+YY_RULE_SETUP
+#line 121 "token.l"
+{ return(DUMP); }
+	YY_BREAK
+case 7:
+YY_RULE_SETUP
+#line 122 "token.l"
+{ return(EXIT); }
+	YY_BREAK
+case 8:
+YY_RULE_SETUP
+#line 123 "token.l"
+{ return(EXIT); }
+	YY_BREAK
+case 9:
+YY_RULE_SETUP
+#line 124 "token.l"
+{ return(EXIT); }
+	YY_BREAK
+/* for management SPD */
+case 10:
+YY_RULE_SETUP
+#line 127 "token.l"
+{ return(SPDADD); }
+	YY_BREAK
+case 11:
+YY_RULE_SETUP
+#line 128 "token.l"
+{ return(SPDDELETE); }
+	YY_BREAK
+case 12:
+YY_RULE_SETUP
+#line 129 "token.l"
+{ return(SPDDUMP); }
+	YY_BREAK
+case 13:
+YY_RULE_SETUP
+#line 130 "token.l"
+{ return(SPDFLUSH); }
+	YY_BREAK
+case 14:
+YY_RULE_SETUP
+#line 131 "token.l"
+{ return(TAGGED); }
+	YY_BREAK
+case 15:
+YY_RULE_SETUP
+#line 132 "token.l"
+{ BEGIN S_PL; return(F_POLICY); }
+	YY_BREAK
+case 16:
+/* rule 16 can match eol */
+YY_RULE_SETUP
+#line 133 "token.l"
+{
+			yymore();
+
+			/* count up for nl */
+			    {
+				char *p;
+				for (p = yytext; *p != '\0'; p++)
+					if (*p == '\n')
+						lineno++;
+			    }
+
+			yylval.val.len = strlen(yytext);
+			yylval.val.buf = strdup(yytext);
+			if (!yylval.val.buf)
+				yyfatal("insufficient memory");
+
+			return(PL_REQUESTS);
+		}
+	YY_BREAK
+case 17:
+YY_RULE_SETUP
+#line 151 "token.l"
+{ BEGIN INITIAL; return(EOT); }
+	YY_BREAK
+/* address resolution flags */
+case 18:
+YY_RULE_SETUP
+#line 154 "token.l"
+{
+			yylval.val.len = strlen(yytext);
+			yylval.val.buf = strdup(yytext);
+			if (!yylval.val.buf)
+				yyfatal("insufficient memory");
+			return(F_AIFLAGS);
+		}
+	YY_BREAK
+/* security protocols */
+case 19:
+YY_RULE_SETUP
+#line 163 "token.l"
+{ yylval.num = 0; return(PR_AH); }
+	YY_BREAK
+case 20:
+YY_RULE_SETUP
+#line 164 "token.l"
+{ yylval.num = 0; return(PR_ESP); }
+	YY_BREAK
+case 21:
+YY_RULE_SETUP
+#line 165 "token.l"
+{ yylval.num = 1; return(PR_AH); }
+	YY_BREAK
+case 22:
+YY_RULE_SETUP
+#line 166 "token.l"
+{ yylval.num = 1; return(PR_ESP); }
+	YY_BREAK
+case 23:
+YY_RULE_SETUP
+#line 167 "token.l"
+{ yylval.num = 0; return(PR_ESPUDP); }
+	YY_BREAK
+case 24:
+YY_RULE_SETUP
+#line 168 "token.l"
+{ yylval.num = 0; return(PR_IPCOMP); }
+	YY_BREAK
+case 25:
+YY_RULE_SETUP
+#line 169 "token.l"
+{ 
+			yylval.num = 0; return(PR_TCP); 
+		}
+	YY_BREAK
+/* authentication alogorithm */
+case 26:
+YY_RULE_SETUP
+#line 174 "token.l"
+{ BEGIN S_AUTHALG; return(F_AUTH); }
+	YY_BREAK
+case 27:
+YY_RULE_SETUP
+#line 175 "token.l"
+{ yylval.num = SADB_AALG_MD5HMAC; BEGIN INITIAL; return(ALG_AUTH); }
+	YY_BREAK
+case 28:
+YY_RULE_SETUP
+#line 176 "token.l"
+{ yylval.num = SADB_AALG_SHA1HMAC; BEGIN INITIAL; return(ALG_AUTH); }
+	YY_BREAK
+case 29:
+YY_RULE_SETUP
+#line 177 "token.l"
+{ yylval.num = SADB_X_AALG_MD5; BEGIN INITIAL; return(ALG_AUTH); }
+	YY_BREAK
+case 30:
+YY_RULE_SETUP
+#line 178 "token.l"
+{ yylval.num = SADB_X_AALG_SHA; BEGIN INITIAL; return(ALG_AUTH); }
+	YY_BREAK
+case 31:
+YY_RULE_SETUP
+#line 179 "token.l"
+{ yylval.num = SADB_X_AALG_SHA2_256; BEGIN INITIAL; return(ALG_AUTH); }
+	YY_BREAK
+case 32:
+YY_RULE_SETUP
+#line 180 "token.l"
+{ yylval.num = SADB_X_AALG_SHA2_256; BEGIN INITIAL; return(ALG_AUTH); }
+	YY_BREAK
+case 33:
+YY_RULE_SETUP
+#line 181 "token.l"
+{ yylval.num = SADB_X_AALG_SHA2_384; BEGIN INITIAL; return(ALG_AUTH); }
+	YY_BREAK
+case 34:
+YY_RULE_SETUP
+#line 182 "token.l"
+{ yylval.num = SADB_X_AALG_SHA2_384; BEGIN INITIAL; return(ALG_AUTH); }
+	YY_BREAK
+case 35:
+YY_RULE_SETUP
+#line 183 "token.l"
+{ yylval.num = SADB_X_AALG_SHA2_512; BEGIN INITIAL; return(ALG_AUTH); }
+	YY_BREAK
+case 36:
+YY_RULE_SETUP
+#line 184 "token.l"
+{ yylval.num = SADB_X_AALG_SHA2_512; BEGIN INITIAL; return(ALG_AUTH); }
+	YY_BREAK
+case 37:
+YY_RULE_SETUP
+#line 185 "token.l"
+{ yylval.num = SADB_X_AALG_RIPEMD160HMAC; BEGIN INITIAL; return(ALG_AUTH); }
+	YY_BREAK
+case 38:
+YY_RULE_SETUP
+#line 186 "token.l"
+{ yylval.num = SADB_X_AALG_AES_XCBC_MAC; BEGIN INITIAL; return(ALG_AUTH); }
+	YY_BREAK
+case 39:
+YY_RULE_SETUP
+#line 187 "token.l"
+{ 
+#ifdef SADB_X_AALG_TCP_MD5
+				yylval.num = SADB_X_AALG_TCP_MD5; 
+				BEGIN INITIAL; 
+				return(ALG_AUTH); 
+#endif
+			}
+	YY_BREAK
+case 40:
+YY_RULE_SETUP
+#line 194 "token.l"
+{ yylval.num = SADB_X_AALG_NULL; BEGIN INITIAL; return(ALG_AUTH_NOKEY); }
+	YY_BREAK
+/* encryption alogorithm */
+case 41:
+YY_RULE_SETUP
+#line 197 "token.l"
+{ BEGIN S_ENCALG; return(F_ENC); }
+	YY_BREAK
+case 42:
+YY_RULE_SETUP
+#line 198 "token.l"
+{ yylval.num = SADB_EALG_DESCBC; BEGIN INITIAL; return(ALG_ENC); }
+	YY_BREAK
+case 43:
+YY_RULE_SETUP
+#line 199 "token.l"
+{ yylval.num = SADB_EALG_3DESCBC; BEGIN INITIAL; return(ALG_ENC); }
+	YY_BREAK
+case 44:
+YY_RULE_SETUP
+#line 200 "token.l"
+{ yylval.num = SADB_EALG_NULL; BEGIN INITIAL; return(ALG_ENC_NOKEY); }
+	YY_BREAK
+case 45:
+YY_RULE_SETUP
+#line 201 "token.l"
+{ yylval.num = SADB_EALG_NULL; BEGIN INITIAL; return(ALG_ENC_OLD); }
+	YY_BREAK
+case 46:
+YY_RULE_SETUP
+#line 202 "token.l"
+{ yylval.num = SADB_X_EALG_BLOWFISHCBC; BEGIN INITIAL; return(ALG_ENC); }
+	YY_BREAK
+case 47:
+YY_RULE_SETUP
+#line 203 "token.l"
+{ yylval.num = SADB_X_EALG_CAST128CBC; BEGIN INITIAL; return(ALG_ENC); }
+	YY_BREAK
+case 48:
+YY_RULE_SETUP
+#line 204 "token.l"
+{ yylval.num = SADB_EALG_DESCBC; BEGIN INITIAL; return(ALG_ENC_DESDERIV); }
+	YY_BREAK
+case 49:
+YY_RULE_SETUP
+#line 205 "token.l"
+{ yylval.num = SADB_EALG_DESCBC; BEGIN INITIAL; return(ALG_ENC_DES32IV); }
+	YY_BREAK
+case 50:
+YY_RULE_SETUP
+#line 206 "token.l"
+{ yylval.num = SADB_X_EALG_TWOFISHCBC; BEGIN INITIAL; return(ALG_ENC); }
+	YY_BREAK
+case 51:
+YY_RULE_SETUP
+#line 207 "token.l"
+{ 
+#ifdef SADB_X_EALG_AESCBC
+	yylval.num = SADB_X_EALG_AESCBC; BEGIN INITIAL; return(ALG_ENC); 
+#endif
+}
+	YY_BREAK
+case 52:
+YY_RULE_SETUP
+#line 212 "token.l"
+{ 
+#ifdef SADB_X_EALG_AESCBC
+	yylval.num = SADB_X_EALG_AESCBC; BEGIN INITIAL; return(ALG_ENC); 
+#endif
+}
+	YY_BREAK
+case 53:
+YY_RULE_SETUP
+#line 217 "token.l"
+{ yylval.num = SADB_X_EALG_AESCTR; BEGIN INITIAL; return(ALG_ENC); }
+	YY_BREAK
+case 54:
+YY_RULE_SETUP
+#line 218 "token.l"
+{ 
+#ifdef SADB_X_EALG_CAMELLIACBC
+	yylval.num = SADB_X_EALG_CAMELLIACBC; BEGIN INITIAL; return(ALG_ENC); 
+#endif
+}
+	YY_BREAK
+/* compression algorithms */
+case 55:
+YY_RULE_SETUP
+#line 225 "token.l"
+{ return(F_COMP); }
+	YY_BREAK
+case 56:
+YY_RULE_SETUP
+#line 226 "token.l"
+{ yylval.num = SADB_X_CALG_OUI; return(ALG_COMP); }
+	YY_BREAK
+case 57:
+YY_RULE_SETUP
+#line 227 "token.l"
+{ yylval.num = SADB_X_CALG_DEFLATE; return(ALG_COMP); }
+	YY_BREAK
+case 58:
+YY_RULE_SETUP
+#line 228 "token.l"
+{ yylval.num = SADB_X_CALG_LZS; return(ALG_COMP); }
+	YY_BREAK
+case 59:
+YY_RULE_SETUP
+#line 229 "token.l"
+{ return(F_RAWCPI); }
+	YY_BREAK
+/* extension */
+case 60:
+YY_RULE_SETUP
+#line 232 "token.l"
+{ return(F_MODE); }
+	YY_BREAK
+case 61:
+YY_RULE_SETUP
+#line 233 "token.l"
+{ yylval.num = IPSEC_MODE_TRANSPORT; return(MODE); }
+	YY_BREAK
+case 62:
+YY_RULE_SETUP
+#line 234 "token.l"
+{ yylval.num = IPSEC_MODE_TUNNEL; return(MODE); }
+	YY_BREAK
+case 63:
+YY_RULE_SETUP
+#line 235 "token.l"
+{ return(F_REQID); }
+	YY_BREAK
+case 64:
+YY_RULE_SETUP
+#line 236 "token.l"
+{ return(F_EXT); }
+	YY_BREAK
+case 65:
+YY_RULE_SETUP
+#line 237 "token.l"
+{ yylval.num = SADB_X_EXT_PRAND; return(EXTENSION); }
+	YY_BREAK
+case 66:
+YY_RULE_SETUP
+#line 238 "token.l"
+{ yylval.num = SADB_X_EXT_PSEQ; return(EXTENSION); }
+	YY_BREAK
+case 67:
+YY_RULE_SETUP
+#line 239 "token.l"
+{ yylval.num = SADB_X_EXT_PZERO; return(EXTENSION); }
+	YY_BREAK
+case 68:
+YY_RULE_SETUP
+#line 240 "token.l"
+{ return(NOCYCLICSEQ); }
+	YY_BREAK
+case 69:
+YY_RULE_SETUP
+#line 241 "token.l"
+{ return(F_REPLAY); }
+	YY_BREAK
+case 70:
+YY_RULE_SETUP
+#line 242 "token.l"
+{ return(F_LIFETIME_HARD); }
+	YY_BREAK
+case 71:
+YY_RULE_SETUP
+#line 243 "token.l"
+{ return(F_LIFETIME_SOFT); }
+	YY_BREAK
+case 72:
+YY_RULE_SETUP
+#line 244 "token.l"
+{ return(F_LIFEBYTE_HARD); }
+	YY_BREAK
+case 73:
+YY_RULE_SETUP
+#line 245 "token.l"
+{ return(F_LIFEBYTE_SOFT); }
+	YY_BREAK
+case 74:
+YY_RULE_SETUP
+#line 246 "token.l"
+{ return(SECURITY_CTX); }
+	YY_BREAK
+/* ... */
+case 75:
+YY_RULE_SETUP
+#line 249 "token.l"
+{ return(ANY); }
+	YY_BREAK
+case 76:
+YY_RULE_SETUP
+#line 250 "token.l"
+{ }
+	YY_BREAK
+case 77:
+/* rule 77 can match eol */
+YY_RULE_SETUP
+#line 251 "token.l"
+{ lineno++; }
+	YY_BREAK
+case 78:
+YY_RULE_SETUP
+#line 252 "token.l"
+
+	YY_BREAK
+case 79:
+YY_RULE_SETUP
+#line 253 "token.l"
+{ return(EOT); }
+	YY_BREAK
+/* for address parameters: /prefix, [port] */
+case 80:
+YY_RULE_SETUP
+#line 256 "token.l"
+{ return SLASH; }
+	YY_BREAK
+case 81:
+YY_RULE_SETUP
+#line 257 "token.l"
+{ return BLCL; }
+	YY_BREAK
+case 82:
+YY_RULE_SETUP
+#line 258 "token.l"
+{ return ELCL; }
+	YY_BREAK
+/* parameter */
+case 83:
+YY_RULE_SETUP
+#line 261 "token.l"
+{
+			char *bp;
+
+			yylval.ulnum = strtoul(yytext, &bp, 10);
+			return(DECSTRING);
+		}
+	YY_BREAK
+case 84:
+YY_RULE_SETUP
+#line 268 "token.l"
+{
+			yylval.val.buf = strdup(yytext + 2);
+			if (!yylval.val.buf)
+				yyfatal("insufficient memory");
+			yylval.val.len = strlen(yylval.val.buf);
+
+			return(HEXSTRING);
+		}
+	YY_BREAK
+case 85:
+/* rule 85 can match eol */
+YY_RULE_SETUP
+#line 277 "token.l"
+{
+			char *p = yytext;
+			while (*++p != '"') ;
+			*p = '\0';
+			yytext++;
+			yylval.val.len = yyleng - 2;
+			yylval.val.buf = strdup(yytext);
+			if (!yylval.val.buf)
+				yyfatal("insufficient memory");
+
+			return(QUOTEDSTRING);
+		}
+	YY_BREAK
+case 86:
+YY_RULE_SETUP
+#line 290 "token.l"
+{
+			yylval.val.len = yyleng;
+			yylval.val.buf = strdup(yytext);
+			if (!yylval.val.buf)
+				yyfatal("insufficient memory");
+			return(STRING);
+		}
+	YY_BREAK
+case 87:
+YY_RULE_SETUP
+#line 298 "token.l"
+{
+			yylval.val.len = yyleng;
+			yylval.val.buf = strdup(yytext);
+			if (!yylval.val.buf)
+				yyfatal("insufficient memory");
+			return(STRING);
+		}
+	YY_BREAK
+case 88:
+YY_RULE_SETUP
+#line 306 "token.l"
+{
+			yyfatal("Syntax error");
+			/*NOTREACHED*/
+		}
+	YY_BREAK
+case 89:
+YY_RULE_SETUP
+#line 311 "token.l"
+ECHO;
+	YY_BREAK
+#line 1885 "token.c"
+case YY_STATE_EOF(INITIAL):
+case YY_STATE_EOF(S_PL):
+case YY_STATE_EOF(S_AUTHALG):
+case YY_STATE_EOF(S_ENCALG):
+	yyterminate();
+
+	case YY_END_OF_BUFFER:
+		{
+		/* Amount of text matched not including the EOB char. */
+		int yy_amount_of_matched_text = (int) (yy_cp - (yytext_ptr)) - 1;
+
+		/* Undo the effects of YY_DO_BEFORE_ACTION. */
+		*yy_cp = (yy_hold_char);
+		YY_RESTORE_YY_MORE_OFFSET
+
+		if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW )
+			{
+			/* We're scanning a new file or input source.  It's
+			 * possible that this happened because the user
+			 * just pointed yyin at a new source and called
+			 * yylex().  If so, then we have to assure
+			 * consistency between YY_CURRENT_BUFFER and our
+			 * globals.  Here is the right place to do so, because
+			 * this is the first action (other than possibly a
+			 * back-up) that will match for the new input source.
+			 */
+			(yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
+			YY_CURRENT_BUFFER_LVALUE->yy_input_file = yyin;
+			YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL;
+			}
+
+		/* Note that here we test for yy_c_buf_p "<=" to the position
+		 * of the first EOB in the buffer, since yy_c_buf_p will
+		 * already have been incremented past the NUL character
+		 * (since all states make transitions on EOB to the
+		 * end-of-buffer state).  Contrast this with the test
+		 * in input().
+		 */
+		if ( (yy_c_buf_p) <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] )
+			{ /* This was really a NUL. */
+			yy_state_type yy_next_state;
+
+			(yy_c_buf_p) = (yytext_ptr) + yy_amount_of_matched_text;
+
+			yy_current_state = yy_get_previous_state(  );
+
+			/* Okay, we're now positioned to make the NUL
+			 * transition.  We couldn't have
+			 * yy_get_previous_state() go ahead and do it
+			 * for us because it doesn't know how to deal
+			 * with the possibility of jamming (and we don't
+			 * want to build jamming into it because then it
+			 * will run more slowly).
+			 */
+
+			yy_next_state = yy_try_NUL_trans( yy_current_state );
+
+			yy_bp = (yytext_ptr) + YY_MORE_ADJ;
+
+			if ( yy_next_state )
+				{
+				/* Consume the NUL. */
+				yy_cp = ++(yy_c_buf_p);
+				yy_current_state = yy_next_state;
+				goto yy_match;
+				}
+
+			else
+				{
+				yy_cp = (yy_c_buf_p);
+				goto yy_find_action;
+				}
+			}
+
+		else switch ( yy_get_next_buffer(  ) )
+			{
+			case EOB_ACT_END_OF_FILE:
+				{
+				(yy_did_buffer_switch_on_eof) = 0;
+
+				if ( yywrap( ) )
+					{
+					/* Note: because we've taken care in
+					 * yy_get_next_buffer() to have set up
+					 * yytext, we can now set up
+					 * yy_c_buf_p so that if some total
+					 * hoser (like flex itself) wants to
+					 * call the scanner after we return the
+					 * YY_NULL, it'll still work - another
+					 * YY_NULL will get returned.
+					 */
+					(yy_c_buf_p) = (yytext_ptr) + YY_MORE_ADJ;
+
+					yy_act = YY_STATE_EOF(YY_START);
+					goto do_action;
+					}
+
+				else
+					{
+					if ( ! (yy_did_buffer_switch_on_eof) )
+						YY_NEW_FILE;
+					}
+				break;
+				}
+
+			case EOB_ACT_CONTINUE_SCAN:
+				(yy_c_buf_p) =
+					(yytext_ptr) + yy_amount_of_matched_text;
+
+				yy_current_state = yy_get_previous_state(  );
+
+				yy_cp = (yy_c_buf_p);
+				yy_bp = (yytext_ptr) + YY_MORE_ADJ;
+				goto yy_match;
+
+			case EOB_ACT_LAST_MATCH:
+				(yy_c_buf_p) =
+				&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)];
+
+				yy_current_state = yy_get_previous_state(  );
+
+				yy_cp = (yy_c_buf_p);
+				yy_bp = (yytext_ptr) + YY_MORE_ADJ;
+				goto yy_find_action;
+			}
+		break;
+		}
+
+	default:
+		YY_FATAL_ERROR(
+			"fatal flex scanner internal error--no action found" );
+	} /* end of action switch */
+		} /* end of scanning one token */
+} /* end of yylex */
+
+/* yy_get_next_buffer - try to read in a new buffer
+ *
+ * Returns a code representing an action:
+ *	EOB_ACT_LAST_MATCH -
+ *	EOB_ACT_CONTINUE_SCAN - continue scanning from current position
+ *	EOB_ACT_END_OF_FILE - end of file
+ */
+static int yy_get_next_buffer (void)
+{
+    	register char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf;
+	register char *source = (yytext_ptr);
+	register int number_to_move, i;
+	int ret_val;
+
+	if ( (yy_c_buf_p) > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] )
+		YY_FATAL_ERROR(
+		"fatal flex scanner internal error--end of buffer missed" );
+
+	if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 )
+		{ /* Don't try to fill the buffer, so this is an EOF. */
+		if ( (yy_c_buf_p) - (yytext_ptr) - YY_MORE_ADJ == 1 )
+			{
+			/* We matched a single character, the EOB, so
+			 * treat this as a final EOF.
+			 */
+			return EOB_ACT_END_OF_FILE;
+			}
+
+		else
+			{
+			/* We matched some text prior to the EOB, first
+			 * process it.
+			 */
+			return EOB_ACT_LAST_MATCH;
+			}
+		}
+
+	/* Try to read more data. */
+
+	/* First move last chars to start of buffer. */
+	number_to_move = (int) ((yy_c_buf_p) - (yytext_ptr)) - 1;
+
+	for ( i = 0; i < number_to_move; ++i )
+		*(dest++) = *(source++);
+
+	if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING )
+		/* don't do the read, it's not guaranteed to return an EOF,
+		 * just force an EOF
+		 */
+		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars) = 0;
+
+	else
+		{
+			int num_to_read =
+			YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1;
+
+		while ( num_to_read <= 0 )
+			{ /* Not enough room in the buffer - grow it. */
+
+			/* just a shorter name for the current buffer */
+			YY_BUFFER_STATE b = YY_CURRENT_BUFFER;
+
+			int yy_c_buf_p_offset =
+				(int) ((yy_c_buf_p) - b->yy_ch_buf);
+
+			if ( b->yy_is_our_buffer )
+				{
+				int new_size = b->yy_buf_size * 2;
+
+				if ( new_size <= 0 )
+					b->yy_buf_size += b->yy_buf_size / 8;
+				else
+					b->yy_buf_size *= 2;
+
+				b->yy_ch_buf = (char *)
+					/* Include room in for 2 EOB chars. */
+					yyrealloc((void *) b->yy_ch_buf,b->yy_buf_size + 2  );
+				}
+			else
+				/* Can't grow it, we don't own it. */
+				b->yy_ch_buf = 0;
+
+			if ( ! b->yy_ch_buf )
+				YY_FATAL_ERROR(
+				"fatal error - scanner input buffer overflow" );
+
+			(yy_c_buf_p) = &b->yy_ch_buf[yy_c_buf_p_offset];
+
+			num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size -
+						number_to_move - 1;
+
+			}
+
+		if ( num_to_read > YY_READ_BUF_SIZE )
+			num_to_read = YY_READ_BUF_SIZE;
+
+		/* Read in more data. */
+		YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]),
+			(yy_n_chars), (size_t) num_to_read );
+
+		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
+		}
+
+	if ( (yy_n_chars) == 0 )
+		{
+		if ( number_to_move == YY_MORE_ADJ )
+			{
+			ret_val = EOB_ACT_END_OF_FILE;
+			yyrestart(yyin  );
+			}
+
+		else
+			{
+			ret_val = EOB_ACT_LAST_MATCH;
+			YY_CURRENT_BUFFER_LVALUE->yy_buffer_status =
+				YY_BUFFER_EOF_PENDING;
+			}
+		}
+
+	else
+		ret_val = EOB_ACT_CONTINUE_SCAN;
+
+	if ((yy_size_t) ((yy_n_chars) + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) {
+		/* Extend the array by 50%, plus the number we really need. */
+		yy_size_t new_size = (yy_n_chars) + number_to_move + ((yy_n_chars) >> 1);
+		YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) yyrealloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size  );
+		if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
+			YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" );
+	}
+
+	(yy_n_chars) += number_to_move;
+	YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] = YY_END_OF_BUFFER_CHAR;
+	YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] = YY_END_OF_BUFFER_CHAR;
+
+	(yytext_ptr) = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0];
+
+	return ret_val;
+}
+
+/* yy_get_previous_state - get the state just before the EOB char was reached */
+
+    static yy_state_type yy_get_previous_state (void)
+{
+	register yy_state_type yy_current_state;
+	register char *yy_cp;
+    
+	yy_current_state = (yy_start);
+
+	for ( yy_cp = (yytext_ptr) + YY_MORE_ADJ; yy_cp < (yy_c_buf_p); ++yy_cp )
+		{
+		register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1);
+		if ( yy_accept[yy_current_state] )
+			{
+			(yy_last_accepting_state) = yy_current_state;
+			(yy_last_accepting_cpos) = yy_cp;
+			}
+		while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+			{
+			yy_current_state = (int) yy_def[yy_current_state];
+			if ( yy_current_state >= 552 )
+				yy_c = yy_meta[(unsigned int) yy_c];
+			}
+		yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+		}
+
+	return yy_current_state;
+}
+
+/* yy_try_NUL_trans - try to make a transition on the NUL character
+ *
+ * synopsis
+ *	next_state = yy_try_NUL_trans( current_state );
+ */
+    static yy_state_type yy_try_NUL_trans  (yy_state_type yy_current_state )
+{
+	register int yy_is_jam;
+    	register char *yy_cp = (yy_c_buf_p);
+
+	register YY_CHAR yy_c = 1;
+	if ( yy_accept[yy_current_state] )
+		{
+		(yy_last_accepting_state) = yy_current_state;
+		(yy_last_accepting_cpos) = yy_cp;
+		}
+	while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+		{
+		yy_current_state = (int) yy_def[yy_current_state];
+		if ( yy_current_state >= 552 )
+			yy_c = yy_meta[(unsigned int) yy_c];
+		}
+	yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+	yy_is_jam = (yy_current_state == 551);
+
+	return yy_is_jam ? 0 : yy_current_state;
+}
+
+    static void yyunput (int c, register char * yy_bp )
+{
+	register char *yy_cp;
+    
+    yy_cp = (yy_c_buf_p);
+
+	/* undo effects of setting up yytext */
+	*yy_cp = (yy_hold_char);
+
+	if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 )
+		{ /* need to shift things up to make room */
+		/* +2 for EOB chars. */
+		register int number_to_move = (yy_n_chars) + 2;
+		register char *dest = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[
+					YY_CURRENT_BUFFER_LVALUE->yy_buf_size + 2];
+		register char *source =
+				&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move];
+
+		while ( source > YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
+			*--dest = *--source;
+
+		yy_cp += (int) (dest - source);
+		yy_bp += (int) (dest - source);
+		YY_CURRENT_BUFFER_LVALUE->yy_n_chars =
+			(yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_buf_size;
+
+		if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 )
+			YY_FATAL_ERROR( "flex scanner push-back overflow" );
+		}
+
+	*--yy_cp = (char) c;
+
+	(yytext_ptr) = yy_bp;
+	(yy_hold_char) = *yy_cp;
+	(yy_c_buf_p) = yy_cp;
+}
+
+#ifndef YY_NO_INPUT
+#ifdef __cplusplus
+    static int yyinput (void)
+#else
+    static int input  (void)
+#endif
+
+{
+	int c;
+    
+	*(yy_c_buf_p) = (yy_hold_char);
+
+	if ( *(yy_c_buf_p) == YY_END_OF_BUFFER_CHAR )
+		{
+		/* yy_c_buf_p now points to the character we want to return.
+		 * If this occurs *before* the EOB characters, then it's a
+		 * valid NUL; if not, then we've hit the end of the buffer.
+		 */
+		if ( (yy_c_buf_p) < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] )
+			/* This was really a NUL. */
+			*(yy_c_buf_p) = '\0';
+
+		else
+			{ /* need more input */
+			int offset = (yy_c_buf_p) - (yytext_ptr);
+			++(yy_c_buf_p);
+
+			switch ( yy_get_next_buffer(  ) )
+				{
+				case EOB_ACT_LAST_MATCH:
+					/* This happens because yy_g_n_b()
+					 * sees that we've accumulated a
+					 * token and flags that we need to
+					 * try matching the token before
+					 * proceeding.  But for input(),
+					 * there's no matching to consider.
+					 * So convert the EOB_ACT_LAST_MATCH
+					 * to EOB_ACT_END_OF_FILE.
+					 */
+
+					/* Reset buffer status. */
+					yyrestart(yyin );
+
+					/*FALLTHROUGH*/
+
+				case EOB_ACT_END_OF_FILE:
+					{
+					if ( yywrap( ) )
+						return EOF;
+
+					if ( ! (yy_did_buffer_switch_on_eof) )
+						YY_NEW_FILE;
+#ifdef __cplusplus
+					return yyinput();
+#else
+					return input();
+#endif
+					}
+
+				case EOB_ACT_CONTINUE_SCAN:
+					(yy_c_buf_p) = (yytext_ptr) + offset;
+					break;
+				}
+			}
+		}
+
+	c = *(unsigned char *) (yy_c_buf_p);	/* cast for 8-bit char's */
+	*(yy_c_buf_p) = '\0';	/* preserve yytext */
+	(yy_hold_char) = *++(yy_c_buf_p);
+
+	return c;
+}
+#endif	/* ifndef YY_NO_INPUT */
+
+/** Immediately switch to a different input stream.
+ * @param input_file A readable stream.
+ * 
+ * @note This function does not reset the start condition to @c INITIAL .
+ */
+    void yyrestart  (FILE * input_file )
+{
+    
+	if ( ! YY_CURRENT_BUFFER ){
+        yyensure_buffer_stack ();
+		YY_CURRENT_BUFFER_LVALUE =
+            yy_create_buffer(yyin,YY_BUF_SIZE );
+	}
+
+	yy_init_buffer(YY_CURRENT_BUFFER,input_file );
+	yy_load_buffer_state( );
+}
+
+/** Switch to a different input buffer.
+ * @param new_buffer The new input buffer.
+ * 
+ */
+    void yy_switch_to_buffer  (YY_BUFFER_STATE  new_buffer )
+{
+    
+	/* TODO. We should be able to replace this entire function body
+	 * with
+	 *		yypop_buffer_state();
+	 *		yypush_buffer_state(new_buffer);
+     */
+	yyensure_buffer_stack ();
+	if ( YY_CURRENT_BUFFER == new_buffer )
+		return;
+
+	if ( YY_CURRENT_BUFFER )
+		{
+		/* Flush out information for old buffer. */
+		*(yy_c_buf_p) = (yy_hold_char);
+		YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p);
+		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
+		}
+
+	YY_CURRENT_BUFFER_LVALUE = new_buffer;
+	yy_load_buffer_state( );
+
+	/* We don't actually know whether we did this switch during
+	 * EOF (yywrap()) processing, but the only time this flag
+	 * is looked at is after yywrap() is called, so it's safe
+	 * to go ahead and always set it.
+	 */
+	(yy_did_buffer_switch_on_eof) = 1;
+}
+
+static void yy_load_buffer_state  (void)
+{
+    	(yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
+	(yytext_ptr) = (yy_c_buf_p) = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos;
+	yyin = YY_CURRENT_BUFFER_LVALUE->yy_input_file;
+	(yy_hold_char) = *(yy_c_buf_p);
+}
+
+/** Allocate and initialize an input buffer state.
+ * @param file A readable stream.
+ * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE.
+ * 
+ * @return the allocated buffer state.
+ */
+    YY_BUFFER_STATE yy_create_buffer  (FILE * file, int  size )
+{
+	YY_BUFFER_STATE b;
+    
+	b = (YY_BUFFER_STATE) yyalloc(sizeof( struct yy_buffer_state )  );
+	if ( ! b )
+		YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
+
+	b->yy_buf_size = size;
+
+	/* yy_ch_buf has to be 2 characters longer than the size given because
+	 * we need to put in 2 end-of-buffer characters.
+	 */
+	b->yy_ch_buf = (char *) yyalloc(b->yy_buf_size + 2  );
+	if ( ! b->yy_ch_buf )
+		YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
+
+	b->yy_is_our_buffer = 1;
+
+	yy_init_buffer(b,file );
+
+	return b;
+}
+
+/** Destroy the buffer.
+ * @param b a buffer created with yy_create_buffer()
+ * 
+ */
+    void yy_delete_buffer (YY_BUFFER_STATE  b )
+{
+    
+	if ( ! b )
+		return;
+
+	if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */
+		YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0;
+
+	if ( b->yy_is_our_buffer )
+		yyfree((void *) b->yy_ch_buf  );
+
+	yyfree((void *) b  );
+}
+
+#ifndef __cplusplus
+extern int isatty (int );
+#endif /* __cplusplus */
+    
+/* Initializes or reinitializes a buffer.
+ * This function is sometimes called more than once on the same buffer,
+ * such as during a yyrestart() or at EOF.
+ */
+    static void yy_init_buffer  (YY_BUFFER_STATE  b, FILE * file )
+
+{
+	int oerrno = errno;
+    
+	yy_flush_buffer(b );
+
+	b->yy_input_file = file;
+	b->yy_fill_buffer = 1;
+
+    /* If b is the current buffer, then yy_init_buffer was _probably_
+     * called from yyrestart() or through yy_get_next_buffer.
+     * In that case, we don't want to reset the lineno or column.
+     */
+    if (b != YY_CURRENT_BUFFER){
+        b->yy_bs_lineno = 1;
+        b->yy_bs_column = 0;
+    }
+
+        b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0;
+    
+	errno = oerrno;
+}
+
+/** Discard all buffered characters. On the next scan, YY_INPUT will be called.
+ * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER.
+ * 
+ */
+    void yy_flush_buffer (YY_BUFFER_STATE  b )
+{
+    	if ( ! b )
+		return;
+
+	b->yy_n_chars = 0;
+
+	/* We always need two end-of-buffer characters.  The first causes
+	 * a transition to the end-of-buffer state.  The second causes
+	 * a jam in that state.
+	 */
+	b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR;
+	b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR;
+
+	b->yy_buf_pos = &b->yy_ch_buf[0];
+
+	b->yy_at_bol = 1;
+	b->yy_buffer_status = YY_BUFFER_NEW;
+
+	if ( b == YY_CURRENT_BUFFER )
+		yy_load_buffer_state( );
+}
+
+/** Pushes the new state onto the stack. The new state becomes
+ *  the current state. This function will allocate the stack
+ *  if necessary.
+ *  @param new_buffer The new state.
+ *  
+ */
+void yypush_buffer_state (YY_BUFFER_STATE new_buffer )
+{
+    	if (new_buffer == NULL)
+		return;
+
+	yyensure_buffer_stack();
+
+	/* This block is copied from yy_switch_to_buffer. */
+	if ( YY_CURRENT_BUFFER )
+		{
+		/* Flush out information for old buffer. */
+		*(yy_c_buf_p) = (yy_hold_char);
+		YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p);
+		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
+		}
+
+	/* Only push if top exists. Otherwise, replace top. */
+	if (YY_CURRENT_BUFFER)
+		(yy_buffer_stack_top)++;
+	YY_CURRENT_BUFFER_LVALUE = new_buffer;
+
+	/* copied from yy_switch_to_buffer. */
+	yy_load_buffer_state( );
+	(yy_did_buffer_switch_on_eof) = 1;
+}
+
+/** Removes and deletes the top of the stack, if present.
+ *  The next element becomes the new top.
+ *  
+ */
+void yypop_buffer_state (void)
+{
+    	if (!YY_CURRENT_BUFFER)
+		return;
+
+	yy_delete_buffer(YY_CURRENT_BUFFER );
+	YY_CURRENT_BUFFER_LVALUE = NULL;
+	if ((yy_buffer_stack_top) > 0)
+		--(yy_buffer_stack_top);
+
+	if (YY_CURRENT_BUFFER) {
+		yy_load_buffer_state( );
+		(yy_did_buffer_switch_on_eof) = 1;
+	}
+}
+
+/* Allocates the stack if it does not exist.
+ *  Guarantees space for at least one push.
+ */
+static void yyensure_buffer_stack (void)
+{
+	int num_to_alloc;
+    
+	if (!(yy_buffer_stack)) {
+
+		/* First allocation is just for 2 elements, since we don't know if this
+		 * scanner will even need a stack. We use 2 instead of 1 to avoid an
+		 * immediate realloc on the next call.
+         */
+		num_to_alloc = 1;
+		(yy_buffer_stack) = (struct yy_buffer_state**)yyalloc
+								(num_to_alloc * sizeof(struct yy_buffer_state*)
+								);
+		if ( ! (yy_buffer_stack) )
+			YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" );
+								  
+		memset((yy_buffer_stack), 0, num_to_alloc * sizeof(struct yy_buffer_state*));
+				
+		(yy_buffer_stack_max) = num_to_alloc;
+		(yy_buffer_stack_top) = 0;
+		return;
+	}
+
+	if ((yy_buffer_stack_top) >= ((yy_buffer_stack_max)) - 1){
+
+		/* Increase the buffer to prepare for a possible push. */
+		int grow_size = 8 /* arbitrary grow size */;
+
+		num_to_alloc = (yy_buffer_stack_max) + grow_size;
+		(yy_buffer_stack) = (struct yy_buffer_state**)yyrealloc
+								((yy_buffer_stack),
+								num_to_alloc * sizeof(struct yy_buffer_state*)
+								);
+		if ( ! (yy_buffer_stack) )
+			YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" );
+
+		/* zero only the new slots.*/
+		memset((yy_buffer_stack) + (yy_buffer_stack_max), 0, grow_size * sizeof(struct yy_buffer_state*));
+		(yy_buffer_stack_max) = num_to_alloc;
+	}
+}
+
+/** Setup the input buffer state to scan directly from a user-specified character buffer.
+ * @param base the character buffer
+ * @param size the size in bytes of the character buffer
+ * 
+ * @return the newly allocated buffer state object. 
+ */
+YY_BUFFER_STATE yy_scan_buffer  (char * base, yy_size_t  size )
+{
+	YY_BUFFER_STATE b;
+    
+	if ( size < 2 ||
+	     base[size-2] != YY_END_OF_BUFFER_CHAR ||
+	     base[size-1] != YY_END_OF_BUFFER_CHAR )
+		/* They forgot to leave room for the EOB's. */
+		return 0;
+
+	b = (YY_BUFFER_STATE) yyalloc(sizeof( struct yy_buffer_state )  );
+	if ( ! b )
+		YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" );
+
+	b->yy_buf_size = size - 2;	/* "- 2" to take care of EOB's */
+	b->yy_buf_pos = b->yy_ch_buf = base;
+	b->yy_is_our_buffer = 0;
+	b->yy_input_file = 0;
+	b->yy_n_chars = b->yy_buf_size;
+	b->yy_is_interactive = 0;
+	b->yy_at_bol = 1;
+	b->yy_fill_buffer = 0;
+	b->yy_buffer_status = YY_BUFFER_NEW;
+
+	yy_switch_to_buffer(b  );
+
+	return b;
+}
+
+/** Setup the input buffer state to scan a string. The next call to yylex() will
+ * scan from a @e copy of @a str.
+ * @param yystr a NUL-terminated string to scan
+ * 
+ * @return the newly allocated buffer state object.
+ * @note If you want to scan bytes that may contain NUL values, then use
+ *       yy_scan_bytes() instead.
+ */
+YY_BUFFER_STATE yy_scan_string (yyconst char * yystr )
+{
+    
+	return yy_scan_bytes(yystr,strlen(yystr) );
+}
+
+/** Setup the input buffer state to scan the given bytes. The next call to yylex() will
+ * scan from a @e copy of @a bytes.
+ * @param bytes the byte buffer to scan
+ * @param len the number of bytes in the buffer pointed to by @a bytes.
+ * 
+ * @return the newly allocated buffer state object.
+ */
+YY_BUFFER_STATE yy_scan_bytes  (yyconst char * yybytes, int  _yybytes_len )
+{
+	YY_BUFFER_STATE b;
+	char *buf;
+	yy_size_t n;
+	int i;
+    
+	/* Get memory for full buffer, including space for trailing EOB's. */
+	n = _yybytes_len + 2;
+	buf = (char *) yyalloc(n  );
+	if ( ! buf )
+		YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" );
+
+	for ( i = 0; i < _yybytes_len; ++i )
+		buf[i] = yybytes[i];
+
+	buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR;
+
+	b = yy_scan_buffer(buf,n );
+	if ( ! b )
+		YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" );
+
+	/* It's okay to grow etc. this buffer, and we should throw it
+	 * away when we're done.
+	 */
+	b->yy_is_our_buffer = 1;
+
+	return b;
+}
+
+#ifndef YY_EXIT_FAILURE
+#define YY_EXIT_FAILURE 2
+#endif
+
+static void yy_fatal_error (yyconst char* msg )
+{
+    	(void) fprintf( stderr, "%s\n", msg );
+	exit( YY_EXIT_FAILURE );
+}
+
+/* Redefine yyless() so it works in section 3 code. */
+
+#undef yyless
+#define yyless(n) \
+	do \
+		{ \
+		/* Undo effects of setting up yytext. */ \
+        int yyless_macro_arg = (n); \
+        YY_LESS_LINENO(yyless_macro_arg);\
+		yytext[yyleng] = (yy_hold_char); \
+		(yy_c_buf_p) = yytext + yyless_macro_arg; \
+		(yy_hold_char) = *(yy_c_buf_p); \
+		*(yy_c_buf_p) = '\0'; \
+		yyleng = yyless_macro_arg; \
+		} \
+	while ( 0 )
+
+/* Accessor  methods (get/set functions) to struct members. */
+
+/** Get the current line number.
+ * 
+ */
+int yyget_lineno  (void)
+{
+        
+    return yylineno;
+}
+
+/** Get the input stream.
+ * 
+ */
+FILE *yyget_in  (void)
+{
+        return yyin;
+}
+
+/** Get the output stream.
+ * 
+ */
+FILE *yyget_out  (void)
+{
+        return yyout;
+}
+
+/** Get the length of the current token.
+ * 
+ */
+int yyget_leng  (void)
+{
+        return yyleng;
+}
+
+/** Get the current token.
+ * 
+ */
+
+char *yyget_text  (void)
+{
+        return yytext;
+}
+
+/** Set the current line number.
+ * @param line_number
+ * 
+ */
+void yyset_lineno (int  line_number )
+{
+    
+    yylineno = line_number;
+}
+
+/** Set the input stream. This does not discard the current
+ * input buffer.
+ * @param in_str A readable stream.
+ * 
+ * @see yy_switch_to_buffer
+ */
+void yyset_in (FILE *  in_str )
+{
+        yyin = in_str ;
+}
+
+void yyset_out (FILE *  out_str )
+{
+        yyout = out_str ;
+}
+
+int yyget_debug  (void)
+{
+        return yy_flex_debug;
+}
+
+void yyset_debug (int  bdebug )
+{
+        yy_flex_debug = bdebug ;
+}
+
+static int yy_init_globals (void)
+{
+        /* Initialization is the same as for the non-reentrant scanner.
+     * This function is called from yylex_destroy(), so don't allocate here.
+     */
+
+    (yy_buffer_stack) = 0;
+    (yy_buffer_stack_top) = 0;
+    (yy_buffer_stack_max) = 0;
+    (yy_c_buf_p) = (char *) 0;
+    (yy_init) = 0;
+    (yy_start) = 0;
+
+/* Defined in main.c */
+#ifdef YY_STDINIT
+    yyin = stdin;
+    yyout = stdout;
+#else
+    yyin = (FILE *) 0;
+    yyout = (FILE *) 0;
+#endif
+
+    /* For future reference: Set errno on error, since we are called by
+     * yylex_init()
+     */
+    return 0;
+}
+
+/* yylex_destroy is for both reentrant and non-reentrant scanners. */
+int yylex_destroy  (void)
+{
+    
+    /* Pop the buffer stack, destroying each element. */
+	while(YY_CURRENT_BUFFER){
+		yy_delete_buffer(YY_CURRENT_BUFFER  );
+		YY_CURRENT_BUFFER_LVALUE = NULL;
+		yypop_buffer_state();
+	}
+
+	/* Destroy the stack itself. */
+	yyfree((yy_buffer_stack) );
+	(yy_buffer_stack) = NULL;
+
+    /* Reset the globals. This is important in a non-reentrant scanner so the next time
+     * yylex() is called, initialization will occur. */
+    yy_init_globals( );
+
+    return 0;
+}
+
+/*
+ * Internal utility routines.
+ */
+
+#ifndef yytext_ptr
+static void yy_flex_strncpy (char* s1, yyconst char * s2, int n )
+{
+	register int i;
+	for ( i = 0; i < n; ++i )
+		s1[i] = s2[i];
+}
+#endif
+
+#ifdef YY_NEED_STRLEN
+static int yy_flex_strlen (yyconst char * s )
+{
+	register int n;
+	for ( n = 0; s[n]; ++n )
+		;
+
+	return n;
+}
+#endif
+
+void *yyalloc (yy_size_t  size )
+{
+	return (void *) malloc( size );
+}
+
+void *yyrealloc  (void * ptr, yy_size_t  size )
+{
+	/* The cast to (char *) in the following accommodates both
+	 * implementations that use char* generic pointers, and those
+	 * that use void* generic pointers.  It works with the latter
+	 * because both ANSI C and C++ allow castless assignment from
+	 * any pointer type to void*, and deal with argument conversions
+	 * as though doing an assignment.
+	 */
+	return (void *) realloc( (char *) ptr, size );
+}
+
+void yyfree (void * ptr )
+{
+	free( (char *) ptr );	/* see yyrealloc() for (char *) cast */
+}
+
+#define YYTABLES_NAME "yytables"
+
+#line 311 "token.l"
+
+
+
+void
+yyfatal(s)
+	const char *s;
+{
+	yyerror(s);
+	exit(1);
+}
+
+void
+yyerror(s)
+	const char *s;
+{
+	printf("line %d: %s at [%s]\n", lineno, s, yytext);
+}
+
+int
+parse(fp)
+	FILE **fp;
+{
+	yyin = *fp;
+
+	lineno = 1;
+	parse_init();
+
+	if (yyparse()) {
+		printf("parse failed, line %d.\n", lineno);
+		return(-1);
+	}
+
+	return(0);
+}
+
+int
+parse_string (char *src)
+{
+	int             result;
+	YY_BUFFER_STATE buf_state;
+
+	buf_state = yy_scan_string(src);
+	result = yyparse();
+	yy_delete_buffer(buf_state);
+	return result;
+}
+
+
diff --git a/src/setkey/token.l b/src/setkey/token.l
new file mode 100644
index 0000000..9b60ffc
--- /dev/null
+++ b/src/setkey/token.l
@@ -0,0 +1,356 @@
+/*	$NetBSD: token.l,v 1.11.6.1 2007/08/01 11:52:23 vanhu Exp $	*/
+
+/*	$KAME: token.l,v 1.44 2003/10/21 07:20:58 itojun Exp $	*/
+
+/*
+ * Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+%{
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <net/pfkeyv2.h>
+#include <netinet/in.h>
+#include PATH_IPSEC_H
+
+#include <stdlib.h>
+#include <limits.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <netdb.h>
+
+#include "vchar.h"
+#if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__linux__) || \
+(defined(__APPLE__) && defined(__MACH__))
+#include "parse.h"
+#else
+#include "y.tab.h"
+#endif
+
+#include "extern.h"
+
+/* make the code compile on *BSD-current */
+#ifndef SADB_X_AALG_SHA2_256
+#define SADB_X_AALG_SHA2_256	(-1)
+#endif
+#ifndef SADB_X_AALG_SHA2_384
+#define SADB_X_AALG_SHA2_384	(-1)
+#endif
+#ifndef SADB_X_AALG_SHA2_512
+#define SADB_X_AALG_SHA2_512	(-1)
+#endif
+#ifndef SADB_X_AALG_RIPEMD160HMAC
+#define SADB_X_AALG_RIPEMD160HMAC	(-1)
+#endif
+#ifndef SADB_X_AALG_AES_XCBC_MAC
+#define SADB_X_AALG_AES_XCBC_MAC	(-1)
+#endif
+#ifndef SADB_X_EALG_TWOFISHCBC
+#define SADB_X_EALG_TWOFISHCBC	(-1)
+#endif
+#ifndef SADB_X_EALG_AESCTR
+#define SADB_X_EALG_AESCTR	(-1)
+#endif
+#if defined(SADB_X_EALG_AES) && ! defined(SADB_X_EALG_AESCBC)
+#define SADB_X_EALG_AESCBC  SADB_X_EALG_AES
+#endif
+%}
+
+/* common section */
+nl		\n
+ws		[ \t]+
+digit		[0-9]
+letter		[0-9A-Za-z]
+hexdigit	[0-9A-Fa-f]
+dot		\.
+hyphen		\-
+slash		\/
+blcl		\[
+elcl		\]
+semi		\;
+comment		\#.*
+quotedstring	\"[^"]*\"
+decstring	{digit}+
+hexstring	0[xX]{hexdigit}+
+ipaddress	[a-fA-F0-9:]([a-fA-F0-9:\.]*|[a-fA-F0-9:\.]*%[a-zA-Z0-9]*)
+ipaddrmask	{slash}{digit}{1,3}
+name		{letter}(({letter}|{digit}|{hyphen})*({letter}|{digit}))*
+hostname	{name}(({dot}{name})+{dot}?)?
+
+%s S_PL S_AUTHALG S_ENCALG
+
+%%
+
+add		{ return(ADD); }
+delete		{ return(DELETE); }
+deleteall	{ return(DELETEALL); }
+get		{ return(GET); }
+flush		{ return(FLUSH); }
+dump		{ return(DUMP); }
+exit		{ return(EXIT); }
+quit		{ return(EXIT); }
+bye		{ return(EXIT); }
+
+	/* for management SPD */
+spdadd		{ return(SPDADD); }
+spddelete	{ return(SPDDELETE); }
+spddump		{ return(SPDDUMP); }
+spdflush	{ return(SPDFLUSH); }
+tagged		{ return(TAGGED); }
+{hyphen}P	{ BEGIN S_PL; return(F_POLICY); }
+<S_PL>[a-zA-Z0-9:\.\-_/ \n\t][a-zA-Z0-9:\.%\-+_/ \n\t\]\[]* {
+			yymore();
+
+			/* count up for nl */
+			    {
+				char *p;
+				for (p = yytext; *p != '\0'; p++)
+					if (*p == '\n')
+						lineno++;
+			    }
+
+			yylval.val.len = strlen(yytext);
+			yylval.val.buf = strdup(yytext);
+			if (!yylval.val.buf)
+				yyfatal("insufficient memory");
+
+			return(PL_REQUESTS);
+		}
+<S_PL>{semi}	{ BEGIN INITIAL; return(EOT); }
+
+	/* address resolution flags */
+{hyphen}[n46][n46]*	{
+			yylval.val.len = strlen(yytext);
+			yylval.val.buf = strdup(yytext);
+			if (!yylval.val.buf)
+				yyfatal("insufficient memory");
+			return(F_AIFLAGS);
+		}
+
+	/* security protocols */
+ah		{ yylval.num = 0; return(PR_AH); }
+esp		{ yylval.num = 0; return(PR_ESP); }
+ah-old		{ yylval.num = 1; return(PR_AH); }
+esp-old		{ yylval.num = 1; return(PR_ESP); }
+esp-udp		{ yylval.num = 0; return(PR_ESPUDP); }
+ipcomp		{ yylval.num = 0; return(PR_IPCOMP); }
+tcp		{ 
+			yylval.num = 0; return(PR_TCP); 
+		}
+
+	/* authentication alogorithm */
+{hyphen}A	{ BEGIN S_AUTHALG; return(F_AUTH); }
+<S_AUTHALG>hmac-md5	{ yylval.num = SADB_AALG_MD5HMAC; BEGIN INITIAL; return(ALG_AUTH); }
+<S_AUTHALG>hmac-sha1	{ yylval.num = SADB_AALG_SHA1HMAC; BEGIN INITIAL; return(ALG_AUTH); }
+<S_AUTHALG>keyed-md5	{ yylval.num = SADB_X_AALG_MD5; BEGIN INITIAL; return(ALG_AUTH); }
+<S_AUTHALG>keyed-sha1	{ yylval.num = SADB_X_AALG_SHA; BEGIN INITIAL; return(ALG_AUTH); }
+<S_AUTHALG>hmac-sha2-256 { yylval.num = SADB_X_AALG_SHA2_256; BEGIN INITIAL; return(ALG_AUTH); }
+<S_AUTHALG>hmac-sha256 { yylval.num = SADB_X_AALG_SHA2_256; BEGIN INITIAL; return(ALG_AUTH); }
+<S_AUTHALG>hmac-sha2-384 { yylval.num = SADB_X_AALG_SHA2_384; BEGIN INITIAL; return(ALG_AUTH); }
+<S_AUTHALG>hmac-sha384 { yylval.num = SADB_X_AALG_SHA2_384; BEGIN INITIAL; return(ALG_AUTH); }
+<S_AUTHALG>hmac-sha2-512 { yylval.num = SADB_X_AALG_SHA2_512; BEGIN INITIAL; return(ALG_AUTH); }
+<S_AUTHALG>hmac-sha512 { yylval.num = SADB_X_AALG_SHA2_512; BEGIN INITIAL; return(ALG_AUTH); }
+<S_AUTHALG>hmac-ripemd160 { yylval.num = SADB_X_AALG_RIPEMD160HMAC; BEGIN INITIAL; return(ALG_AUTH); }
+<S_AUTHALG>aes-xcbc-mac { yylval.num = SADB_X_AALG_AES_XCBC_MAC; BEGIN INITIAL; return(ALG_AUTH); }
+<S_AUTHALG>tcp-md5	{ 
+#ifdef SADB_X_AALG_TCP_MD5
+				yylval.num = SADB_X_AALG_TCP_MD5; 
+				BEGIN INITIAL; 
+				return(ALG_AUTH); 
+#endif
+			}
+<S_AUTHALG>null { yylval.num = SADB_X_AALG_NULL; BEGIN INITIAL; return(ALG_AUTH_NOKEY); }
+
+	/* encryption alogorithm */
+{hyphen}E	{ BEGIN S_ENCALG; return(F_ENC); }
+<S_ENCALG>des-cbc	{ yylval.num = SADB_EALG_DESCBC; BEGIN INITIAL; return(ALG_ENC); }
+<S_ENCALG>3des-cbc	{ yylval.num = SADB_EALG_3DESCBC; BEGIN INITIAL; return(ALG_ENC); }
+<S_ENCALG>null		{ yylval.num = SADB_EALG_NULL; BEGIN INITIAL; return(ALG_ENC_NOKEY); }
+<S_ENCALG>simple	{ yylval.num = SADB_EALG_NULL; BEGIN INITIAL; return(ALG_ENC_OLD); }
+<S_ENCALG>blowfish-cbc	{ yylval.num = SADB_X_EALG_BLOWFISHCBC; BEGIN INITIAL; return(ALG_ENC); }
+<S_ENCALG>cast128-cbc	{ yylval.num = SADB_X_EALG_CAST128CBC; BEGIN INITIAL; return(ALG_ENC); }
+<S_ENCALG>des-deriv	{ yylval.num = SADB_EALG_DESCBC; BEGIN INITIAL; return(ALG_ENC_DESDERIV); }
+<S_ENCALG>des-32iv	{ yylval.num = SADB_EALG_DESCBC; BEGIN INITIAL; return(ALG_ENC_DES32IV); }
+<S_ENCALG>twofish-cbc	{ yylval.num = SADB_X_EALG_TWOFISHCBC; BEGIN INITIAL; return(ALG_ENC); }
+<S_ENCALG>aes-cbc	{ 
+#ifdef SADB_X_EALG_AESCBC
+	yylval.num = SADB_X_EALG_AESCBC; BEGIN INITIAL; return(ALG_ENC); 
+#endif
+}
+<S_ENCALG>rijndael-cbc	{ 
+#ifdef SADB_X_EALG_AESCBC
+	yylval.num = SADB_X_EALG_AESCBC; BEGIN INITIAL; return(ALG_ENC); 
+#endif
+}
+<S_ENCALG>aes-ctr	{ yylval.num = SADB_X_EALG_AESCTR; BEGIN INITIAL; return(ALG_ENC); }
+<S_ENCALG>camellia-cbc	{ 
+#ifdef SADB_X_EALG_CAMELLIACBC
+	yylval.num = SADB_X_EALG_CAMELLIACBC; BEGIN INITIAL; return(ALG_ENC); 
+#endif
+}
+
+	/* compression algorithms */
+{hyphen}C	{ return(F_COMP); }
+oui		{ yylval.num = SADB_X_CALG_OUI; return(ALG_COMP); }
+deflate		{ yylval.num = SADB_X_CALG_DEFLATE; return(ALG_COMP); }
+lzs		{ yylval.num = SADB_X_CALG_LZS; return(ALG_COMP); }
+{hyphen}R	{ return(F_RAWCPI); }
+
+	/* extension */
+{hyphen}m	{ return(F_MODE); }
+transport	{ yylval.num = IPSEC_MODE_TRANSPORT; return(MODE); }
+tunnel		{ yylval.num = IPSEC_MODE_TUNNEL; return(MODE); }
+{hyphen}u	{ return(F_REQID); }
+{hyphen}f	{ return(F_EXT); }
+random-pad	{ yylval.num = SADB_X_EXT_PRAND; return(EXTENSION); }
+seq-pad		{ yylval.num = SADB_X_EXT_PSEQ; return(EXTENSION); }
+zero-pad	{ yylval.num = SADB_X_EXT_PZERO; return(EXTENSION); }
+nocyclic-seq	{ return(NOCYCLICSEQ); }
+{hyphen}r	{ return(F_REPLAY); }
+{hyphen}lh	{ return(F_LIFETIME_HARD); }
+{hyphen}ls	{ return(F_LIFETIME_SOFT); }
+{hyphen}bh	{ return(F_LIFEBYTE_HARD); }
+{hyphen}bs	{ return(F_LIFEBYTE_SOFT); }
+{hyphen}ctx	{ return(SECURITY_CTX); }
+
+	/* ... */
+any		{ return(ANY); }
+{ws}		{ }
+{nl}		{ lineno++; }
+{comment}
+{semi}		{ return(EOT); }
+
+	/* for address parameters: /prefix, [port] */
+{slash}		{ return SLASH; }
+{blcl}		{ return BLCL; }
+{elcl}		{ return ELCL; }
+
+	/* parameter */
+{decstring}	{
+			char *bp;
+
+			yylval.ulnum = strtoul(yytext, &bp, 10);
+			return(DECSTRING);
+		}
+
+{hexstring}	{
+			yylval.val.buf = strdup(yytext + 2);
+			if (!yylval.val.buf)
+				yyfatal("insufficient memory");
+			yylval.val.len = strlen(yylval.val.buf);
+
+			return(HEXSTRING);
+		}
+
+{quotedstring}	{
+			char *p = yytext;
+			while (*++p != '"') ;
+			*p = '\0';
+			yytext++;
+			yylval.val.len = yyleng - 2;
+			yylval.val.buf = strdup(yytext);
+			if (!yylval.val.buf)
+				yyfatal("insufficient memory");
+
+			return(QUOTEDSTRING);
+		}
+
+[A-Za-z0-9:][A-Za-z0-9:%\.-]* {
+			yylval.val.len = yyleng;
+			yylval.val.buf = strdup(yytext);
+			if (!yylval.val.buf)
+				yyfatal("insufficient memory");
+			return(STRING);
+		}
+
+[0-9,]+ {
+			yylval.val.len = yyleng;
+			yylval.val.buf = strdup(yytext);
+			if (!yylval.val.buf)
+				yyfatal("insufficient memory");
+			return(STRING);
+		}
+
+.		{
+			yyfatal("Syntax error");
+			/*NOTREACHED*/
+		}
+
+%%
+
+void
+yyfatal(s)
+	const char *s;
+{
+	yyerror(s);
+	exit(1);
+}
+
+void
+yyerror(s)
+	const char *s;
+{
+	printf("line %d: %s at [%s]\n", lineno, s, yytext);
+}
+
+int
+parse(fp)
+	FILE **fp;
+{
+	yyin = *fp;
+
+	lineno = 1;
+	parse_init();
+
+	if (yyparse()) {
+		printf("parse failed, line %d.\n", lineno);
+		return(-1);
+	}
+
+	return(0);
+}
+
+int
+parse_string (char *src)
+{
+	int             result;
+	YY_BUFFER_STATE buf_state;
+
+	buf_state = yy_scan_string(src);
+	result = yyparse();
+	yy_delete_buffer(buf_state);
+	return result;
+}
+
diff --git a/src/setkey/vchar.h b/src/setkey/vchar.h
new file mode 100644
index 0000000..5529291
--- /dev/null
+++ b/src/setkey/vchar.h
@@ -0,0 +1,42 @@
+/*	$NetBSD: vchar.h,v 1.4 2006/09/09 16:22:37 manu Exp $	*/
+
+/* Id: vchar.h,v 1.2 2004/06/07 09:18:47 ludvigm Exp */
+
+/*
+ * Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _VCHAR_H
+#define _VCHAR_H
+
+typedef struct {
+	u_int len;
+	caddr_t buf;
+} vchar_t;
+
+#endif /* _VCHAR_H */